Difference between revisions of "STM32 Rotary Encoder"

From Stm32World Wiki
Jump to navigation Jump to search
Line 75: Line 75:
 
== Interrupt driven state machine ==
 
== Interrupt driven state machine ==
  
To be added.
+
In order to handle the rotary decoder using interrupts let us look more closely at the signals.
 +
 
 +
As mentioned earlier, rotary encoders have two signals A and B which are phase offset.  If we do a bit of binary match on these two bits:
 +
 
 +
<pre>
 +
S = B << 1 + A
 +
</pre>
 +
 
 +
We realise that there can be 4 different distinct phases: 0, 1, 2 and 3.  When rotating in one direction the signals will look like this:
 +
 
 +
[[File:Rotary Encoder Signals.png|600px]]
 +
 
 +
When rotating in the opposite direction
  
 
== Miscellaneous Links ==
 
== Miscellaneous Links ==

Revision as of 02:29, 31 July 2021

Rotary encoder on de-bouncing breakout board

Rotary Encoders are devices which will generate pulses when they are turned.

Typically they will have two outputs with the pulses out of phase. By checking which pulse "comes first" the direction of the turn can be determined. It is not overly complicated to handle this manually, for example by hooking the signals up to an external GPIO Interrupt.

On this page, we will go through two different approaches:

  1. Using a Timer to decode rotary encoders
  2. Interrupt driven

Rotary encoder signals

A rotary encoder will output 2 signals 90 degrees out of phase with each other.

Rotary encoder signals.jpeg

By analysing the order of the transitions the steps can be counted and the direction can be detected.

Rotary encoder de-bouncing

Rotary encoders are build with mechanical contacts and they are prone to "bouncing" (one press generate more than one interrupt". The "signals" can be cleaned up by implementing a low-pass filter like this:

Rotary debounce.png

I just happened to have a few of those rotary encoder breakout boards lying around.

Timer

STM32 Timers can be configured in encoder mode and do most of the "heavy lifting".

In STM32CubeMX a timer can be configured to combine two channels in Encoder mode.

Timer Encoder.png

This will highlight the necessary pins:

Rotary encoder pins.png

The various Parameter settings can then be adjusted:

Encoder parameter settings.png

The "Counter period" will determine the "range" of the counts. In this case, the counter period is set to 99, so the counter will count up to 99 and then wrap around to 0, and vice versa when rotating in the opposite direction.

Finally we can, if needed, enable an interrupt:

Encoder Timer interrupt.png

STM32CubeMX will now generate the bulk of the code needed.

We need to start the Timer:

HAL_TIM_Encoder_Start_IT(&htim3, TIM_CHANNEL_ALL);

We can now read out the encoder counter like this:

uint32_t last_print = 0, now = 0;

for (;;) {

	now = HAL_GetTick();
	if (now - last_print >= 1000) {
		DBG("Encoder counter = %lu", TIM3->CNT);
		last_print = now;
	}

}

Interrupt driven state machine

In order to handle the rotary decoder using interrupts let us look more closely at the signals.

As mentioned earlier, rotary encoders have two signals A and B which are phase offset. If we do a bit of binary match on these two bits:

S = B << 1 + A

We realise that there can be 4 different distinct phases: 0, 1, 2 and 3. When rotating in one direction the signals will look like this:

Rotary Encoder Signals.png

When rotating in the opposite direction

Miscellaneous Links