Skip to content

Instantly share code, notes, and snippets.

@n3rd
Last active December 3, 2019 14:26
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save n3rd/dbaca08a48b74f970307 to your computer and use it in GitHub Desktop.
Save n3rd/dbaca08a48b74f970307 to your computer and use it in GitHub Desktop.
Raspberry Pi + KY040 Rotary Encoder (+ S/W Volume Control)
#!/usr/local/bin/python
import RPi.GPIO as GPIO
class RotaryEncoder:
DIRECTION_CLOCKWISE = 1
DIRECTION_COUNTERCLOCKWISE = 3
prv_seq = 0
direction = 0
def __init__(self, pinA, pinB, button, callback):
self.pinA = pinA
self.pinB = pinB
self.button = button
self.callback = callback
GPIO.setup(self.pinA, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(self.pinB, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(self.button, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(self.pinA, GPIO.FALLING, callback=self.evt)
GPIO.add_event_detect(self.pinB, GPIO.FALLING, callback=self.evt)
def evt(self, channel):
a = GPIO.input(self.pinA)
b = GPIO.input(self.pinB)
c = a ^ b
seq = c | b << 1
delta = (seq - self.prv_seq) % 4
if delta == 1:
if self.direction == self.DIRECTION_CLOCKWISE:
self.callback(self.DIRECTION_CLOCKWISE, self.button_press())
else:
self.direction = self.DIRECTION_CLOCKWISE
elif delta == 2:
if self.direction == self.DIRECTION_CLOCKWISE:
self.callback(self.DIRECTION_CLOCKWISE, self.button_press())
elif self.direction == self.DIRECTION_COUNTERCLOCKWISE:
self.callback(self.DIRECTION_COUNTERCLOCKWISE, self.button_press())
elif delta == 3:
if self.direction == self.DIRECTION_COUNTERCLOCKWISE:
self.callback(self.DIRECTION_COUNTERCLOCKWISE, self.button_press())
else:
self.direction = self.DIRECTION_COUNTERCLOCKWISE
self.prv_seq = seq
def button_press(self):
return GPIO.input(self.button) == GPIO.LOW
#!/usr/local/bin/python
# KY040 Rotary Encoder + Raspberry Pi (Model A+)
# ===
# + (5V) e.g. GPIO.BOARD 2
# BTN is on GPIO.BOARD 12
# GND e.g. GPIO.BOARD 14
# B (DT) is on GPIO.BOARD 16
# A (CLK) is on GPIO.BOARD 18
import sys
import time
import RPi.GPIO as GPIO
from RotaryEncoder import RotaryEncoder
# (!) use BOARD NRs for PINs
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
def main_loop():
while True:
time.sleep(0.5)
def callback(direction, btn_pressed):
if direction == RotaryEncoder.DIRECTION_CLOCKWISE and not btn_pressed:
print 'CLOCKWISE'
elif direction == RotaryEncoder.DIRECTION_COUNTERCLOCKWISE and not btn_pressed:
print 'COUNTERCLOCKWISE'
elif direction == RotaryEncoder.DIRECTION_CLOCKWISE and btn_pressed:
print 'CLOCKWISE + BUTTON'
elif direction == RotaryEncoder.DIRECTION_COUNTERCLOCKWISE and btn_pressed:
print 'COUNTERCLOCKWISE + BUTTON'
if __name__ == '__main__':
try:
enc = RotaryEncoder(18, 16, 12, callback)
print "listening..."
main_loop()
except KeyboardInterrupt:
print >> sys.stderr, '\nExiting by user request.\n'
sys.exit(0)
#!/usr/local/bin/python
# depends on: http://pyalsaaudio.sourceforge.net
# sudo apt-get install python-alsaaudio
# KY040 Rotary Encoder + Raspberry Pi (model A+)
# ===
# + (5V) e.g. GPIO.BOARD 2
# BTN is on GPIO.BOARD 12
# GND e.g. GPIO.BOARD 14
# B (DT) is on GPIO.BOARD 16
# A (CLK) is on GPIO.BOARD 18
import sys
import time
import alsaaudio
import RPi.GPIO as GPIO
from RotaryEncoder import RotaryEncoder
# (!) use BOARD NRs for PINs
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
class Volume:
def __init__(self):
self.mixer = alsaaudio.Mixer(control='PCM')
def get_volume(self):
return self.mixer.getvolume('playback')[0]
def set_volume(self, percentage):
if percentage < 0:
percentage = 0
elif percentage > 100:
percentage = 100
self.mixer.setvolume(percentage)
time.sleep(.2)
def volume_up(self):
self.set_volume(self.get_volume() + 5)
def volume_down(self):
self.set_volume(self.get_volume() - 5)
def callback(self, direction, btn_pressed):
if direction == RotaryEncoder.DIRECTION_CLOCKWISE:
self.volume_up()
elif direction == RotaryEncoder.DIRECTION_COUNTERCLOCKWISE:
self.volume_down()
def main_loop():
while True:
time.sleep(0.5)
if __name__ == '__main__':
try:
vol = Volume()
enc = RotaryEncoder(18, 16, 12, vol.callback)
main_loop()
except KeyboardInterrupt:
print >> sys.stderr, '\nExiting by user request.\n'
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment