1. 4FIPS
  4. APPS
  5. CODE
  7. ABOUT


Forums dedicated to the projects hosted at 4FipS.com

Skip to content

Using rotary encoders for keyboard emulation (RPi)

> Coding, hacking, graphics, game dev, and such...

Using rotary encoders for keyboard emulation (RPi)

Postby fips on Sat Feb 03, 2018 4:44 pm

I've been using the official Raspberry Pi 7" touchscreen display as a home dashboard (running Domoticz in Chromium kiosk mode) for a couple of years now, overall with great success. Recently, however, the capacitive touchscreen started to act up, and gradually became totally unresponsive. This accelerated my long-standing wish of making the whole setup more tactile and human friendly by employing a rotary encoder for content scrolling, as an alternative to touch or keyboard navigation, which has always frustrated me a bit for its clumsiness. So I set to work and shortly after came up with this:


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:

$ sudo nano /etc/modules

then add 'uinput' at the end, in my case '/etc/modules' looks like this:
# /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.


then reboot, after that install Python's uinput module, like so:
$ sudo pip install python-uinput

Finally we need some Python code to glue all this together. I've spent some time figuring out how rotary encoders work and mainly how to make use of interrupts for edge detection instead of polling encoder's state, this is quite important, because polling would needlessly burn your CPU cycles, which is not a good idea especially on cooperative platforms like RPi. Anyway, the code came out like this (it needs to be run as sudo):

#!/usr/bin/env python

import RPi.GPIO as GPIO
import uinput
from time import sleep

pin_a = 11 # GPIO 17
pin_b = 13 # GPIO 27

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:
    elif seq_a == 0b1001 and seq_b == 0b0011:

GPIO.add_event_detect(pin_a, GPIO.BOTH, callback=on_edge)
GPIO.add_event_detect(pin_b, GPIO.BOTH, callback=on_edge)

    while True:
except KeyboardInterrupt:

Overall, I'm pretty happy with the result. It patiently sits on my shelf, providing instant access to my home automation system.

Related articles:
Home automation with Domoticz, ESP8266 and BME280
Controlling the TP-Link HS110 smart plug with Domoticz
User avatar
Site Admin
Posts: 163
Joined: Wed Nov 12, 2008 9:49 pm
Location: Prague

Using rotary encoders for keyboard emulation (RPi)



Return to General Discussion, Tech Talk & Blog

Who is online

Users browsing this forum: Google [Bot] and 2 guests