Rotary encoders are position sensors that measure an axis’s angular position (or rotation). They’re mostly used in motors for PID control and user interfaces as an alternative to potentiometers. Furthermore, many encoders used in DIY kits have a push button built-in.
Getting started with a rotary encoder: the KY-040
This tutorial will explore utilizing a KY-040 rotary encoder module, a common component in DIY kits. We can use this module to create a user interface for our program; for example, to select options from a menu or change the value of a variable.
Difference between rotary encoder and potentiometer
At first, the rotary encoder KY-040
may look like a potentiometer. However, a potentiometer is an analog sensor while the rotary encoder is digital. A potentiometer changes the value of a resistor, but its range is limited.
A rotary encoder can detect a specific number of “steps” for each revolution and sends a signal at each step. It also can turn endlessly. You can physically feel the difference between the two; a potentiometer rotates smoothly, while a rotary encoder turns jerkily.
A rotary encoder is a device that can be easily used with a microcontroller, as it sends digital signals. The precision of the encoder is based on the number of steps per rotation. At the same time, the accuracy of a potentiometer is determined by the resolution of the ADC that is used to measure its position.
Note
A potentiometer is a device utilized to modify analog settings, such as the volume of an amplifier. In contrast, a rotary encoder is employed to get an angular direction and position accurately.
How works a rotary encoder?
This guide provides an overview of rotary encoders but does not dive into technical details.🤓 To gain a deeper understanding of the physical processes, different technologies, and classic topologies (such as the operation of an optical quadrature phase rotary encoder 😨), please refer to the theoretical presentation of a rotary encoder.
Connections of the KY-040 rotary encoder to the ESP32
This rotary encoder has 2 signals to know the position: CLK
and DT
. The pin SW
is connected to the integrated push button (SWitch).
Warning
If you use a raw rotary encoder, not a breakout module, you must add pull-up resistors to the 3 logic pins. This is because these resistors must distinguish between the different logic levels as with the standard push-button circuit.
Here is a proposal for a connection to an ESP32 board :
Rotary Encoder |
ESP32 |
---|---|
|
|
|
|
|
|
|
|
|
|
The circuit to be done is as follows:
And here is an example of breadboard mounting:
Get the angular position of the KY-040 rotary encoder in Arduino code
Incremental encoders are used to measure the angular position in degrees based on the number of increments made by the user. Instead of providing an exact angular position, this type of encoder returns the number of increments done. To get the angle, the value of the increment must be determined in the program.
Finding the amount of steps an encoder has made is possible through various methods. It is best to use a reliable way to get steps without blocking the program. A basic approach where a loop looks for logical signals received from the encoder carries the risk of missing steps if the encoder is rotated fast.
Note
Programs can sometimes struggle with tasks and count in the wrong direction. (A traditional bug)
Many code sources are available online if you want to use rotary encoders. However, not all of them are the same! The best choice is to trigger hardware interrupts when a logical level change is detected. These interrupts are independent of the CPU and won’t stop the code from running.
Note
The ESP32 can attach an interrupt to any output pins, which is impossible when using an Arduino, as only a few pins can have interrupts.
esphome:
name: esphome-web-747aa4
friendly_name: ESPHome1
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API...Uncomment these three lines if you want ESP32 data to also go to a homeassistant server.
#api:
# encryption:
# key: "fEt5mzpehw423nU7JFGYhGIUiaHmuwzW4h85drE/puc="
ota:
#This is the myServer 6 IP address
mqtt:
broker: 192.168.1.216
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "LiHome5"
password: "D6A6D6D6A6"
captive_portal:
# Example configuration entry
sensor:
- platform: rotary_encoder
name: "Rotary Encoder"
pin_a: 22
pin_b: 23
resolution: 1
min_value: 0
id: rotary
on_value:
- mqtt.publish:
# topic: N/${vrm_id}/test
topic: myserver/command
payload: !lambda |-
char buf[128];
sprintf(buf, "setvariable|sensor_inclinebench_state~%.0f", id(rotary).state);
return buf;
# return esphome::to_string(id(rotary).state);