O UNIHIKER M10 é uma placa compacta que integra um sistema baseado em Linux, sensores e interfaces de hardware numa única placa. Contém um processador quad-core Arm Cortex-A35 com 512 MB de RAM e 16 GB de armazenamento eMMC.
A placa também inclui um ecrã tátil de 2,8 polegadas com resolução de 240 × 320 pixels, conectividade Wi-Fi e Bluetooth. Os sensores integrados incluem um sensor de luz, acelerómetro, giroscópio e microfone.
Como a placa corre Linux e suporta programação em Python, pode ser usada para muitas aplicações. Neste tutorial, vai aprender a implementar um Assistente de Voz na placa UNIHIKER M10. O seguinte vídeo curto demonstra o Assistente de Voz:
Pode ser necessário aumentar o volume do seu computador para ouvir a minha voz. Note também que este assistente não tem saída de voz, embora seja fácil de adicionar.
Peças Necessárias
Vai precisar de uma placa UNIHIKER M10. Pode adquiri-la na DFRobot ou na Amazon, por exemplo:

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 do Unihiker M10
O UNIHIKER M10 é construído em torno do chip Rockchip RK3308. Este chip usa quatro núcleos Arm Cortex-A35 e opera a uma frequência de até 1,2 GHz. O processador corre um sistema operativo Debian Linux completo com Python 3.7 pré-instalado. Também estão pré-instaladas várias bibliotecas científicas Python como Numpy, Matplotlib, Jupyter, Pandas, Seaborn, Tensorflow e outras.
A placa inclui 512 MB de memória DDR3 para o sistema. Esta memória é usada pelo sistema operativo Linux e pelas aplicações do utilizador. O armazenamento dos programas é fornecido por 16 GB de memória flash eMMC integrada.
Além do processador principal, a placa integra um microcontrolador GD32VF103C8T6 como co-processador. Este contém 64 KB de memória flash e 32 KB de SRAM. O microcontrolador gere muitas tarefas a nível de hardware, como gestão de sensores, controlo de GPIO e operação de atuadores.
Ecrã e Interface do Utilizador
O UNIHIKER M10 vem com um ecrã tátil a cores de 2,8 polegadas. O ecrã tem uma resolução de 240 × 320 pixels. A placa inclui um botão Home e dois botões programáveis de utilizador rotulados A e B, como mostrado abaixo:

Sensores Integrados
Os sensores integrados incluem um sensor de luz, acelerómetro, giroscópio e microfone. A expansão de hardware está disponível através de portas USB, conectores Gravity para sensores e um conector edge compatível com micro:bit que expõe interfaces GPIO, I2C, SPI e UART.

Além disso, um buzzer passivo e um LED de estado fornecem saída áudio e visual simples para notificações e depuração. Um altifalante externo pode ser ligado via porta USB.
Conectividade e Rede
A comunicação sem fios está disponível através de um módulo combinado Wi-Fi e Bluetooth. A placa suporta Wi-Fi a 2,4 GHz e conectividade Bluetooth 4.0. O Wi-Fi pode ser configurado via uma interface Web em 10.1.2.3.
Interfaces e Opções de Expansão
A placa oferece várias interfaces físicas para ligar hardware externo. Um conector USB Type-C é usado para alimentação e comunicação com um computador. A placa pode ser alimentada com 5 V através desta porta.
Uma porta USB Type-A host permite a ligação de periféricos USB como dispositivos de armazenamento, teclados ou adaptadores. A placa também inclui um slot para cartão microSD para expandir a capacidade de armazenamento ou transferir ficheiros.
Além disso, estão disponíveis múltiplos conectores de expansão para sensores e atuadores. Conectores Gravity de 3 pinos fornecem acesso a entradas PWM e analógicas. Conectores dedicados de 4 pinos fornecem comunicação I2C para sensores e módulos digitais.

Conector Edge
A placa também possui um conector edge compatível com micro:bit. Este conector expõe até 19 pinos GPIO e suporta interfaces como I2C, UART e SPI. Também fornece várias entradas ADC e saídas PWM para controlo de hardware externo. A imagem abaixo mostra o pinout do conector edge:

Esquemas
Para informações técnicas mais detalhadas, consulte os Esquemas do UNIHIKER M10 ligados abaixo:
Especificações Técnicas
A tabela seguinte resume as Especificações Técnicas da placa UNIHIKER M10:
| Característica | Especificação |
|---|---|
| Processador Principal | Rockchip RK3308 |
| Arquitetura CPU | Quad-core Arm Cortex-A35 |
| Frequência CPU | Até 1,2 GHz |
| Memória do Sistema | 512 MB DDR3 |
| Armazenamento Interno | 16 GB eMMC |
| Co-Processador | Microcontrolador GD32VF103C8T6 RISC-V |
| Velocidade do MCU | Até 108 MHz |
| Memória do MCU | 64 KB Flash, 32 KB SRAM |
| Sistema Operativo | Debian Linux |
| Ecrã | Ecrã tátil de 2,8 polegadas |
| Resolução do Ecrã | 240 × 320 pixels |
| Conectividade Sem Fios | Wi-Fi 802.11 b/g/n (2.4 GHz), Bluetooth 4.0 |
| Sensores | Sensor de luz, IMU de 6 eixos (acelerómetro + giroscópio), microfone |
| Entradas do Utilizador | Botão Home, botões de utilizador A/B, ecrã tátil |
| Saída de Áudio | Buzzer passivo |
| Portas USB | 1 × USB-C (alimentação e dados), 1 × USB-A host |
| Expansão de Armazenamento | Slot para cartão microSD |
| Interfaces de Expansão | Conectores Gravity de 3 pinos (analógico/PWM), conectores I2C |
| Conector Edge | Conector edge compatível com micro:bit |
| Interfaces Suportadas | GPIO, ADC, PWM, I2C, SPI, UART |
| Tensão de Funcionamento | Entrada de 5 V via USB-C |
| Nível Lógico | 3,3 V |
| Corrente Típica | Até ~2 A |
| Dimensões da Placa | Aproximadamente 51,6 mm × 83 mm × 13 mm |
Programar o UNIHIKER M10
Existem várias aplicações que pode usar para programar o UNIHIKER M10, como Jupyter Notebook, Mind+, VSCode, Python IDLE ou Thonny. Para instruções detalhadas sobre como configurar estas aplicações, veja a Getting Started secção da documentação do UNIHIKER.
Instalar o Thonny
Pessoalmente, achei Thonny o mais fácil de usar para um projeto pequeno como este tutorial. Para instruções de instalação, veja a Download and Install secção Thonny da documentação do UNIHIKER.
Ligar o Thonny ao UNIHIKER M10
Após instalar o Thonny, ligue o seu UNIHIKER M10 ao computador com o cabo USB. Depois abra o Thonny e clique em “Run -> Select interpreter …”:

Isto abrirá uma caixa de diálogo onde deve escolher “Remote Python 3 (SSH)” como interpretador. Em Host insira “10.1.2.3”, no Username escreva “root” e o método de autenticação é “password”:

Depois de clicar em “Run -> Stop/Restart backend”, o Thonny estará ligado ao seu UNIHIKER M10 e poderá editar e executar programas Python nele.

Instalar Putty e a biblioteca OpenAI
De seguida, vamos precisar de uma ferramenta que nos permita instalar bibliotecas Python, como a OpenAI biblioteca no UNIHIKER M10. Tentei instalar bibliotecas via Thonny (“Manage Packages”, “Open System Shell…”) mas não consegui.
Em vez disso, usei Putty. Para instruções de instalação veja a SSH Tools da documentação do UNIHIKER. Depois de instalado, abra o Putty e crie uma Sessão com 10.1.2.3 como HOST:

Depois clique no botão “Open” e na shell do Putty insira “root” como nome de utilizador e “dfrobot” como palavra-passe:

Agora pode instalar a biblioteca OpenAI com o comando “pip install openai”:

Se faltar alguma outra biblioteca Python, pode instalá-la da mesma forma. Note que o UNIHIKER M10 deve estar ligado via cabo USB.
Configurar o Wi-Fi
Finalmente, também precisamos de configurar a ligação Wi-Fi, para que o nosso Assistente de Voz tenha acesso à internet para chamar as ferramentas AI da OpenAI.
Para isso, abra um navegador e insira “10.1.2.3” na barra de endereços. Vai ver uma página com um item “Network Settings” na barra lateral. Clique nele e insira as credenciais do seu Wi-Fi no diálogo à direita:

Obter a Chave API da OpenAI
O nosso Assistente de Voz vai usar modelos AI fornecidos pela OpenAI. Por isso, vai precisar de uma conta OpenAI. Vá a https://platform.openai.com e registe-se com um endereço de email ou uma conta Google ou Microsoft existente.
Depois de verificar o seu email e completar a configuração inicial, faça login no painel da OpenAI, platform.openai.com/api-keys e encontre ou crie a sua Chave API (=SECRET KEY) como mostrado abaixo:

A Chave API é uma cadeia única e longa, começando com “sk-proj-“, necessária para autenticar os seus pedidos API (veja abaixo). Mais tarde, terá de copiar esta cadeia inteira para o código do Assistente de Voz.
sk-proj-xcA.......................OtDu0U
Isto é tudo o que realmente precisa, mas recomendo definir um limite de uso para a sua conta. Isto garante que não acaba com uma conta cara devido a um bug no seu código (ex. enviar centenas de pedidos).
Pode definir Limites de Uso e também consultar os Preços (Custos) dos diferentes modelos AI na aba Billing (platform.openai.com/settings/organization/billing).
Agora estamos prontos para escrever o código do Assistente de Voz.
Código para o Assistente de Voz
No Thonny crie um ficheiro novo, eu chamei o meu “assistant_tk.py” e copie e cole o código abaixo.

Este código implementa um assistente de voz. Grava áudio enquanto o botão A está pressionado, transcreve a fala para texto usando o modelo Whisper da OpenAI, envia o texto para um modelo de linguagem GPT para obter uma resposta, e mostra a pergunta e a resposta na interface gráfica do 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()
Importações
O código começa por importar vários módulos necessários para a sua funcionalidade. Inclui bibliotecas padrão como time, threading, e io para temporização, execução concorrente e manipulação de fluxos de bytes. Também importa numpy para operações numéricas em dados de áudio, pyaudio para gravação de áudio, e wave para manipulação do formato WAV.
O cliente Python da OpenAI é importado para interagir com a API da OpenAI. O módulo específico do UNIHIKER button_a é importado para detetar pressões dos botões. Finalmente, tkinter e ttk são importados para criar a GUI, e List do typing é usado para tipagem.
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 Inicialização do Cliente
São definidas várias constantes para configurar os parâmetros de gravação de áudio, como a chave API para OpenAI, o índice do dispositivo de entrada de áudio, taxa de amostragem, número de canais e tamanho do buffer de áudio. Um objeto cliente OpenAI é criado com a chave API fornecida, permitindo comunicação com os serviços OpenAI.
API_KEY = "sk-proj-my-api-key" DEVICE_INDEX = 2 SAMPLE_RATE = 16000 CHANNELS = 1 CHUNK = 1024 client = OpenAI(api_key=API_KEY)
Note que deve substituir o valor fictício “sk-proj-my-api-key” da API_KEY pela sua chave API da OpenAI!
Interface Gráfica do Utilizador (GUI)
A GUI é construída usando tkinter. É criada uma janela principal com título e tamanho fixo. Um rótulo de estado é adicionado para informar o utilizador sobre o estado atual, como pedir para manter o botão A pressionado para falar ou mostrar mensagens de progresso.

Abaixo do rótulo de estado, há uma caixa de texto com barra de rolagem para mostrar a pergunta transcrita e a resposta do assistente. A caixa de texto está configurada para ser só de leitura, desativando interações do rato que modifiquem o seu conteúdo.
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)
Funções de Estado e Exibição
Duas funções auxiliares gerem as atualizações da GUI. A função set_status() atualiza o texto do rótulo de estado e força a GUI a atualizar imediatamente. A função show_answer() limpa a caixa de texto, insere novo texto e faz scroll até ao fim para garantir que o conteúdo mais recente está visível.
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)
Auxiliares de Áudio
O código inclui várias funções para processar áudio. A função normalize() recebe bytes PCM brutos, converte-os em amostras em ponto flutuante e escala para que a amplitude máxima atinja 90% do máximo de um inteiro de 16 bits. Esta normalização assegura volume consistente para a transcrição.
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()
A função record_while_held() grava áudio do dispositivo de entrada especificado enquanto o botão A está pressionado.
Inicializa um fluxo PyAudio com os parâmetros configurados e espera até o botão A ser pressionado. Depois, lê continuamente blocos de áudio e adiciona-os a uma lista até o botão ser libertado. Os frames de áudio gravados são concatenados e retornados como bytes brutos 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)
A função pcm_to_wav() converte os bytes PCM brutos num fluxo de bytes em formato WAV usando o módulo wave. Isto é necessário porque a API de transcrição da OpenAI espera ficheiros áudio em formatos padrão 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()
Interação com a API OpenAI
Duas funções gerem a comunicação com a API da OpenAI. A função transcribe() envia os bytes de áudio WAV para o modelo Whisper para obter a transcrição em texto. Atualiza o rótulo de estado para indicar que a transcrição está em progresso e retorna o texto reconhecido.
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
A função ask_gpt() envia a pergunta transcrita para um modelo de chat baseado em GPT. Define o estado para “a pensar…” enquanto espera pela resposta. Depois, constrói a mensagem do sistema que instrui o modelo a ser um assistente útil. Finalmente, retorna o texto da resposta do 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
Loop Principal do Assistente
A funcionalidade principal corre dentro da função assistant_loop(), que é executada numa thread separada para manter a GUI responsiva.
Espera continuamente que o utilizador mantenha o botão A pressionado e grava áudio enquanto o botão está pressionado. Se não for capturado áudio, reinicia o loop. Caso contrário, normaliza o áudio, converte para formato WAV, transcreve a fala e consulta o modelo GPT para obter uma resposta.
Após o processamento, atualiza o estado para “pronto” e mostra a pergunta e a resposta na caixa 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)
Iniciar o Assistente e o Mainloop da GUI
Finalmente, o loop do assistente é iniciado numa thread daemon, permitindo que corra em segundo plano. O loop principal de eventos da GUI é então iniciado com root.mainloop(), que mantém a janela aberta e responsiva às interações do utilizador.
threading.Thread(target=assistant_loop, daemon=True).start() root.mainloop()
Mensagens de Erro
Se executar o código, pode ver os seguintes avisos no console do 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
Isto acontece porque ao inicializar pyaudio.PyAudio(), a biblioteca ALSA (Advanced Linux Sound Architecture) subjacente verifica todos os dispositivos e configurações de áudio possíveis no sistema (como som surround 5.1, HDMI ou S/PDIF digital).
Como o UNIHIKER M10 é um computador de placa única compacto, não tem “altifalantes traseiros” nem “portas de modem”, por isso o ALSA queixa-se de não os encontrar. Se o seu código realmente corre e processa áudio após estes avisos, a sua configuração está a funcionar bem.
Conclusões
Neste tutorial aprendeu a implementar um Assistente de Voz no UNIHIKER M10 usando os serviços da OpenAI. Para outros exemplos de código mais simples, veja a Python Coding Examples da documentação do UNIHIKER.
Note que pode facilmente expandir e melhorar o Assistente de Voz adicionando histórico de chat e funcionalidade de chamada a ferramentas. Também usei Tkinter para criar uma interface simples, mas para uma GUI melhor pode usar QtPy, que também está pré-instalado no UNIHIKER M10.
Além disso, pode adicionar um altifalante, via USB, Bluetooth ou saída de linha, para que o seu Assistente de Voz responda com áudio. Veja o tutorial AI Language Tutor with UNIHIKER M10 para um exemplo.
Para um Chatbot de Visão que pode ver e responder a perguntas sobre imagens, veja o nosso tutorial Vision Chatbot with DFRobot ESP32-S3 AI Camera and OpenAI. E para mais exemplos de AI, veja a AI Projects secção da documentação do UNIHIKER.
Se tiver alguma dúvida, sinta-se à vontade para deixar nos comentários.
Boas experiências de construção 😉

