Need more speed when changing PWM duty cycle.
Posted: Tue Jul 21, 2020 2:49 pm
Hello there,
Is there any way to sped up the speed of HardwareTimer::setCaptureCompare()?. I need it to be pretty fast, to be used on 100kHz timer interrupt, because i use it for my PWM-DAC on my digital power supply. I have tested the speed of setCaptureCompare on my BluePill and it was around 12us~15us and sometime it jump to whopping 120us, which is a big problem, because i call that function on a 100kHz timer interrupt. And because it can't accomodate the speed of my 100kHz timer, the chip actually goes freeze, and once i reduce it to like 40kHz the cpu run buttt realllly sloooowww, if i run it on 10kHz the cpu seems to working fine, but it was out of my target frequency which is 100kHz, or probably faster because it was dual channel.
I use BluePill board and STM32Core.
Here is my code:
Is there any way to sped up the speed of HardwareTimer::setCaptureCompare()?. I need it to be pretty fast, to be used on 100kHz timer interrupt, because i use it for my PWM-DAC on my digital power supply. I have tested the speed of setCaptureCompare on my BluePill and it was around 12us~15us and sometime it jump to whopping 120us, which is a big problem, because i call that function on a 100kHz timer interrupt. And because it can't accomodate the speed of my 100kHz timer, the chip actually goes freeze, and once i reduce it to like 40kHz the cpu run buttt realllly sloooowww, if i run it on 10kHz the cpu seems to working fine, but it was out of my target frequency which is 100kHz, or probably faster because it was dual channel.
I use BluePill board and STM32Core.
Here is my code:
Code: Select all
void Update_IT_callback(void){
int ch1AV = ch1Voltage.getAverage();
int ch1AA = ch1Current.getAverage();
int ch2AV = ch2Voltage.getAverage();
int ch2AA = ch2Current.getAverage();
setPwmValue(1,bufferDutyCh1);
bufferDutyCh1 = pwmDuty1;
if (raw_ch1Current > pre_ch1PresetA + pre_ch1PresetA / 2) {
bufferDutyCh1 = bufferDutyCh1/2;
}
else if (ch1AA > pre_ch1PresetA) {
bufferDutyCh1 = bufferDutyCh1-1;
}
else if (ch1AV > pre_ch1PresetV) {
bufferDutyCh1 = bufferDutyCh1-1;
}
else if (ch1AV < pre_ch1PresetV){
bufferDutyCh1 = bufferDutyCh1+1;
}
}
void pwmSetup(){
pwmTimer->setMode(CH1_TC, TIMER_OUTPUT_COMPARE_PWM1, PB8);
pwmTimer->setMode(CH2_TC, TIMER_OUTPUT_COMPARE_PWM1, PB7);
pwmTimer->setMode(DL_TC, TIMER_OUTPUT_COMPARE_PWM1, PB9);
pwmTimer->setOverflow(10, MICROSEC_FORMAT);
pwmTimer->setCaptureCompare(CH1_TC, 0, PERCENT_COMPARE_FORMAT);
pwmTimer->setCaptureCompare(CH2_TC, 0, PERCENT_COMPARE_FORMAT);
pwmTimer->setCaptureCompare(DL_TC, 0, PERCENT_COMPARE_FORMAT);
pwmTimer->resume();
cces->setOverflow(100, MICROSEC_FORMAT);
cces->attachInterrupt(Update_IT_callback);
cces->resume();
}
unsigned long mci1;
unsigned long mci2;
void setPwmValue(int channel,int val){
mci1 = micros();
val = constrain(val,0,8191);
if(channel == 1){
pwmDuty1 = val;
val = map(val, 0, 8191, 0, 65535);
pwmTimer->setCaptureCompare(CH1_TC,val,RESOLUTION_16B_COMPARE_FORMAT); // this guy takes 12~15us, and sometime 113us
}else if(channel == 2){
pwmDuty2 = val;
val = map(val, 0, 8191, 0, 65535);
pwmTimer->setCaptureCompare(CH2_TC,val,RESOLUTION_16B_COMPARE_FORMAT);
}
mci2 = micros()-mci1;
}