Change GPIO state on mpd play / stop - tristanc - 01-23-2019
I've borrrowed / adapted a bash script I found on the internet to control a relay based on the contents of the /proc/asound/card0/pcm0p/sub0/status file.
It sits and checks that file every n seconds, and if 'RUNNING' is found, changes the state of y GPIO.
If 'RUNNING' is then not found it waits x seconds before changing the state of the y GPIO back again.
I run this as a service and it works well with mpd / shairport etc. However, it would be great to incorporate this in worker.php or somewhere more suitable.
The feature could be generalised - so if 'RUNNING' is found run 'up.sh' / not found run 'down.sh' - just like network configuration, as I'm sure there are other things people would like to run if they hit play.
The variables could be:
Check interval (seconds): n
State change delay (seconds): x
Set-up script (optional): allows initialisation of a specified GPIO pin on boot
Play script: user set field like the LCD update script
Stop script: user set field like the LCD update script
And in these two files the user could implement anything they want.
Or it could be made 'amplifier relay specific' as someone on the forum has done - with a dedicated page for amplifier control.
Code: #!/bin/bash
set -e
# Exports pin to userspace
echo "23" > /sys/class/gpio/export
# Sets pin 23 as an output
echo "out" > /sys/class/gpio/gpio23/direction
#time to wait until the amplifier is turned off in seconds
off_timer_time=60
#set variables
last_is_playing=0
off_timer=0
while true
do
if cat /proc/asound/card0/pcm0p/sub0/status | grep -i RUNNING > /dev/null
then
is_playing=1
else
is_playing=0
fi
#0->1
if [[ "$last_is_playing" -eq "0" && "$is_playing" -eq "1" ]]
then
off_timer=0
echo "Turning amplifier on"
echo "1" > /sys/class/gpio/gpio23/value
fi
#1->0
if [[ "$last_is_playing" -eq "1" && "$is_playing" -eq "0" ]]
then
off_timer=1
fi
if [ "$off_timer" -ne "0" ]
then
if [ "$off_timer" -eq "$off_timer_time" ]
then
off_timer=0
echo "Turning amplifier off"
echo "0" > /sys/class/gpio/gpio23/value
else
((off_timer++))
#echo $off_timer
fi
fi
last_is_playing=$is_playing
sleep 1
done
Code: [Unit]
Description=Automatic Amplifier Control
[Service]
Type=simple
ExecStart=/home/pi/autoamp.sh
User=root
[Install]
WantedBy=multi-user.target
#systemctl enable autoamp.service
#systemctl daemon-reload
#systemctl start autoamp.service
RE: Change GPIO state on mpd play / stop - TheOldPresbyope - 01-23-2019
Thanks to this, I finally got around to looking at the /proc/asound virtual file system maintained by ALSA. Cool beans.
At first blush, the generalization would have to include the possibility that it's not card0 that's been selected. Case in point, my USB DAC is card1 (because card0 is the "onboard audio device").
Regards,
Kent
RE: Change GPIO state on mpd play / stop - Tim Curtis - 01-23-2019
Hi @tristanc,
Scripts that contain their own polling loops and delays need to be run separately from worker.php. This is because worker contains its own polling loop for processing jobs, updating renderer status, etc., and this loop requires a fixed time interval.
-Tim
RE: Change GPIO state on mpd play / stop - tristanc - 01-24-2019
(01-23-2019, 05:06 PM)Tim Curtis Wrote: Hi @tristanc,
Scripts that contain their own polling loops and delays need to be run separately from worker.php. This is because worker contains its own polling loop for processing jobs, updating renderer status, etc., and this loop requires a fixed time interval.
-Tim
Ah, so there'd need to be something 'above' worker.php. And doing a quick google suggests multi-threaded PHP is not recommended for web purposes...
Perhaps best left as a service outside of Moode then unless there's something clever that can be done.
RE: Change GPIO state on mpd play / stop - pepus - 01-23-2024
(01-23-2019, 10:54 AM)tristanc Wrote: I've borrrowed / adapted a bash script I found on the internet to control a relay based on the contents of the /proc/asound/card0/pcm0p/sub0/status file.
It sits and checks that file every n seconds, and if 'RUNNING' is found, changes the state of y GPIO.
If 'RUNNING' is then not found it waits x seconds before changing the state of the y GPIO back again.
I run this as a service and it works well with mpd / shairport etc. However, it would be great to incorporate this in worker.php or somewhere more suitable.
The feature could be generalised - so if 'RUNNING' is found run 'up.sh' / not found run 'down.sh' - just like network configuration, as I'm sure there are other things people would like to run if they hit play.
The variables could be:
Check interval (seconds): n
State change delay (seconds): x
Set-up script (optional): allows initialisation of a specified GPIO pin on boot
Play script: user set field like the LCD update script
Stop script: user set field like the LCD update script
And in these two files the user could implement anything they want.
Or it could be made 'amplifier relay specific' as someone on the forum has done - with a dedicated page for amplifier control.
Code: #!/bin/bash
set -e
# Exports pin to userspace
echo "23" > /sys/class/gpio/export
# Sets pin 23 as an output
echo "out" > /sys/class/gpio/gpio23/direction
#time to wait until the amplifier is turned off in seconds
off_timer_time=60
#set variables
last_is_playing=0
off_timer=0
while true
do
if cat /proc/asound/card0/pcm0p/sub0/status | grep -i RUNNING > /dev/null
then
is_playing=1
else
is_playing=0
fi
#0->1
if [[ "$last_is_playing" -eq "0" && "$is_playing" -eq "1" ]]
then
off_timer=0
echo "Turning amplifier on"
echo "1" > /sys/class/gpio/gpio23/value
fi
#1->0
if [[ "$last_is_playing" -eq "1" && "$is_playing" -eq "0" ]]
then
off_timer=1
fi
if [ "$off_timer" -ne "0" ]
then
if [ "$off_timer" -eq "$off_timer_time" ]
then
off_timer=0
echo "Turning amplifier off"
echo "0" > /sys/class/gpio/gpio23/value
else
((off_timer++))
#echo $off_timer
fi
fi
last_is_playing=$is_playing
sleep 1
done
Code: [Unit]
Description=Automatic Amplifier Control
[Service]
Type=simple
ExecStart=/home/pi/autoamp.sh
User=root
[Install]
WantedBy=multi-user.target
#systemctl enable autoamp.service
#systemctl daemon-reload
#systemctl start autoamp.service
Haha I'm like a mole, digging up old old topics. ![Wink Wink](https://moodeaudio.org/forum/images/smilies/wink.png)
As I have little problems with GPIO in shell, I rewrote your script to python. I hope no one will be offended.
Just be sure to carefully check that the path is proc/asound/.... refers to your card.
Code: #!/usr/bin/python3
import RPi.GPIO as GPIO
import os
import time
Pin_mute = 16
off_timer_time = 60
last_is_playing = 0
off_timer = 0
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(Pin_mute, GPIO.OUT)
while True:
if os.system('cat /proc/asound/card0/pcm0p/sub0/status | grep -i RUNNING > /dev/null') == 0:
is_playing = 1
else:
is_playing = 0
#0->1
if last_is_playing == 0 and is_playing == 1:
off_timer = 0
print('Turning amplifier ON')
GPIO.output(Pin_mute, 1)
#1->0
if last_is_playing == 1 and is_playing == 0:
off_timer = 1
if off_timer != 0:
if off_timer == off_timer_time:
off_timer = 0
print('Turning amplifier OFF')
GPIO.output(Pin_mute, 0)
else:
off_timer += 1
last_is_playing = is_playing
time.sleep(1)
Cheers.
AD.
2 hours later...
I found a solution to the message problem when initializing the GPIO port
echo 16 > /sys/class/gpio/export
-bash: echo: write error: device or resource busy
Code: echo "16" > /sys/class/gpio/export
to this
Code: [ -L /sys/class/gpio/gpio16 ] || echo "16" > /sys/class/gpio/export
to prevent a message a write error: device or resource busy
found here: Raspbery Pi forum
|