How to set GPIO high on RasPi when sound is played
Aleady some time - a year ago I bought couple of simple Easy Digi devices from KF5INZ. Accidentaly I got one extra - there was some mistake. I offered to send it back, but as shipping was costly, than seller kindly left it as bonus.
At that time I hoped, that it can help me to pair my old Kenwood TS-50S with PC and do some digital modes, but it was not so easy as that radio has pretty old and there was not so much info on PC interfacing on net. So these Easy Digi Boxes has almoust forgoten until I finaly decided to buy and tinker around RasPi. The idea was similar - to do some interfacing with a radio. But in this case at first to try to make some simple tasks, like simple parrot repeater, auto transmission recorder or pair with some voice recognition AI software.
I had some success with Mycroft AI on my big linux box, when I used it with Easy Digi and some handheld with VOX option activated. I could ask questions and got anwers by using another handheld radio. Those was Che-Chi PoC radios like UV-5R or similar and I was not satisfied about VOX stability. So I was thinking how to fire PTT line on sound output.
I got near solution when started to tinker around RasPi. Here also some note on Easy Digi - it is actualy as very simple device with two sound transformers for RF isolation and also simple orthocoupler circuit for shorting PTT lines. It can be used with some serial port programming or for RasPi case gpio programing.
I was not very succesful for diging some samples for serial port programming on linux, but for RasPi there was plenty info regarding gpoi programing and samples. So my joyrney was suucessfull.
So bellow is my notes how to achieve this task - set gpio high on RasPi when sound is played. Then we can use gpio voltage level to switch on some device or “push PTT” on the transceiver.
Requirements: Some knowledge about RasPi and linux command line. Rasbery Pi with USB sound card. Configured and installed necesary sound drivers and utilities. Unfortunately I did not documented it, but mainly it is just the same “apt-get install …” method
By digging net I found that it is possible to check sound output by checkin some status “directory”. But first I had to setup my USB sound card as RasPi has just sound outputs, but for my case I need also input i.e. microphone input. We can also live by just plugging in an USB sound card and use default set up. But it means that attached USB sound card will be some secondary etc. after RasPi onboard sound outputs, that are not just one (remember, that HDMI also has sound out). So as my plans was use RasPi in headless mode I also whanted that my USB sound card was primary or sound card 0.
First I checked what is sound cards order:
$ cat /proc/asound/modules
0 snd_bcm2835
1 snd_usb_audio
To reorder soundcards I used file: /etc/modprobe.d/usb-sound.conf The file name could be any thing as far it have .conf extension. The contents of /etc/modprobe.d/usb-sound.conf
# Set the index value of the cards.
options snd_usb_audio index=0
options snd_bcm2835 index=1
# Reorder sound cards
options snd slots=snd_usb_audio,snd_bcm2835
Now reboot RasPi and check:
By attaching some microphone or sound input to USB card testing for sound input:
$ arecord test.wav
And similar way for output:
aplay test.wav
The sound should came in and out through attached USB sound card.
To check is the sound output active we can specific dir or rather some virtual file that is created each time when a sound card is activated:
/proc/asound/card0/pcm0p/sub0/status
You can check whichever is yours, but as I ordered my sound card as card with index=0, than is now card0.
We also need to know which GPIO we should and/or want to use. I choosed to used GPIO 27, because it has righ behind them groud GPIO. So it is ieasier to find them and also possible to use paired GPIO connectors.
Create main script file, that checks for sound card status file and accordingly set GPIO voltage level high or low:
sudo nano /usr/local/bin/sound2gpio.sh
Paste script content in nano editor and exit from nano text editor and save the file:
#!/bin/bash
#Sound card statuss "file"
DIR='/proc/asound/card0/pcm0p/sub0/status'
#GPIO number
OUTPIO=27
#Here probably should be the check are this GPIO are not in use already
#but as we will use it as service started upon boot and not planning to use other scripts
#than it can be left out
echo $OUTPIO > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio$OUTPIO/direction
# When script is stopped release GPIO
function cleanup()
{
echo $OUTPIO > /sys/class/gpio/unexport
exit 0
}
trap cleanup SIGINT
status1='closed'
while true
do
if grep -q 'state: RUNNING' $DIR ; then
status2='open'
elif grep -q 'closed' $DIR ; then
status2='closed'
fi
if [[ $status1 != $status2 ]] ; then
if grep -q 'state: RUNNING' $DIR ; then
echo "1" > /sys/class/gpio/gpio$OUTPIO/value
echo "Sound Detected!"
status1='open'
elif grep -q 'closed' $DIR ; then
echo "0" > /sys/class/gpio/gpio$OUTPIO/value
echo "Sound Stopped!"
status1='closed'
fi
fi
done
Make file executable:
sudo chmod +x /usr/local/bin/sound2gpio.sh
Now we can check how it works by running the script and playing some sound and using some multimeter to check does the voltage between GPIO 27 and Ground GPIO changes.
If it is going well and voltage changes accordingly when sound is played than we can go furtherand automate RasPi to run the sound catcher script on boot and in background as service.
To do so we have to create service for that:
sudo nano /etc/systemd/system/sound2gpio.service
Paste there service file content in nano editor and exit from nano text editor and save the file:
[Unit]
Description=Sets GPIO hight when sound is outputing on sound card
After=network.target
[Service]
Type=simple
Restart=on-failure
ExecStart=/usr/local/bin/sound2gpio.sh
[Install]
WantedBy=multi-user.target
Now run:
sudo systemctl daemon-reload
sudo systemctl start sound2gpio.service
# Check for errors
journalctl -xe
# Set the service to start at each boot
sudo systemctl enable sound2gpio.service
Then last check by rebooting your RasPi and testing voltage levels on GPIO 27 when sound is playing.
Now we can attach Easy Digi and start receive and send some transmissions. But before we will need last step - somehow to control volumes on sound input and output. While we can control radio sound volume it is sometimes worth to switch of mikrophone auto gain control or in some situations we can have some specific radio, that has no volume control or it is limited, like some old military radios. Also we have to tune sound output lever from RasPi USB soun card, because not all radios has feature to set it’s microphone gain.
To tune sound card we can use amixer Following command will output sound card parameters:
$ amixer --card 0 contents
numid=10,iface=CARD,name='Keep Interface'
; type=BOOLEAN,access=rw------,values=1
: values=off
numid=3,iface=MIXER,name='Mic Playback Switch'
; type=BOOLEAN,access=rw------,values=1
: values=off
numid=4,iface=MIXER,name='Mic Playback Volume'
; type=INTEGER,access=rw---R--,values=1,min=0,max=31,step=0
: values=16
| dBminmaxmute-min=-23.00dB,max=8.00dB
numid=7,iface=MIXER,name='Mic Capture Switch'
; type=BOOLEAN,access=rw------,values=1
: values=on
numid=8,iface=MIXER,name='Mic Capture Volume'
; type=INTEGER,access=rw---R--,values=1,min=0,max=35,step=0
: values=16
| dBminmax-min=-12.00dB,max=23.00dB
numid=9,iface=MIXER,name='Auto Gain Control'
; type=BOOLEAN,access=rw------,values=1
: values=on
numid=5,iface=MIXER,name='Speaker Playback Switch'
; type=BOOLEAN,access=rw------,values=1
: values=on
numid=6,iface=MIXER,name='Speaker Playback Volume'
; type=INTEGER,access=rw---R--,values=2,min=0,max=37,step=0
: values=4,4
| dBminmaxmute-min=-37.00dB,max=0.00dB
numid=2,iface=PCM,name='Capture Channel Map'
; type=INTEGER,access=r----R--,values=1,min=0,max=36,step=0
: values=0
| container
| chmap-fixed=MONO
numid=1,iface=PCM,name='Playback Channel Map'
; type=INTEGER,access=r----R--,values=2,min=0,max=36,step=0
: values=0,0
| container
| chmap-fixed=FL,FR
To set the Auto Gain Control off:
$ amixer -c 0 cset numid=9,iface=MIXER,name='Auto Gain Control' 0
numid=9,iface=MIXER,name='Auto Gain Control'
; type=BOOLEAN,access=rw------,values=1
: values=off
To set the recording volume to 25:
$ amixer -c 0 cset numid=8,iface=MIXER,name='Mic Capture Volume' 25
numid=8,iface=MIXER,name='Mic Capture Volume'
; type=INTEGER,access=rw---R--,values=1,min=0,max=35,step=0
: values=25
| dBminmax-min=-12.00dB,max=23.00dB
When we are tuned our sound card acordingly to our transceiver we can start to make some automation regarding receiving and sending, add some voice recognition or AI, or just simple parrot repeater. It just depends on our imagination and knowledge. But let it be another blog record… ;-)