2026-03-31 1:32 AM - edited 2026-03-31 1:36 AM
Hello world!
I want to move a motor with serial commands. I use the stm32g051 PWM and a DC motor. And for the sake of lower consumption of energy and cpu I use a dma in circular mode. And of course I want to change the pwm from time to time.
But somehow, there is always a delay of more than 10 seconds between the calling of the function and the change in the motor behaviour.
mid_error_t tim_forward_buffers(void)
{
for (uint16_t i=0; i<PWM_BUF_LEN; i++){
pwm_ch1[i] = (uint32_t)(param.speed * (htim2.Init.Period-2))/ MAX_SPEED;
//pwm_ch1[i] = 0; // htim2.Init.Period;
pwm_ch2[i] = 0;
}
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm_ch1[0]);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, pwm_ch2[0]);
return MID_ERROR_OK;
}You may guess that the PWM_BUF_LEN is too big... There is just one element in pwm_ch1 and pwm_ch2. What may cause this problem?
I use the __HAL_TIM_SET_COMPARE to change the pwm faster and the pwm_ch1 pwm_ch2 just contain one element so the DMA doesn't have to wait to change it.
Solved! Go to Solution.
2026-03-31 5:56 AM - edited 2026-03-31 5:59 AM
> there is always a delay of more than 10 seconds between the calling of the function and the change in the motor behaviour
How do you know? How do you observe the point in time when the function is called?
Have you measured the actual PWM output?
> I use the __HAL_TIM_SET_COMPARE to change the pwm faster and the pwm_ch1 pwm_ch2 just contain one element so the DMA doesn't have to wait to change it.
...and still it takes 10 seconds until the effect?
JW
2026-03-31 1:56 AM
My guess: the timer period is long.
Changing the compare value has no immediate effect, but is buffered in a shadow register and updated at the next update event. You may force update by
TIM2->CCR1 = new_value;
TIM2->EGR |= TIM_EGR_UG; // force update eventor disable buffering in advance:
TIM2->CCMR1 &= ~TIM_CCMR1_OC1PE; // for channel 1hth
KnarfB
2026-03-31 2:55 AM
I am going to change the timer period -I guess it is the pwm period too-.
/* TIM2 init function */
/**
* @brief Initialize TIM2 for PWM generation on channels 1 and 2 with DMA support
*/
mid_error_t MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 3;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 399; // 20kHz PWM frequency with 64MHz timer clock
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
return MID_ERROR_FAILED_INIT;
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
return MID_ERROR_FAILED_INIT;
}
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
return MID_ERROR_FAILED_INIT;
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
return MID_ERROR_FAILED_INIT;
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
return MID_ERROR_FAILED_INIT;
}
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
return MID_ERROR_FAILED_INIT;
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
HAL_TIM_MspPostInit(&htim2);
// if( tim_brake_buffers() != MID_ERROR_OK) // brake by default
// {
// return MID_ERROR_FAILED_INIT;
// }
HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_1, pwm_ch1, PWM_BUF_LEN);
HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_2, pwm_ch2, PWM_BUF_LEN);
return MID_ERROR_OK;
}
2026-03-31 5:07 AM
I don't see anything wrong with the posted code. I would recheck your assumptions here.
> //pwm_ch1[i] = 0; // htim2.Init.Period;
This is not the "Period" parameter. It's the "pulse" parameter.
2026-03-31 5:56 AM - edited 2026-03-31 5:59 AM
> there is always a delay of more than 10 seconds between the calling of the function and the change in the motor behaviour
How do you know? How do you observe the point in time when the function is called?
Have you measured the actual PWM output?
> I use the __HAL_TIM_SET_COMPARE to change the pwm faster and the pwm_ch1 pwm_ch2 just contain one element so the DMA doesn't have to wait to change it.
...and still it takes 10 seconds until the effect?
JW
2026-04-01 2:31 AM
My guess is that this is a hardware issue... it seems related to the elecrtonics behind it.
Thanks you all.