cancel
Showing results for 
Search instead for 
Did you mean: 

High speed error with encoder, STM32F103

pccasio
Associate II

Hello,

We are using an encoder ( https://www.andymark.com/products/redline-encoder-kit ) with 4096 CPR and are trying to measure speed and direction of a motor with an STM32F103. However, we cannot read stable values and in high frequencies we cannot read at all. Currently, our MCU is working on 72 MHz frequency and in TIM2 we are using the Encoder mode with interrupt. (Prescaler value=0, Counter period value=65535)

Should we use the DMA as well? Would it make any difference? Do you have any suggestions on what improvements we could make to our system?

Below is our snippet of user code regarding the issue.

Thanks in advance.

*EDIT: Updated the prescaler and counter period value

typedef struct encoderStruct {
	uint32_t counter_u32;
	_Bool measuredDirection_bool;
	float measuredSpeed_f32;
}ENCODER_HandleTypeDef;
 
// ***
void Measure_Speed(TIMER_HandleTypeDef *timer, FLAG_HandleTypeDef *flag, ENCODER_HandleTypeDef *encoder){
	if(TIM2->CR1 == 1) {
		encoder->measuredDirection_bool = 0;
		encoder->counter_u32 = (uint32_t)(TIM2->CNT);
		if(timer->velocityCalculator_u16 > VELOCITY_TIME) {
			TIM2->CNT = 0;
			encoder->measuredSpeed_f32 = ((float)encoder->counter_u32 / ENCODER_PULS) * 60.0;
			timer->velocityCalculator_u16 = 0;
			flag->LED.motorForward_bit = 1;
			flag->LED.motorBackward_bit = 0;
		}
	} else if(TIM2->CR1 == 17) {
		encoder->measuredDirection_bool = 1;
		encoder->counter_u32 = 65535 - (uint32_t)TIM2->CNT;
		if(timer->velocityCalculator_u16 > VELOCITY_TIME) {
			TIM2->CNT = 65535;
			encoder->measuredSpeed_f32 = ((float)encoder->counter_u32 / ENCODER_PULS) * 60.0;
			timer->velocityCalculator_u16 = 0;
			flag->LED.motorForward_bit = 0;
			flag->LED.motorBackward_bit = 1;
		}
	}
}
 
//***
HAL_TIM_Encoder_Start_IT(&htim2, encoderA_Pin);
HAL_TIM_Encoder_Start_IT(&htim2, encoderB_Pin);

1 ACCEPTED SOLUTION

Accepted Solutions

Alright, we converted it to 32-bit and now it seems to be reading stable values. Thanks a lot for the suggestion!

View solution in original post

6 REPLIES 6
Uwe Bonnes
Principal II

Rethink your concept. The encoder is meant to run free. For speed measurement, sample the TIM2 value and calculate the difference/

What do you mean by encoder being meant to run free? And what exactly should we calculate the difference of? Could you please rephrase your suggestion as I did not quite understand it.

Still, thanks for your attention.

Never use prescaler with Encoder mode.

Set ARR ("Period") to maximum value, never change CNT, and, as Uwe said, for speed calculation, subtract values read out of CNT at subsequent timing points.

JW

The prescaler and the period given in the question was not for the encoder but I updated it as you said, however we still have the same problems. Also, we are already doing that subtraction. Could we use the DMA as well?

Thanks for your answer, and sorry for the trouble.

Read it and post content of encoder timer registers.

What are the values you read? Isn't TIM2 a 32-bit timer, i.e. why restricting it to 16 bits?

JW

Alright, we converted it to 32-bit and now it seems to be reading stable values. Thanks a lot for the suggestion!