Freier Toniebox Klon auf Raspberry Pi Basis

Freier Toniebox Klon auf Raspberry Pi Basis
Inhaltsverzeichnis

Dieser Artikel beschreibt den Aufbau eines Tonabspielgerät für Kleinkinder. Vorbild ist das kommerzielle Produkt Toniebox bei der kleine Figuren au ein würfelförmiges Abspielgerät gestellt werden und so die Musikwiedergabe, z.B. von Hörspielen, starten.

Update 2020-03

Features

  • Gleicher Formfaktor wie das kommerzielle Gerät
  • Tasten für Pause, Lauter und Leiser
  • Unterstützung von RFID-Karten statt Tonies zur Auswahl der Hörspielen
  • Automatischer Sync neuer Hörspiele per Webdav aus einer Nextcloud-Installation
  • Hotspot-Modus um neue WLAN-Zugangsdaten zu konfigurieren

Liste der Bauteile

Folgende Bauteile sind zum Einsatz gekommen:

Komponente Bezeichnung Preis
Systemplatine Raspberry Pi Zero [2] 13,58€
Soundkarte Externe soundkarte Virtual Audio USB Sound karte Adapter 7,1 Kanal Für Laptop PC [1] 1,00€
USB-Hub Mini Micro USB To 4 Port USB OTG Hub For Raspberry Zero ODROID White 2017 [1] 1,50€
Verstärker 2/4stk PAM8403 Digital Audio Verstärker Lautsprecher Verstärkerplatine 2.5-5V [1] 1,00€
Taster 6 Stücke Lange Länge Arcade Spiel HAPP Stil Push Button für Mame und Jamma ED [1] 2,55€
Knöpfe 6x arcade Knöpfe happ druckknopf für jamma mame spiel Neu [1] 3,59€
Gehäuse Eigenbau aus Sperrholz 6,69€
Stromanschluss 30cm/50cm Micro USB 2.0 Male to Female Hole Panel Mount Extension Cable Kits Neu [1] 1,09€
Lautsprecher 3W 4 Ohm Metallgehaeuse Runder Magnet Lautsprecher Lautsprecher 2 Stueck M3G5 [1] 1,40€
RFID-Leser 125Khz EM4100 USB RFID ID Card Reader Swipe Card Reader Plug and Play With Cable [1] 3,32€
RFID-Karten 50 Stueck Intelligente Naehe EM4100 125kHz RFID Proximity Karte Eintrag Lee Q4F7 [1] 8,63€
Stabilisierungskondensator RAD LXZ 16/3K3 [3] 0,65€
45,00€

Bezugsquellen: [1]ebay, [2]pimoroni, [3]reichelt

Bilder

Basissystem

Es kommt Void Linux zum Einsatz. Void nutzt Runit als Init-System und startet damit besonders schnell. Zum Starten von Diensten wird die Syntax sv start dienst verwendet.

Schritte zur Installation

bash
loadkeys de
cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOL
ctrl_interface=/run/wpa_supplicant
ctrl_interface_group=wheel
eapol_version=1
ap_scan=1
fast_reauth=1
update_config=1
EOL

# replace SSID and PWD with WLAN credentials
# escape characters like '!' with an '\', e.g. password! is password\!
wpa_passphrase $SSID $PWD >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
ln -s /etc/sv/dhcpcd /var/service
ln -s /etc/sv/sshd /var/service
ntpd
xbps-install -Su python3 python3-devel python3-pip vlc linux-headers gcc alsa-utils samba hostapd dnsmasq davfs2 rsync alsa-lib-devel
#optional
xbps-install alsa-utils
pip install python-vlc evdev RPi.GPIO pyalsaaudio
echo "majobox" > /etc/hostname

mkdir -p /etc/sv/majobox-control
cat > /etc/sv/majobox-control/run <<EOL
#!/bin/sh
exec python /srv/control/control.py
EOL
chmod +x  /etc/sv/majobox-control/run

mkdir -p /etc/sv/majobox-sync
cat > /etc/sv/majobox-syn/run <<EOL
#!/bin/sh
exec bash /srv/control/sync.sh
EOL
chmod +x /etc/sv/majobox-sync/run

ln -s /etc/sv/majobox-sync /var/service
ln -s /etc/sv/majobox-control /var/service

# rename "rw" to "ro"
vi /boot/cmdline.txt

# add "defaults,ro" for / and /boot partitions
vi /etc/fstab

# comment rw-remount
vi /etc/runit/core-services/03-filesystems.sh

ln -s /run/runit/supervise.majobox-control /etc/sv/majobox-control/supervise
ln -s /run/runit/supervise.majobox-sync /etc/sv/majobox-sync/supervise
rm /etc/resolv.conf && ln -s /tmp/resolv.conf /etc/resolv.conf
ln -s /srv/control/change-wifi.sh /root/change-wifi.sh

# create third parition with defaults
fdisk /dev/mmcblk0 // -> create partition primary alle default werte, dann w, dann q
partx -u /dev/mmcblk0
mkfs.ext4 /dev/mmcblk0p3
tune2fs -m 0 /dev/mmcblk0p3
mkdir /srv
mkdir /srv/control /srv/music
mkdir /var/samba
useradd -M user
chown -R user.user /srv
cat >> /etc/fstab <<EOL
/dev/mmcblk0p3 /srv ext4 defaults,ro 0 1
tmpfs /var/log tmpfs defaults 0 0
tmpfs /var/samba tmpfs defaults 0 0
EOL

Skripte


#!/usr/bin/python
#
# Run this before first startup:
# - pip install evdev python-vlc RPi.GPIO
#

import vlc
import time
import string
import os
from evdev import InputDevice
from select import select
import glob
import RPi.GPIO as GPIO
import alsaaudio

mixer = alsaaudio.Mixer(control='Speaker')
Instance = vlc.Instance('--aout alsa')
list_player = Instance.media_list_player_new()
player = vlc.MediaPlayer("/srv/control/startup.mp3")
player.audio_output_device_set("alsa", "hw0:0")

player.play()

keys = "X^1234567890XXXXqwertzuiopXXXXasdfghjklXXXXXyxcvbnmXXXXXXXXXXXXXXXXXXXXXXX"
dev = InputDevice('/dev/input/event1')

GPIO.setmode(GPIO.BOARD)
pin_stop = 40
pin_vol_down = 32
pin_vol_up = 36
volume = 15
mixer.setvolume(volume)
pins = [ pin_stop, pin_vol_down, pin_vol_up ]
GPIO.setup(pins, GPIO.IN, pull_up_down=GPIO.PUD_UP)
for pin in pins:
	GPIO.add_event_detect(pin, GPIO.FALLING, bouncetime=1000)

id = ""
while True:
	r,w,x = select([dev], [], [], 0.2)
	if r:
		for event in dev.read():
			if event.type==1 and event.value==1:
				print( keys[ event.code ] )
				if keys[event.code] == 'X':
					print("Recognized card with id " + id)
					if id == "0016188996":
						player = vlc.MediaPlayer("/srv/control/hotspot.mp3")
						player.play()
						time.sleep(5)
						os.system("bash /srv/control/hotspot.sh")
					else:
						files = glob.glob("/srv/music/*"+id+"*")
						player.stop()
						list_player.stop()
						if len(files) == 0:
							player = vlc.MediaPlayer("/srv/control/error.mp3")
							player.play()
						else:
							Media_list = Instance.media_list_new([files[0]])
							list_player.set_media_list(Media_list)
							list_player.play()
					id = ""
				else:
					id += keys[event.code]

	count = 1;
	if GPIO.event_detected(pin_stop):
		print("Pause\n")
		count+= 1
		list_player.pause()
	if GPIO.event_detected(pin_vol_up):
		volume += 4
		if volume > 31:
			volume = 31
		count+= 1
		print("Up " + str(volume) + "\n")
		mixer.setvolume(volume)
	if GPIO.event_detected(pin_vol_down):
		volume -= 4
		if volume < 3:
			volume = 3
		count+= 1
		print("Down " + str(volume) + "\n")
		mixer.setvolume(volume)


# https://sourceforge.net/p/raspberry-gpio-python/wiki/Inputs/
#!/bin/bash

sleep 30

while [ /bin/true ]; do
ntpd -s
mount -o remount,rw /srv
mkdir -p /tmp/dav
mount -t tmpfs none /var/cache/davfs2
sleep 5
mount -t davfs https://nextcloudserver/remote.php/webdav /tmp/dav
rsync -avu --delete /tmp/dav/* /srv
umount /tmp/dav
umount /var/cache/davfs2
mount -o remount,ro /srv
sleep 3600

done
#!/bin/bash

echo "WLAN SSID eingeben:"
read SSID
echo "Passwort eingeben:"
read PWD

mount -o remount,rw /

cat >/etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOL
ctrl_interface=/run/wpa_supplicant
ctrl_interface_group=wheel
eapol_version=1
ap_scan=1
fast_reauth=1
update_config=1
EOL

wpa_passphrase $SSID $PWD >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
echo "Starte neu. Die Konsole kann geschlossen werden."
reboot
#!/bin/bash

mount -o remount,rw /srv
mount -o remount,rw /
mkdir -p /var/lib/misc
iw dev wlan0 interface add uap0 type __ap
ip link set dev uap0 up
ip addr add 192.168.50.1/24 dev uap0
dnsmasq -k --enable-dbus -u dnsmasq -g dnsmasq &
hostapd /srv/control/hotspot.conf &
interface=uap0
ssid=majobox
#hw_mode=g
channel=1
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=xxx
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP