cancel
Showing results for 
Search instead for 
Did you mean: 

When TIM4 is set to encoder mode, what is the minimum pulse width it can capture

DChan.2
Associate II

I use to stm32f302 to measure the external encoder signal. There is no problem at low speed, but it will not work when the pulse width is reduced to about 11us. I want to know what is the limit pulse width (minimum) when TIM is set to encoder mode.

Pulse width as shown:0693W000001pP5lQAE.png

The initialization code is as:

void encoder_pin_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOB, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	
	GPIO_Init( GPIOB, &GPIO_InitStructure );	
	
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_2);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_2);	
}
 
void encoder_timer_init(void)
{
	TIM_TimeBaseInitTypeDef  	TIM_TimeBaseStructure;
/* 	TIM_ICInitTypeDef 				TIM_ICInitStructure;
 */
	RCC_APB1PeriphClockCmd(	RCC_APB1Periph_TIM4, ENABLE );
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
 
	TIM_DeInit(TIM4);
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);		
	    
	TIM_TimeBaseStructure.TIM_Period =0xffffu;
	TIM_TimeBaseStructure.TIM_Prescaler =0u; 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0u;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;     
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);	    	
	
	TIM_EncoderInterfaceConfig( TIM4, 
								TIM_EncoderMode_TI1,
								TIM_ICPolarity_Rising, 
								TIM_ICPolarity_Rising );
	
/* 	TIM_ICStructInit(&TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_ICFilter = 6;
	TIM_ICInit(TIM4, &TIM_ICInitStructure);
	
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	TIM_ICInit(TIM4, &TIM_ICInitStructure); */
 
	TIM_Cmd(TIM4, ENABLE); 	
}

1 ACCEPTED SOLUTION

Accepted Solutions
berendi
Principal

So here is an improved version thanks to the comments by @Community member​ 

It counts the edges on TIM4_CH2, counting direction is determined by CH1 XOR CH3. Connect the direction signal to either CH1 or CH3, and pull down the other pin to GND. Leaving the unused timer input unconfigured, i.e. no pin assigned should work too, but this is not officially documented.

TIM4->CR2 = TIM_CR2_TI1S;            // TIMx_CH1, CH2 and CH3 pins are connected to the TI1 input (XOR combination)
TIM4->SMCR = TIM_SMCR_SMS_1;         // 0b0010: Encoder mode 2 - Counter counts up/down on TI2FP2 edge depending on TI1FP1 level.
TIM4->CCMR1 =
    (0b01 << TIM_CCMR1_CC1S_Pos)   | // 0b01: CC1 channel is configured as input, IC1 is mapped on TI1
    (0b0010 << TIM_CCMR1_IC1F_Pos) | // 0b0010: fSAMPLING=***_INT, N=4
    (0b01 << TIM_CCMR1_CC2S_Pos)   | // 0b01: CC2 channel is configured as input, IC2 is mapped on TI2
    (0b0011 << TIM_CCMR1_IC2F_Pos) | // 0b0011: fSAMPLING=***_INT, N=8
    0;
TIM4->CR1 = TIM_CR1_CEN;             // enable counter

The timer is in encoder mode 2, counting the edges on TI2FP2, and using TI1FP1 (which is actually CH1^CH2^CH3) as the direction signal. Channels 1 and 2 are configured as inputs connected to TI1FP1 and TI2FP2 respectively. Look up the General-purpose timer block diagram in the reference manual if this makes little sense to you so far. There is a 4 cycles digital filter on TI1, and 8 cycles on TI2 to ensure that a transition on CH2 reaches TI1FP1 first.

0693W000001pXL8QAM.png

Let's suppose all inputs are initially low, then there is a rising edge on CH2. The input filter duration on TI1 is shorter, so the "opposite signal" is rising first, followed by TI2FP2 rising, resulting in the counter going up. Then there is a falling edge on CH2, "opposite signal" is already low when TI2FP2 is falling, causing the counter going up again. When CH1^CH3 is high, TI1 is the opposite of CH2, so the counter counts down on both the rising and the falling edge of CH2.

Some filtering is apparently necessary on TI1, the counter is sporadically changing when I remove the TI1 filter (IC1F) and change the direction repeatedly. It might be the result of my not too sophisticated test setup, which means touching dangling jumper wires to ground and using the internal pullups.

PS. direct link to this comment.

View solution in original post

21 REPLIES 21
TDK
Guru

Should work as long as edges are separated by at least one timer tick.

But a pulse on one of the encoder inputs won't change the counter. It'll increment on the rising edge and decrement on the falling (or the opposite depending on the other signal) so no net change after the pulse is done.

If you feel a post has answered your question, please click "Accept as Solution".
berendi
Principal

If you'd like to know what you are doing, read the TIM2/TIM3/TIM4 functional description chapter of the reference manual, up to and including PWM input mode.

 

You will be rewarded with a step-by-step description of what you need at the end.

Never mind, I've misunderstood the question

Thanks Reply, I got understand, the stm32 only can decode the Quadrature signals, but can’t decode the Dir-Step signals.

The encoder is not designed to decode DIR/STEP signals as given to a stepper motor driver, if that's what you're trying to do.

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

Timers in the new 'G4 family can decode DIR/STEP, they call it Clock plus direction encoder mode , see RM0440.

JW

berendi
Principal

Looks like the encoder mode and the TI1^TI2^TI3 XOR feature (TIM_CR2_TI1S) can be abused to produce a dir/step encoder. It counts on CH2 pulses, CH1 XOR CH3 determines the direction, connect one of them to the actual direction signal, and pull the other one low.

TIM4->CR2 = TIM_CR2_TI1S;
TIM4->SMCR = TIM_SMCR_SMS_0;
TIM4->CCMR1 =
		TIM_CCMR1_CC1S_0 |
		TIM_CCMR1_IC1F_0 |
		TIM_CCMR1_IC1F_1 |
		TIM_CCMR1_CC2S_0 |
		TIM_CCMR1_IC2F_0 |
		TIM_CCMR1_IC2F_1;
TIM4->CR1 = TIM_CR1_CEN;

The timer is in encoder mode 1, actually counting the edges on TI1, and using TI2 as the direction signal. When CH1^CH3 is low and CH2 is rising, TI2 becomes high so the direction is downcounting on rising edge, the rising edge on TI1 decreases the counter by one. When CH2 is falling, TI2 becomes low so the direction is downcounting on falling edge, the falling edge on TI1 decreases the counter again. When CH1^CH3 is high, TI1 is the opposite of CH2, so the counter goes up on both edges.

It probably depends on some undocumented aspect of the hardware design, maybe the XOR logic delaying the edge on TI1. It doesn't work in encoder mode 2. It is also completely unreliable without some filtering on the timer input (IC1F and IC2F bits).

I have no STM32F3, so I have tested it on a STM32H743 which happened to sit on my desk, so it might work with your MCU, but there is no guarantee.

That's news to me. Thanks for the correction.

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

That was not a correction but an amendment. The 'F3 used by DChan.2 indeed can't handle this mode.

JW

Interesting idea, but I'd expect the filters been set to two distinct values, to produce a defined phase shift...

Doesn't the direction change alone produce false counts in this scheme?

JW