2018-10-22 09:30 PM
I have L432KC nucleo. I’ve set Timer 1 for PWM generation. I’m controlling the duty cycle via the CCR register. When increasing o decreasing the duty cycle, I want it to be slow. It works with a for loop and delay. But HAL_Delay prevents from doing another thing in the loop. Is there another way of doing this?
2018-10-23 12:18 AM
can you show your code ?
you could set a flag to decrease in steps...
you could set the PWM timer over flow interrupt ON
and if the flag is set decrement/increment the PWM dutyCycle if your conditions are right...
2018-10-23 01:11 AM
Perhaps use a second timer to manage the duty cycle. So TIM1 does PWM at 10kHz (say), and TIM2 changes the duty at 100Hz (say). Fewer interrupts that way, but at the cost of a timer. I generally use a software timer implementation based around SysTick for this sort of thing.
2018-10-23 04:54 AM
This is what I have: two functions, one to go up and another to fade out.
The problem is I don't want to use HAL_Delay, as I can't do anything else until the for loop is done.
void ramp_down(){
int real_dutyCycle = 8*command_dutyC;
for (int fadeValue = actual_dutyC;fadeValue == real_dutyCycle;fadeValue -= 1) {
htim1.Instance->CCR1=fadeValue;
// wait for 30 milliseconds to see the dimming effect
HAL_Delay(30);
}
actual_dutyC = real_dutyCycle;
}
void ramp_up(){
int real_dutyCycle = 8*command_dutyC;
for (int fadeValue = actual_dutyC;fadeValue == real_dutyCycle;fadeValue += 1) {
htim1.Instance->CCR1=fadeValue;
// wait for 30 milliseconds to see the dimming effect
HAL_Delay(30);
}
actual_dutyC = real_dutyCycle;
}
2018-10-23 05:34 AM
Yes, you need a state machine, easy enough..
are you running RTOS ?
I use a single thread and check all my state machines every mS
In your case you would initialise the CCR1 in Start_Ramp_Down();
htim1.Instance->CCR1=fadeValue;
and then set a flag like this...
set some global vars;
char mSint,secondInt,seconds,minuteInt;
char resetActualDutyCycle_mS,rampingDown;
int real_dutyCycle,actual_dutyC,fadeValue;
int16_t mS;
in Systick(){ // add these lines
msint = true;
mS++;
if(mS>=1000){
mS=0;
secondInt=true;
seconds++;
if(seconds>=60){
seconds=0;
minuteInt = true;
}
}
void start_ramp_down(){
real_dutyCycle = 8*command_dutyC;
rampingDown = true;
fadeValue = actual_dutyC;
htim1.Instance->CCR1=fadeValue;
// wait for 30 milliseconds to see the dimming effect
//HAL_Delay(30);
resetActualDutyCycle_mS = 30; //mS
CurrentDutyCycle_mS = resetActualDutyCycle_mS;
}
under while(1){
checkStateMachines();
}
checkStateMachines(){ //every mS
if(msInt){ // this remains running forever
mSint = false;
if(rampingDown ) // state machine flag
if(!CurrentDutyCycle_mS --){ //this checks if the 30mS is over.
CurrentDutyCycle_mS = resetActualDutyCycle_mS; // this resets the 30mS counter
if(fadeValue > real_dutyCycle){
fadeValue -=1;
htim1.Instance->CCR1=fadeValue;
}else //reached end
{
rampingDown = false; // this will stop the statemachine
actual_dutyC = real_dutyCycle;
}
// check other states/flags here every mS
}
}
well that's the general idea
2018-10-23 06:09 AM
A different approach to loops is to use a moving average filter on the PWM value.
Changing the PWM setpoint has to pass through the moving average filter, that you can make as slow as you'd like by changing the calculation interval or by cascading multiple.
2018-10-23 07:21 AM
Thank you. I'm not running RTOS actually. I will review your ideas. It would take me a while to get it working as I'm not a software-oriented guy.
2018-10-23 07:43 AM
Put the code in the TIM update interrupt, rather than waiting.
2018-10-23 08:13 AM
Do you mean setting another timer interrupt and put the code in it?