Thank you for your donation!


Cloudsmith graciously provides open-source package management and distribution for our project.


Rotary encoder for switching tracks
#1
Hi all,

I want to use a rotary encoder (KY-040) for track skipping (previous/next track) rather than volume.  I can see that there is native support for an encoder wired to certain GPIO pins on the Pi.  Can anyone please point me in the direction of which files to edit/configure so that it performs the track skipping function rather than volume up/down?

The KY-040 also has a push button function which I'd like to use for play/pause. I assume this acts as a normal button and I can map it using the GPIO button function in Moode directly?

Thank you Smile
Reply
#2
In case anyone else wants to do this, I initially started by trying to modify the Moode script that does the volume but I couldn't get it working satisfactorily. in the end I achieved this by writing a separate Python script which calls the mpc commands for prev/next, and setting it as a service, with an adequate sleep time so as not to absolutely nail the CPU.  

The debounce time and part of the script that ignores inputs if there are less than two consecutive clicks each direction help to make my cheap KY-040 encoder work smoothly.

See below:


Code:
import RPi.GPIO as GPIO
import subprocess
import time

# GPIO pins (BCM numbering)
clk = 23
dt = 24

# Set up GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(clk, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(dt, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Initial states
clkLastState = GPIO.input(clk)
directionCounter = 0  # Counts consecutive moves in the same direction
lastDirection = None
debounceTime = 0.04

def read_rotary():
   global clkLastState, directionCounter, lastDirection
   clkState = GPIO.input(clk)
   dtState = GPIO.input(dt)
   
   if clkState != clkLastState:
       if dtState != clkState:
           currentDirection = "next"
       else:
           currentDirection = "prev"
       
       if currentDirection == lastDirection:
           directionCounter += 1
       else:
           directionCounter = 1  # Reset counter on direction change
       
       # Act only if there have been two consecutive clicks in the same direction
       if directionCounter >= 2:
           if currentDirection == "next":
               subprocess.run(['mpc', 'next'])
           else:
               subprocess.run(['mpc', 'prev'])
           
           # Reset after action
           directionCounter = 0
           lastDirection = None
       else:
           # Update lastDirection for next comparison
           lastDirection = currentDirection

       time.sleep(debounceTime)  # Debounce delay

   clkLastState = clkState

# Polling loop
try:
   while True:
       read_rotary()
       time.sleep(0.01)  # Short sleep to reduce CPU usage
except KeyboardInterrupt:
   GPIO.cleanup()  # Clean up GPIO on CTRL+C exit
Reply


Forum Jump: