# 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 1. Öffne [https://www.raspberrypi.com/software/](https://www.raspberrypi.com/software/) 2. Lade **Raspberry Pi Imager** für dein Betriebssystem herunter 3. Installiere die Anwendung #### Schritt 2: SD-Karte flashen 1. Stecke die microSD-Karte in deinen Kartenleser und verbinde ihn mit dem PC 2. Öffne Raspberry Pi Imager 3. Klicke auf **"Gerät auswählen"** und wähle **"Raspberry Pi Zero 2"** 4. 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* 5. Klicke auf **"Speicher auswählen"** und wähle deine microSD-Karte 6. 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` 7. Klicke **"Speichern"** und dann **"Schreiben"** 8. Warte bis zum Abschluss (5-10 Minuten) 9. Entnehme die SD-Karte #### Schritt 3: Erster Start 1. Stecke die SD-Karte in den **Pi Zero 2W** ein 2. Verbinde den ReSpeaker Hat mit dem Pi: - Ausrichten der GPIO-Pins (40-polige Reihe) - ReSpeaker sollte fest aufgesetzt sein 3. Verbinde die USB-Stromversorgung 4. Warte 1-2 Minuten für den ersten Start #### Schritt 4: IP-Adresse ermitteln Methode A (über Router): 1. Öffne die Verwaltungsoberfläche deines WLAN-Routers 2. Suche nach verbundenen Geräten 3. Notiere die IP-Adresse von `respeaker-pi` Methode B (mit arp-scan auf Linux/Mac): ```bash sudo arp-scan -l | grep -i "raspberry\|b8:27" ``` Methode C (mit Advanced IP Scanner auf Windows): 1. Lade [Advanced IP Scanner](https://www.advanced-ip-scanner.com/) herunter 2. Scanne dein Netzwerk 3. Suche nach `respeaker-pi` Beispiel-IP: `192.168.1.100` --- ## TEIL 2: RASPBERRY PI KONFIGURATION ### 2.1 SSH-Verbindung herstellen Auf Linux/Mac (Terminal): ```bash ssh pi@192.168.1.100 # Gib dein Passwort ein ``` Auf Windows: Nutze PuTTY 1. Lade [PuTTY](https://www.putty.org/) herunter 2. Öffne PuTTY 3. Host: `192.168.1.100` 4. Port: `22` 5. Klicke "Open" 6. Login: `pi` 7. Passwort: (dein gesetztes Passwort) ### 2.2 System aktualisieren ```bash 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 ```bash sudo raspi-config ``` Navigiere zu: 1. **Schnittstellen** → **I2C** → **Aktivieren** 2. **Schnittstellen** → **SPI** → **Aktivieren** 3. **Lokalisierungsoptionen** → **Zeitzone** → **Europa** → **Berlin** 4. **Lokalisierungsoptionen** → **Sprache** → **de_DE.UTF-8** 5. Bestätige alle Änderungen und **Starten Sie neu**. Nach dem Reboot erneut verbinden: ```bash 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: ```bash 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: ```bash sudo reboot now ``` Nach dem Reboot wieder verbinden: ```bash ssh pi@192.168.1.100 ``` ### 3.2 ReSpeaker-Installation verifizieren Überprüfe, ob die Sound-Karte erkannt wurde: ```bash 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: ```bash arecord -l ``` Du solltest auch hier `seeed-2mic-voicecard` sehen. ### 3.3 Ton-Tests **Lautsprecher testen:** ```bash 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:** ```bash 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: ```bash aplay -D hw:1,0 test_recording.wav ``` --- ## TEIL 4: PYTHON-UMGEBUNG EINRICHTEN ### 4.1 Notwendige Python-Pakete installieren ```bash # 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 ```bash 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`: ```bash nano ~/voice_assistant/speech_recognizer.py ``` Kopiere folgenden Code ein: ```python #!/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: ```bash chmod +x ~/voice_assistant/speech_recognizer.py ``` ### 5.2 Test-Sounddateien erstellen Erstelle einfache Test-Sounds: ```bash # 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 ```bash 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:** 1. Sprich: "Computer" 2. Nach dem Beep sprich: "Musik" 3. Der Pi sollte `music.wav` abspielen 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: ```bash sudo nano /etc/systemd/system/voice-assistant.service ``` Füge folgenden Inhalt ein: ```ini [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 ```bash # 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 ```bash # 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 ```bash # 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: ```bash 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: ```bash nano ~/voice_assistant/monitor.py ``` ```python #!/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: ```bash 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`: ```python 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: ```python 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: ```bash pip3 install gpiozero ``` Beispiel in `ActionHandler`: ```python 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" ```bash # Überprüfe Geräte aplay -l arecord -l # Überprüfe I2C-Verbindung i2cdetect -y 1 # Reboot sudo reboot now ``` #### Problem: "Vosk-Modell nicht gefunden" ```bash # Ü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" ```bash # Ü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" ```bash # Ü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" ```bash # Ü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`: ```python # KONFIGURATION class Config: # ... LOG_LEVEL = logging.DEBUG # Vorher: logging.INFO ``` Starte das Skript mit ausführlichem Logging: ```bash 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: ```bash # 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 ```bash # 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`: ```python 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.py` manuell getestet - [ ] Sound-Dateien erstellt - [ ] systemctl-Service erstellt und aktiviert - [ ] Service-Logs überprüft - [ ] Aktivierungswort reagiert und Sounds abspielen --- ## NÄCHSTE SCHRITTE 1. **Web-Interface:** Erstelle ein Web-Dashboard zur Verwaltung 2. **Datenbank:** Speichere Kommandos und Logs in SQLite 3. **Integration:** Verbinde mit MQTT für Smart Home 4. **Machine Learning:** Trainiere eigene Sprachmodelle 5. **Mehrsprachigkeit:** Unterstütze zusätzliche Sprachen --- ## RESSOURCEN UND REFERENZEN - [Raspberry Pi Dokumentation](https://www.raspberrypi.com/documentation/) - [Seeed Studio ReSpeaker Wiki](https://wiki.seeedstudio.com/) - [Vosk Offline Speech Recognition](https://alphacephei.com/vosk/) - [SpeechRecognition Library](https://github.com/Uberi/speech_recognition) - [ALSA Audio Tutorial](https://www.alsa-project.org/) --- ## 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: 1. Überprüfe die Logs: `sudo journalctl -u voice-assistant.service` 2. Konsultiere das Troubleshooting-Kapitel 3. Öffne ein Issue im GitHub-Repository 4. Kontaktiere Seeed Studio Support --- **Fertig! Dein Pi Zero 2W mit ReSpeaker sollte nun vollständig funktionsfähig sein! 🎉**