hifiberry / hifiberry-os

Linux distribution optimized for audio playback
MIT License
987 stars 125 forks source link

Control GPIO pins #103

Open armatron opened 4 years ago

armatron commented 4 years ago

I would be great feature to be able to control some unused GPIO pins. Pin configuration and trigger can be set in interact action.

Example: Trigger: start playing from any source Action: pull up GPIO26 Trigger: stop playing Action: pull down GPIO26

This would have possibility for example, to turn off power amplifier when nothing is playing.

hifiberry commented 4 years ago

It's an interesting feature that we may implement at some time. To get it faster, you may contribute to the software: https://github.com/hifiberry/hifiberry-os/blob/master/FEATURE_REQUESTS.md

Greylinux commented 4 years ago

I am also interested in this feature and would love to contribute (although my skills are very limited ) to it, however I'm several projects deep that require my attention first , currently I use Moode audio as the software for my speaker. I very interested in transitioning to HifiberryOS and have been keenly watching its progress, this is however the final piece that is preventing me switching This is not a criticism as I cant believe the progress HifiberryOS has made its incredible.

This was my original enquiry when I first discovered hifiberryOS here and since then the progress is as I said incredible .

To the case in point I will try to help as best I can , Moode audio uses a script to detect gpio events

here is the github page

sadly my only contribution to this was the addition of the additonal de-bounce and detection of valid edges , to remove ghost events present with mechanical buttons .

I hope this can help further development in this issues .

Greylinux commented 3 years ago

just an update if this helps development of this feature , currently I use a python script that uses sub process calls to tell an mpd client to change volume play/pause , I wonder if you can utilise this script to make calls to what ever process alters volume , etc ,etc

#!/usr/bin/python

import RPi.GPIO as GPIO
import sys
import time
import os
import subprocess

# Use SoC pin numbering
GPIO.setmode(GPIO.BCM)

#configuration of pins
SW_TOGGLE = 26 # Pin 37
SW_VOL_UP = 27
SW_VOL_DN = 23

bounce_time = 500

GPIO.setup(SW_TOGGLE, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_VOL_UP, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SW_VOL_DN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

if GPIO.input(SW_TOGGLE) == 1:

    def switch_event_toggle(event):
        time.sleep(0.005)
        # only deal with valid edges
        if GPIO.input(event) == 1:
            subprocess.call(['mpc', 'toggle' ])
            #print ('TOGGLE')

    GPIO.add_event_detect(SW_TOGGLE, GPIO.RISING, callback=switch_event_toggle, bouncetime=bounce_time)

if GPIO.input(SW_VOL_UP) == 1:

    def switch_event_vol_up(event):
        time.sleep(0.005)
        # only deal with valid edges
        if GPIO.input(event) == 1:
            subprocess.call(['mpc', 'volume', '+1' ])
            #print ('VOLUME UP')

    GPIO.add_event_detect(SW_VOL_UP, GPIO.RISING, callback=switch_event_vol_up, bouncetime=bounce_time)

if GPIO.input(SW_VOL_DN) == 1:

    def switch_event_vol_dn(event):
        time.sleep(0.005)
        # only deal with valid edges
        if GPIO.input(event) == 1:
            subprocess.call(['mpc', 'volume', '-1' ])
            #print ('VOLUME DOWN')

    GPIO.add_event_detect(SW_VOL_DN, GPIO.RISING, callback=switch_event_vol_dn, bouncetime=bounce_time)

# Main
while True:
    time.sleep(1)
chalojak commented 1 year ago

I am not experienced enough to contribute to the project, but here is a script that I am using to control the relay, anytime the audio plays. It runs as a service, with a timer to prevent switching on and off in case the song is jumped etc. Hopefully, this helps to add such a feature by someone capable of integrating this.


#!/bin/bash

set -e

#   Exports pin to userspace
echo "26" > /sys/class/gpio/export

# Sets pin 26 as an output
echo "out" > /sys/class/gpio/gpio26/direction

#time to wait until the amplifier is turned off in seconds
off_timer_time=90

#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/gpio26/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/gpio26/value
        else
            ((off_timer++))
            #echo $off_timer
        fi
    fi

    last_is_playing=$is_playing
    sleep 1
done
``