Rotary Encoder Library
encoder.py provides a module to read a rotary encoder connected
to a MicroPython board. The class
encoder.Encoder works with ESP-8266 boards.
pyb_encoder.py provides a subclass (
works with the pyboard or any board using the stmhal port (for example a
The rotary encoder needs to connect to two digital input pins of of the board, for which external interrupts can be enabled. The code employs gray code error checking using the technique described in this blog post, so no further hardware or software debouncing is needed and the library works well even with cheap encoders, which usually have switches with lots of bouncing.
- Connect the GND pin of the encoder to ground.
- Connect the CLK pin of the encoder to a GPIO pin on the board (e.g. 'X11' on the pyboard).
- Connect the DT pin of the encoder to another GPIO on the board (e.g. 'X12' on the pyboard).
If you configure the input pins with the internal pull-up resistors turned on, you don't need to connect 5V from the board to anything, since the input pins will provide the current for the switches in the encoder to function. Without the pull-up resistors, connect 5V or 3V3 from the board to the plus pin of the encoder.
When everything is hooked up, use the
Encoder class like this:
from machine import sleep_ms from encoder import Encoder # or from pyb_encoder import Encoder e = Encoder('X11', 'X12') # optional: add pin_mode=Pin.PULL_UP lastval = e.value while True: val = e.value if lastval != val: lastpos = val print(val) sleep_ms(100)
Clicks and Acceleration
Normally the encoder value is de-/increased by one for every encoder pulse.
Most encoders generate several pulses per detent ("click"). You can pass the
clicks keyword when instantiating the
Encoder class to set the number of
pulses per detent. A common value is four. This will result in an increment /
decrement of one for every click with no acceleration.
If you have a large value range (you can set the range with the
max_val keyword arguments), scrolling from one end of the range to the other
can be very cumbersome. You can enable acceleration by passing a positive
integer to the
accel keyword argument. The proper value depends on value
range and the type of the encoder, but usually low one-digit numbers like 3-5
work well. With acceleration enabled the increment/decrement per click
increases the faster your turn the encoder. You can still make fine adjustment
by turning the encoder slowly.
Currently, if you use the acceleration feature, you need to take care of decreasing the the current acceleration, which increases everytime a valid pulse is read from the encoder. Normally you would do this at the end of your main loop, i.e. once per poll interval:
oldval = 0 while True: val = enc.value if oldval != val: print(val) oldval = val enc.cur_accel = max(0, enc.cur_accel - enc.accel) sleep_ms(50)
- Integrate de-acceleration into interrupt callback (time-based).