Not applicable
Feb 27, 2014
04:04 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Feb 27, 2014
04:04 AM
Hi,
Does anyone know what how to use DACWG002? especially its restrictions of desired frequency when DAC is made to generate a sinusoidal waveform?
I actually would like to create SPWM. So I use two DACWG002, one for sine waveform and the other for triangle waveform. I obtained correct SPWM waveform when the desired frequency for sine and triangle waveforms are 6Hz and 1000Hz respectively. But when I made them to be 60Hz and 1kHz, the resulted SPWM was flat.
Below is my code :
--------------------------------------------------------------------------
#include //Declarations from DAVE3 Code Generation (includes SFR declaration)
#include
double global_timer_inst = 0.0;
//double sine_amplitude = 1.0;
//double frequency = 50.0;
int32_t sineval = 0;
int32_t trival = 0;
DACWG002_Config DACconf_sine = //for sine wave
{
.Scale = 0,
.MulDivBit = 1,
.Offset = 0,
.BurstSize = 0,
.StartPhase = 0,
.Frequency = 60 // this is the problem
};
DACWG002_Config DACconf_tri = //for triangle wave
{
.Scale = 0,
.MulDivBit = 1,
.Offset = 0,
.BurstSize = 0,
.StartPhase = 0,
.Frequency = 10000 //bad freq
};
DACWG002_DynamicDataType DACdata_sine;
int main(void)
{
status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)
DAVE_Init(); // Initialization of DAVE Apps
status = PWMSP001_Start(&PWMSP001_Handle0);
status = CNT001_Start(&CNT001_Handle0);
status = DACWG002_Start(&DACWG002_Handle0);
status = DACWG002_Start(&DACWG002_Handle1);
while(1)
{
status = DACWG002_GetConfig(&DACWG002_Handle0, &DACconf_sine);
status = DACWG002_GetConfig(&DACWG002_Handle1, &DACconf_tri);
trival = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut];
sineval = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut];
}
return 0;
}
void CountMatch_InterruptHandler(void)
{
}
void PeriodMatch_InterruptHandler(void)
{
if(sineval > trival)
{
IO004_SetPin(IO004_Handle0);
}
else
{
IO004_ResetPin(IO004_Handle0);
}
}
void DAC_sine_Interrupt(void)
{
DACWG002_UpdateNextPoint(&DACWG002_Handle0);
}
void DAC_tri_Interrupt(void)
{
DACWG002_UpdateNextPoint(&DACWG002_Handle1);
}
-------------------------------------------------------------------------------
I was totally lost on this. Hope someone can help me on this. Thanks
Does anyone know what how to use DACWG002? especially its restrictions of desired frequency when DAC is made to generate a sinusoidal waveform?
I actually would like to create SPWM. So I use two DACWG002, one for sine waveform and the other for triangle waveform. I obtained correct SPWM waveform when the desired frequency for sine and triangle waveforms are 6Hz and 1000Hz respectively. But when I made them to be 60Hz and 1kHz, the resulted SPWM was flat.
Below is my code :
--------------------------------------------------------------------------
#include
#include
double global_timer_inst = 0.0;
//double sine_amplitude = 1.0;
//double frequency = 50.0;
int32_t sineval = 0;
int32_t trival = 0;
DACWG002_Config DACconf_sine = //for sine wave
{
.Scale = 0,
.MulDivBit = 1,
.Offset = 0,
.BurstSize = 0,
.StartPhase = 0,
.Frequency = 60 // this is the problem
};
DACWG002_Config DACconf_tri = //for triangle wave
{
.Scale = 0,
.MulDivBit = 1,
.Offset = 0,
.BurstSize = 0,
.StartPhase = 0,
.Frequency = 10000 //bad freq
};
DACWG002_DynamicDataType DACdata_sine;
int main(void)
{
status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)
DAVE_Init(); // Initialization of DAVE Apps
status = PWMSP001_Start(&PWMSP001_Handle0);
status = CNT001_Start(&CNT001_Handle0);
status = DACWG002_Start(&DACWG002_Handle0);
status = DACWG002_Start(&DACWG002_Handle1);
while(1)
{
status = DACWG002_GetConfig(&DACWG002_Handle0, &DACconf_sine);
status = DACWG002_GetConfig(&DACWG002_Handle1, &DACconf_tri);
trival = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut];
sineval = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut];
}
return 0;
}
void CountMatch_InterruptHandler(void)
{
}
void PeriodMatch_InterruptHandler(void)
{
if(sineval > trival)
{
IO004_SetPin(IO004_Handle0);
}
else
{
IO004_ResetPin(IO004_Handle0);
}
}
void DAC_sine_Interrupt(void)
{
DACWG002_UpdateNextPoint(&DACWG002_Handle0);
}
void DAC_tri_Interrupt(void)
{
DACWG002_UpdateNextPoint(&DACWG002_Handle1);
}
-------------------------------------------------------------------------------
I was totally lost on this. Hope someone can help me on this. Thanks
7 Replies
Not applicable
Mar 03, 2014
01:58 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 03, 2014
01:58 AM
Hi,
I don't have any experience on this application but I think it is a very interesting topic.
Just some thought from me: do you think direct writing to register could be faster?!
BR,
Zain
I don't have any experience on this application but I think it is a very interesting topic.
Just some thought from me: do you think direct writing to register could be faster?!
BR,
Zain
Mar 04, 2014
02:50 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 04, 2014
02:50 AM
Hallo Sarah,
I guess you use the DAC for SPWM to see the result on the oscilloscope.
Therefore the DAC is very good.
But there is an easier way to generate a SPWM.
I recommend using the CCU4 to generate a PWM and use the Period Interrupt for a Duty Cycle update.
This will decrease the CPU load a lot.
How to do this:
Use the PWMSP001 App to configure a CCU4 slice.
- select the frequency you want.
- enable period Interrupt.
- use Pin assignment to select the Output pin of the SPWM
Add a NVIC002 App to define a function witch can be called by a Hardware Interrupt (in this case CCU4 period Interrupt)
- in my case the "User defined Interrupt handler" has the Name "SPWM_update"
- enalbe also Interrupt.
Connect PWMSP001 to the NVIC002
- use "Signal Connection" to connect the period match Interrupt to the NVIC
Now the HW is configured. Let's go to the SW:
In the SPWM_update function I update the dutycyle of the CCU4. To generate a sine wave I Need a LUT.
You can still use the LUT from DACWG002 in Folder: Dave/Generated/src/DACWG002 /DACWG002_Config.c
Than you only have to typecast the Feedback to float and divide it by 2*"Amplitude" (entered in the DACWG app).
So you have a sine wave in float from 0-100% witch you can enter in the PMWSP001.
The Length of the LUT is then also the "oversampling" between Timer period and sine period.
There are faster and more ROM saving solution to use the LUT but for the beginning it should be ok.
int main(void)
{
// status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)
DAVE_Init(); // Initialization of DAVE Apps
PWMSP001_Start(&PWMSP001_Handle0);
while(1)
{}
return 0;
}
void SPWM_update (void)
{
// TODO: get Dutycycle from LUT
PWMSP001_SetDutyCycle(&PWMSP001_Handle0,dutycycle);
}
Hints:
- You can also use PWMSVM001 but then you provide 3 sine waves and use 3*CCU8 slices but much less Manual configuration.
- You still can use the DAC to Output the sine wave. For this use DACWG001 in single value (no scale) mode and call DACWG001_SetSingleValue with the scaled dutycycle (0- 4096).
I hope this was helpful.
Regards
Eric
I guess you use the DAC for SPWM to see the result on the oscilloscope.
Therefore the DAC is very good.
But there is an easier way to generate a SPWM.
I recommend using the CCU4 to generate a PWM and use the Period Interrupt for a Duty Cycle update.
This will decrease the CPU load a lot.
How to do this:
Use the PWMSP001 App to configure a CCU4 slice.
- select the frequency you want.
- enable period Interrupt.
- use Pin assignment to select the Output pin of the SPWM
Add a NVIC002 App to define a function witch can be called by a Hardware Interrupt (in this case CCU4 period Interrupt)
- in my case the "User defined Interrupt handler" has the Name "SPWM_update"
- enalbe also Interrupt.
Connect PWMSP001 to the NVIC002
- use "Signal Connection" to connect the period match Interrupt to the NVIC
Now the HW is configured. Let's go to the SW:
In the SPWM_update function I update the dutycyle of the CCU4. To generate a sine wave I Need a LUT.
You can still use the LUT from DACWG002 in Folder: Dave/Generated/src/DACWG002 /DACWG002_Config.c
Than you only have to typecast the Feedback to float and divide it by 2*"Amplitude" (entered in the DACWG app).
So you have a sine wave in float from 0-100% witch you can enter in the PMWSP001.
The Length of the LUT is then also the "oversampling" between Timer period and sine period.
There are faster and more ROM saving solution to use the LUT but for the beginning it should be ok.
int main(void)
{
// status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)
DAVE_Init(); // Initialization of DAVE Apps
PWMSP001_Start(&PWMSP001_Handle0);
while(1)
{}
return 0;
}
void SPWM_update (void)
{
// TODO: get Dutycycle from LUT
PWMSP001_SetDutyCycle(&PWMSP001_Handle0,dutycycle);
}
Hints:
- You can also use PWMSVM001 but then you provide 3 sine waves and use 3*CCU8 slices but much less Manual configuration.
- You still can use the DAC to Output the sine wave. For this use DACWG001 in single value (no scale) mode and call DACWG001_SetSingleValue with the scaled dutycycle (0- 4096).
I hope this was helpful.
Regards
Eric
Not applicable
Mar 04, 2014
06:26 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 04, 2014
06:26 AM
Hi Eric,
Thanks for the help. I tried to follow your sugesstion. Since I would like to use it to drive IGBTs in my 3-phase inverter which needs complementary signals, I used PWMSP002 instead of PWMSP001. I followed your instruction, and below is my code :
#include //Declarations from DAVE3 Code Generation (includes SFR declaration)
float dutycycle1 = 0;
float dutycycle2 = 0;
float dutycycle3 = 0;
int main(void)
{
// status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)
DAVE_Init(); // Initialization of DAVE Apps
PWMSP002_Start(&PWMSP002_Handle0);
PWMSP002_Start(&PWMSP002_Handle1);
PWMSP002_Start(&PWMSP002_Handle2);
while(1)
{}
return 0;
}
void SPWMUpdate(void)
{
dutycycle1 = (float) DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut];
dutycycle1 = ((float) (dutycycle1 + 500) / 1000.00) * 100.0;
PWMSP002_SetDutyCycle(&PWMSP002_Handle0, dutycycle1,0,0);
dutycycle2 = (float) DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 167];
dutycycle2 = ((float) (dutycycle2 + 500) / 1000.00) * 100.0;
PWMSP002_SetDutyCycle(&PWMSP002_Handle1,dutycycle2,0,0);
dutycycle3 = (float) DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 333];
dutycycle3 = ((float) (dutycycle3 + 500) / 1000.00) * 100.0;
PWMSP002_SetDutyCycle(&PWMSP002_Handle2,dutycycle3,0,0);
DACWG002_UpdateNextPoint(&DACWG002_Handle0);
}
LUT length was set at 1000, while PWMSP002 frequencies were at 50kHz to create a 50Hz SPWM. And the amplitude in DACWG002 was set at 500, signed int. It actually generated 50Hz SPWM waveform in my oscilloscope, but my inverter output was suffering significant harmonic distortion when the signals were fed into IGBTs. I guess there is something in the algorithm that can be improved to remove these distortions. I suspect that duty cycle approximation must be improved, not just : dutycycle1 = ((float) (dutycycle1 + Amplitude) / 2*Amplitude) * 100.0;
Do you have any suggestion to approximate duty cycle better? Thank you Eric.
Thanks for the help. I tried to follow your sugesstion. Since I would like to use it to drive IGBTs in my 3-phase inverter which needs complementary signals, I used PWMSP002 instead of PWMSP001. I followed your instruction, and below is my code :
#include
float dutycycle1 = 0;
float dutycycle2 = 0;
float dutycycle3 = 0;
int main(void)
{
// status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)
DAVE_Init(); // Initialization of DAVE Apps
PWMSP002_Start(&PWMSP002_Handle0);
PWMSP002_Start(&PWMSP002_Handle1);
PWMSP002_Start(&PWMSP002_Handle2);
while(1)
{}
return 0;
}
void SPWMUpdate(void)
{
dutycycle1 = (float) DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut];
dutycycle1 = ((float) (dutycycle1 + 500) / 1000.00) * 100.0;
PWMSP002_SetDutyCycle(&PWMSP002_Handle0, dutycycle1,0,0);
dutycycle2 = (float) DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 167];
dutycycle2 = ((float) (dutycycle2 + 500) / 1000.00) * 100.0;
PWMSP002_SetDutyCycle(&PWMSP002_Handle1,dutycycle2,0,0);
dutycycle3 = (float) DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 333];
dutycycle3 = ((float) (dutycycle3 + 500) / 1000.00) * 100.0;
PWMSP002_SetDutyCycle(&PWMSP002_Handle2,dutycycle3,0,0);
DACWG002_UpdateNextPoint(&DACWG002_Handle0);
}
LUT length was set at 1000, while PWMSP002 frequencies were at 50kHz to create a 50Hz SPWM. And the amplitude in DACWG002 was set at 500, signed int. It actually generated 50Hz SPWM waveform in my oscilloscope, but my inverter output was suffering significant harmonic distortion when the signals were fed into IGBTs. I guess there is something in the algorithm that can be improved to remove these distortions. I suspect that duty cycle approximation must be improved, not just : dutycycle1 = ((float) (dutycycle1 + Amplitude) / 2*Amplitude) * 100.0;
Do you have any suggestion to approximate duty cycle better? Thank you Eric.
Not applicable
Mar 04, 2014
12:09 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 04, 2014
12:09 PM
Hi Zain,
It is possibly faster. But it actually depends on what do you use to write the register. I heard that we have two choices, either using DMA or CPU. DMA performs "better" since it will reduce the work of CPU. So it eventually depends a lot on the type of project that you'd like to make. If your project needs numerous apps, it is better to use DMA to reduce the work of CPU. But if you need few apps for your project, I guess CPU will be better choice since the cycles wont be stolen by DMA to write onto register. CMIIW
Rgds,
Sarah
It is possibly faster. But it actually depends on what do you use to write the register. I heard that we have two choices, either using DMA or CPU. DMA performs "better" since it will reduce the work of CPU. So it eventually depends a lot on the type of project that you'd like to make. If your project needs numerous apps, it is better to use DMA to reduce the work of CPU. But if you need few apps for your project, I guess CPU will be better choice since the cycles wont be stolen by DMA to write onto register. CMIIW
Rgds,
Sarah
Not applicable
Mar 05, 2014
03:05 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 05, 2014
03:05 AM
Hi Sarah,
Thank you very much for the suggestions. I will try it when i have time…
BTW, would you mind to share your project when it works as you expect?
BR,
Zain
Thank you very much for the suggestions. I will try it when i have time…
BTW, would you mind to share your project when it works as you expect?
BR,
Zain
Mar 05, 2014
04:23 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 05, 2014
04:23 AM
Hallo Sarah,
I assumed that you need only one SPWM without dead time. Because of this I gave you the example with the PWMSP001.
When you need 3 Phase inverter with dead time the PWMSVM001 is the perfect solution. You can directly enter the angle and amplitude. And the PWM pattern for all 3 phases are generated. The using of the LUT is faster and the precision higher than my last example.
When you want to do Motorcontrol you can also use one of the Motorcontrol apps like PMSMFOCSL01 for example for PMSM motor with FOC control and sensor less single shunt feedback. Here also the startup, the current measurement and the FOC calculation is implemented. This top level App also use the PWMSVM001. Just have a look at the Motorcontrol Apps there are many more.
Otherwise you can also only use the PWMSVM001, trigger the NVIC and update the angle manualy.
If you need more information about the Peripherals we also have good documentation:
http://www.infineon.com/XMC4000
Also for motor control we have examples and getting startets:
www.infineon.com/xmc-dev -> Motorcontrol -> XMC4400/XMC4500
Also you can use the Dave examples. I recommend the PMSMFOCSL02_Example1, the Encoder_FOC_Motor_Example2 or the Resolver_FOC_Motor_Example1 here you have also additional documentation witch can be helpful.
Regards
Frederic
I assumed that you need only one SPWM without dead time. Because of this I gave you the example with the PWMSP001.
When you need 3 Phase inverter with dead time the PWMSVM001 is the perfect solution. You can directly enter the angle and amplitude. And the PWM pattern for all 3 phases are generated. The using of the LUT is faster and the precision higher than my last example.
When you want to do Motorcontrol you can also use one of the Motorcontrol apps like PMSMFOCSL01 for example for PMSM motor with FOC control and sensor less single shunt feedback. Here also the startup, the current measurement and the FOC calculation is implemented. This top level App also use the PWMSVM001. Just have a look at the Motorcontrol Apps there are many more.
Otherwise you can also only use the PWMSVM001, trigger the NVIC and update the angle manualy.
If you need more information about the Peripherals we also have good documentation:
http://www.infineon.com/XMC4000
Also for motor control we have examples and getting startets:
www.infineon.com/xmc-dev -> Motorcontrol -> XMC4400/XMC4500
Also you can use the Dave examples. I recommend the PMSMFOCSL02_Example1, the Encoder_FOC_Motor_Example2 or the Resolver_FOC_Motor_Example1 here you have also additional documentation witch can be helpful.
Regards
Frederic
Not applicable
Mar 05, 2014
11:28 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mar 05, 2014
11:28 PM
Hi Eric,
thanks for the suggestion. I finally found the good approximation of SPWM by using PWMSP001 Interrupt. But I was doing calculation to find the right time to update LUT using UpdateNextPoint. Here is my code :
#include //Declarations from DAVE3 Code Generation (includes SFR declaration)
#include
double global_timer_inst = 0.0;
double sine_amplitude = 1.0;
double frequency = 50.0;
bool initializer = TRUE;
int32_t sineval_A = 0;
int32_t trival_A = 0;
int32_t sineval_B = 0;
int32_t trival_B = 0;
int32_t sineval_C = 0;
int32_t trival_C = 0;
uint32_t globalcounter = 0;
uint16_t resultInv1 = 0;
uint16_t resultInv2 = 0;
//debugging variables
uint32_t sine_int = 0;;
uint32_t triangle_int = 0;
DACWG002_Config DACconf_sine = //for sine wave
{
.Scale = 0,
.MulDivBit = 1,
.Offset = 0,
.BurstSize = 0,
.StartPhase = 0,
.Frequency = 50
};
DACWG002_Config DACconf_tri = //for triangle wave
{
.Scale = 0,
.MulDivBit = 1,
.Offset = 0,
.BurstSize = 0,
.StartPhase = 0,
.Frequency = 10000
};
DACWG002_DynamicDataType DACdata_sine;
int main(void)
{
status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)
uint32_t delay;
ADC002_QueueEntryHandleType ADC002_QueueEntryHandleInv1
= {
.Active = 1,
.ChannelNumber = 0,
.Refill = 0,
.ExternalTrigger = 0,
.Interrupt = 0,
};
ADC002_QueueEntryHandleType ADC002_QueueEntryHandleInv2
= {
.Active = 1,
.ChannelNumber = 2,
.Refill = 0,
.ExternalTrigger = 0,
.Interrupt = 0,
};
DAVE_Init(); // Initialization of DAVE Apps
status = PWMSP001_Start(&PWMSP001_Handle0);
status = DACWG002_Start(&DACWG002_Handle0);
status = DACWG002_Start(&DACWG002_Handle1);
while(1)
{
status = DACWG002_GetConfig(&DACWG002_Handle0, &DACconf_sine);
status = DACWG002_GetConfig(&DACWG002_Handle1, &DACconf_tri);
ADC002_AddQueueEntry((ADC002_HandleType*)&ADC002_Handle0, &ADC002_QueueEntryHandleInv1);
ADC002_AddQueueEntry((ADC002_HandleType*)&ADC002_Handle0, &ADC002_QueueEntryHandleInv2);
for(delay=0; delay < 0xffff; delay++);
}
return 0;
}
void PeriodMatch_InterruptHandler(void)
{
//positionsine = DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut;
//positiontri = DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut;
if(!initializer)
{
DACWG002_UpdateNextPoint(&DACWG002_Handle1);
}
if((globalcounter % 26) == 0 && !initializer)
{
DACWG002_UpdateNextPoint(&DACWG002_Handle0);
globalcounter = 0;
}
initializer = FALSE;
//phase A
trival_A = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut];
sineval_A = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut];
if(sineval_A > trival_A)
{
IO004_SetPin(IO004_Handle0);
IO004_ResetPin(IO004_Handle3);
}
else
{
IO004_ResetPin(IO004_Handle0);
IO004_SetPin(IO004_Handle3);
}
//phase B
if(DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 67 > 200)
{
trival_B = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 67 - 200];
}
else
{
trival_B = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 67];
}
if(DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 67 > 200)
{
sineval_B = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 67 - 200];
}
else
{
sineval_B = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 67];
}
//phase C
if(DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 133 > 200)
{
trival_C = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 133 - 200];
}
else
{
trival_C = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 133];
}
if(DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 133 > 200)
{
sineval_C = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 133 - 200];
}
else
{
sineval_C = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 133];
}
if(sineval_B > trival_B)
{
IO004_SetPin(IO004_Handle1);
IO004_ResetPin(IO004_Handle4);
}
else
{
IO004_ResetPin(IO004_Handle1);
IO004_SetPin(IO004_Handle4);
}
if(sineval_C > trival_C)
{
IO004_SetPin(IO004_Handle2);
IO004_ResetPin(IO004_Handle5);
}
else
{
IO004_ResetPin(IO004_Handle2);
IO004_SetPin(IO004_Handle5);
}
globalcounter++;
}
void ADCInterrupt0(void)
{
status_t status;
status = ADCCH001_GetResult(&ADCCH001_Handle0, &resultInv1);
if(resultInv1 < 2048)
{
IO004_SetPin(IO004_Handle6);
}
else
{
IO004_ResetPin(IO004_Handle6);
}
ADCCH001_ClearResultEvtFlag(&ADCCH001_Handle0);
}
void ADCInterrupt2(void)
{
status_t status;
status = ADCCH001_GetResult(&ADCCH001_Handle2, &resultInv2);
if(resultInv1 < 2048)
{
IO004_SetPin(IO004_Handle7);
}
else
{
IO004_ResetPin(IO004_Handle7);
}
ADCCH001_ClearResultEvtFlag(&ADCCH001_Handle2);
}
-------------------------------------------------
The code works well and my 3-phase waveforms are free from distortions. Now I am facing interrupt problems when I want to combine it with ADC interrupts :eek: . Thanks anyway.
Rgds,
Sarah
thanks for the suggestion. I finally found the good approximation of SPWM by using PWMSP001 Interrupt. But I was doing calculation to find the right time to update LUT using UpdateNextPoint. Here is my code :
#include
#include
double global_timer_inst = 0.0;
double sine_amplitude = 1.0;
double frequency = 50.0;
bool initializer = TRUE;
int32_t sineval_A = 0;
int32_t trival_A = 0;
int32_t sineval_B = 0;
int32_t trival_B = 0;
int32_t sineval_C = 0;
int32_t trival_C = 0;
uint32_t globalcounter = 0;
uint16_t resultInv1 = 0;
uint16_t resultInv2 = 0;
//debugging variables
uint32_t sine_int = 0;;
uint32_t triangle_int = 0;
DACWG002_Config DACconf_sine = //for sine wave
{
.Scale = 0,
.MulDivBit = 1,
.Offset = 0,
.BurstSize = 0,
.StartPhase = 0,
.Frequency = 50
};
DACWG002_Config DACconf_tri = //for triangle wave
{
.Scale = 0,
.MulDivBit = 1,
.Offset = 0,
.BurstSize = 0,
.StartPhase = 0,
.Frequency = 10000
};
DACWG002_DynamicDataType DACdata_sine;
int main(void)
{
status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)
uint32_t delay;
ADC002_QueueEntryHandleType ADC002_QueueEntryHandleInv1
= {
.Active = 1,
.ChannelNumber = 0,
.Refill = 0,
.ExternalTrigger = 0,
.Interrupt = 0,
};
ADC002_QueueEntryHandleType ADC002_QueueEntryHandleInv2
= {
.Active = 1,
.ChannelNumber = 2,
.Refill = 0,
.ExternalTrigger = 0,
.Interrupt = 0,
};
DAVE_Init(); // Initialization of DAVE Apps
status = PWMSP001_Start(&PWMSP001_Handle0);
status = DACWG002_Start(&DACWG002_Handle0);
status = DACWG002_Start(&DACWG002_Handle1);
while(1)
{
status = DACWG002_GetConfig(&DACWG002_Handle0, &DACconf_sine);
status = DACWG002_GetConfig(&DACWG002_Handle1, &DACconf_tri);
ADC002_AddQueueEntry((ADC002_HandleType*)&ADC002_Handle0, &ADC002_QueueEntryHandleInv1);
ADC002_AddQueueEntry((ADC002_HandleType*)&ADC002_Handle0, &ADC002_QueueEntryHandleInv2);
for(delay=0; delay < 0xffff; delay++);
}
return 0;
}
void PeriodMatch_InterruptHandler(void)
{
//positionsine = DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut;
//positiontri = DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut;
if(!initializer)
{
DACWG002_UpdateNextPoint(&DACWG002_Handle1);
}
if((globalcounter % 26) == 0 && !initializer)
{
DACWG002_UpdateNextPoint(&DACWG002_Handle0);
globalcounter = 0;
}
initializer = FALSE;
//phase A
trival_A = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut];
sineval_A = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut];
if(sineval_A > trival_A)
{
IO004_SetPin(IO004_Handle0);
IO004_ResetPin(IO004_Handle3);
}
else
{
IO004_ResetPin(IO004_Handle0);
IO004_SetPin(IO004_Handle3);
}
//phase B
if(DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 67 > 200)
{
trival_B = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 67 - 200];
}
else
{
trival_B = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 67];
}
if(DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 67 > 200)
{
sineval_B = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 67 - 200];
}
else
{
sineval_B = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 67];
}
//phase C
if(DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 133 > 200)
{
trival_C = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 133 - 200];
}
else
{
trival_C = DACWG002_Handle1.WaveLutPtr[DACWG002_Handle1.DynamicDataPtr->CurrentPosInLut + 133];
}
if(DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 133 > 200)
{
sineval_C = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 133 - 200];
}
else
{
sineval_C = DACWG002_Handle0.WaveLutPtr[DACWG002_Handle0.DynamicDataPtr->CurrentPosInLut + 133];
}
if(sineval_B > trival_B)
{
IO004_SetPin(IO004_Handle1);
IO004_ResetPin(IO004_Handle4);
}
else
{
IO004_ResetPin(IO004_Handle1);
IO004_SetPin(IO004_Handle4);
}
if(sineval_C > trival_C)
{
IO004_SetPin(IO004_Handle2);
IO004_ResetPin(IO004_Handle5);
}
else
{
IO004_ResetPin(IO004_Handle2);
IO004_SetPin(IO004_Handle5);
}
globalcounter++;
}
void ADCInterrupt0(void)
{
status_t status;
status = ADCCH001_GetResult(&ADCCH001_Handle0, &resultInv1);
if(resultInv1 < 2048)
{
IO004_SetPin(IO004_Handle6);
}
else
{
IO004_ResetPin(IO004_Handle6);
}
ADCCH001_ClearResultEvtFlag(&ADCCH001_Handle0);
}
void ADCInterrupt2(void)
{
status_t status;
status = ADCCH001_GetResult(&ADCCH001_Handle2, &resultInv2);
if(resultInv1 < 2048)
{
IO004_SetPin(IO004_Handle7);
}
else
{
IO004_ResetPin(IO004_Handle7);
}
ADCCH001_ClearResultEvtFlag(&ADCCH001_Handle2);
}
-------------------------------------------------
The code works well and my 3-phase waveforms are free from distortions. Now I am facing interrupt problems when I want to combine it with ADC interrupts :eek: . Thanks anyway.
Rgds,
Sarah