2025-08-20 9:44 PM
I am using stm32G431C8U6 microcontroller and I use TB6612 motor driver to control two motors with encoders. I have enabled timer 2 channel 3 and 4 for PWM generation and Timer3 and Timer 4 for combined channel encoder mode. Also I have used Timer15 for timer interrupt. I need to move the two motors for a specific counter pulses (eg:25,000) and then I need to stop them when timer3 counter reaches to specified counter pulses. In the code it will not exactly stop at 25,000(specified counter pulses) and it will deviated more than 25,000 (like 25,123,25,200) .Hence I have used PID function to mitigate this issue. I have enabled timer 15 for interrupt and in that interrupt function I have called back my PID function.
In the PID function it is supposed to be that counter starts from 0 and every 100ms it will increment by one. For an example initially timer 3 counter at 0 and then next 100ms it will reach to one. Then I have designed the pid function as below,
apply_pid(int error)
{
int Kp=0.01;
int16_t output =0;
error = 25,000 - CounterTicks;
output = (Kp)*error;
TIM2->CCR3 == output;
}
In here CounterTicks is the variable for counterpulses. Here I have used only proportional part for simplicity.
According to theory that interrupt function will callback the PID function and there
counterticks will increment by instance of every 100ms and each instance it will calculate error and assign that value to PWM CCR variable.Then error will be proportional to pwm and eventually motors should stop intended counterpulses which is 25,000.
The issue is code does not work as intended. Hence I need your help to configure this issue. Thank you.
2025-08-20 10:37 PM
I don't understand the complete code but one mistake i could see is
TIM2->CCR3 == output;
you have used "==" instead of "="
2025-08-20 11:46 PM
Here is the complete PID function that I have written
apply_pid(int error)
{
int8_t MSG[20] = {'\0'};
int8_t PID[20] = {'\0'};
int8_t OPT[20] = {'\0'};
int16_t CounterTicks = 0;
int16_t out_pid = 0;
int16_t output =0;
int Kp =0.01;
error = 25,000 - CounterTicks;
output = (Kp)*error;
TIM2->CCR3 = output;
if (error = 0)//Stop
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,0);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4,1);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,1);
}
else if(error < 0)//rotate reverse
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,0);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,0);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,1);
TIM2->CCR3 = output;
TIM2->CCR4 = output;
}
else //rotate forward
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,0);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);
TIM2->CCR3 = output;
TIM2->CCR4 = output;
if(output >= 499)
{
TIM2->CCR3 =499;
}
else
{
TIM2->CCR3 = output;
}
}
return error;
}
I still could not find out how to substarct each counter pulses in each instance from 25,000(specified counter pulse) to get error. Counterticks value and Current PWM value(out_pid) will be transmitted to serial monitor as UART signal in main function.
2025-08-20 11:55 PM
if (error = 0)//Stop
i suggest you use some static analyzer tool.