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); 	
}

21 REPLIES 21

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

Right, changing IC1F to 0b0010 (N=4) and leaving IC2F at 0b0011 (N=8) changed the direction and made it work with encoder mode 2 too.

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

Yes it does. But it affects only the least significant bit, which would be discarded anyway to get a pulse count, because it counts on both edges of the CH2 pulse.

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

>>

> Yes it does. But it affects only the least significant bit, which would be discarded anyway to get a pulse count, because it counts on both edges of the CH2 pulse.

Okay, but counting on TI2FP2 (I don't know how the respective mode is called) should eliminate this problem, am I right?

Can you please post then the resulting "consolidated" code, so that we can use it in the future as a reference? Can you please use the binary constants and shifts for the non-single-bit bitfields, perhaps adding also comments?

It's a very smart trick, solving a problem which was brought up here several times - even if has the constraint given by the need for filtering and for CH3 to remain stationary - whih probably can be solved by simply not assigning TIM3 to any pin - ST might finally confirm this to be a guaranteed 0 as it behaves when tested. Thank you for posting and testing it.

Jan

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.

thank you reply

That’s a good news , ​ but the hardware has already designed. So I have to find the other solution

Thanks for the sophisticated testing, the detailed writeup and the link 😉

Jan

Cool�?that’s a genius idea, I already test it on stm32f302​ and it works good. But the reliability of this method still needs to be tested.

Can please the ST staff who made the comment hidden to public but making this thread resurface after half a year, please work towards public confirmation of the assertion needed to get this trick be reliable (i.e. that AF inputs unassigned in GPIO are reliably 0)?

JW

Laurent Ca...
Lead II

Dear @Community member​ 

From mid of September, I'm trying to improve the forum for all posts with the tag "STM32 Motor control".

To make them more readable for all users, each time a technical question seems solved, I indicate it. This is why this thread has moved this week.

And I will soon have finished analyzing all the existing messages with the "STM32 Motor control" tag.

On the other hand I do not see at all what a hidden message is, to my knowledge it does not exist and therefore it is not possible to make it visible.

Best regards

Laurent Ca...

Hi @Laurent Ca...​ ,

OK I see.

It would still be nice if ST could confirm that AF inputs unassigned in GPIO are reliably 0. This would make solutions to several - perhaps niche, but still existing - problems possible.

JW