Use rpi-rotary-encoder library

This commit is contained in:
ABelliqueux 2024-12-19 17:54:38 +01:00
parent 485586af3e
commit 5260330863
5 changed files with 108 additions and 23 deletions

View File

@ -32,12 +32,11 @@ RELAIS_1_GPIO = 17
GPIO.setup(RELAIS_1_GPIO, GPIO.OUT) # GPIO Assign mode
# Rotary encoder
from rot_lib import Encoder
clk = 27
dt = 22
GPIO.setup(clk, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(dt, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
volume = 0
clkLastState = GPIO.input(clk)
init_volume = 30
enc=Encoder(dt,clk,0,100,3)
# Buttons GPIO
BTNS = { 'BTN_1' : dict(GPIO=7, state=1),
@ -379,28 +378,20 @@ def main(args):
# List song by album
# ~ songs_from_album = client.list('title', 'album', album_by_x[x])
# Set Init volume in encoder and mpd
enc.setCounter(init_volume)
client.setvol(init_volume)
offset_polygons(MODES)
global ui_vol_icon_polygon
ui_vol_icon_polygon = apply_xy_offset(ui_vol_icon_polygon, ui_vol_icon_coords)
global static_ui
static_ui = generate_static_ui(current_mode)
while ctrlc_pressed is False:
global volume, clkLastState
global volume
# Rotary encoder
clkState = GPIO.input(clk)
dtState = GPIO.input(dt)
if clkState != clkLastState:
if dtState != clkState:
if volume < 100:
volume += 1
else:
if volume > 0:
volume -= 1
print(volume)
client.setvol(volume)
ui_idle_for = 0
# ~ clkLastState = clkState
# ~ sleep(0.01)
client.setvol(int(enc.getValue()))
#ui_idle_for = 0
# MPD
mpd_status = client.status()
if len(mpd_status):
@ -457,7 +448,6 @@ def main(args):
# Avoid further execution
ui_idle_for = 11
device.hide()
clkLastState = clkState
device.cleanup()
client.disconnect()

View File

@ -5,7 +5,7 @@ After=mpd.service
[Service]
WorkingDirectory=/home/%u/mpdlisten
ExecStart=/home/%u/mpdlisten/mpdlisten.py
ExecStart=/home/%u/mpdlisten/mpdlistenpy.sh
KillSignal=SIGINT
Restart=always

3
mpdlistenpy.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/env bash
cd "$(dirname "$0")"
python mpdlisten.py

View File

@ -5,8 +5,8 @@ This python script is supposed to run on a rpi and does the following :
* Relay trigger : Watches a MPD instance for play/pause/stop states and activates a relay via GPIOs accordingly ; the usecase for this is powering on/off a pair of speakers only when something is running.
* OLED display : Drives a 0.96" OLED display (ssd1306) to display MPD status (volume, current artist, album, title...)
* Button input : watches GPIOs for button input ; I'm using 5 push buttons for controlling playback (previous, next, toggle playback, stop, menu) or browse the database and add stuff to the playlist.
* Potentiometer input : Watches a GPIO for estimating the resistance of a rotary potentiometer and set volume accordingly.
* Rotary encoder for volume control.
## Setup
### Software

92
rot_lib.py Executable file
View File

@ -0,0 +1,92 @@
# 2023 - Tr3m
# Source : https://github.com/Tr3m/rpi-rotary-encoder
# Added a setCounter() method
import RPi.GPIO as GPIO
from time import sleep
class Encoder:
def __init__(self, pin_a: int, pin_b: int, range_min, range_max, increment):
if type(pin_a) == type(pin_b) == int:
self.__pin_a = pin_a
self.__pin_b = pin_b
self.__counter = None
self.__range_min = None
self.__range_max = None
self.__increment = None
self.setRange(range_min, range_max, increment)
GPIO.setwarnings(True)
GPIO.setmode(GPIO.BCM)
GPIO.setup(self.__pin_a, GPIO.IN)
GPIO.setup(self.__pin_b, GPIO.IN)
GPIO.add_event_detect(self.__pin_a, GPIO.RISING, callback=self.__rotation_decode, bouncetime=10)
else:
raise TypeError("Arguments need to be of type int")
def getValue(self):
return self.__counter
def setRange(self, range_min, range_max, increment):
if type(range_min) != type(range_max):
raise TypeError("Arguments need to be same type (int or float)")
if type(range_min) == int or type(range_min) == float:
if type(increment) != type(range_min):
raise TypeError("Increment type needs to be the same type as range_min and range_max")
if range_min > range_max:
raise Exception("Invalid range")
self.__range_min = range_min
self.__range_max = range_max
self.__increment = increment
self.__counter = (range_min + range_max) / 2
return
raise TypeError("Unsupported operand:", type(range_min))
def setCounter(self, counter):
self.__counter = float(counter)
def __rotation_decode(self, pin: int):
sleep(0.002)
Switch_A = GPIO.input(self.__pin_a)
Switch_B = GPIO.input(self.__pin_b)
if (Switch_A == 1) and (Switch_B == 0):
if (self.__counter > self.__range_min) and ((self.__counter - self.__increment) > self.__range_min):
self.__counter -= self.__increment
else:
self.__counter = self.__range_min
while Switch_B == 0:
Switch_B = GPIO.input(self.__pin_a)
while Switch_B == 1:
Switch_B = GPIO.input(self.__pin_b)
return
elif (Switch_A == 1) and (Switch_B == 1):
if (self.__counter < self.__range_max) and (self.__counter + self.__increment < self.__range_max):
self.__counter += self.__increment
else:
self.__counter = self.__range_max
while Switch_A == 1:
Switch_A = GPIO.input(pin)
return
else:
return
def __clear(self):
GPIO.remove_event_detect(self.__pin_a)