Hello, i'm using an stm32f4 to control a stepper motor.
I'm not sure if i need PWM mode or OC Mode or OnePulse Mode. I can generate a fixed frequency PWM wave but since i need a particular acceleration/deceleration i need to vary the frequency of the wave with a ramp.
Something like: - 1 pulse at 745hz - 1 pulse at 1867hz - 1 pulse at 2459hz - 1 pulse at ... - 1 pulse at ... - N pulses at ... (constant speed)
Right now in the callback HAL_TIM_PWM_PulseFinishedCallback i'm issuing new TIMx->ARR and TIMx->CCR1 values based on a given logic.
Here is my init
void MX_TIM9_Init(void) { TIM_OC_InitTypeDef sConfigOC; htim9.Instance = TIM9; htim9.Init.Prescaler = PSC; // Get clock to <freq> Hz htim9.Init.CounterMode = TIM_COUNTERMODE_UP; htim9.Init.Period = 1582; // useless since it is varying htim9.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim9); HAL_TIM_PWM_Init(&htim9); sConfigOC.OCMode = TIM_OCMODE_PWM2; sConfigOC.Pulse = htim9.Init.Period / 2; //useless but always 50% of CCR1 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; HAL_TIM_PWM_ConfigChannel(&htim9, &sConfigOC, TIM_CHANNEL_1); } void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef* htim){ if (htim->Instance == TIM9){ // logic TIM9->ARR = v; TIM9->CCR1 = v/2; } } int main(void) { //other MX_TIM9_Init(); //logic and if needed HAL_TIM_PWM_Start_IT(&m->htim, TIM_CHANNEL_1); }
What i'm noticing is that the wave is not perfectly shaped as if the Update Event that update the shadow register happens sporadicly. Is the PWM the right way to do it or should i use OC or OnePulse mode?
Regards,
Set interrupt on rising/falling (only one) edge od pin with PWM and in that interrupt change settings for pwm (and force timer register update in that interrupt!).
Can you elaborate on that? Basically i should discard the interrupt coming from the PWM and use the one on the GPIO? How do i set the interrupt for the GPIO?
Thank you
For a GPIO interrupt use the EXTI, associating the pin as a source.
To get more accurate timing, use the form
TIM9->ARR = v - 1; // N-1, CNT goes 0 thru N-1 state, you encode last state TIM9->CCR1 = v/2;
To get finer granularity decrease the prescaler to the minimum number so the period (ARR) fits within the 16-bit or 32-bit range of the counter.
The integer nature of the prescaler and period mean some frequencies cannot be hit exactly without play games with the source clocks, ie PLL and crystal
How does this differ from using the PWM callback? How can i ensure that there will be only a single pulse with a given frequency and then another with the following one?
Just check. Like engineer.
(and consider of writting your own hardware libraries; those are not as good as you think)
The problem were the preload register, as mentioned in en.DM00236305.pdf for STM32 there could be sporadics frequencies.