Difference between revisions of "STM32 Rotary Encoder"
Line 68: | Line 68: | ||
== Miscellaneous Links == | == Miscellaneous Links == | ||
+ | * [https://github.com/lbthomsen/greenpill/tree/master/rotary_encoder Rotary Encoder STM32 firmware] | ||
* [https://github.com/lbthomsen/rotary-encoder-breakout Rotary Encoder Breakout w. de-bouncing circuit] | * [https://github.com/lbthomsen/rotary-encoder-breakout Rotary Encoder Breakout w. de-bouncing circuit] |
Revision as of 11:52, 26 July 2021
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.
Rotary encoder signals
A rotary encoder will output 2 signals 90 degrees out of phase with each other.
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:
I just happened to have a few of those rotary encoder breakout boards lying around.
Using Timer to decode rotary encoder
In STM32CubeMX a timer can be configured to combine two channels in Encoder mode.
This will highlight the necessary pins:
The various Parameter settings can then be adjusted:
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:
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; } }