From 52603308637ac75af814cb77746dfc5463bfe720 Mon Sep 17 00:00:00 2001 From: ABelliqueux Date: Thu, 19 Dec 2024 17:54:38 +0100 Subject: [PATCH] Use rpi-rotary-encoder library --- mpdlisten.py | 30 +++++---------- mpdlistenpy.service | 2 +- mpdlistenpy.sh | 3 ++ readme.md | 4 +- rot_lib.py | 92 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 23 deletions(-) create mode 100755 mpdlistenpy.sh create mode 100755 rot_lib.py diff --git a/mpdlisten.py b/mpdlisten.py index e03b383..180793d 100755 --- a/mpdlisten.py +++ b/mpdlisten.py @@ -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() diff --git a/mpdlistenpy.service b/mpdlistenpy.service index 63b044f..2359cbd 100644 --- a/mpdlistenpy.service +++ b/mpdlistenpy.service @@ -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 diff --git a/mpdlistenpy.sh b/mpdlistenpy.sh new file mode 100755 index 0000000..6e5befc --- /dev/null +++ b/mpdlistenpy.sh @@ -0,0 +1,3 @@ +#!/bin/env bash +cd "$(dirname "$0")" +python mpdlisten.py diff --git a/readme.md b/readme.md index 0ba48b0..6114e5b 100644 --- a/readme.md +++ b/readme.md @@ -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 diff --git a/rot_lib.py b/rot_lib.py new file mode 100755 index 0000000..eb855e6 --- /dev/null +++ b/rot_lib.py @@ -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)