Emiglio bluetooth speaker (Parte 3)
Trasformare Emiglio in uno speaker bluetooth
Nella Parte 2 abbiamo provato a rendere intelligente Emiglio configurando un AI assistant in locale. Oggi vediamo come trasformare Emiglio in uno speaker bluetooth in modo da poter riprodurre audio facilmente collegandoci con il telefono.
Vedo emiglio come uno speaker bluetooth
I componenti necessari
Nel tutorial precedente abbiamo configurato il Raspberry pi zero W2 e installato i driver per scheda audio Respeaker, quindi già si collega in automatico alla nostra rete locale e possiamo collegarci ad esso via ssh per programmarlo. Se partite da zero allora dovete prima flashare il sistema operativo Pi OS lite sul raspberry con PI imager e poi installare i drivers.
Verifica che microfono e altoparlante funzionino
1
2
arecord -L
aplay -L
Dovresti vedere tra i dispositivi:
1
2
3
plughw:CARD=seeed2micvoicec,DEV=0
seeed-2mic-voicecard, bcm2835-i2s-wm8960-hifi wm8960-hifi-0
Hardware device with all software conversions
Registra 5 secondi e riascolta per verificare che funzioni:
1
2
arecord -D plughw:CARD=seeed2micvoicec,DEV=0 -r 16000 -c 1 -f S16_LE -t wav -d 5 test.wav
aplay -D plughw:CARD=seeed2micvoicec,DEV=0 test.wav
Come trasformare il Raspberry Pi in una cassa Bluetooth
Prima di tutto: come “viaggia” la musica?
Prima di digitare comandi, capiamo il percorso che fa la musica dal telefono ai coni della ReSpeaker. Useremo uno stack leggerissimo per la CPU del Pi Zero:
- BlueZ è lo stack Bluetooth di Linux, aggancia l’antenna del telefono e riceve lo stream audio grezzo nel protocollo A2DP (il protocollo che gli auricolari e le casse usano per la musica in stereo).
- BlueALSA fa il traduttore: prende i pacchetti da BlueZ e li trasforma in un normale flusso audio PCM (l’audio “non compresso”, il formato che il resto del sistema capisce).
- ALSA è il motore audio di basso livello del Kernel. Riceve il PCM, applica al volo il resampling matematico a 48kHz (più sotto spiego perché serve) e lo consegna ai driver della scheda audio.
- Il processo demone
bluealsa-aplaysta in ascolto perenne su BlueALSA e, appena arrivano dei byte, li spinge fisicamente nell’altoparlante.
Per far funzionare questo stack, dobbiamo però eliminare un programma che altrimenti andrebbe in conflitto con BlueALSA (lo vediamo al Passo 1).
Controlli prima del Passo 1
Questi tre controlli ti fanno risparmiare un pomeriggio di imprecazioni al computer:
- Stai usando Raspberry Pi OS “Bookworm” (Debian 12) o successivo (es. Trixie)? Digita:
1
cat /etc/os-releaseAlla riga
VERSION_CODENAMEdevi leggere bookworm oppure trixie. Se leggi bullseye o buster, fermati: il pacchetto che installeremo al Passo 2 non esiste nei vecchi repository. Aggiorna prima il sistema operativo, altrimenti non andrai da nessuna parte. - Il Bluetooth hardware è acceso? Se in passato avevi disabilitato il BT per risparmiare RAM, riaccendilo:
1
sudo raspi-confige vai in System Options, Network at Boot / Bluetooth, poi accendilo.
Passo 1: Togliere il Bluetooth a PipeWire
Perché: sulle immagini Desktop di Bookworm il server audio predefinito è PipeWire, che gestisce anche il Bluetooth ed entra quindi in conflitto con BlueALSA. Per risolvere basta rimuovere il plugin Bluetooth di PipeWire (libspa-0.2-bluetooth): PipeWire smette di occuparsi del Bluetooth (che passa a BlueALSA) ma continua a gestire l’audio locale e USB.
Sulle immagini Lite (tipiche di un Pi headless) PipeWire di norma non è installato: in quel caso questo passo non serve e puoi saltare al Passo 2.
Prima controlla se il plugin è presente:
1
2
sudo apt update --fix-missing
apt list --installed 2>/dev/null | grep -E "libspa-0.2-bluetooth|pipewire"
Se compare libspa-0.2-bluetooth, rimuovilo:
1
sudo apt remove libspa-0.2-bluetooth -y
Opzionale: puoi rimuovere anche
pipewire-pulsese non usi applicazioni che parlano con l’API PulseAudio (pactl). Non è necessario per il Bluetooth.
Se PipeWire è installato, riavvialo per applicare la rimozione del plugin:
1
systemctl --user restart pipewire wireplumber
(Eventuali avvisi sono normali: stai riavviando un servizio a cui hai appena tolto un componente.)
Passo 2: Installare BlueALSA e configurare ALSA
Perché: installiamo BlueALSA e gli strumenti per gestire la scheda, poi scriviamo una regola che indica ad ALSA dove inviare il suono.
Installa i pacchetti:
1
sudo apt install bluez-alsa-utils alsa-utils -y
Ora creiamo il file ~/.asoundrc (la ~ è la tua cartella personale; il punto iniziale lo rende un file di configurazione nascosto).
Nota hardware: la ReSpeaker ha un oscillatore al quarzo fissato a 48.000 Hz, quindi la scheda lavora solo a quella frequenza. Se il telefono trasmette un MP3 a 44.100 Hz, senza adattamento la scheda va in errore. Il parametro type plug ordina ad ALSA di eseguire il resampling a 48.000 Hz in tempo reale e in modo trasparente.
Apri il file:
1
nano ~/.asoundrc
Cancella l’eventuale contenuto e incolla esattamente questo blocco (in nano: incolli, poi Ctrl+O e Invio per salvare, Ctrl+X per uscire):
1
2
3
4
5
6
7
8
defaults.bluealsa.interface "hci0"
defaults.bluealsa.device "00:00:00:00:00:00"
defaults.bluealsa.profile "a2dp"
pcm.!default {
type plug
slave.pcm "plughw:CARD=seeed2micvoicec,DEV=0"
}
Significato delle righe:
hci0è l’antenna Bluetooth del Pi (quasi semprehci0).00:00:00:00:00:00non è un indirizzo reale: è un valore speciale che significa “qualsiasi dispositivo”. Lascialo così.a2dpè il profilo della musica stereo.- Il blocco
pcm.!defaultimposta come uscita predefinita la scheda ReSpeaker (seeed2micvoicec), contype plugper l’adattamento automatico della frequenza.
Passo 3: Verificare il profilo a2dp-sink
Perché: BlueALSA può lavorare come sorgente (a2dp-source, invia audio a una cassa) o come ricevitore (a2dp-sink, riceve audio da un telefono). Per una cassa serve il ruolo ricevitore. Sulla maggior parte delle installazioni Bookworm il servizio bluez-alsa è già configurato per offrire a2dp-sink, quindi spesso questo passo è solo una verifica.
Controlla la riga di avvio del demone:
1
systemctl cat bluealsa.service | grep -i exec
Aggiungi l’override solo se nell’ExecStart non c’è -p a2dp-sink e il telefono si connette per poi disconnettersi subito. In tal caso:
1
sudo systemctl edit bluealsa.service
Incolla esattamente queste righe nello spazio indicato:
1
2
3
[Service]
ExecStart=
ExecStart=/usr/bin/bluealsa -p a2dp-sink
La riga vuota
ExecStart=non è un errore. La prima riga azzera il comando predefinito, la seconda imposta quello nuovo. Senza la riga vuota, systemd rifiuta la configurazione. È un comportamento specifico degli override di systemd.
Salva ed esci, poi ricarica e riavvia:
1
2
sudo systemctl daemon-reload
sudo systemctl restart bluealsa
Se in futuro vuoi che il Pi possa anche inviare musica ad altre casse, usa
-p a2dp-source -p a2dp-sink. Per una cassa è sufficiente-p a2dp-sink.
Passo 4: Alzare i volumi della scheda
Perché: il chip WM8960 della ReSpeaker esce dalla fabbrica con i registri del volume a zero. L’audio risulta in riproduzione ma non si sente nulla finché non alzi questi volumi (operazione una tantum).
- Apri il mixer della scheda:
1
alsamixer -D plughw:CARD=seeed2micvoicec,DEV=0
- Con le frecce destra/sinistra ti sposti tra i canali, con su/giù regoli il livello. Porta Playback, Headphone e Speaker all’85%.
I controlli di volume in ALSA seguono una curva logaritmica: sotto il 60% circa il suono è quasi inudibile, e l’ultimo tratto contiene la parte utile. Per questo si imposta un valore alto.
- Se sotto un canale leggi
[MM], è in mute: premi il tastoMper sbloccarlo (diventa[OO]). - Premi
Escper uscire, poi salva le impostazioni nella memoria della scheda (così restano dopo un riavvio):1
sudo alsactl store
Passo 5: Rendere il Bluetooth sempre visibile
Perché: di default BlueZ rende il dispositivo non più individuabile dopo 180 secondi. Per una cassa sempre disponibile conviene disattivare questo timeout.
Apri il file di configurazione:
1
sudo nano /etc/bluetooth/main.conf
Nel blocco [General] trova DiscoverableTimeout e impostalo a zero (0 = nessuna scadenza):
1
DiscoverableTimeout = 0
Salva ed esci, poi riavvia il servizio:
1
sudo systemctl restart bluetooth
Passo 6: Accoppiare il telefono e impostare il trust
Perché: per un dispositivo personale non serve uno script che confermi il PIN a ogni connessione. È sufficiente accoppiare una volta e marcare il telefono come trusted (fidato): da quel momento la riconnessione è automatica.
- Entra nella console interattiva del Bluetooth:
1
sudo bluetoothctl - Imposta l’agente senza interfaccia (
NoInputNoOutputindica che il Pi non ha schermo né tastiera per inserire un PIN, quindi accetta l’accoppiamento “Just Works”):1 2 3 4 5
power on discoverable on pairable on agent NoInputNoOutput default-agent
- Sul telefono: vai nelle impostazioni Bluetooth e, se il Pi compare già, scegli “Dimentica questo dispositivo” (per cancellare un eventuale accoppiamento precedente difettoso). Disattiva e riattiva il Bluetooth, poi tocca il nome del tuo Pi (il suo hostname).
- Sul Raspberry vedrai scorrere le righe della connessione. Copia il MAC Address del telefono che compare.
Formato del MAC: va scritto con i due punti, es.
AA:BB:CC:11:22:33, non tutto attaccato. Un formato errato fa fallire il comando senza messaggi chiari.Poi, sempre dentro
bluetoothctl, segna il telefono come fidato (sostituisci con il MAC reale del tuo dispositivo):1 2
trust AA:BB:CC:11:22:33 exit
Da ora in poi, quando quel telefono è nelle vicinanze e ha il Bluetooth attivo, la riconnessione avviene in automatico.
Passo 7: Avvio automatico del player BlueALSA
Perché: bluealsa-aplay è il processo che instrada l’audio Bluetooth verso la scheda. Per averlo sempre attivo lo configuriamo come servizio systemd, che parte all’avvio e si riavvia in caso di errore.
Crea il file del servizio:
1
sudo nano /etc/systemd/system/bt-speaker.service
Contenuto:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=Player audio Bluetooth (BlueALSA)
After=bluetooth.service bluealsa.service
Requires=bluetooth.service bluealsa.service
[Service]
Type=simple
User=pi
ExecStart=/usr/bin/bluealsa-aplay --profile-a2dp 00:00:00:00:00:00
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Note:
After/Requires: il player non parte prima che Bluetooth e BlueALSA siano pronti.User=pi: se il tuo utente non si chiamapi, cambia questo campo. L’utente indicato deve essere nel gruppoaudio(vedi i controlli iniziali).00:00:00:00:00:00: di nuovo il valore “qualsiasi dispositivo”.Restart=on-failure: il servizio si riavvia da solo dopo 5 secondi se si interrompe.
Salva ed esci, poi abilita e avvia il servizio:
1
2
sudo systemctl daemon-reload
sudo systemctl enable --now bt-speaker.service
Verifica lo stato:
1
sudo systemctl status bt-speaker.service
Se vedi active (running), il servizio è attivo.
Verifica finale
Riavvia il Pi e, senza toccare altro, sblocca il telefono e avvia una traccia: l’audio dovrebbe uscire dall’altoparlante della ReSpeaker.
Questa configurazione convive con un server locale come la Soundboard Flask: avendo tolto a PipeWire solo la gestione del Bluetooth, PipeWire continua a riprodurre i file .wav locali sulla stessa scheda, mentre il Bluetooth passa per BlueALSA. I due percorsi non si contendono più il Bluetooth.
Nota sulla riproduzione simultanea: l’accesso diretto alla scheda (
plughw) può essere esclusivo, quindi se vuoi che audio locale e Bluetooth suonino nello stesso istante conviene verificarlo sul tuo hardware. In molti casi PipeWire rilascia la scheda quando non riproduce nulla, lasciandola libera per il Bluetooth.
Nella prossima parte vedremo l’integrazione del Wake Word engine (“Ehi Emiglio”) in esecuzione locale sul Pi Zero.
Risultato finale
Ora potete collegarvi al bluetooth di Emiglio e fargli dire tutte le boiate che vi vengono in mente
Risoluzione dei problemi
- Il telefono non vede la cassa, o si connette e si disconnette subito → verifica il profilo
a2dp-sink(Passo 3). - Si connette ma non si sente nulla → controlla i volumi con
alsamixer(Passo 4): canali non a zero e non in[MM]. Permission deniedsulla scheda audio → l’utente non è nel gruppoaudio(controlli iniziali) oppure il campoUser=del Passo 7 è errato.- Funziona nella sessione ma non dopo il riavvio → controlla che il servizio del Passo 7 sia
enablede chebluealsa-aplayriparta da solo:systemctl status bt-speaker.service. - Comportamento incoerente dopo l’installazione → un
sudo rebootpermette a tutti i servizi di avviarsi nell’ordine corretto.
