2021-04-12 02:37 AM
I want to control BLDC motor in six step method using STM32G474RE (nucleo board).
I'm using TIM1 CHx/CHxN complementary PWM output for 6 pwm signal, like below:
The problem I have is that the PWM output does not switch synchronously when switching steps, like below:
The desired switch looks like this:
How can I synchronaize the PWM when switching the steps, with STM32G474 MPU?
Please give me some advice.
My setting for TIM1 PWM:
And, a part of code for six step:
void MC_NEXT_step(mc_six_step_t *p)
{
switch (p->step_count)
{
case 0:
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, p->compare_value);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
break;
case 1:
HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, p->pwm.period);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
break;
case 2:
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, p->compare_value);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
break;
case 3:
HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, p->pwm.period);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
break;
case 4:
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, p->compare_value);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
break;
case 5:
HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, p->pwm.period);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
break;
default:
break;
}
}
2021-04-19 02:54 AM
Hi Javier-san
#.1 The way to set low both PWM-UL and PWM-UH is to write code like this:
htim1.Instance->CCER &= (uint16_t) ~TIM_CCER_CC1E;
htim1.Instance->CCER &= (uint16_t) ~TIM_CCER_CC1NE;
But this code not not switch properly like below:
#2. To switch properly, I can use this code.
TIM1->CCMR1 &= TIM_CCMR1_OC2M;
TIM1->CCMR1 |= TIM_OCMODE_FORCED_INACTIVE;
But when use this code, the PWM output cannot be restarted as shown in the figure.
2021-04-19 03:06 AM
@Kenji what if you use TIM_OCMODE_INACTIVE?
This would not force the channel inactive untill next commutation event.
2021-04-19 03:30 AM
Javier-san
I use for PWM-UH/HL
for off:
TIM1->CCMR1 &= TIM_CCMR1_OC2M;
TIM1->CCMR1 |= TIM_OCMODE_INACTIVE;
for on:
TIM1->CCMR1 |= TIM_OCMODE_ACTIVE;
and the result is as bellow. It works correctly only in the two steps of starting the drive.
2021-04-19 03:48 AM
sorry @Kenji thats all i remember without getting my hands in bldc again.
Hope you break trough this issues ;)
i would play a bit with the enable/disable and force inactives....
2021-04-19 10:17 PM
I think your triggering the required channel for every case. you need to stop the third floating channel in every case.
2021-04-20 07:37 PM
Hi Karthik-san
The combination of these registers in TIM1 and the functions used for commutation updates changes the situation.
I don't know the best combination for now. PWMs are not synchronized.
/***************************************/
/* Disabling OCx and OCNx outputs */
/***************************************/
/* Disable the Channel: Reset the CC1E Bit */
TIM1->CCER &= (uint16_t) ~TIM_CCER_CC1E;
/* Disable the Channel: Reset the CC1E Bit */
TIM1->CCER &= (uint16_t) ~TIM_CCER_CC1NE;
#elif defined (SET_CHANNEL_TO_INACTIVE_STATE) /* not DISABLING_CHANNELS_OUTPUTS */
/****************************************/
/* Using OCxM bits to inactive channel */
/****************************************/
/* Reset the OC1M bits in the CCMR1 register */
TIM1->CCMR1 &= TIM_CCMR1_OC2M;
/* Configure the OC2M bits in the CCMRx register to inactive mode*/
TIM1->CCMR1 |= TIM_OCMODE_FORCED_INACTIVE;
I just want to do this, using STM32 MPU.
That all PWMs are synchronized on commutation timing.