Compare commits
5 Commits
e68aa673af
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5016ca5567 | |||
| a22b2158e1 | |||
| 00e3d27774 | |||
| 74aea45d73 | |||
| 42f9c8f94d |
20
.asoundrc
20
.asoundrc
@@ -1,17 +1,7 @@
|
|||||||
pcm.my_sound_device {
|
pcm.hw0mix {
|
||||||
type hw
|
type dmix
|
||||||
card USB
|
ipc_key 1939 # must be unique
|
||||||
# card PCH
|
slave { pcm "hw:Zero" }
|
||||||
# card Headphones
|
|
||||||
device 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pcm.my_sound_device_with_converter {
|
pcm.!default hw0mix
|
||||||
type plug
|
|
||||||
slave {
|
|
||||||
pcm my_sound_device
|
|
||||||
format S16_LE
|
|
||||||
channels 2
|
|
||||||
rate 48000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
38
README.md
38
README.md
@@ -12,7 +12,12 @@ Hardware
|
|||||||
- Buttons connected to the Raspberry pi GPIO as shown in the schema to debounce noisy contacts
|
- Buttons connected to the Raspberry pi GPIO as shown in the schema to debounce noisy contacts
|
||||||

|

|
||||||
|
|
||||||
- USB speaker with a microphone e.g. [Jabra Speak 410](https://www.jabra.com/_/media/Jabra_VXi_Product-Documentation/Jabra-SPEAK-410-Series/technical-specifications/RevB/Jabra-Speak-410-Techsheet-A4-290420-Web.pdf)
|
- USB speaker with a microphone e.g. [Jabra Speak 410](https://www.jabra.com/_/media/Jabra_VXi_Product-Documentation/Jabra-SPEAK-410-Series/technical-specifications/RevB/Jabra-Speak-410-Techsheet-A4-290420-Web.pdf) or [Codec Zero](https://www.raspberrypi.com/products/codec-zero/)
|
||||||
|
|
||||||
|
- for the `Codec Zero` make follwoing changes
|
||||||
|
> `sudo nano /boot/config.txt`
|
||||||
|
`#dtparam=audio=on`
|
||||||
|
`dtoverlay=rpi-codeczero`
|
||||||
|
|
||||||
- microSD card 8GB
|
- microSD card 8GB
|
||||||
|
|
||||||
@@ -22,7 +27,7 @@ Operating system
|
|||||||
----------------
|
----------------
|
||||||
Install [Raspberry Pi Imager](https://www.raspberrypi.com/news/raspberry-pi-imager-imaging-utility/) into your notebook. Launch it and choose `Raspberry Pi OS Lite` to write into the microSD card
|
Install [Raspberry Pi Imager](https://www.raspberrypi.com/news/raspberry-pi-imager-imaging-utility/) into your notebook. Launch it and choose `Raspberry Pi OS Lite` to write into the microSD card
|
||||||
|
|
||||||
Power on the Raspberry pi and finish the installation process. Log into its console using either:
|
Power on the `Raspberry Pi` and finish the installation process. Log into its console using either:
|
||||||
- ethernet/wifi from your notebook: `ssh pi@raspberrypi`
|
- ethernet/wifi from your notebook: `ssh pi@raspberrypi`
|
||||||
- connected keyboard and monitor
|
- connected keyboard and monitor
|
||||||
- serial port
|
- serial port
|
||||||
@@ -33,7 +38,7 @@ Once you are logged into the `Raspberry pi` console update your system
|
|||||||
> `sudo apt update`
|
> `sudo apt update`
|
||||||
`sudo apt upgrade`
|
`sudo apt upgrade`
|
||||||
|
|
||||||
and install `git`. It will be used to download the `dog-trainer`
|
Install `git`. It will be used to download the `dog-trainer`
|
||||||
> `sudo apt install -y git`
|
> `sudo apt install -y git`
|
||||||
|
|
||||||
Recordings must be edited a little bit therefore some audio processing tool is needed. Install `ffmpeg` which will do the job
|
Recordings must be edited a little bit therefore some audio processing tool is needed. Install `ffmpeg` which will do the job
|
||||||
@@ -52,13 +57,17 @@ Go into the newly created directory
|
|||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
First try using default audio device for playback and recording. Edit `dog-trainer.py` and activate `PLAY_DEVICE="default"` and `REC_DEVICE="default"`
|
Check your Raspberry pi board pin layout and make sure your buttons GPIOs match `PINS = [17, 22, 27]` from `dog-trainer.py`
|
||||||
|
> `pinout`
|
||||||
|
|
||||||
|
Try using default audio device for playback and recording. Edit `dog-trainer.py` and activate `PLAY_DEVICE="default"` and `REC_DEVICE="default"`
|
||||||
> `nano dog-trainer.py`
|
> `nano dog-trainer.py`
|
||||||
|
|
||||||
Skip to the next section `Run it!`. If either playback or recording does not work check your sound cards
|
Skip to the next section `Run it!`. If either playback or recording does not work check your sound cards
|
||||||
> `aplay -L | grep ^hw:CARD=`
|
> `aplay -L | grep ^hw:CARD=`
|
||||||
|
`arecord -L | grep ^hw:CARD=`
|
||||||
|
|
||||||
If your sound device is other then `USB` then change the line `card USB` in ALSA config
|
Put your sound device name `"hw:Zero"` or `"hw:USB"` into the ALSA config file
|
||||||
> `nano .asoundrc`
|
> `nano .asoundrc`
|
||||||
|
|
||||||
Install the ALSA config file
|
Install the ALSA config file
|
||||||
@@ -82,14 +91,18 @@ If your username and group is other then `pi` and `pi` then also run
|
|||||||
> `sed -i "s#User=pi#User=$USER#" dog-trainer.service`
|
> `sed -i "s#User=pi#User=$USER#" dog-trainer.service`
|
||||||
`sed -i "s#Group=pi#Group=$(id -gn)#" dog-trainer.service`
|
`sed -i "s#Group=pi#Group=$(id -gn)#" dog-trainer.service`
|
||||||
|
|
||||||
Install the systemd service file
|
> `sed -i "s#User=pi#User=$USER#" sound-init.service`
|
||||||
> `sudo mv dog-trainer.service /etc/systemd/system/`
|
`sed -i "s#Group=pi#Group=$(id -gn)#" sound-init.service`
|
||||||
|
|
||||||
|
Install the systemd service files
|
||||||
|
> `sudo mv dog-trainer.service /etc/systemd/system/`
|
||||||
|
`sudo mv sound-init.service /etc/systemd/system/`
|
||||||
|
|
||||||
Reload systemd manager configuration
|
Reload systemd manager configuration
|
||||||
> `systemctl daemon-reload`
|
> `sudo systemctl daemon-reload`
|
||||||
|
|
||||||
Enable the `dog-trainer` service at boot time and also run it
|
Enable the `dog-trainer` service at boot time and also run it
|
||||||
> `systemctl enable --now dog-trainer`
|
> `sudo systemctl enable --now dog-trainer`
|
||||||
|
|
||||||
If it does not work check logs
|
If it does not work check logs
|
||||||
> `journalctl -f -u dog-trainer`
|
> `journalctl -f -u dog-trainer`
|
||||||
@@ -100,4 +113,7 @@ Set volume for playback and recording
|
|||||||
Launch soundcard mixer
|
Launch soundcard mixer
|
||||||
> `alsamixer`
|
> `alsamixer`
|
||||||
|
|
||||||
Press F6 to select a soundcard. Find your USB sound device in the list e.g. `Jabra Speak 410 USB`. Press F4 and use up/down arrow keys to set recording volume and repeat also for the playback (F3). Make sure it is not muted. Press (m) to toggle mute. Press ESC to exit.
|
Press F6 to select a soundcard. Find your USB sound device in the list e.g. `Jabra Speak 410 USB`. Press F4 and use up/down arrow keys to set recording volume and repeat also for the playback (F3). Make sure it is not muted. Press (m) to toggle mute. Press ESC to exit.
|
||||||
|
|
||||||
|
To preserve audio setting after the boot run
|
||||||
|
> `sudo alsactl store`
|
||||||
@@ -4,16 +4,13 @@ from datetime import datetime
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# PLAY_DEVICE = "default" # Playback/recording through the PulseAudio sound server
|
PLAY_DEVICE = "default" # as defined in '~/.asoundrc'
|
||||||
# REC_DEVICE = "default" # Playback/recording through the PulseAudio sound server
|
REC_DEVICE = "plughw:Zero" # as listed by 'arecord -L'
|
||||||
|
|
||||||
PLAY_DEVICE = "my_sound_device_with_converter" # as defined in '~/.asoundrc'
|
|
||||||
REC_DEVICE = "my_sound_device" # as defined in '~/.asoundrc'
|
|
||||||
|
|
||||||
MAX_RECORDING_TIME = 30 # limit recordings to only e.g. 30 seconds long
|
MAX_RECORDING_TIME = 30 # limit recordings to only e.g. 30 seconds long
|
||||||
TRIM_RECORDING_END = 0.8 # remove the clicking noise from the end of recordings
|
TRIM_RECORDING_END = 0.6 # remove the clicking noise from the end of recordings
|
||||||
RECORD_BUTTON_PRESS_TIME = 2 # pressing and holding a button longer then e.g. 2 seconds triggers recording otherwise playing
|
RECORD_BUTTON_PRESS_TIME = 2 # pressing and holding a button longer then e.g. 2 seconds triggers recording otherwise playing
|
||||||
PINS = [17, 23] # listen to changes on this GPIOs e.g. [4, 17, 23, 0, 5, 6]
|
PINS = [17, 22, 27] # listen to changes on this GPIOs e.g. [4, 17, 23, 0, 5, 6]
|
||||||
GPIO.setmode(GPIO.BCM) # use BCM pin layout
|
GPIO.setmode(GPIO.BCM) # use BCM pin layout
|
||||||
GPIO.setwarnings(False)
|
GPIO.setwarnings(False)
|
||||||
|
|
||||||
@@ -40,8 +37,7 @@ def terminate_recording(proc, pin):
|
|||||||
"-of",
|
"-of",
|
||||||
"default=noprint_wrappers=1:nokey=1",
|
"default=noprint_wrappers=1:nokey=1",
|
||||||
f"recording_temp_{pin}.wav",
|
f"recording_temp_{pin}.wav",
|
||||||
],
|
], check=True, stdout=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
).stdout.decode("utf-8")
|
).stdout.decode("utf-8")
|
||||||
subprocess.call(
|
subprocess.call(
|
||||||
[
|
[
|
||||||
@@ -66,7 +62,8 @@ def terminate_recording(proc, pin):
|
|||||||
|
|
||||||
|
|
||||||
def play(file):
|
def play(file):
|
||||||
subprocess.call(["aplay", "-D", PLAY_DEVICE, file])
|
print(f"Playing {file}")
|
||||||
|
subprocess.run(["aplay", f"-D{PLAY_DEVICE}", file], check=True)
|
||||||
|
|
||||||
|
|
||||||
def play_sound(pin):
|
def play_sound(pin):
|
||||||
@@ -86,20 +83,17 @@ def record_sound(pin):
|
|||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
[
|
[
|
||||||
"arecord",
|
"arecord",
|
||||||
"-D",
|
f"-D{REC_DEVICE}",
|
||||||
REC_DEVICE,
|
"-fS16_LE",
|
||||||
"-f",
|
"-r48000",
|
||||||
"S16_LE",
|
"-c2",
|
||||||
"-r",
|
f"-d{MAX_RECORDING_TIME}",
|
||||||
"16000",
|
|
||||||
"-c",
|
|
||||||
"1",
|
|
||||||
"-d",
|
|
||||||
f"{MAX_RECORDING_TIME}",
|
|
||||||
f"recording_temp_{pin}.wav",
|
f"recording_temp_{pin}.wav",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
print(f"Recording in progress (max {MAX_RECORDING_TIME} seconds)...")
|
print(f"Recording in progress (max {MAX_RECORDING_TIME} seconds)...")
|
||||||
|
time.sleep(0.5)
|
||||||
|
play_beep()
|
||||||
wait_for_button_release_or_timeout(pin, MAX_RECORDING_TIME)
|
wait_for_button_release_or_timeout(pin, MAX_RECORDING_TIME)
|
||||||
print("GPIO went HIGH - terminating recording")
|
print("GPIO went HIGH - terminating recording")
|
||||||
play_beep()
|
play_beep()
|
||||||
@@ -121,7 +115,6 @@ def handle_pin(pin):
|
|||||||
|
|
||||||
if time.time() - timeout_start >= RECORD_BUTTON_PRESS_TIME:
|
if time.time() - timeout_start >= RECORD_BUTTON_PRESS_TIME:
|
||||||
# Pin was LOW for longer time; recording
|
# Pin was LOW for longer time; recording
|
||||||
play_beep()
|
|
||||||
record_sound(pin)
|
record_sound(pin)
|
||||||
else:
|
else:
|
||||||
# Pin was LOW for shorter time; playing
|
# Pin was LOW for shorter time; playing
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Dog Trainer
|
Description=Dog Trainer
|
||||||
After=sound.target
|
After=sound-init.service
|
||||||
|
Requires=sound-init.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
|
|||||||
BIN
recording_17.wav
BIN
recording_17.wav
Binary file not shown.
BIN
recording_22.wav
Normal file
BIN
recording_22.wav
Normal file
Binary file not shown.
BIN
recording_23.wav
BIN
recording_23.wav
Binary file not shown.
BIN
recording_27.wav
Normal file
BIN
recording_27.wav
Normal file
Binary file not shown.
14
sound-init.service
Normal file
14
sound-init.service
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Sound Initialization Service
|
||||||
|
PartOf=dog-trainer.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=pi
|
||||||
|
Group=pi
|
||||||
|
ExecStart=/bin/sh -c 'cat /dev/zero | aplay -Ddefault -fS16_LE -c2 -r 48000'
|
||||||
|
Restart=always
|
||||||
|
RestartSec=3
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
Reference in New Issue
Block a user