El UNIHIKER M10 es una placa compacta que integra un sistema basado en Linux, sensores e interfaces de hardware en una sola placa. Cuenta con un procesador Arm Cortex-A35 de cuatro núcleos, 512 MB de RAM y 16 GB de almacenamiento eMMC.
La placa también incluye una pantalla táctil de 2,8 pulgadas con resolución de 240 × 320 píxeles, conectividad Wi-Fi y Bluetooth. Los sensores integrados incluyen un sensor de luz, acelerómetro, giroscopio y micrófono.
Como la placa ejecuta Linux y soporta programación en Python, puede usarse para muchas aplicaciones. En este tutorial aprenderás a implementar un Asistente de Voz en la placa UNIHIKER M10. El siguiente video corto muestra el Asistente de Voz:
Puede que necesites subir el volumen de tu ordenador para escuchar mi voz. También ten en cuenta que este asistente no tiene salida de voz, aunque sería fácil añadirla.
Partes necesarias
Necesitarás una placa UNIHIKER M10. Puedes conseguirla en DFRobot o en Amazon, por ejemplo:

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
El UNIHIKER M10 está construido alrededor del chip Rockchip RK3308. Este chip utiliza cuatro núcleos Arm Cortex-A35 y funciona a una frecuencia de hasta 1,2 GHz. El procesador ejecuta un sistema operativo Debian Linux completo con Python 3.7 preinstalado. También incluye muchas librerías científicas de Python como Numpy, Matplotlib, Jupyter, Pandas, Seaborn, Tensorflow y otras.
La placa incluye 512 MB de memoria del sistema DDR3. Esta memoria es usada por el sistema operativo Linux y las aplicaciones de usuario. El almacenamiento de programas se proporciona mediante 16 GB de memoria flash eMMC integrada.
Además del procesador principal, la placa integra un microcontrolador GD32VF103C8T6 como coprocesador. Contiene 64 KB de memoria flash y 32 KB de SRAM. El microcontrolador gestiona muchas tareas a nivel de hardware como la gestión de sensores, control de GPIO y operación de actuadores.
Pantalla e Interfaz de Usuario
El UNIHIKER M10 viene con una pantalla táctil a color de 2,8 pulgadas. La pantalla tiene una resolución de 240 × 320 píxeles. La placa incluye un botón Home y dos botones de usuario programables etiquetados como A y B, como se muestra a continuación:

Sensores Integrados
Los sensores integrados incluyen un sensor de luz, acelerómetro, giroscopio y micrófono. La expansión de hardware está disponible a través de puertos USB, conectores Gravity para sensores y un conector edge compatible con micro:bit que expone interfaces GPIO, I2C, SPI y UART.

Además, un zumbador pasivo y un LED de estado proporcionan salidas simples de audio y visuales para notificaciones y depuración. Se puede conectar un altavoz externo mediante el puerto USB.
Conectividad y Redes
La comunicación inalámbrica está disponible mediante un módulo combinado de Wi-Fi y Bluetooth. La placa soporta Wi-Fi a 2.4 GHz y conectividad Bluetooth 4.0. El Wi-Fi puede configurarse a través de una interfaz web que corre en 10.1.2.3.
Interfaces y Opciones de Expansión
La placa ofrece varias interfaces físicas para conectar hardware externo. Un conector USB Tipo-C se usa para la alimentación y comunicación con un ordenador. La placa puede alimentarse con una fuente de 5 V a través de este puerto.
Un puerto host USB Tipo-A permite la conexión de periféricos USB como dispositivos de almacenamiento, teclados o adaptadores. La placa también incluye una ranura para tarjeta microSD para ampliar la capacidad de almacenamiento o transferir archivos.
Además, hay múltiples conectores de expansión disponibles para sensores y actuadores. Los conectores de 3 pines compatibles con Gravity proporcionan acceso a entradas PWM y analógicas. Los conectores dedicados de 4 pines ofrecen comunicación I2C para sensores y módulos digitales.

Conector Edge
La placa también cuenta con un conector edge compatible con micro:bit. Este conector expone hasta 19 pines GPIO y soporta interfaces como I2C, UART y SPI. También proporciona varias entradas ADC y salidas PWM para controlar hardware externo. La imagen a continuación muestra el pinout del conector edge:

Esquemas
Para información técnica más detallada, consulta los esquemas del UNIHIKER M10 enlazados a continuación:
Especificaciones Técnicas
La siguiente tabla resume las especificaciones técnicas de la placa UNIHIKER M10:
| Característica | Especificación |
|---|---|
| Procesador Principal | Rockchip RK3308 |
| Arquitectura CPU | Cuatro núcleos Arm Cortex-A35 |
| Frecuencia CPU | Hasta 1.2 GHz |
| Memoria del Sistema | 512 MB DDR3 |
| Almacenamiento Interno | 16 GB eMMC |
| Coprocesador | Microcontrolador GD32VF103C8T6 RISC-V |
| Velocidad de Reloj MCU | Hasta 108 MHz |
| Memoria MCU | 64 KB Flash, 32 KB SRAM |
| Sistema Operativo | Debian Linux |
| Pantalla | Pantalla táctil de 2.8 pulgadas |
| Resolución de Pantalla | 240 × 320 píxeles |
| Conectividad Inalámbrica | Wi-Fi 802.11 b/g/n (2.4 GHz), Bluetooth 4.0 |
| Sensores | Sensor de luz, IMU de 6 ejes (acelerómetro + giroscopio), micrófono |
| Entradas de Usuario | Botón Home, botones de usuario A/B, pantalla táctil |
| Salida de Audio | Zumbador pasivo |
| Puertos USB | 1 × USB-C (alimentación y datos), 1 × USB-A host |
| Expansión de Almacenamiento | Ranura para tarjeta microSD |
| Interfaces de Expansión | Conectores Gravity de 3 pines (analógico/PWM), conectores I2C |
| Conector Edge | Conector edge compatible con micro:bit |
| Interfaces Soportadas | GPIO, ADC, PWM, I2C, SPI, UART |
| Voltaje de Operación | Entrada de 5 V vía USB-C |
| Nivel Lógico | 3.3 V |
| Corriente Típica | Hasta ~2 A |
| Dimensiones de la Placa | Aproximadamente 51.6 mm × 83 mm × 13 mm |
Programando el UNIHIKER M10
Existen varias aplicaciones que puedes usar para programar el UNIHIKER M10, como Jupyter Notebook, Mind+, VSCode, Python IDLE o Thonny. Para instrucciones detalladas sobre cómo configurar estas aplicaciones, consulta la Getting Started sección de la documentación del UNIHIKER.
Instalando Thonny
Personalmente encontré Thonny la más fácil de usar para un proyecto pequeño como el de este tutorial. Para instrucciones sobre cómo instalarla, consulta la Download and Install sección Thonny de la documentación del UNIHIKER.
Conectando Thonny al UNIHIKER M10
Después de instalar Thonny, conecta tu UNIHIKER M10 al ordenador con el cable USB. Luego abre Thonny y haz clic en «Run -> Select interpreter …»:

Se abrirá un cuadro de diálogo donde debes elegir «Remote Python 3 (SSH)» como intérprete. En Host escribe «10.1.2.3», en Username escribe «root» y el método de autenticación es «password»:

Después de hacer clic en «Run -> Stop/Restart backend», Thonny se conectará a tu UNIHIKER M10 y podrás editar y ejecutar programas Python en él.

Instalando Putty y la librería OpenAI
A continuación necesitaremos una herramienta que nos permita instalar librerías Python, como la OpenAI librería en el UNIHIKER M10. Intenté instalar librerías vía Thonny («Manage Packages», «Open System Shell…») pero no pude hacerlo funcionar.
En su lugar usé Putty. Para instrucciones de instalación consulta la SSH Tools de la documentación del UNIHIKER. Una vez instalado, abre Putty y crea una sesión con 10.1.2.3 como HOST:

Luego haz clic en el botón «Open» y en la consola de Putty introduce «root» como usuario y «dfrobot» como contraseña:

Ahora puedes instalar la librería OpenAI con el comando «pip install openai»:

Si faltan otras librerías Python, puedes instalarlas de la misma forma. Ten en cuenta que el UNIHIKER M10 debe estar conectado vía cable USB.
Configurando Wi-Fi
Finalmente, también necesitamos configurar la conexión Wi-Fi para que nuestro Asistente de Voz tenga acceso a internet y pueda llamar a las herramientas AI de OpenAI.
Para ello, abre un navegador web y escribe «10.1.2.3» en la barra de direcciones. Verás una página con un elemento «Network Settings» en la barra lateral. Haz clic y escribe tus credenciales Wi-Fi en el diálogo a la derecha:

Obteniendo la clave API de OpenAI
Nuestro Asistente de Voz usará modelos AI proporcionados por OpenAI. Por lo tanto, necesitarás una cuenta OpenAI. Ve a https://platform.openai.com y regístrate con un correo electrónico o una cuenta existente de Google o Microsoft.
Después de verificar tu correo y completar la configuración inicial, inicia sesión en el panel de OpenAI, platform.openai.com/api-keys y encuentra o crea tu clave API (=SECRET KEY) como se muestra a continuación:

La clave API es una cadena única y larga, que comienza con «sk-proj-«, necesaria para autenticar tus solicitudes API (ver más abajo). Luego deberás copiar esta cadena completa en el código del Asistente de Voz.
sk-proj-xcA.......................OtDu0U
Eso es todo lo que realmente necesitas, pero te recomiendo establecer un límite de uso para tu cuenta. Esto asegura que no termines con una factura costosa por un error en tu código (por ejemplo, enviando cientos de solicitudes).
Puedes establecer Límites de Uso y también consultar los Precios (Costos) de los diferentes modelos AI en la pestaña Billing (platform.openai.com/settings/organization/billing).
Ahora estamos listos para escribir el código del Asistente de Voz.
Código para el Asistente de Voz
En Thonny crea un archivo nuevo, yo lo llamé «assistant_tk.py» y copia y pega el código siguiente.

Este código implementa un asistente de voz. Graba audio mientras se mantiene presionado el botón A, transcribe el habla a texto usando el modelo Whisper de OpenAI, envía el texto a un modelo de lenguaje grande (LLM) basado en GPT para obtener una respuesta, y muestra tanto la pregunta como la respuesta en la interfaz gráfica 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()
Importaciones
El código comienza importando varios módulos necesarios para su funcionamiento. Incluye librerías estándar como time, threading y io para temporización, ejecución concurrente y manejo de flujos de bytes. También importa numpy para operaciones numéricas sobre datos de audio, pyaudio para grabación de audio, y wave para manejo del formato WAV.
El cliente Python de OpenAI se importa para interactuar con la API de OpenAI. Se importa el módulo específico de UNIHIKER button_a para detectar pulsaciones de botones. Finalmente, se importan tkinter y ttk para crear la GUI, y List de typing se usa para anotaciones de tipos.
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
Constantes e Inicialización del Cliente
Se definen varias constantes para configurar los parámetros de grabación de audio, como la clave API para OpenAI, el índice del dispositivo de entrada de audio, la tasa de muestreo, el número de canales y el tamaño de los fragmentos para el buffer de audio. Luego se crea un objeto cliente de OpenAI usando la clave API proporcionada, habilitando la comunicación con los servicios de OpenAI.
API_KEY = "sk-proj-my-api-key" DEVICE_INDEX = 2 SAMPLE_RATE = 16000 CHANNELS = 1 CHUNK = 1024 client = OpenAI(api_key=API_KEY)
Ten en cuenta que debes reemplazar el valor ficticio «sk-proj-my-api-key» en API_KEY por tu clave API de OpenAI.
Interfaz Gráfica de Usuario (GUI)
La GUI está construida usando tkinter. Se crea una ventana principal con un título y tamaño fijo. Se añade una etiqueta de estado para informar al usuario sobre el estado actual, como indicar que mantenga presionado el botón A para hablar o mostrar mensajes de progreso.

Debajo de la etiqueta de estado, se proporciona un cuadro de texto con barra de desplazamiento para mostrar la pregunta transcrita y la respuesta del asistente. El cuadro de texto está configurado como solo lectura, deshabilitando interacciones del ratón que modifiquen su contenido.
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)
Funciones de Estado y Visualización
Dos funciones auxiliares gestionan las actualizaciones de la GUI. La función set_status() actualiza el texto de la etiqueta de estado y fuerza la actualización inmediata de la GUI. La función show_answer() limpia el cuadro de texto e inserta nuevo texto, luego desplaza hasta el final para asegurar que el contenido más reciente sea visible.
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)
Funciones Auxiliares de Audio
El código incluye varias funciones para manejar el procesamiento de audio. La función normalize() toma bytes de audio PCM en bruto, los convierte a muestras en punto flotante y las escala para que la amplitud máxima alcance el 90% del rango máximo de enteros de 16 bits. Esta normalización asegura un volumen de audio consistente para la transcripción.
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 función record_while_held() graba audio desde el dispositivo de entrada especificado mientras se mantiene presionado el botón A.
Inicializa un flujo PyAudio con los parámetros configurados y espera hasta que se presione el botón A. Luego, lee continuamente fragmentos de audio y los añade a una lista hasta que se suelta el botón. Los cuadros de audio grabados se concatenan y se devuelven como bytes PCM en bruto.
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 función pcm_to_wav() convierte los bytes PCM en bruto a un flujo de bytes en formato WAV usando el módulo wave. Esto es necesario porque la API de transcripción de OpenAI espera archivos de audio en formatos estándar como 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()
Interacción con la API de OpenAI
Dos funciones manejan la comunicación con la API de OpenAI. La función transcribe() envía los bytes de audio WAV al modelo Whisper para obtener una transcripción de texto. Actualiza la etiqueta de estado para indicar que la transcripción está en progreso y devuelve el texto reconocido.
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 función ask_gpt() envía la pregunta transcrita a un modelo de chat basado en GPT. Establece el estado en «pensando…» mientras espera la respuesta. Luego, construye el mensaje del sistema que instruye al modelo a ser un asistente útil. Finalmente, la función devuelve el texto de la respuesta del asistente.
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
Bucle Principal del Asistente
La funcionalidad principal se ejecuta dentro de la función assistant_loop(), que corre en un hilo separado para mantener la GUI receptiva.
Espera continuamente a que el usuario mantenga presionado el botón A y graba audio mientras el botón está presionado. Si no se captura audio, reinicia el bucle. De lo contrario, normaliza el audio, lo convierte a formato WAV, transcribe el habla y consulta el modelo GPT para obtener una respuesta.
Después del procesamiento, actualiza el estado a «listo» y muestra tanto la pregunta como la respuesta en el cuadro de texto.
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)
Iniciando el Asistente y el Bucle Principal de la GUI
Finalmente, el bucle del asistente se inicia en un hilo daemon, permitiendo que corra en segundo plano. Luego se inicia el bucle principal de eventos de la GUI con root.mainloop(), que mantiene la ventana abierta y receptiva a las interacciones del usuario.
threading.Thread(target=assistant_loop, daemon=True).start() root.mainloop()
Mensajes de error
Si ejecutas el código, puede que veas las siguientes advertencias en la consola de 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
Esto ocurre porque al inicializar pyaudio.PyAudio(), la biblioteca ALSA (Advanced Linux Sound Architecture) subyacente escanea tu sistema en busca de todos los dispositivos y configuraciones de audio posibles (como sonido envolvente 5.1, HDMI o S/PDIF digital).
Como el UNIHIKER M10 es un ordenador de placa única compacto, no tiene «altavoces traseros» ni «puertos de módem», por lo que ALSA se queja de no encontrarlos. Si tu código realmente funciona y maneja audio después de estas advertencias, tu configuración está bien.
Conclusiones
En este tutorial aprendiste a implementar un Asistente de Voz en el UNIHIKER M10 usando los servicios de OpenAI. Para otros ejemplos de código más simples, consulta la Python Coding Examples de la documentación del UNIHIKER.
Ten en cuenta que podrías ampliar y mejorar fácilmente el Asistente de Voz añadiendo un historial de chat y funcionalidad para llamar a herramientas. Además, usé Tkinter para crear una interfaz sencilla, pero para una GUI mejor podrías usar QtPy, que también está preinstalado en el UNIHIKER M10.
Además, podrías añadir un altavoz, ya sea por USB, Bluetooth o salida de línea, para que tu Asistente de Voz responda con audio. Consulta el tutorial AI Language Tutor with UNIHIKER M10 para un ejemplo.
Para un Chatbot de Visión que pueda ver y responder preguntas sobre imágenes, consulta nuestro tutorial Vision Chatbot with DFRobot ESP32-S3 AI Camera and OpenAI. Y para más ejemplos de IA, consulta la AI Projects sección de la documentación del UNIHIKER.
Si tienes alguna pregunta, no dudes en dejarla en la sección de comentarios.
¡Feliz bricolaje! 😉

