Moode Forum
[How to do instruction] Use hardware momentary switches to control moOde - Printable Version

+- Moode Forum (https://moodeaudio.org/forum)
+-- Forum: moOde audio player (https://moodeaudio.org/forum/forumdisplay.php?fid=3)
+--- Forum: FAQ and Guides (https://moodeaudio.org/forum/forumdisplay.php?fid=9)
+--- Thread: [How to do instruction] Use hardware momentary switches to control moOde (/showthread.php?tid=198)

Pages: 1 2 3 4 5 6 7 8 9


RE: Use hardware momentary switches to control moOde - quarryman - 01-12-2021

Opened the thread to ask exactly the same question Smile


RE: Use hardware momentary switches to control moOde - Tim Curtis - 01-12-2021

Just put the commands in a BASH script and assign the script to the button

1. Create myscript.sh in your home directory /home/pi/ otherwise referred to as ~
See example below.

#!/bin/bash
mpc clear
mpc load "my_playlist"
mpc play

2. Mark it executable

chmod +x ~/myscript.sh


RE: Use hardware momentary switches to control moOde - quarryman - 01-13-2021

Thanks Tim. When you say assign the script to that button you mean put "~/my script.sh" into the GPIO dialog box in Moode instead of "mpc play" etc?


RE: Use hardware momentary switches to control moOde - Tim Curtis - 01-13-2021

Yes, but use the absolute path instead of ~/

/home/pi/myscript.sh


RE: Use hardware momentary switches to control moOde - vandalsavage - 04-14-2021

Hi every 1.First of all i will like to thank Tim for all his work end effort invested in this great project.i realy love it.now to my problem/request.for my moode project i would to add only one button(pull-down) for both power up and power down.my problem is although i possess a fair amount of  knowledge about electronics my coding knowledge is close to zero and from my researches for this project  some coding is necessary(i might be wrong).so if anyone has some ideas i will be very happy to put them in practice.thank you.i forgot to mention that i'm useing a rasberry pi 3+ 1Gb board plus IQaudIO Pi-DigiAMP+ with a 5 inch touchscreen display.


RE: Use hardware momentary switches to control moOde - Geiiga - 08-10-2021

Sorry for the noob question, but I'm hapless with code. I'm trying to make a super-simple radio for my mother-in-law that has two dials -- volume, and track change (I'd rather it be playlist change, but I'll take what I can get). I have the rotary encoders wired up, and I borrowed Cyanoazemins' script and edited it, which is I'm sure where my problems start. Instead of having one rotary encoder that does volume, one that changes track, and the pushbutton switch toggling pause/play on both, I have one rotary encoder that mutes the audio if I push the button.

Here's the code I came up with:

Code:
#!/usr/bin/python
#coding: utf8
# Script for mpc/mpd audio GPIO buttons partly based on remy1961's code on http://moodeaudio.org/forum/showthread.php?tid=198&pid=8382#pid8382
# Rotary encoder mostly based on hrvoje's code https://www.raspberrypi.org/forums/viewtopic.php?t=140250 . Comments on the reliability of RPi.GPIO library there
# mpd on default settings: localhost 6600
# Worked with one rotary encoder only (with two not reliably enough) in my case
# All buttons and rotary encoder connect to ground without hardware debouncing or hardware pull-up/-down. Rotary encoder bouncing is not improved with capacitors across A/B and ground.

import RPi.GPIO as GPIO             # pigpio library does NOT work, due to loud noise (louder than the music)
import threading                    # rotary interrupt
import time
import os
import subprocess
#import datetime                    # for testing only

#GPIO.setwarnings(True)
GPIO.setmode(GPIO.BCM)              # dset GPIO mode instead of GPIO.setmode(GPIO.BOARD) - Zählweise der Pins festlegen


#Define your GPIO pins (pin 20, 18, etc. not suitable in my case, i.e. not working or crashing), 7 buttons + 1 rotary encoder with button
RO_PREV = 27                        # Previous
RO_NEXT = 22                         # Next
SW_PLAY2 = 12                     # Toggle play/pause, e.g. button on the rotary encoder
RO_A = 6                           # Volume up
RO_B = 5                           # Volume down

PRELL = 500                         # debouncing for regular buttons
PRELLL = 1500                       # debouncing for "add to list" buttons
PRELLROT = 30                       # debouncing for rotary, favorable to diminish skipping. Higher value allows only slow volume increase
SCHRITT = 5                         # % change in Volume
SPRING = 10                         # % forward within current song
LockRotary = threading.Lock()        # create lock for rotary switch
Current_A = 0                        # Assume that rotary switch is not moving while we init software
Current_B = 0
Current_PREV = 0
Current_NEXT 0

#Code to manage BUTTONS
GPIO.setup(RO_PREV, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(RO_NEXT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_PLAY2, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_PLAY, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(RO_A, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(RO_B, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Rotary encoder interrupt is called for both inputs from rotary switch (A and B)
def eRO(PREV_or_NEXT):
    global Current_PREV, Current_NEXT, LockRotary
  
    Switch_PREV = GPIO.input(RO_PREV)                                         # Read both of the switches
    Switch_NEXT = GPIO.input(RO_NEXT)
  
    if Current_PREV == Switch_PREV and Current_NEXT == Switch_NEXT:                    # Now check if state of A or B has changed. If not that means that bouncing caused it
        return                                                               # Same interrupt as before (Bouncing)? Ignore interrupt!

    Current_PREV = Switch_PREV                                                # remember new state
    Current_NEXT = Switch_NEXT                                                # for next bouncing check

    if (Switch_PREV == 0 and Switch_NEXT == 0):                                # Both one active? Yes -> end of sequence
        LockRotary.acquire()                                            # get lock
        if PREV_or_NEXT == RO_NEXT:                                                # Turning direction depends on which input gave last interrupt
                   subprocess.call(['mpc', 'next', '-'+str(SCHRITT) ])
        else:                                                            # so depending on direction either increase or decrease counter
                   subprocess.call(['mpc', 'prev', '-'+str(SCHRITT) ])
        LockRotary.release()                                            # and release lock
    return                                                                # done

def eSW_PLAY2(channel):
   subprocess.call(['mpc', 'toggle' ])
#   print str(datetime.datetime.now())[:19] + " play"                   # for testing only

def eSW_PLAY(channel):
   subprocess.call(['mpc', 'toggle' ])
#   print str(datetime.datetime.now())[:19] + " play"                   # for testing only


# Rotary encoder interrupt is called for both inputs from rotary switch (A and B)
def eRO(A_or_B):
    global Current_A, Current_B, LockRotary
  
    Switch_A = GPIO.input(RO_A)                                         # Read both of the switches
    Switch_B = GPIO.input(RO_B)
  
    if Current_A == Switch_A and Current_B == Switch_B:                    # Now check if state of A or B has changed. If not that means that bouncing caused it
        return                                                               # Same interrupt as before (Bouncing)? Ignore interrupt!

    Current_A = Switch_A                                                # remember new state
    Current_B = Switch_B                                                # for next bouncing check

    if (Switch_A == 0 and Switch_B == 0):                                # Both one active? Yes -> end of sequence
        LockRotary.acquire()                                            # get lock
        if A_or_B == RO_B:                                                # Turning direction depends on which input gave last interrupt
                   subprocess.call(['mpc', 'volume', '+'+str(SCHRITT) ])
        else:                                                            # so depending on direction either increase or decrease counter
                   subprocess.call(['mpc', 'volume', '-'+str(SCHRITT) ])
        LockRotary.release()                                            # and release lock
    return                                                                # done

# Declare interrupt events
GPIO.add_event_detect(RO_PREV, GPIO.FALLING, callback = eRO_PREV, bouncetime = PRELL)
GPIO.add_event_detect(RO_NEXT, GPIO.FALLING, callback = eRO_NEXT, bouncetime = PRELL)
GPIO.add_event_detect(SW_PLAY2, GPIO.FALLING, callback = eSW_POWEROFF, bouncetime = PRELL)
GPIO.add_event_detect(SW_PLAY, GPIO.FALLING, callback = eSW_PLAY, bouncetime = PRELL)
GPIO.add_event_detect(RO_A, GPIO.FALLING, callback=eRO, bouncetime = PRELLROT)
GPIO.add_event_detect(RO_B, GPIO.FALLING, callback=eRO, bouncetime = PRELLROT)

# Main
while True:
   time.sleep(1)
# the following is for testing pins. In my case e.g. pin 20 was low (0) all the time
'''
   print str(GPIO.input(RO_PREV)) + " RO_PREV " + str(RO_PREV) + "   |    " +  \
   str(GPIO.input(RO_NEXT)) + " RO_NEXT " + str(RO_NEXT) + "   |    " +  \
   str(GPIO.input(SW_PLAY2)) + " SW_PLAY2 " + str(SW_PLAY2) + "   |    " +  \
   str(GPIO.input(SW_PLAY)) + " SW_PLAY " + str(SW_PLAY) + "   |    " +  \
   str(GPIO.input(RO_A)) + " RO_A " + str(RO_A) + "   |    " +  \
   str(GPIO.input(RO_B)) + " RO_B " + str(RO_B) + "   |    " +  \       # for testing only
'''

I followed the directions in the first post on this thread for creating the buttons.py file and pointing rc.local to it, but...nope. No controls other than mute as long as I'm holding down the tuner dial's button.

Thanks for the help! (I don't know what 'reliably enough' might mean in that comment line which I didn't notice before now, so if that's my problem -- I guess I just need to lose the volume. Which is acceptable)

EDIT: So I got it. I commented out every line that didn't directly impact my situation, then I went to the config and told the GPIO configurator what the pins were supposed to do, said a short prayer to Baphomet, rebooted, and shazam.


RE: Use hardware momentary switches to control moOde - manderso - 08-27-2021

Not sure if this is the thread, but it hopefully is.
How well will a rotary connector work here when there's a rotary connector in use for the volume control?