L’UNIHIKER M10 è una scheda compatta che integra un sistema basato su Linux, sensori e interfacce hardware in un unico dispositivo. È dotata di un processore quad-core Arm Cortex-A35 con 512 MB di RAM e 16 GB di memoria eMMC.
La scheda include anche un touchscreen da 2,8 pollici con risoluzione 240 × 320 pixel, connettività Wi-Fi e Bluetooth. I sensori integrati comprendono un sensore di luce, accelerometro, giroscopio e microfono.
Poiché la scheda esegue Linux e supporta la programmazione in Python, può essere utilizzata per molte applicazioni. In questo tutorial imparerai come implementare un Assistente Vocale sulla scheda UNIHIKER M10. Il breve video seguente mostra l’Assistente Vocale:
Potresti dover aumentare il volume del tuo computer per sentire la mia voce. Nota inoltre che questo assistente non ha output vocale, anche se sarebbe facile aggiungerlo.
Componenti necessari
Ti servirà una scheda UNIHIKER M10. Puoi acquistarla su DFRobot o su Amazon, per esempio:

UNIHIKER M10
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Hardware del Unihiker M10
L’UNIHIKER M10 è basato su un chip Rockchip RK3308. Questo chip utilizza quattro core Arm Cortex-A35 e funziona a una frequenza fino a 1,2 GHz. Il processore esegue un sistema operativo Debian Linux completo con Python 3.7 preinstallato. Sono inoltre preinstallate molte librerie scientifiche Python come Numpy, Matplotlib, Jupyter, Pandas, Seaborn, Tensorflow e altre.
La scheda include 512 MB di memoria di sistema DDR3, utilizzata dal sistema operativo Linux e dalle applicazioni utente. Lo storage dei programmi è fornito da 16 GB di memoria flash eMMC integrata.
Oltre al processore principale, la scheda integra un microcontrollore GD32VF103C8T6 come co-processore. Contiene 64 KB di memoria flash e 32 KB di SRAM. Il microcontrollore gestisce molte operazioni a livello hardware come la gestione dei sensori, il controllo dei GPIO e il funzionamento degli attuatori.
Display e Interfaccia Utente
L’UNIHIKER M10 è dotato di un display touchscreen a colori da 2,8 pollici con risoluzione 240 × 320 pixel. La scheda include un pulsante Home e due pulsanti utente programmabili etichettati A e B, come mostrato di seguito:

Sensori Integrati
I sensori integrati comprendono un sensore di luce, accelerometro, giroscopio e microfono. L’espansione hardware è possibile tramite porte USB, connettori Gravity per sensori e un connettore edge compatibile con micro:bit che espone interfacce GPIO, I2C, SPI e UART.

Inoltre, un buzzer passivo e un LED di stato forniscono semplici output audio e visivi per notifiche e debug. Un altoparlante esterno può essere collegato tramite la porta USB.
Connettività e Rete
La comunicazione wireless è disponibile tramite un modulo combinato Wi-Fi e Bluetooth. La scheda supporta Wi-Fi a 2,4 GHz e Bluetooth 4.0. Il Wi-Fi può essere configurato tramite un’interfaccia Web accessibile all’indirizzo 10.1.2.3.
Interfacce e Opzioni di Espansione
La scheda offre diverse interfacce fisiche per collegare hardware esterno. Un connettore USB Type-C è usato per l’alimentazione e la comunicazione con un computer. La scheda può essere alimentata con una tensione di 5 V tramite questa porta.
Una porta USB Type-A host consente il collegamento di periferiche USB come dispositivi di archiviazione, tastiere o adattatori. La scheda include anche uno slot per schede microSD per espandere la capacità di archiviazione o trasferire file.
Inoltre, sono disponibili molteplici connettori di espansione per sensori e attuatori. I connettori a 3 pin compatibili con Gravity forniscono accesso a ingressi PWM e analogici. I connettori dedicati a 4 pin offrono comunicazione I2C per sensori e moduli digitali.

Connettore Edge
La scheda dispone anche di un connettore edge compatibile con micro:bit. Questo connettore espone fino a 19 pin GPIO e supporta interfacce come I2C, UART e SPI. Fornisce inoltre diversi ingressi ADC e uscite PWM per il controllo di hardware esterno. L’immagine seguente mostra il pinout del connettore edge:

Schema elettrico
Per informazioni tecniche più dettagliate consulta lo schema elettrico dell’UNIHIKER M10 linkato di seguito:
Specifiche Tecniche
La tabella seguente riassume le specifiche tecniche della scheda UNIHIKER M10:
| Caratteristica | Specifiche |
|---|---|
| Processore Principale | Rockchip RK3308 |
| Architettura CPU | Quad-core Arm Cortex-A35 |
| Frequenza CPU | Fino a 1,2 GHz |
| Memoria di Sistema | 512 MB DDR3 |
| Memoria Interna | 16 GB eMMC |
| Co-Processore | Microcontrollore GD32VF103C8T6 RISC-V |
| Frequenza MCU | Fino a 108 MHz |
| Memoria MCU | 64 KB Flash, 32 KB SRAM |
| Sistema Operativo | Debian Linux |
| Display | Touchscreen da 2,8 pollici |
| Risoluzione Display | 240 × 320 pixel |
| Connettività Wireless | Wi-Fi 802.11 b/g/n (2.4 GHz), Bluetooth 4.0 |
| Sensori | Sensore di luce, IMU a 6 assi (accelerometro + giroscopio), microfono |
| Ingressi Utente | Pulsante Home, pulsanti utente A/B, touchscreen |
| Uscita Audio | Buzzer passivo |
| Porte USB | 1 × USB-C (alimentazione e dati), 1 × USB-A host |
| Espansione Memoria | Slot per scheda microSD |
| Interfacce di Espansione | Connettori Gravity a 3 pin (analogico/PWM), connettori I2C |
| Connettore Edge | Connettore edge compatibile con micro:bit |
| Interfacce Supportate | GPIO, ADC, PWM, I2C, SPI, UART |
| Tensione di Funzionamento | 5 V in ingresso via USB-C |
| Livello Logico | 3,3 V |
| Corrente Tipica | Fino a ~2 A |
| Dimensioni della Scheda | Circa 51,6 mm × 83 mm × 13 mm |
Programmare l’UNIHIKER M10
Ci sono varie applicazioni che puoi usare per programmare l’UNIHIKER M10, come Jupyter Notebook, Mind+, VSCode, Python IDLE o Thonny. Per istruzioni dettagliate su come configurare queste applicazioni consulta la Getting Started sezione della documentazione UNIHIKER.
Installare Thonny
Personalmente ho trovato Thonny il più semplice da usare per un piccolo progetto come questo tutorial. Per istruzioni su come installarlo, consulta la Download and Install sezione Thonny della documentazione UNIHIKER.
Collegare Thonny a UNIHIKER M10
Dopo aver installato Thonny collega il tuo UNIHIKER M10 al computer con il cavo USB. Poi apri Thonny e clicca su “Run -> Select interpreter …”:

Si aprirà una finestra di dialogo dove selezionerai “Remote Python 3 (SSH)” come interprete. In Host inserisci “10.1.2.3”, per Username inserisci “root” e come metodo di autenticazione scegli “password”:

Dopo aver cliccato su “Run -> Stop/Restart backend” Thonny sarà connesso al tuo UNIHIKER M10 e potrai modificare ed eseguire programmi Python su di esso.

Installare Putty e la libreria OpenAI
Successivamente ci servirà uno strumento che ci permetta di installare librerie Python, come la OpenAI libreria sull’UNIHIKER M10. Ho provato a installare librerie tramite Thonny (“Manage Packages”, “Open System Shell…”) ma non sono riuscito a farlo funzionare.
Invece ho usato Putty. Per istruzioni di installazione consulta la SSH Tools della documentazione UNIHIKER. Una volta installato, apri Putty e crea una sessione con 10.1.2.3 come HOST:

Poi clicca sul pulsante “Open” e nella shell di Putty inserisci “root” come username e “dfrobot” come password:

Ora puoi installare la libreria OpenAI con il comando “pip install openai”:

Se mancano altre librerie Python puoi installarle allo stesso modo. Nota però che l’UNIHIKER M10 deve essere collegato tramite cavo USB.
Configurare il Wi-Fi
Infine, dobbiamo configurare la connessione Wi-Fi, così che il nostro Assistente Vocale abbia accesso a internet per chiamare gli strumenti AI di OpenAI.
Per farlo, apri un browser e inserisci “10.1.2.3” nella barra degli indirizzi. Vedrai una pagina web con una voce “Network Settings” nella barra laterale. Cliccaci e inserisci le credenziali Wi-Fi nel dialog a destra:

Ottenere la chiave API OpenAI
Il nostro Assistente Vocale userà modelli AI forniti da OpenAI. Perciò ti servirà un account OpenAI. Vai su https://platform.openai.com e registrati con un indirizzo email o un account Google o Microsoft esistente.
Dopo aver verificato la tua email e completato la configurazione iniziale, accedi alla dashboard OpenAI, platform.openai.com/api-keys e trova o crea la tua API Key (=SECRET KEY) come mostrato di seguito:

La API Key è una stringa unica e lunga, che inizia con “sk-proj-“, necessaria per autenticare le richieste API (vedi sotto). Successivamente dovrai copiare questa stringa intera nel codice dell’Assistente Vocale.
sk-proj-xcA.......................OtDu0U
Questo è tutto ciò che serve, ma ti consiglio di impostare anche un limite di utilizzo per il tuo account. Questo evita di incorrere in costi elevati a causa di un bug nel codice (ad esempio inviando centinaia di richieste).
Puoi impostare i Limiti di Utilizzo e consultare i Prezzi (Costi) per i diversi modelli AI nella scheda Billing (platform.openai.com/settings/organization/billing).
Ora siamo pronti per scrivere il codice per l’Assistente Vocale.
Codice per l’Assistente Vocale
In Thonny crea un nuovo file, io l’ho chiamato “assistant_tk.py” e copia e incolla il codice qui sotto.

Questo codice implementa un assistente vocale. Registra l’audio mentre si tiene premuto il pulsante A, trascrive il parlato in testo usando il modello Whisper di OpenAI, invia il testo a un modello GPT basato su Large Language Model (LLM) per una risposta, e mostra sia la domanda che la risposta nell’interfaccia grafica del dispositivo.
# www.makerguides.com
# Python 3.7
# openai 1.39.0
# PyAudio 0.2.11
# pinpong 0.6.1
# numpy 1.21.6
import time
import threading
import numpy as np
import pyaudio
import io
import wave
from openai import OpenAI
from pinpong.extension.unihiker import button_a
import tkinter as tk
from tkinter import ttk
from typing import List
API_KEY = "sk-proj-my-api-key"
DEVICE_INDEX = 2
SAMPLE_RATE = 16000
CHANNELS = 1
CHUNK = 1024
client = OpenAI(api_key=API_KEY)
# GUI -----------------------------------------------------
root = tk.Tk()
root.title("Voice Chatbot")
root.geometry("240x320")
status_var = tk.StringVar()
status_var.set("Hold Button A to speak")
status_label = ttk.Label(root, textvariable=status_var,
font=("Arial", 11), anchor="center")
status_label.pack(fill="x", padx=6, pady=4)
frame = tk.Frame(root)
frame.pack(fill="both", expand=True)
scrollbar = tk.Scrollbar(frame, width=18)
scrollbar.pack(side="right", fill="y")
text_box = tk.Text(frame, wrap="word",
yscrollcommand=scrollbar.set, font=("Arial", 10))
text_box.bind("<Motion>", lambda e: "break")
text_box.bind("<B1-Motion>", lambda e: "break")
text_box.bind("<Button-1>", lambda e: "break")
text_box.pack(side="left", fill="both", expand=True)
scrollbar.config(command=text_box.yview)
def set_status(text):
status_var.set(text)
root.update_idletasks()
def show_answer(text):
text_box.delete("1.0", tk.END)
text_box.insert(tk.END, text)
text_box.see(tk.END)
# Audio helpers -----------------------------------------------
def normalize(pcm_bytes: bytes) -> bytes:
samples = np.frombuffer(pcm_bytes, dtype=np.int16).astype(np.float32)
peak = np.max(np.abs(samples))
if peak == 0:
return pcm_bytes
gain = (0.9 * 32767) / peak
normalized = np.clip(samples * gain, -32768, 32767).astype(np.int16)
return normalized.tobytes()
def record_while_held() -> bytes:
frames: List[bytes] = []
pa = pyaudio.PyAudio()
stream = pa.open(
format=pyaudio.paInt16,
channels=CHANNELS,
rate=SAMPLE_RATE,
input=True,
input_device_index=DEVICE_INDEX,
frames_per_buffer=CHUNK
)
set_status("Hold Button A to speak")
while not button_a.is_pressed():
time.sleep(0.01)
set_status("recording...")
while button_a.is_pressed():
data = stream.read(CHUNK, exception_on_overflow=False)
frames.append(data)
stream.stop_stream()
stream.close()
pa.terminate()
return b"".join(frames)
def pcm_to_wav(pcm_bytes: bytes) -> bytes:
buf = io.BytesIO()
with wave.open(buf, "wb") as wf:
wf.setnchannels(CHANNELS)
wf.setsampwidth(2)
wf.setframerate(SAMPLE_RATE)
wf.writeframes(pcm_bytes)
return buf.getvalue()
# OpenAI -----------------------------------------------
def transcribe(wav_bytes: bytes) -> str:
audio_file = io.BytesIO(wav_bytes)
audio_file.name = "recording.wav"
set_status("transcribing...")
response = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
language="en",
temperature=0
)
return response.text
def ask_gpt(question: str) -> str:
set_status("thinking...")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": "You are a helpful assistant. Answer clearly and concisely."
},
{"role": "user", "content": question}
],
)
return response.choices[0].message.content
# Main assistant loop -----------------------------------------------
def assistant_loop():
while True:
raw_pcm = record_while_held()
if not raw_pcm:
continue
normalized_pcm = normalize(raw_pcm)
wav_bytes = pcm_to_wav(normalized_pcm)
question = transcribe(wav_bytes)
answer = ask_gpt(question)
set_status("ready")
show_answer(question + "\n\n" + answer)
threading.Thread(target=assistant_loop, daemon=True).start()
root.mainloop()
Importazioni
Il codice inizia importando diversi moduli necessari per il suo funzionamento. Questi includono librerie standard come time, threading e io per la gestione del tempo, l’esecuzione concorrente e la gestione di flussi di byte. Importa anche numpy per operazioni numeriche su dati audio, pyaudio per la registrazione audio, e wave per la gestione del formato audio WAV.
Il client Python di OpenAI è importato per interagire con l’API di OpenAI. Il modulo specifico UNIHIKER button_a è importato per rilevare la pressione dei pulsanti. Infine, tkinter e ttk sono importati per creare l’interfaccia grafica, e List da typing è usato per i type hinting.
import time import threading import numpy as np import pyaudio import io import wave from openai import OpenAI from pinpong.extension.unihiker import button_a import tkinter as tk from tkinter import ttk from typing import List
Costanti e Inizializzazione Client
Vengono definite diverse costanti per configurare i parametri di registrazione audio, come la chiave API per OpenAI, l’indice del dispositivo di input audio, la frequenza di campionamento, il numero di canali e la dimensione del buffer audio. Viene quindi creato un oggetto client OpenAI usando la chiave API fornita, abilitando la comunicazione con i servizi OpenAI.
API_KEY = "sk-proj-my-api-key" DEVICE_INDEX = 2 SAMPLE_RATE = 16000 CHANNELS = 1 CHUNK = 1024 client = OpenAI(api_key=API_KEY)
Ricorda di sostituire il valore fittizio “sk-proj-my-api-key” per API_KEY con la tua chiave API OpenAI!
Interfaccia Grafica (GUI)
La GUI è costruita usando tkinter. Viene creata una finestra principale con un titolo e dimensioni fisse. Viene aggiunta un’etichetta di stato per informare l’utente sullo stato corrente, come l’invito a tenere premuto il pulsante A per parlare o messaggi di progresso.

Sotto l’etichetta di stato, è presente una casella di testo con barra di scorrimento per mostrare la domanda trascritta e la risposta dell’assistente. La casella di testo è impostata in sola lettura disabilitando le interazioni del mouse che modificherebbero il contenuto.
root = tk.Tk()
root.title("Voice Chatbot")
root.geometry("240x320")
status_var = tk.StringVar()
status_var.set("Hold Button A to speak")
status_label = ttk.Label(root, textvariable=status_var,
font=("Arial", 11), anchor="center")
status_label.pack(fill="x", padx=6, pady=4)
frame = tk.Frame(root)
frame.pack(fill="both", expand=True)
scrollbar = tk.Scrollbar(frame, width=18)
scrollbar.pack(side="right", fill="y")
text_box = tk.Text(frame, wrap="word",
yscrollcommand=scrollbar.set, font=("Arial", 10))
text_box.bind("<Motion>", lambda e: "break")
text_box.bind("<B1-Motion>", lambda e: "break")
text_box.bind("<Button-1>", lambda e: "break")
text_box.pack(side="left", fill="both", expand=True)
scrollbar.config(command=text_box.yview)
Funzioni di Stato e Visualizzazione
Due funzioni di supporto gestiscono gli aggiornamenti della GUI. La funzione set_status() aggiorna il testo dell’etichetta di stato e forza l’aggiornamento immediato della GUI. La funzione show_answer() cancella la casella di testo, inserisce nuovo testo e scorre fino alla fine per mostrare il contenuto più recente.
def set_status(text):
status_var.set(text)
root.update_idletasks()
def show_answer(text):
text_box.delete("1.0", tk.END)
text_box.insert(tk.END, text)
text_box.see(tk.END)
Funzioni Audio
Il codice include diverse funzioni per la gestione dell’audio. La funzione normalize() prende i byte audio PCM grezzi, li converte in campioni floating-point e li scala in modo che l’ampiezza massima raggiunga il 90% del range massimo di un intero a 16 bit. Questa normalizzazione garantisce un volume audio costante per la trascrizione.
def normalize(pcm_bytes: bytes) -> bytes:
samples = np.frombuffer(pcm_bytes, dtype=np.int16).astype(np.float32)
peak = np.max(np.abs(samples))
if peak == 0:
return pcm_bytes
gain = (0.9 * 32767) / peak
normalized = np.clip(samples * gain, -32768, 32767).astype(np.int16)
return normalized.tobytes()
La funzione record_while_held() registra l’audio dal dispositivo di input specificato mentre il pulsante A è premuto.
Inizializza uno stream PyAudio con i parametri configurati e attende che il pulsante A venga premuto. Poi legge continuamente blocchi audio e li aggiunge a una lista finché il pulsante non viene rilasciato. I frame audio registrati vengono concatenati e restituiti come byte raw PCM.
def record_while_held() -> bytes:
frames: List[bytes] = []
pa = pyaudio.PyAudio()
stream = pa.open(
format=pyaudio.paInt16,
channels=CHANNELS,
rate=SAMPLE_RATE,
input=True,
input_device_index=DEVICE_INDEX,
frames_per_buffer=CHUNK
)
set_status("Hold Button A to speak")
while not button_a.is_pressed():
time.sleep(0.01)
set_status("recording...")
while button_a.is_pressed():
data = stream.read(CHUNK, exception_on_overflow=False)
frames.append(data)
stream.stop_stream()
stream.close()
pa.terminate()
return b"".join(frames)
La funzione pcm_to_wav() converte i byte PCM raw in un flusso di byte in formato WAV usando il modulo wave. Questo è necessario perché l’API di trascrizione OpenAI si aspetta file audio in formati standard come WAV.
def pcm_to_wav(pcm_bytes: bytes) -> bytes:
buf = io.BytesIO()
with wave.open(buf, "wb") as wf:
wf.setnchannels(CHANNELS)
wf.setsampwidth(2)
wf.setframerate(SAMPLE_RATE)
wf.writeframes(pcm_bytes)
return buf.getvalue()
Interazione con l’API OpenAI
Due funzioni gestiscono la comunicazione con l’API OpenAI. La funzione transcribe() invia i byte audio WAV al modello Whisper per ottenere una trascrizione testuale. Aggiorna l’etichetta di stato per indicare che la trascrizione è in corso e restituisce il testo riconosciuto.
def transcribe(wav_bytes: bytes) -> str:
audio_file = io.BytesIO(wav_bytes)
audio_file.name = "recording.wav"
set_status("transcribing...")
response = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
language="en",
temperature=0
)
return response.text
La funzione ask_gpt() invia la domanda trascritta a un modello di completamento chat basato su GPT. Imposta lo stato su “thinking…” mentre attende la risposta. Poi costruisce il messaggio di sistema che istruisce il modello a essere un assistente utile. Infine, la funzione restituisce il testo della risposta dell’assistente.
def ask_gpt(question: str) -> str:
set_status("thinking...")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": "You are a helpful assistant. Answer clearly and concisely."
},
{"role": "user", "content": question}
],
)
return response.choices[0].message.content
Ciclo Principale dell’Assistente
La funzionalità principale è eseguita nella funzione assistant_loop(), che gira in un thread separato per mantenere la GUI reattiva.
Attende continuamente che l’utente tenga premuto il pulsante A e registra l’audio mentre il pulsante è premuto. Se non viene catturato audio, ricomincia il ciclo. Altrimenti normalizza l’audio, lo converte in formato WAV, trascrive il parlato e interroga il modello GPT per una risposta.
Dopo l’elaborazione, aggiorna lo stato a “ready” e mostra sia la domanda che la risposta nella casella di testo.
def assistant_loop():
while True:
raw_pcm = record_while_held()
if not raw_pcm:
continue
normalized_pcm = normalize(raw_pcm)
wav_bytes = pcm_to_wav(normalized_pcm)
question = transcribe(wav_bytes)
answer = ask_gpt(question)
set_status("ready")
show_answer(question + "\n\n" + answer)
Avvio dell’Assistente e Mainloop della GUI
Infine, il ciclo dell’assistente viene avviato in un thread daemon, permettendo di girare in background. Viene quindi avviato il mainloop degli eventi della GUI con root.mainloop(), che mantiene la finestra aperta e reattiva alle interazioni dell’utente.
threading.Thread(target=assistant_loop, daemon=True).start() root.mainloop()
Messaggi di errore
Se esegui il codice potresti vedere i seguenti avvisi nella console di Thonny:
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.iec958
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.iec958
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.iec958
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.hdmi
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.hdmi
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.modem
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.modem
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.phoneline
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.phoneline
ALSA lib pcm_oss.c:377:(_snd_pcm_oss_open) Unknown field port
ALSA lib pcm_oss.c:377:(_snd_pcm_oss_open) Unknown field port
ALSA lib pcm_a52.c:823:(_snd_pcm_a52_open) a52 is only for playback
ALSA lib conf.c:5014:(snd_config_expand) Unknown parameters {AES0 0x6 AES1 0x82 AES2 0x0 AES3 0x2 CARD 0}
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM iec958:{AES0 0x6 AES1 0x82 AES2 0x0 AES3 0x2 CARD 0}
ALSA lib pcm_usb_stream.c:486:(_snd_pcm_usb_stream_open) Invalid type for card
ALSA lib pcm_usb_stream.c:486:(_snd_pcm_usb_stream_open) Invalid type for card
Questo accade perché quando inizializzi pyaudio.PyAudio(), la libreria ALSA (Advanced Linux Sound Architecture) sottostante scansiona il sistema per tutti i dispositivi audio e configurazioni possibili (come audio surround 5.1, HDMI o digitale S/PDIF).
Poiché l’UNIHIKER M10 è un Single Board Computer compatto, non ha “altoparlanti posteriori” o “porte modem”, quindi ALSA segnala che non li trova. Se il tuo codice funziona e gestisce l’audio dopo questi avvisi, la configurazione è corretta.
Conclusioni
In questo tutorial hai imparato come implementare un Assistente Vocale sull’UNIHIKER M10 usando i servizi OpenAI. Per altri esempi di codice più semplici dai un’occhiata alla Python Coding Examples della documentazione UNIHIKER.
Nota che potresti facilmente estendere e migliorare l’Assistente Vocale aggiungendo una cronologia chat e funzionalità di chiamata a strumenti. Inoltre, ho usato Tkinter per creare un’interfaccia semplice, ma per una GUI migliore potresti usare QtPy, che è preinstallato sull’UNIHIKER M10.
Inoltre, potresti aggiungere un altoparlante, via USB, Bluetooth o line-out, per far rispondere l’Assistente Vocale con audio. Vedi il tutorial AI Language Tutor with UNIHIKER M10 per un esempio.
Per un Vision Chatbot che può vedere e rispondere a domande su immagini, consulta il nostro tutorial Vision Chatbot with DFRobot ESP32-S3 AI Camera and OpenAI. E per altri esempi AI, vedi la AI Projects sezione della documentazione UNIHIKER.
Se hai domande sentiti libero di lasciarle nella sezione commenti.
Buon divertimento con il tinkering 😉

