Posts: 6
Threads: 0
Joined: Mar 2019
Reputation:
0
(03-29-2019, 12:14 PM)Tim Curtis Wrote: The feature will be in RC1 which I hope to make available sometime this week :-)
That’s great!!!
Posts: 5
Threads: 0
Joined: Feb 2019
Reputation:
1
Dear Tim and Remy, I have added a rotaty encoder for volume control (based on hrvoje's algorithm, see link in code). And a way to add the current song to a favorites list (or a list of files to be deleted) by communicating with mpd directly.
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
#On playlist names no spaces
PLFAV = "Favoriten" # This is the playlist to which files are saved when pushing the button. /var/lib/mpd/playlists/Favoriten.m3u will be created if it does not exist yet.
PLDEF = "Aktuell" # This is the default playlist which is played when pushing the respective button (/var/lib/mpd/playlists/Aktuell.m3u needs to be generated e.g. by renaming an existing .m3u)
PLDLT = "Delete" # This is the delete list. /var/lib/mpd/playlists/Delete.m3u will be created if it does not exist.
#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
SW_PREV = 22 # Previous
SW_NEXT = 4 # Next
SW_FAV = 26 # Add to favorites
SW_POWEROFF = 6 # Shut down
SW_PLAY = 17 # Toggle play/pause, e.g. button on the rotary encoder
SW_FW = 5 # Go forward within current song
SW_DEF = 13 # Play default playlist
SW_DLT = 25 # adds the currently played song to the delete list (to be deleted semi-manually on the master repository - the Raspberry Pi accesses a copy on my NAS only)
RO_A = 24 # Volume up
RO_B = 23 # 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
#Code to manage BUTTONS
GPIO.setup(SW_PREV, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_NEXT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_FAV, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_POWEROFF, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_PLAY, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_FW, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_DEF, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_DLT, 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)
#Interrupt events
def eSW_PREV(channel):
subprocess.call(['mpc', 'prev' ])
# print str(datetime.datetime.now())[:19] + " previous" # for testing only
def eSW_NEXT(channel):
subprocess.call(['mpc', 'next' ])
# print str(datetime.datetime.now())[:19] + " next" # for testing only
def eSW_FAV(channel):
NAMEN = subprocess.check_output("mpc -f %file% current", shell=True)[:-1]
NAME = NAMEN.replace("\'","\\'\\'\'") # for the sigle quotes in echo
PFAD = "echo 'playlistadd " + PLFAV + " \"" + NAME + "\"' | netcat -q 0 localhost 6600" # or "-w 1" instead of "-q 0" if not saving reliably?
os.system(PFAD)
print "Zu " + PLFAV + ": " + NAMEN
def eSW_POWEROFF(channel):
subprocess.call(['mpc', 'stop' ])
subprocess.call(['sudo', 'poweroff' ])
# print str(datetime.datetime.now())[:19] + " shutting down" # for testing only
def eSW_PLAY(channel):
subprocess.call(['mpc', 'toggle' ])
# print str(datetime.datetime.now())[:19] + " play" # for testing only
def eSW_FW(channel):
subprocess.call(['mpc', 'seek', '+'+str(SPRING)+'%' ])
# print str(datetime.datetime.now())[:19] + " forward" # for testing only
def eSW_DEF(channel):
subprocess.call(['mpc','clear' ])
subprocess.call(['mpc','load',PLDEF ])
subprocess.call(['mpc','play' ])
# print str(datetime.datetime.now())[:19] + " default playlist" # for testing only
def eSW_DLT(channel):
NAMEN = subprocess.check_output("mpc -f %file% current", shell=True)[:-1]
NAME = NAMEN.replace("\'","\\'\\'\'") # for the sigle quotes in echo
PFAD = "echo 'playlistadd " + PLDLT + " \"" + NAME + "\"' | netcat -q 0 localhost 6600" # or "-w 1" instead of "-q 0" if not saving reliably?
os.system(PFAD)
print "Zur Löschliste " + PLDLT + ": " + NAMEN
# 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(SW_PREV, GPIO.FALLING, callback = eSW_PREV, bouncetime = PRELL)
GPIO.add_event_detect(SW_NEXT, GPIO.FALLING, callback = eSW_NEXT, bouncetime = PRELL)
GPIO.add_event_detect(SW_FAV, GPIO.FALLING, callback = eSW_FAV, bouncetime = PRELLL)
GPIO.add_event_detect(SW_POWEROFF, GPIO.FALLING, callback = eSW_POWEROFF, bouncetime = PRELL)
GPIO.add_event_detect(SW_PLAY, GPIO.FALLING, callback = eSW_PLAY, bouncetime = PRELL)
GPIO.add_event_detect(SW_FW, GPIO.FALLING, callback = eSW_FW, bouncetime = PRELL)
GPIO.add_event_detect(SW_DEF, GPIO.FALLING, callback = eSW_DEF, bouncetime = PRELL)
GPIO.add_event_detect(SW_DLT, GPIO.FALLING, callback = eSW_DLT, bouncetime = PRELLL)
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(SW_PREV)) + " SW_PREV " + str(SW_PREV) + " | " + \
str(GPIO.input(SW_NEXT)) + " SW_NEXT " + str(SW_NEXT) + " | " + \
str(GPIO.input(SW_POWEROFF)) + " SW_POWEROFF " + str(SW_POWEROFF) + " | " + \
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
'''
Posts: 36
Threads: 3
Joined: Jun 2018
Reputation:
2
Hello!
For use one button power on/off this
[img] [/img]
Use pnp transistor
Posts: 2
Threads: 0
Joined: May 2019
Reputation:
0
Hello Tim,
I absolute like Moode audio !
And the GPIO Config screen is working for me close to perfection.
How can I config a Button to :
MPC clear MPC Load Playlist MPC play in one row ?
regards
Guido
Raspi 3 B +
Iqaudio AMP pro
IQaudio cosmic controller with OLED Display and Rotary Encoder
All powered by Moode Audio 5.3 :heart:
Posts: 111
Threads: 12
Joined: Apr 2018
Reputation:
14
(05-20-2019, 11:27 AM)fedormil Wrote: Hello!
For use one button power on/off this
[img][/img]
Use pnp transistor
Hi. You don't need to install a particular script for this to work?
Remy
Posts: 36
Threads: 3
Joined: Jun 2018
Reputation:
2
(07-09-2019, 07:07 AM)remy1961 Wrote: (05-20-2019, 11:27 AM)fedormil Wrote: Hello!
For use one button power on/off this
[img][/img]
Use pnp transistor
Hi. You don't need to install a particular script for this to work?
Remy
Hi, I use standart script for button, only just added 2 lines:
Code: GPIO.setup(16, GPIO.OUT)
GPIO.output (16, GPIO.HIGH)
It uses the principle of blocking voltage. When the script is running, the transistor is closed, and the button starts the shutdown or reboot command. When MK is turned off, the script stops and the transistor opens. When you press a button, the ground closes on contact P6, and the raspberry wakes up.
Pins can be used any.)
Posts: 111
Threads: 12
Joined: Apr 2018
Reputation:
14
(07-14-2019, 07:29 PM)fedormil Wrote: (07-09-2019, 07:07 AM)remy1961 Wrote: (05-20-2019, 11:27 AM)fedormil Wrote: Hello!
For use one button power on/off this
[img][/img]
Use pnp transistor
Hi. You don't need to install a particular script for this to work?
Remy
Hi, I use standart script for button, only just added 2 lines:
Code: GPIO.setup(16, GPIO.OUT)
GPIO.output (16, GPIO.HIGH)
It uses the principle of blocking voltage. When the script is running, the transistor is closed, and the button starts the shutdown or reboot command. When MK is turned off, the script stops and the transistor opens. When you press a button, the ground closes on contact P6, and the raspberry wakes up.
Pins can be used any.) Thanx. Remy.
Posts: 4
Threads: 1
Joined: Feb 2019
Reputation:
0
hello,
Sorry to bother you, but I have the same problem as gschmitz .
When I use "load playlist" fonction in the gpio handler config, the playlist load after.
I used gpio buttons before it was build in, and the load fonction used to clear load and play.
I tried few method like put a one line command in the config but nothing happened( it worked in SSH )
Do anyone have an idea?
I hope I have been understandable.
Thanks
Posts: 13,403
Threads: 304
Joined: Mar 2018
Reputation:
543
Hi,
Multiple commands have to be placed in a script file. You would enter the script file path as the CMD in GPIO button config.
Example:
1. Create the script file
Code: pi@rp3:~ $ sudo nano test.sh
pi@rp3:~ $ cat test.sh
#!/bin/bash
mpc stop && mpc play 5
pi@rp3:~ $ sudo chmod +x test.sh
2. In GPIO button config set CMD = /home/pi/test.sh
-Tim
Posts: 8
Threads: 1
Joined: Aug 2019
Reputation:
0
Hello,
with the help of Cyanoazemins' script I added two rotary encoders to my Raspberry (volume, loading a certain playlist and navigate through it).
As I am also running an OLED display via I2C it would be really great to choose a certain folder/file to play and use it as a stand-alone device without using the webinterface. Is there any chance to do so?
Bernd
|