Variable overflows inside timer irq handler - stm32f427
Hello,
i am using a stm32f427 trough C with IAR compiler, and i am facing a strange situation.
To have a overview, the functionality of the app, is relaying on 3 ISR's.
Timer1 IRQ handler - runs at 25khz where some comutation, and update dutycycle registers is performed
Timer2 IRQ handler - is used to calculate the rpm of the motor, via 3 hall sensors events, the rate of this isr can vary, depending on the speed of the hall signals.
Timer4 IRQ handler - runs at a fixed 1000hz rate, where i compute some PID algorithm
The problem is in timer4 irq handler, if the value of pid is less than 0, the returned value of DutyCycle is somewhere like 65123,
For example :
DutyCycle = (uint16_t)50 - (int)(-2) , i would expect to get 48.
If the pid_out is <=0, the dutycycle value is ok.
Why is this behaviour?
I have posted bellow the code from the irq handlers, as well as the variables declared globaly
uint16_t DutyCycle = 50;
float iTerm = 0.0;
float iTerm_last = 0.0;float dTerm = 0.0;float p_out = 0.0;float KP = 0.2;
float KI = 0;float KD = 0;float SampleTime = 0.001;
int16_t pid_out =0;void TIM4_IRQHandler(){ if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM4, TIM_IT_Update);p_SetPoint = 200; // set desired speed for motor at 200rpm
p_error = p_SetPoint - mrpm; // calculate the error iTerm = iTerm_last + ((float)p_error * SampleTime); iTerm_last = iTerm; // save current iTerm for the next cycledTerm = (p_error - p_error_last)/SampleTime;pid_out = (KP * p_error) + (KI*iTerm) + (KD*dTerm);p_error_last = p_error; if(pid_out > 400) DutyCycle= 400; // this works okelse if(pid_out < 0)
DutyCycle = DutyCycle + pid_out; // this is overflowingelse
DutyCycle = pid_out;}
}void TIM1_CC_IRQHandler(){if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)
{ TIM_ClearITPendingBit(TIM1, TIM_IT_CC4);if(DutyCycle < 400)
{ // safe guard not to exceed 400 dutycycle
TIM1->CCR1=DutyCycle; // update Ch1 duty cycle TIM1->CCR2=DutyCycle;// update Ch1 duty cycle
TIM1->CCR3=DutyCycle;// update Ch1 duty cycle
}
}
void TIM2_IRQHandler()
{ uint8_t nSample = 6;if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{ TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);t_sum = (uint16_t)TIM2->CCR1;
t = (uint32_t)(t_sum *14); t= t * 18; t = t/1000; t= 60000/t; t_buf=t_buf+t; // store in the buffer for average t_cnt++; if(t_cnt==nSample){
mrpm = t_buf/t_cnt; t_cnt=0; t_buf=0; }}
}
