Hello
I am trying to vary the PWM duty-cycle based on an ADC value.PWM frequency is 16khz
What i am trying to achieve is keep an output current constant by driving MOSFETs through a QG8.An ADC channel measures this current value.
What i see is that the duty-cycle remains unchanged even when ADC values change.
I think i am doing a very basic mistake , someone please correct me..writing init and ISR codes here
#define TIMER_OVERFLOW 60 // us
interrupt 7 void TimerCH1 (void)
{
// Stops Timer1
TPMSC = TIMER_STOP;
if(current_adjust>512) // 1.5v corresponds to 5A
{
duty_cycle_variation--;
if(duty_cycle_variation<=1)duty_cycle_variation=1;
}
if(current_adjust<512)
{
duty_cycle_variation++;
if(duty_cycle_variation>=100)duty_cycle_variation=100;
}
TPMC1V = duty_cycle_variation;
// Restarts Timer1
TPMSC = TIMER_START;
}
void Timer1_init(void)
{
// Timer1 period
TPMMOD = TIMER_OVERFLOW; //15ms
//Initial duty cycle
TPMC1V=0;
// Selects PWM Low-true pulses in the Timer1 Channel0 (PTA0/TPM1CH0)
TPMC1SC = 0x028; //flag=0|ch_int_dis=0|MSnBA=10=edge aligned PWM|ELSBA=01=set o/p on compare|00
// Starts Timer1 ELSBA=10=clr o/p on compare
//TPMSC = TIMER_START; //0,TOIE=1,CPWMS=0,CLKSAB=01 PS2-0=011(div/8=1us)
}
Someone please help
Thanks and regards
Solved! Go to Solution.
Hello,
There are a few factors that you need to take into account -
One possible approach to synchronise the ADC and PWM operation would be to utilise the TPM overflow interrupt. Within the ISR code, the previous ADC conversion would be read, and a new ADC conversion started. The result just obtained would then be processed to update the TPMC1V register. Since the actual PWM duty would udate just prior to the next overflow, the control would lag by at least one PWM period. However, you would need substantial filtering, over many PWM periods, to sense the average load current.
Assume you were using a bus frequency of 10 MHz and an ADC clock of 5 MHz. With short sampling interval, the ADC conversion time would be equivalent 45 bus cycles. To this you would need to add the number of cycles required to enter the ISR, plus the cycles for reading of the previous result and starting the new conversion. The minimum PWM period should be somewhat greater than this value, provided the additional cycles to complete and exit the ISR does not exceed 45 cycles.
It is also possible that the occurrence of other interrupts may affect the stability of your control system.
Regards,
Mac
Hello,
There are a few factors that you need to take into account -
One possible approach to synchronise the ADC and PWM operation would be to utilise the TPM overflow interrupt. Within the ISR code, the previous ADC conversion would be read, and a new ADC conversion started. The result just obtained would then be processed to update the TPMC1V register. Since the actual PWM duty would udate just prior to the next overflow, the control would lag by at least one PWM period. However, you would need substantial filtering, over many PWM periods, to sense the average load current.
Assume you were using a bus frequency of 10 MHz and an ADC clock of 5 MHz. With short sampling interval, the ADC conversion time would be equivalent 45 bus cycles. To this you would need to add the number of cycles required to enter the ISR, plus the cycles for reading of the previous result and starting the new conversion. The minimum PWM period should be somewhat greater than this value, provided the additional cycles to complete and exit the ISR does not exceed 45 cycles.
It is also possible that the occurrence of other interrupts may affect the stability of your control system.
Regards,
Mac
Hello Mac,
Not meaning to hijack this thread but could I get you to explain this comment you made in your answer please?
"To achieve this you would need to reduce your PWM frequency (this will also increase the PWM resolution)."
Is there anywhere I could refer to about this to gain a better understanding in preparation of using the TPM in PWM mode for an RGB LED project I'm about to start.
Thank you,
Ian
Hello Ian
What Mac means is
Increase TPMMOD (overflow value) so that effectively frequency is reduced
Hi Abhijit,
Thanks for the reply and yes I can see how increasing TPMMOD will reduce the frequency but how is the PWM resolution calculated/changed? As I understand it's a 16 bit timer but if the TPMMOD is 255 max then the PWM resolution is 8 bits... is it that simple!?
Thanks,
Ian
Hello Ian,
The TPM module uses a 16-bit counter, with the ability to adjust the modulo value to a smaller value. For PWM operation, the modulo value TPMMOD, in conjunction with the TPM prescale value and the bus frequency, will determine the PWM frequency. The PWM period is given by (TPMMOD + 1) * prescale / fbus.
This means that the maximum count is TPMMOD, and the counter will again become zero on the next TPM clock. The PWM duty is given by TPMCnV / (TPMMOD + 1).
Regards,
Mac
Hi Mac,
Thank you for the explanation, much appreciated. Can you clarify how I calculate the PWM resolution that you mentioned about increasing to Abhijit. My guess is that a TPMMOD value of 255 would deliver an 8 bit resolution or is it not that simple?
Thanks,
Ian
Hello Ian,
The step increment in duty is given by 1/(TPMMOD + 1). The OP was using a TPMMOD value of 60, with a prescale factor of 8. My previous comment suggested that the prescale value could be set to 1, and the TPMMOD value increased to 487, so as to produce exactly the same PWM frequency. This would result in the step increment being reduced by a factor of 8, i.e. 1/488 instead of 1/61.
Regards,
Mac
Hi Mac
Thanks for replying!
I have done some changes according to your suggestion.
I am measuring 4 ADC values (8 samples each) a 16x2 LCD and other interrupts as well.So the loop is bound to be sluggish
I do not expect instantaneous correction in PWM since i am trying to charge a battery and it isn't hazardous.
What i want to achieve is driving a source from a MOSFET to a battery and another load.The other load demands much more current than the battery.
I want to keep the battery charging at 10A and provide the load with whatever current it demands.So i want to keep the dutycycle under check till battery demands 10A current and when load demands more current duty cycle has to be increased
I will write some snippets here...
ADC init
void Init_ADC(void)
{
ADCSC1 = 0x1F; // No ADC channel selected during config
// ADCCFG = 0xF8; // Bus clk, 10-bit, long sampling, clock/2 & low power
ADCCFG = 0x09; // Bus clk, 10-bit, short sampling, clock/2 & high speed
ADCSC2 = 0x00; // S/w trigger, no compare
APCTL1_ADPC7 = 1 ; // Pin I/O disabled for ADP7
APCTL1_ADPC6 = 1 ; // Pin I/O disabled for ADP6
APCTL1_ADPC5 = 1 ; // Pin I/O disabled for ADP5
APCTL1_ADPC4 = 1 ; // Pin I/O disabled for ADP4
}
interrupt 7 void TimerCH1 (void)
{
// Stops Timer1
TPMSC = TIMER_STOP;
ADCSC1_test= ADCSC1; //to unharm other ADC reads which r out of this ISR
ADCSC1 = 0x07 ;
while (!ADCSC1_COCO);
current_adjust=ADCR;
if(current_adjust<=4) current_adjust=4; //min duty
TPMC1V = current_adjust;
ADCSC1= ADCSC1_test ; //to retain other ADC readings
// Restarts Timer1
TPMSC = TIMER_START;
}
void Timer1_init(void)
{
// Timer1 period
TPMMOD = TIMER_OVERFLOW; //200us
//Initial duty cycle
TPMC1V=0;
// Selects PWM Low-true pulses in the Timer1 Channel0 (PTA0/TPM1CH0)
TPMC1SC = 0x024; //flag=0|ch_int_dis=0|MSnBA=10=edge aligned PWM|ELSBA=01=set o/p on compare|00
// Starts Timer1 ELSBA=10=clr o/p on compare
//TPMSC = TIMER_START; //0,TOIE=1,CPWMS=0,CLKSAB=01 PS2-0=011(div/8=1us)
}
Your suggestion to keep TPM enabled does not provide time for other peripherals, so am forced to disable it in ISR.
Hello Abhijit,
Abhijit Jagtap wrote:
Your suggestion to keep TPM enabled does not provide time for other peripherals, so am forced to disable it in ISR.
I do not understand your concern. When the TPM module is operating in PWM mode, the output is quite independent of, and does not affect the operation of any other peripheral module. The PWM channel interrupt would usually remain disabled. When ready to update the duty value, simply write the new value to the TPM channel register (TPMC1V) and the change of waveform will be automatically synchronised, as previously explained. In fact, disabling and re-enabling the TPM module may potentially disrupt the PWM waveform because the normal "coherency" mechanism. would be temporarily disabled.
Since you have no synchronisation issues between the ADC operation and the PWM waveform, the only reason you might have the TPM overflow interrupt enabled would be for general timing purposes.
You're averaging of more than one reading for each ADC channel is presumably to reduce noise fluctuations. To reduce the effect of mains hum, you could equally space the ADC samples for each channel, so that the average value would apply over a 20ms period.
I notice that you have a prescale setting of 8. I suggest that you use a prescale setting of 1, and multiply the TPMMOD value by 8. This will increase the PWM resolution by the same factor.
It is unclear how many ADC channels that you actually require. You appear to have four enabled (channels 4 to 7). However, I would suggest that you simultaneously write to all bits of the APCTL1 register, rather than one bit at a time. This will improve the efficiency of your code (fewer bytes and fewer cycles).
Regards,
Mac
Hello Mac
"When the TPM module is operating in PWM mode, the output is quite independent of, and does not affect the operation of any other peripheral module"
This is not happening.I have to force shut it in the ISR , change the duty and restart the timer, only then will it work.
Not working means that i get the least duty cycle and as i see in the True time simulator , no other variables are being updated.(same thing happens when i am not connecting the debugger)
I tried thus
read ADC value;
check for limits;
increase or decrease duty cycle depending on set values;
check limits for max and min duty;
write to TPMC1V in ISR;
I have selected
TPMMOD = 1024;
TPMSC= 0x48;// tried with 0x49
I repeat , the duty cycle variation works only when i stop and start timer in isr
The only issue here is than i cannot reach Duty cycle above 90%, here waveform becomes unstable.
Can you please help??
Message was edited by: Abhijit Jagtap Forgot to mention one more thing. I have changed TPMC1SC = 0x028;//from 0x24 i get waves as attached (with different time bases) you can see an unwanted SET o/p when o/p should be low... cant understand why this is happening......
Hello,
I suggest that you attach your project to this thread so that others may test.
Using the overflow interrupt, presumably on every overflow, I would expect that there would be a minimum allowable duty dependent on the latency and execution time of the ISR. To minimize the execution time, only the update of the TPMC1V value should be done within the ISR - the limit checks, etc. could be done within the main loop.
Regards,
Mac
Hello Mac
I figured it out.
I wasn't reading and resetting the TOF flag!!
Now it works as expected :smileyhappy:
Thanks and Regards
Abhijit