For this particular project, I've decided to buy a bunch of pre-built rotary encoder modules on eBay, instead of using just bare encoders. The module has the advantage of including an on-board debouncing circuit (a kind of RC filter to my understanding). So no additional components are needed, and from my testing the encoder readings seem quite stable. This saves quite a bit of effort.
So the actual wiring is pretty simple. Just connect encoder's pins: VCC, GND, S1(A), S2(B), to the RPi ones: 3V3(Pin1), Ground(Pin9), GPIO17(Pin11), GPIO27(Pin13), like so:
As for the content scrolling, I've found out that the simplest and most flexible way is to just simulate UP and DOWN key presses each time the encoder's shaft rotates in the respective direction (the fact that a key press wakes up the display is a nice bonus here and makes the whole setup responsive and joy to use). For the keyboard emulation, we will make use of the uinput kernel module, which needs to be enabled first, by editing '/etc/modules', like so:
Code: Select all
$ sudo nano /etc/modules
Code: Select all
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
i2c-dev
uinput
Code: Select all
$ sudo pip install python-uinput
Code: Select all
#!/usr/bin/env python
#[ROTKEY BY FIPS @ 4FIPS.COM, (c) 2018 FILIP STOKLAS, MIT-LICENSED]
import RPi.GPIO as GPIO
import uinput
from time import sleep
pin_a = 11 # GPIO 17
pin_b = 13 # GPIO 27
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin_a, GPIO.IN)
GPIO.setup(pin_b, GPIO.IN)
device = uinput.Device([uinput.KEY_UP, uinput.KEY_DOWN])
seq_a = seq_b = 0
def on_edge(pin):
global seq_a, seq_b
a = GPIO.input(pin_a)
b = GPIO.input(pin_b)
seq_a = ((seq_a << 1) | a) & 0b1111
seq_b = ((seq_b << 1) | b) & 0b1111
if seq_a == 0b0011 and seq_b == 0b1001:
device.emit_click(uinput.KEY_UP)
elif seq_a == 0b1001 and seq_b == 0b0011:
device.emit_click(uinput.KEY_DOWN)
GPIO.add_event_detect(pin_a, GPIO.BOTH, callback=on_edge)
GPIO.add_event_detect(pin_b, GPIO.BOTH, callback=on_edge)
try:
while True:
sleep(3600)
except KeyboardInterrupt:
print("...DONE")
GPIO.cleanup()
Related articles:
Home automation with Domoticz, ESP8266 and BME280
Controlling the TP-Link HS110 smart plug with Domoticz