cancel
Showing results for 
Search instead for 
Did you mean: 

G071 LPTIM encoder mode creeps around

JU
Senior

I'm using LPTIM1 in encoder mode and have noticed that, if there's jitter on one of the encoder signals the count will gradually creep up which should not be possible in encoder mode.

This is on a decent encoder that's got an RC network (per the Bourns data sheet / appnote) in front of it too so this isn't nasty HF noise, it's good solid pulses of 50-100ms or more on one channel but the counter seems to creep up.

Identical encoders wired to TIM2 / TIM3 behave normally, and my colleague has seen the same issue in another project using the same setup - LPTIM has a problem where TIMx does not.

Init code for LPTIM1:

/* LPTIM1 init function */
void MX_LPTIM1_Init(void)
{
  /* USER CODE BEGIN LPTIM1_Init 0 */
  /* USER CODE END LPTIM1_Init 0 */
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_PCLK1);
  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPTIM1);
  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);
  /**LPTIM1 GPIO Configuration
  PB5   ------> LPTIM1_IN1
  PB7   ------> LPTIM1_IN2
  */
  GPIO_InitStruct.Pin = ENC1_As_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(ENC1_As_GPIO_Port, &GPIO_InitStruct);
  GPIO_InitStruct.Pin = ENC1_Bs_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(ENC1_Bs_GPIO_Port, &GPIO_InitStruct);
  /* USER CODE BEGIN LPTIM1_Init 1 */
  /* USER CODE END LPTIM1_Init 1 */
  LL_LPTIM_SetClockSource(LPTIM1, LL_LPTIM_CLK_SOURCE_INTERNAL);
  LL_LPTIM_SetPrescaler(LPTIM1, LL_LPTIM_PRESCALER_DIV1);
  LL_LPTIM_SetPolarity(LPTIM1, LL_LPTIM_OUTPUT_POLARITY_REGULAR);
  LL_LPTIM_SetUpdateMode(LPTIM1, LL_LPTIM_UPDATE_MODE_IMMEDIATE);
  LL_LPTIM_SetCounterMode(LPTIM1, LL_LPTIM_COUNTER_MODE_EXTERNAL);
  LL_LPTIM_ConfigClock(LPTIM1, LL_LPTIM_CLK_FILTER_NONE, LL_LPTIM_CLK_POLARITY_RISING);
  LL_LPTIM_TrigSw(LPTIM1);
  LL_LPTIM_SetInput1Src(LPTIM1, LL_LPTIM_INPUT1_SRC_GPIO);
  LL_LPTIM_SetInput2Src(LPTIM1, LL_LPTIM_INPUT2_SRC_GPIO);
  /* USER CODE BEGIN LPTIM1_Init 2 */
	/*
	 * To activate the Encoder mode the ENC bit has to be set to ‘1’. The LPTIM must first be
	 * configured in Continuous mode.
	 * When Encoder mode is active, the LPTIM counter is modified automatically following the
	 * speed and the direction of the incremental encoder.
	 */
	LL_LPTIM_StartCounter(LPTIM1,LL_LPTIM_OPERATING_MODE_CONTINUOUS);
	// This function must be called when the LPTIM instance is disabled.
	LL_LPTIM_SetEncoderMode(LPTIM1, LL_LPTIM_ENCODER_MODE_RISING/*_FALLING*/);
	/*
	 * This function must be called when the LPTIM instance is disabled.
	 * In this mode the LPTIM instance must be clocked by an internal clock
	 * source. Also, the prescaler division ratio must be equal to 1.
	 * LPTIM instance must be configured in continuous mode prior enabling
	 * the encoder mode.
	 */
	LL_LPTIM_EnableEncoderMode(LPTIM1);
	LL_LPTIM_Enable(LPTIM1);
	/*
	 * The counter just counts continuously between 0 and the
	 * auto-reload value programmed into the LPTIM_ARR register
	 * (0 up to ARR or ARR down to 0 depending on the direction).
	 * Therefore LPTIM_ARR must be configured before starting
	 */
	LL_LPTIM_SetAutoReload(LPTIM1, ENCODER_RELOAD);
	//LPTIM instance must be enabled before starting the counter.
	LL_LPTIM_StartCounter(LPTIM1,LL_LPTIM_OPERATING_MODE_CONTINUOUS);
  /* USER CODE END LPTIM1_Init 2 */
}

 

12 REPLIES 12
waclawek.jan
Super User

> creep up

What does that mean, exactly?

> if there's jitter on one of the encoder signals

Please elaborate; if possible, illustrating it with oscilloscope screenshots.

It also sounds like you do have some setup where there's no such "creep up", do you?

JW

JW,

By "creep up" I mean that it's possible to make the LPTIM count gradually increase without the encoder actually moving off of position - just by ONE channel of the encoder signal going high/low EG because the encoder transition is on a detent position, or someone is resting their finger on it & moving it slightly across the transition without actually rotating it - we can see the encoder *count* in LPTIM increment more than a full circle if there are enough pulses on one channel.

And to be clear - this is not noise on the signal, it's very clear clean robust pulses as I described that should only result in the encoder/timer count going +1 count and then back again -1 because the other channel never changes state.

The setup where there is no creep is the other 2 encoders attached to the MCU - running on TIM2 and TIM3, the hardware is identical for all 3 channels.

waclawek.jan
Super User

And when this happens, the "steady" other channel is low or high?

Can you please read out and post the LPTIM registers content.

JW

I will have to change my setup to read out the registers - I have attached a scope trace of the problem happening, this is purely from me jiggling the encoder so it goes back & forth over a transition on one channel, as you can see the other channel is steady in the "high" state.

According to the datasheet the encoder detent stability point is always when channel A is high and B is near switching.

waclawek.jan
Super User

Can you please zoom in on the edges (both rising and falling) so that we see the RC time constant?

JW

 
waclawek.jan
Super User

Okay so rise/fall times in 100us range? What's the LPTIM's internal clock?

As a quick test, I'd at least try to switch on the glitch filter, if you don't have it already switched on (I don't understand the Cube/LL gobbledygook, mainly that's why I asked for registers content).

JW

LPTIM clock is 16MHz, currently no filtering but I'm just adding that in as an experiment, I will also pull register info out.

LPTIM1:
0x40007C00=0x00000010
0x40007C04=0x00000000
0x40007C08=0x00000000
0x40007C0C=0x01800018
0x40007C10=0x00000001
0x40007C14=0x00000000
0x40007C18=0x000000FF
0x40007C1C=0x00000000
0x40007C20=0x00000000