36 KiB
Raspberry Pi Zero 2W mit Seed Studio ReSpeaker v1.2 - Komplette Anleitung
Offline-Sprachsteuerung mit Soundausgabe
Status: Vollständige Standalone-Konfiguration mit systemctl-Services Zielgruppe: Anfänger bis Fortgeschrittene Geschrieben: Januar 2025
TEIL 1: HARDWARE-VORBEREITUNG UND OS-INSTALLATION
1.1 Hardware-Anforderungen
Du benötigst folgende Komponenten:
- Raspberry Pi Zero 2W (nicht Zero oder Zero W!)
- Seed Studio ReSpeaker Pi Hat v1.2 mit 2 Mikrofonen
- microSD-Karte: mindestens 16GB (Class 10 empfohlen)
- USB-Stromversorgung: 2A Netzteil mit Micro-USB
- SD-Kartenleser zum Flashen auf deinem PC
- Computer mit Internetverbindung
- Optional: HDMI-Monitor, USB-Tastatur/Maus zur Direktverbindung
1.2 Raspberry Pi OS Installation
Schritt 1: Raspberry Pi Imager herunterladen
- Öffne https://www.raspberrypi.com/software/
- Lade Raspberry Pi Imager für dein Betriebssystem herunter
- Installiere die Anwendung
Schritt 2: SD-Karte flashen
- Stecke die microSD-Karte in deinen Kartenleser und verbinde ihn mit dem PC
- Öffne Raspberry Pi Imager
- Klicke auf "Gerät auswählen" und wähle "Raspberry Pi Zero 2"
- Klicke auf "Betriebssystem auswählen" und wähle:
- Raspberry Pi OS (Legacy, 32-Bit) - Bullseye
- Hinweis: v1.2 des ReSpeaker-Hats ist am besten mit Bullseye kompatibel
- Klicke auf "Speicher auswählen" und wähle deine microSD-Karte
- Klicke auf das Zahnrad-Symbol (Erweiterte Optionen) und konfiguriere:
- Hostname:
respeaker-pi(oder ein beliebiger Name) - SSH aktivieren: Ja (mit Passwort)
- Benutzername:
pi - Passwort: Ein sicheres Passwort deiner Wahl (aufschreiben!)
- WLAN konfigurieren:
- SSID: Dein WiFi-Netzwerk
- Passwort: Dein WiFi-Passwort
- Land:
DE(Deutschland)
- Zeitzone:
Europe/Berlin
- Hostname:
- Klicke "Speichern" und dann "Schreiben"
- Warte bis zum Abschluss (5-10 Minuten)
- Entnehme die SD-Karte
Schritt 3: Erster Start
- Stecke die SD-Karte in den Pi Zero 2W ein
- Verbinde den ReSpeaker Hat mit dem Pi:
- Ausrichten der GPIO-Pins (40-polige Reihe)
- ReSpeaker sollte fest aufgesetzt sein
- Verbinde die USB-Stromversorgung
- Warte 1-2 Minuten für den ersten Start
Schritt 4: IP-Adresse ermitteln
Methode A (über Router):
- Öffne die Verwaltungsoberfläche deines WLAN-Routers
- Suche nach verbundenen Geräten
- Notiere die IP-Adresse von
respeaker-pi
Methode B (mit arp-scan auf Linux/Mac):
sudo arp-scan -l | grep -i "raspberry\|b8:27"
Methode C (mit Advanced IP Scanner auf Windows):
- Lade Advanced IP Scanner herunter
- Scanne dein Netzwerk
- Suche nach
respeaker-pi
Beispiel-IP: 192.168.1.100
TEIL 2: RASPBERRY PI KONFIGURATION
2.1 SSH-Verbindung herstellen
Auf Linux/Mac (Terminal):
ssh pi@192.168.1.100
# Gib dein Passwort ein
Auf Windows: Nutze PuTTY
- Lade PuTTY herunter
- Öffne PuTTY
- Host:
192.168.1.100 - Port:
22 - Klicke "Open"
- Login:
pi - Passwort: (dein gesetztes Passwort)
2.2 System aktualisieren
sudo apt update
sudo apt upgrade -y
sudo apt install -y git python3-pip python3-dev libatlas-base-dev
Dieser Prozess dauert 10-15 Minuten. Warte ab.
2.3 Audio- und I2C-Konfiguration
sudo raspi-config
Navigiere zu:
- Schnittstellen → I2C → Aktivieren
- Schnittstellen → SPI → Aktivieren
- Lokalisierungsoptionen → Zeitzone → Europa → Berlin
- Lokalisierungsoptionen → Sprache → de_DE.UTF-8
- Bestätige alle Änderungen und Starten Sie neu.
Nach dem Reboot erneut verbinden:
ssh pi@192.168.1.100
TEIL 3: RESPEAKER HAT INSTALLATION
3.1 seeed-voicecard Treiber installieren
Der ReSpeaker benötigt die speziellen Seeed-Treiber:
cd ~
git clone https://github.com/HinTak/seeed-voicecard.git
cd seeed-voicecard
sudo ./install.sh
Dies dauert 5-10 Minuten. Wenn es fertig ist:
sudo reboot now
Nach dem Reboot wieder verbinden:
ssh pi@192.168.1.100
3.2 ReSpeaker-Installation verifizieren
Überprüfe, ob die Sound-Karte erkannt wurde:
aplay -l
Du solltest folgende Ausgabe sehen:
**** PLAYBACK hardware devices ****
card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
card 1: seeed2miccard [seeed-2mic-voicecard], device 0: ...
Überprüfe auch die Aufnahmegeräte:
arecord -l
Du solltest auch hier seeed-2mic-voicecard sehen.
3.3 Ton-Tests
Lautsprecher testen:
speaker-test -l 1 -c 2 -t sine -f 1000 -r 48000
Du solltest einen Ton hören (drücke Ctrl+C zum Beenden).
Mikrofon testen:
arecord -D hw:1,0 -f S16_LE -c 2 -r 48000 test_recording.wav
Sprich kurz ins Mikrofon und stoppe mit Ctrl+C. Dann abspielen:
aplay -D hw:1,0 test_recording.wav
TEIL 4: PYTHON-UMGEBUNG EINRICHTEN
4.1 Notwendige Python-Pakete installieren
# Audio-Verarbeitung
sudo apt install -y portaudio19-dev libatlas-base-dev
pip3 install pyaudio
# Spracherkennung
pip3 install SpeechRecognition
pip3 install pydub
# Offline-Spracherkennung mit Vosk
pip3 install vosk
# Sprachmodell für Deutsch (kleines Modell, ~50MB)
mkdir -p ~/voice_models
cd ~/voice_models
wget https://alphacephei.com/vosk/models/vosk-model-de-0.21.zip
unzip vosk-model-de-0.21.zip
rm vosk-model-de-0.21.zip
4.2 Ordnerstruktur erstellen
mkdir -p ~/voice_assistant
mkdir -p ~/voice_assistant/sounds
mkdir -p ~/voice_assistant/logs
mkdir -p ~/voice_assistant/config
cd ~/voice_assistant
TEIL 5: PYTHON-SKRIPTE ERSTELLEN
5.1 Haupt-Spracherkennungs-Skript
Erstelle die Datei ~/voice_assistant/speech_recognizer.py:
nano ~/voice_assistant/speech_recognizer.py
Kopiere folgenden Code ein:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Offline-Spracherkennungssystem für Raspberry Pi Zero 2W mit ReSpeaker Hat v1.2
Funktioniert vollständig offline mit lokalem Vosk-Modell
"""
import json
import os
import sys
import logging
import queue
import sounddevice as sd
import vosk
import subprocess
import time
from pathlib import Path
# ============================================================================
# KONFIGURATION
# ============================================================================
class Config:
# Pfade
BASE_DIR = Path(__file__).parent
MODEL_PATH = Path.home() / "voice_models" / "vosk-model-de-0.21"
SOUNDS_DIR = BASE_DIR / "sounds"
LOGS_DIR = BASE_DIR / "logs"
# Audio-Einstellungen
SAMPLERATE = 16000
BLOCKSIZE = 4096
DEVICE_INDEX = None # Wird automatisch erkannt
# Spracherkennung
ACTIVATION_WORD = "computer" # Aktivierungswort
CONFIDENCE_THRESHOLD = 0.5
LISTENING_TIMEOUT = 10 # Sekunden zum Abhören nach Aktivierungswort
# Logging
LOG_FILE = LOGS_DIR / "voice_assistant.log"
LOG_LEVEL = logging.INFO
# Kommandos und Aktionen
COMMANDS = {
"hello": {"sound": "hello.wav", "action": "greet"},
"musik": {"sound": "music.wav", "action": "play_music"},
"stopp": {"sound": "stopped.wav", "action": "stop"},
"zeit": {"sound": "time.wav", "action": "tell_time"},
"helligkeit": {"sound": "brightness.wav", "action": "adjust_brightness"},
}
# ============================================================================
# LOGGING-SETUP
# ============================================================================
def setup_logging():
"""Konfiguriere Logging in Datei und Console"""
Config.LOGS_DIR.mkdir(exist_ok=True)
logger = logging.getLogger("VoiceAssistant")
logger.setLevel(Config.LOG_LEVEL)
# File Handler
fh = logging.FileHandler(Config.LOG_FILE)
fh.setLevel(Config.LOG_LEVEL)
# Console Handler
ch = logging.StreamHandler()
ch.setLevel(Config.LOG_LEVEL)
# Formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(ch)
return logger
logger = setup_logging()
# ============================================================================
# AUDIO-GERÄTE MANAGEMENT
# ============================================================================
def find_respeaker_device():
"""
Suche nach ReSpeaker-Audiogerät und gebe seinen Index zurück
"""
logger.info("Suche nach ReSpeaker-Gerät...")
try:
for index, name in enumerate(sd.query_devices()):
if isinstance(name, dict):
device_name = name.get('name', '')
else:
device_name = str(name)
if 'seeed' in device_name.lower():
logger.info(f"ReSpeaker gefunden: Index {index}, Name: {device_name}")
return index
except Exception as e:
logger.error(f"Fehler bei der Gerätesuche: {e}")
logger.warning("ReSpeaker nicht gefunden, nutze Standard-Eingang")
return None
def list_audio_devices():
"""Zeige alle verfügbaren Audio-Geräte an"""
logger.info("Verfügbare Audio-Geräte:")
for index, name in enumerate(sd.query_devices()):
if isinstance(name, dict):
device_name = name.get('name', 'Unknown')
else:
device_name = str(name)
logger.info(f" {index}: {device_name}")
# ============================================================================
# SPRACHERKENNUNG
# ============================================================================
class SpeechRecognizer:
"""
Offline-Spracherkennung mit Vosk
"""
def __init__(self):
"""Initialisiere Spracherkenner"""
logger.info("Initialisiere Spracherkenner...")
# Überprüfe ob Modell existiert
if not Config.MODEL_PATH.exists():
logger.error(f"Modell nicht gefunden: {Config.MODEL_PATH}")
logger.error("Bitte installiere das Vosk-Modell (siehe Dokumentation)")
raise FileNotFoundError(f"Vosk-Modell nicht gefunden: {Config.MODEL_PATH}")
# Lade Modell
try:
self.model = vosk.Model(str(Config.MODEL_PATH))
logger.info(f"Vosk-Modell geladen: {Config.MODEL_PATH}")
except Exception as e:
logger.error(f"Fehler beim Laden des Modells: {e}")
raise
# Suche ReSpeaker-Gerät
Config.DEVICE_INDEX = find_respeaker_device()
if Config.DEVICE_INDEX is None:
list_audio_devices()
# Erstelle Audio-Queue
self.q = queue.Queue()
self.recognizer = None
self.stream = None
self.is_listening = False
def audio_callback(self, indata, frames, time, status):
"""Callback für Audio-Stream"""
if status:
logger.warning(f"Audio-Status: {status}")
self.q.put(bytes(indata))
def start_listening(self):
"""Starte Audio-Stream"""
logger.info("Starte Audio-Listening...")
try:
self.stream = sd.RawInputStream(
samplerate=Config.SAMPLERATE,
blocksize=Config.BLOCKSIZE,
channels=1,
dtype='int16',
device=Config.DEVICE_INDEX,
callback=self.audio_callback
)
self.stream.start()
self.recognizer = vosk.KaldiRecognizer(self.model, Config.SAMPLERATE)
self.is_listening = True
logger.info("Audio-Listening aktiv")
except Exception as e:
logger.error(f"Fehler beim Starten des Audio-Streams: {e}")
raise
def stop_listening(self):
"""Stoppe Audio-Stream"""
logger.info("Stoppe Audio-Listening...")
if self.stream:
self.stream.stop()
self.stream.close()
self.is_listening = False
def wait_for_activation(self, timeout=None):
"""
Warte auf das Aktivierungswort
Rückgabe: True wenn erkannt, False bei Timeout
"""
logger.info(f"Warte auf Aktivierungswort: '{Config.ACTIVATION_WORD}'")
start_time = time.time()
while True:
if timeout and (time.time() - start_time) > timeout:
logger.info("Aktivierungs-Timeout erreicht")
return False
try:
data = self.q.get(timeout=1)
except queue.Empty:
continue
if self.recognizer.AcceptWaveform(data):
result = json.loads(self.recognizer.Result())
recognized_text = result.get('result', [])
if recognized_text:
text = ' '.join(recognized_text)
logger.info(f"Erkannt (Aktivierung): {text}")
if Config.ACTIVATION_WORD in text.lower():
logger.info("Aktivierungswort erkannt!")
return True
def listen_for_command(self, timeout=Config.LISTENING_TIMEOUT):
"""
Höre auf ein Kommando nach Aktivierung
Rückgabe: erkannter Text oder None
"""
logger.info(f"Höre auf Kommando ({timeout}s)...")
self.recognizer = vosk.KaldiRecognizer(self.model, Config.SAMPLERATE)
start_time = time.time()
while True:
if (time.time() - start_time) > timeout:
logger.info("Kommando-Timeout")
return None
try:
data = self.q.get(timeout=1)
except queue.Empty:
continue
if self.recognizer.AcceptWaveform(data):
result = json.loads(self.recognizer.Result())
recognized_text = result.get('result', [])
if recognized_text:
text = ' '.join(recognized_text)
logger.info(f"Kommando erkannt: {text}")
return text
else:
# Partial result
try:
partial = json.loads(self.recognizer.PartialResult())
partial_text = partial.get('partial', '')
if partial_text:
logger.debug(f"Teilweise: {partial_text}")
except:
pass
# ============================================================================
# SOUND-AUSFÜHRUNG
# ============================================================================
class SoundPlayer:
"""Verwalte Soundausgabe"""
def __init__(self):
self.sounds_dir = Config.SOUNDS_DIR
self.sounds_dir.mkdir(exist_ok=True)
def play_sound(self, filename):
"""Spiele Sounddatei ab"""
sound_path = self.sounds_dir / filename
if not sound_path.exists():
logger.warning(f"Sound nicht gefunden: {sound_path}")
return False
try:
logger.info(f"Spiele Sound ab: {filename}")
# Nutze aplay zur Ausgabe auf ReSpeaker-Lautsprecher
subprocess.run(
['aplay', '-D', 'hw:1,0', str(sound_path)],
check=True,
capture_output=True
)
logger.info(f"Sound abgespielt: {filename}")
return True
except subprocess.CalledProcessError as e:
logger.error(f"Fehler beim Abspielen von {filename}: {e}")
return False
except FileNotFoundError:
logger.error("aplay nicht gefunden - installiere alsa-utils")
return False
def play_beep(self, frequency=440, duration=0.5):
"""Spiele einfachen Beep ab"""
try:
logger.info(f"Spiele Beep ab ({frequency}Hz, {duration}s)")
# Generiere Beep mittels sox
os.system(f'play -n synth {duration} sine {frequency} 2>/dev/null')
except Exception as e:
logger.error(f"Fehler beim Beep: {e}")
# ============================================================================
# AKTION-HANDLER
# ============================================================================
class ActionHandler:
"""Behandle erkannte Kommandos und führe Aktionen aus"""
def __init__(self, sound_player):
self.sound_player = sound_player
def handle_command(self, recognized_text):
"""
Verarbeite erkannten Text und führe entsprechende Aktion aus
"""
if not recognized_text:
logger.warning("Leerer Text erhalten")
return False
text_lower = recognized_text.lower().strip()
logger.info(f"Verarbeite Kommando: {text_lower}")
# Suche nach passendem Kommando
for command, config in Config.COMMANDS.items():
if command in text_lower:
logger.info(f"Kommando erkannt: {command}")
# Spiele Sound ab
if 'sound' in config:
self.sound_player.play_sound(config['sound'])
# Führe Aktion aus
action = config.get('action')
if action:
self.execute_action(action)
return True
logger.info(f"Kommando nicht in Liste: {text_lower}")
return False
def execute_action(self, action):
"""Führe spezifische Aktion aus"""
logger.info(f"Führe Aktion aus: {action}")
if action == "greet":
logger.info("Aktion: Grüßen")
elif action == "play_music":
logger.info("Aktion: Musik abspielen")
elif action == "stop":
logger.info("Aktion: Stoppen")
elif action == "tell_time":
import datetime
now = datetime.datetime.now().strftime("%H:%M")
logger.info(f"Aktuelle Zeit: {now}")
elif action == "adjust_brightness":
logger.info("Aktion: Helligkeit anpassen")
# ============================================================================
# HAUPT-PROGRAMM
# ============================================================================
class VoiceAssistant:
"""Haupt-Sprachassistent"""
def __init__(self):
logger.info("=" * 80)
logger.info("Starte Voice Assistant für Raspberry Pi Zero 2W")
logger.info("=" * 80)
try:
self.recognizer = SpeechRecognizer()
self.sound_player = SoundPlayer()
self.action_handler = ActionHandler(self.sound_player)
self.running = False
except Exception as e:
logger.error(f"Fehler bei der Initialisierung: {e}")
raise
def run(self):
"""Starte Haupt-Schleife"""
logger.info("Starte Haupt-Schleife...")
self.running = True
try:
self.recognizer.start_listening()
while self.running:
try:
# Warte auf Aktivierungswort
if self.recognizer.wait_for_activation(timeout=120):
# Spiele Bestätigungs-Beep
self.sound_player.play_beep(frequency=1000, duration=0.2)
# Höre auf Kommando
command = self.recognizer.listen_for_command()
if command:
# Verarbeite Kommando
self.action_handler.handle_command(command)
else:
logger.info("Kein Kommando erkannt")
except KeyboardInterrupt:
logger.info("Unterbrochen durch Benutzer")
break
except Exception as e:
logger.error(f"Fehler in Haupt-Schleife: {e}")
time.sleep(1)
finally:
self.recognizer.stop_listening()
logger.info("Voice Assistant beendet")
def stop(self):
"""Beende Programm"""
logger.info("Stoppe Voice Assistant...")
self.running = False
# ============================================================================
# EINSTIEGSPUNKT
# ============================================================================
if __name__ == "__main__":
try:
assistant = VoiceAssistant()
assistant.run()
except KeyboardInterrupt:
logger.info("Programm beendet")
sys.exit(0)
except Exception as e:
logger.error(f"Kritischer Fehler: {e}", exc_info=True)
sys.exit(1)
Speichere die Datei (Ctrl+X, dann Y, dann Enter).
Mache das Skript ausführbar:
chmod +x ~/voice_assistant/speech_recognizer.py
5.2 Test-Sounddateien erstellen
Erstelle einfache Test-Sounds:
# Test-Sound 1: Hello
python3 << 'EOF'
import wave
import math
def generate_tone(frequency, duration, sample_rate=16000):
"""Generiere einfachen Ton"""
samples = []
for i in range(int(sample_rate * duration)):
sample = int(32767 * 0.3 * math.sin(2 * math.pi * frequency * i / sample_rate))
samples.append(sample)
return samples
# Erzeuge Ton-Sequenz für "hello"
sounds = []
sounds += generate_tone(440, 0.1) # A4
sounds += generate_tone(494, 0.1) # B4
sounds += generate_tone(523, 0.2) # C5
# Speichere als WAV
with wave.open('/home/pi/voice_assistant/sounds/hello.wav', 'wb') as f:
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(16000)
f.writeframes(b''.join(s.to_bytes(2, byteorder='little', signed=True) for s in sounds))
print("hello.wav erstellt")
EOF
# Test-Sound 2: Music start
python3 << 'EOF'
import wave
import math
def generate_tone(frequency, duration, sample_rate=16000):
samples = []
for i in range(int(sample_rate * duration)):
sample = int(32767 * 0.3 * math.sin(2 * math.pi * frequency * i / sample_rate))
samples.append(sample)
return samples
sounds = []
sounds += generate_tone(523, 0.1) # C5
sounds += generate_tone(587, 0.1) # D5
sounds += generate_tone(659, 0.2) # E5
with wave.open('/home/pi/voice_assistant/sounds/music.wav', 'wb') as f:
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(16000)
f.writeframes(b''.join(s.to_bytes(2, byteorder='little', signed=True) for s in sounds))
print("music.wav erstellt")
EOF
# Weitere Sounds analog...
for sound in stopped time brightness; do
python3 << EOF
import wave
import math
def generate_tone(frequency, duration, sample_rate=16000):
samples = []
for i in range(int(sample_rate * duration)):
sample = int(32767 * 0.3 * math.sin(2 * math.pi * frequency * i / sample_rate))
samples.append(sample)
return samples
sounds = generate_tone(440, 0.3)
with wave.open('/home/pi/voice_assistant/sounds/${sound}.wav', 'wb') as f:
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(16000)
f.writeframes(b''.join(s.to_bytes(2, byteorder='little', signed=True) for s in sounds))
print("${sound}.wav erstellt")
EOF
done
# Verifiziere Dateien
ls -la ~/voice_assistant/sounds/
5.3 Teste das Skript manuell
cd ~/voice_assistant
python3 speech_recognizer.py
Du solltest folgende Ausgabe sehen:
2025-01-18 15:30:45 - VoiceAssistant - INFO - ================================================================================
2025-01-18 15:30:45 - VoiceAssistant - INFO - Starte Voice Assistant für Raspberry Pi Zero 2W
2025-01-18 15:30:45 - VoiceAssistant - INFO - ================================================================================
2025-01-18 15:30:46 - VoiceAssistant - INFO - Initialisiere Spracherkenner...
2025-01-18 15:30:46 - VoiceAssistant - INFO - Vosk-Modell geladen: /home/pi/voice_models/vosk-model-de-0.21
2025-01-18 15:30:46 - VoiceAssistant - INFO - Suche nach ReSpeaker-Gerät...
2025-01-18 15:30:46 - VoiceAssistant - INFO - ReSpeaker gefunden: Index 1, Name: seeed-2mic-voicecard
2025-01-18 15:30:46 - VoiceAssistant - INFO - Starte Audio-Listening...
2025-01-18 15:30:46 - VoiceAssistant - INFO - Audio-Listening aktiv
2025-01-18 15:30:46 - VoiceAssistant - INFO - Haupt-Schleife gestartet
2025-01-18 15:30:46 - VoiceAssistant - INFO - Warte auf Aktivierungswort: 'computer'
Teste jetzt:
- Sprich: "Computer"
- Nach dem Beep sprich: "Musik"
- Der Pi sollte
music.wavabspielen
Beende mit Ctrl+C.
TEIL 6: SYSTEMCTL SERVICE ERSTELLEN
6.1 Service-Datei erstellen
Erstelle eine systemctl-Service-Datei, damit der Voice Assistant beim Booten automatisch startet:
sudo nano /etc/systemd/system/voice-assistant.service
Füge folgenden Inhalt ein:
[Unit]
Description=Voice Assistant Service for ReSpeaker
After=network.target sound.target
Wants=network-online.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/voice_assistant
Environment="PATH=/usr/local/bin:/usr/bin:/bin:/home/pi/.local/bin"
ExecStart=/usr/bin/python3 /home/pi/voice_assistant/speech_recognizer.py
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
# Ressourcen-Limits für Pi Zero
MemoryMax=256M
CPUQuota=50%
[Install]
WantedBy=multi-user.target
Speichere die Datei (Ctrl+X, Y, Enter).
6.2 Service aktivieren und starten
# Lade systemd-Daemon neu
sudo systemctl daemon-reload
# Aktiviere Service für Auto-Start
sudo systemctl enable voice-assistant.service
# Starte Service jetzt
sudo systemctl start voice-assistant.service
# Überprüfe Status
sudo systemctl status voice-assistant.service
6.3 Service-Logs anzeigen
# Zeige aktuelle Logs
sudo journalctl -u voice-assistant.service -f
# Zeige letzte 50 Zeilen
sudo journalctl -u voice-assistant.service -n 50
# Zeige Logs mit Zeitstempel
sudo journalctl -u voice-assistant.service --since "1 hour ago" -a
6.4 Service steuern
# Starte Service
sudo systemctl start voice-assistant.service
# Stoppe Service
sudo systemctl stop voice-assistant.service
# Starte Service neu
sudo systemctl restart voice-assistant.service
# Deaktiviere Auto-Start
sudo systemctl disable voice-assistant.service
TEIL 7: MONITORING UND LOGGING
7.1 Log-Rotation einrichten
Erstelle Logrotate-Konfiguration um Log-Dateien zu verwalten:
sudo nano /etc/logrotate.d/voice-assistant
Füge ein:
/home/pi/voice_assistant/logs/*.log {
daily
rotate 7
compress
delaycompress
notifempty
create 0640 pi pi
sharedscripts
}
7.2 Monitor-Skript erstellen
Erstelle ~/voice_assistant/monitor.py zur Überwachung:
nano ~/voice_assistant/monitor.py
#!/usr/bin/env python3
"""
Monitor-Skript zur Überwachung des Voice Assistant Services
"""
import subprocess
import sys
import time
from datetime import datetime
def check_service_status():
"""Überprüfe Service-Status"""
try:
result = subprocess.run(
['systemctl', 'status', 'voice-assistant.service'],
capture_output=True,
text=True
)
return result.returncode == 0
except:
return False
def get_recent_logs(lines=10):
"""Hole letzte Log-Einträge"""
try:
result = subprocess.run(
['sudo', 'journalctl', '-u', 'voice-assistant.service', '-n', str(lines), '-a'],
capture_output=True,
text=True
)
return result.stdout
except:
return "Logs nicht verfügbar"
def restart_service():
"""Starte Service neu"""
try:
subprocess.run(['sudo', 'systemctl', 'restart', 'voice-assistant.service'], check=True)
return True
except:
return False
def main():
"""Hauptüberwachung"""
print("Voice Assistant Monitor")
print("=" * 60)
while True:
try:
is_running = check_service_status()
status = "✓ LÄUFT" if is_running else "✗ GESTOPPT"
print(f"[{datetime.now().strftime('%H:%M:%S')}] Status: {status}")
if not is_running:
print("Service nicht aktiv, starte neu...")
if restart_service():
print("Service neu gestartet")
time.sleep(5)
# Zeige letzte Logs
print("\nLetzte Log-Einträge:")
print("-" * 60)
logs = get_recent_logs(5)
print(logs)
print("-" * 60)
time.sleep(30) # Überprüfe alle 30 Sekunden
except KeyboardInterrupt:
print("\nMonitor beendet")
sys.exit(0)
except Exception as e:
print(f"Fehler: {e}")
time.sleep(5)
if __name__ == "__main__":
main()
Speichere und starte:
chmod +x ~/voice_assistant/monitor.py
python3 ~/voice_assistant/monitor.py
TEIL 8: ADVANCED - EIGENE KOMMANDOS HINZUFÜGEN
8.1 Neue Kommandos definieren
Bearbeite die COMMANDS Sektion in speech_recognizer.py:
COMMANDS = {
"hello": {"sound": "hello.wav", "action": "greet"},
"musik": {"sound": "music.wav", "action": "play_music"},
"stopp": {"sound": "stopped.wav", "action": "stop"},
"zeit": {"sound": "time.wav", "action": "tell_time"},
"helligkeit": {"sound": "brightness.wav", "action": "adjust_brightness"},
# NEU: Eigene Kommandos hinzufügen
"licht": {"sound": "light.wav", "action": "toggle_light"},
"temperatur": {"sound": "temp.wav", "action": "read_temp"},
}
8.2 Eigene Aktionen implementieren
Bearbeite die execute_action() Methode in der ActionHandler Klasse:
def execute_action(self, action):
"""Führe spezifische Aktion aus"""
logger.info(f"Führe Aktion aus: {action}")
if action == "greet":
logger.info("Aktion: Grüßen")
elif action == "toggle_light":
logger.info("Aktion: Licht umschalten")
# Beispiel: GPIO-Pin steuern
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
GPIO.output(17, not GPIO.input(17)) # Toggle
elif action == "read_temp":
logger.info("Aktion: Temperatur auslesen")
# Beispiel mit Sensor
try:
with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f:
temp = float(f.read()) / 1000
logger.info(f"Aktuelle Temperatur: {temp:.1f}°C")
except:
logger.error("Temperatur-Sensor nicht verfügbar")
8.3 GPIO-Steuerung erweitern
Für komplexere GPIO-Anwendungen:
pip3 install gpiozero
Beispiel in ActionHandler:
from gpiozero import LED, Motor, Buzzer
from gpiozero.pins.rpigpio import RPiGPIOFactory
class ActionHandler:
def __init__(self, sound_player):
self.sound_player = sound_player
# Definiere GPIO-Geräte
# Pin 17: LED
# Pin 27: Buzzer
# Pin 22, 23: Motor (Richtung)
# Pin 24: PWM für Motor-Geschwindigkeit
try:
GPIO.setmode(GPIO.BCM)
self.led = LED(17)
self.buzzer = Buzzer(27)
except:
logger.warning("GPIO-Geräte nicht verfügbar")
TEIL 9: TROUBLESHOOTING
9.1 Häufige Probleme und Lösungen
Problem: "ReSpeaker-Gerät nicht gefunden"
# Überprüfe Geräte
aplay -l
arecord -l
# Überprüfe I2C-Verbindung
i2cdetect -y 1
# Reboot
sudo reboot now
Problem: "Vosk-Modell nicht gefunden"
# Überprüfe Modell-Pfad
ls -la ~/voice_models/
# Download neu
mkdir -p ~/voice_models
cd ~/voice_models
wget https://alphacephei.com/vosk/models/vosk-model-de-0.21.zip
unzip vosk-model-de-0.21.zip
Problem: "Audio sehr leise oder verrauscht"
# Überprüfe Lautstärke
alsamixer
# Nutze Pfeiltasten zur Anpassung
# Mit F6 ReSpeaker-Gerät auswählen
# ESC zum Beenden
# Microphone-Gain erhöhen (rechte Pfeiltaste)
# Playback-Lautstärke erhöhen (linke Pfeiltaste)
Problem: "Service startet nicht beim Boot"
# Überprüfe Service
sudo systemctl status voice-assistant.service
# Zeige Fehler
sudo journalctl -u voice-assistant.service -n 50
# Überprüfe Pfade in Service-Datei
cat /etc/systemd/system/voice-assistant.service
Problem: "SSH-Verbindung möglich, aber Service antwortet nicht"
# Überprüfe Netzwerk
ping 8.8.8.8
# Überprüfe SSH-Key
ssh -vvv pi@192.168.1.100
# Starte Pi neu
sudo reboot now
9.2 Debug-Modus aktivieren
Ändere in speech_recognizer.py:
# KONFIGURATION
class Config:
# ...
LOG_LEVEL = logging.DEBUG # Vorher: logging.INFO
Starte das Skript mit ausführlichem Logging:
python3 ~/voice_assistant/speech_recognizer.py 2>&1 | tee ~/voice_assistant/logs/debug.log
TEIL 10: OPTIMIERUNGEN FÜR PI ZERO 2W
10.1 Speicher-Optimierung
Der Pi Zero 2W hat nur 512MB RAM. Optimierungen:
# Deaktiviere unnötige Services
sudo systemctl disable bluetooth.service
sudo systemctl disable hciuart.service
sudo systemctl disable avahi-daemon.service
sudo systemctl disable cups.service
# Reduziere GPU-Memory
sudo nano /boot/config.txt
Finde oder erstelle diese Zeile:
gpu_mem=64
Dies reduziert GPU auf 64MB, gibt dem CPU mehr RAM.
10.2 CPU-Auslastung überwachen
# Echtzeit-Überwachung
top
# Prozessüberwachung
ps aux | grep python3
# Speichernutzung
free -h
# Disk-Space
df -h
10.3 Performance-Tuning
Erweitere Config in speech_recognizer.py:
class Config:
# ...
# Optimiert für Pi Zero 2W
BLOCKSIZE = 8192 # Größere Blöcke für weniger Overhead
CONFIDENCE_THRESHOLD = 0.4 # Etwas niedriger für schnellere Reaktion
# Nutze nur 1 Kern für Vosk
VOSK_THREADS = 1
CHECKLISTE FÜR ERFOLGREICHE INSTALLATION
- Pi Zero 2W mit Raspberry Pi OS (Bullseye 32-bit) installiert
- ReSpeaker Hat v1.2 korrekt angebracht und verbunden
- seeed-voicecard Treiber installiert
- I2C und SPI aktiviert
- Vosk-Modell (Deutsch) heruntergeladen
- Alle Python-Pakete installiert
speech_recognizer.pymanuell getestet- Sound-Dateien erstellt
- systemctl-Service erstellt und aktiviert
- Service-Logs überprüft
- Aktivierungswort reagiert und Sounds abspielen
NÄCHSTE SCHRITTE
- Web-Interface: Erstelle ein Web-Dashboard zur Verwaltung
- Datenbank: Speichere Kommandos und Logs in SQLite
- Integration: Verbinde mit MQTT für Smart Home
- Machine Learning: Trainiere eigene Sprachmodelle
- Mehrsprachigkeit: Unterstütze zusätzliche Sprachen
RESSOURCEN UND REFERENZEN
- Raspberry Pi Dokumentation
- Seeed Studio ReSpeaker Wiki
- Vosk Offline Speech Recognition
- SpeechRecognition Library
- ALSA Audio Tutorial
HÄUFIG GESTELLTE FRAGEN
F: Kann ich das System auch mit größeren Raspberry Pi Modellen nutzen? A: Ja, das System funktioniert auch mit Pi 3, 4 und 5. Allerdings benötigt der Pi 4/5 mehr Kühlungsvorkehrungen.
F: Wird eine Internetverbindung benötigt? A: Nach der initialen Einrichtung nicht! Das System funktioniert vollständig offline mit Vosk.
F: Kann ich weitere Sprachmodelle nutzen? A: Ja, Vosk bietet Modelle in vielen Sprachen. Lade sie herunter und passe den Modell-Pfad an.
F: Wie erkenne ich, ob der Service läuft?
A: Mit sudo systemctl status voice-assistant.service oder überprüfe die LEDs auf dem ReSpeaker.
SUPPORT UND KONTAKT
Bei Problemen:
- Überprüfe die Logs:
sudo journalctl -u voice-assistant.service - Konsultiere das Troubleshooting-Kapitel
- Öffne ein Issue im GitHub-Repository
- Kontaktiere Seeed Studio Support
Fertig! Dein Pi Zero 2W mit ReSpeaker sollte nun vollständig funktionsfähig sein! 🎉