cancel
Showing results for 
Search instead for 
Did you mean: 

[STM32H7] Counting Pulses to Stepper Motor

bnguy.1
Associate III

I've configured a timer for Output-Compare on a pin that goes to a stepper motor. However is there a way to configure the timer such that it outputs a certain number of reload events / pulses and then stops completely.

In software, I understand I can accumulate the count in the TImer ISR and then stop the timer once the desired count has been reached, but would prefer to have the timer stop automatically.

Also is it recommended to route the output to a timer input to verify the number of pulses generated? Not sure how others implement driving a stepper motor, but I need a highly precise position!

1 ACCEPTED SOLUTION

Accepted Solutions
Chopra.1
Associate II

If you want fixed number of pulses , timer's Output-Compare mode will be sufficient

you just have to increment the capture compare register (CCR) value whenever the program goes to the ISR and keep on incrementing the value till the required pulses

//reqpulses : number of pulses you want , make it a globle variable
//pulsenumber : number of pulses generated ,make it globle
 
void TIM5_IRQHandler()
{
	if(TIM5->SR &= (1 << TIMx_SR_CC1IF))
	{
		TIM5->SR &= ~(1 << TIMx_SR_CC1IF); // clearing the interrupt flag
		if(pulsenumber < reqpulses)
		{
 
 
			CaptureValue = TIM5->CCR1;
			TIM5->CCR1 = CaptureValue + 10000;
			pulsenumber++ ;
 
		}else
		{
			TIM_BASIC_DISABLE(TIM5);
			TIM5->CCR1 = PulseVal;
			TIM5->CNT = 0;
			pulsenumber = 0;
			//TIM5->DIER &= ~(1 << TIMx_DIER_CC4IE);
		}
	}

View solution in original post

4 REPLIES 4
TDK
Guru

If you just want to output X pulses on the line, I can see two ways:

  • Some timers have a repetition counter register which can be used to output an exact number of pulses.
  • Some timers can be driven in gated mode, where the gating timer is in one pulse mode and is active for the exact number of pulses you want. This requires two timers.

Typically, stepper motor control is done within an interrupt called at a very high frequency in which the mcu calculates whether or not to output a pulse on each motor based on the current path segment. This has the advantage of being able to produce paths with varying speed and smooth accelerations.

> Also is it recommended to route the output to a timer input to verify the number of pulses generated?

It's not a good choice to spend resources verifying you get what you want. At high output rates, this is going to be computationally prohibitive. You could route the STEP/DIR signals to a timer in encoder mode, but you're probably going to run out of available timers for this.

If you feel a post has answered your question, please click "Accept as Solution".
Laurent Ca...
Lead II

Dear @bnguy.1​ 

Did the TDK's answer solve your question?

Best regards

Laurent Ca...

Kindof.. at the moment, I have unused timers, so jumpering the step to a capture-compare would be very useful.

So, if the timer output frequency isn't very fast, the capture hardware could count the rising edge, without any software involvement, is that correct? I could say, move the motor for a fixed time, and then read the counter to verify the number of pulses this generated?

The STM32 timer cookbook doesn't seem to have an example to use the timer in this way.. is there another source that shows how to use it? Maximum input frequency?

Chopra.1
Associate II

If you want fixed number of pulses , timer's Output-Compare mode will be sufficient

you just have to increment the capture compare register (CCR) value whenever the program goes to the ISR and keep on incrementing the value till the required pulses

//reqpulses : number of pulses you want , make it a globle variable
//pulsenumber : number of pulses generated ,make it globle
 
void TIM5_IRQHandler()
{
	if(TIM5->SR &= (1 << TIMx_SR_CC1IF))
	{
		TIM5->SR &= ~(1 << TIMx_SR_CC1IF); // clearing the interrupt flag
		if(pulsenumber < reqpulses)
		{
 
 
			CaptureValue = TIM5->CCR1;
			TIM5->CCR1 = CaptureValue + 10000;
			pulsenumber++ ;
 
		}else
		{
			TIM_BASIC_DISABLE(TIM5);
			TIM5->CCR1 = PulseVal;
			TIM5->CNT = 0;
			pulsenumber = 0;
			//TIM5->DIER &= ~(1 << TIMx_DIER_CC4IE);
		}
	}