Monday, 20 November 2017

Dinamically change PWM frequency with interrupt with STM32


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 code



void MX_TIM9_Init(void)
{
TIM_OC_InitTypeDef sConfigOC;

htim9.Instance = TIM9;
htim9.Init.Prescaler = PSC; // Get clock to 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 train is not perfectly shaped as if the Update Event that update the shadow register happens sporadicly. If i'm expecting 1 pulse with 500hz and a second of 700hz that doesn't happen. 7Cleary a constant frequency wave at 500hz and 700hz is generated correctly. I tried to SET-RESET an output to verify at which point the interrupt is called.


When it fails it seems that an interrupt is called when the PWM is still "high"


Is the PWM the right way to do it or should i use OC or OnePulse mode?


Regards,




Answer



The problem was related to the preload registers. As mentioned in en.DM00236305.pdf they are needed in order to have a perfect timing between UEV and register correct loading


No comments:

Post a Comment

arduino - Can I use TI's cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...