Índice:
A Inteligência Artificial está cada vez mais presente em dispositivos embarcados e projetos eletrônicos. Neste projeto, vamos criar um agente de IA utilizando a Unihiker K10 capaz de:
- Escutar comandos de voz
- Converter voz em texto
- Enviar a pergunta para uma Inteligência Artificial
- Receber a resposta da IA
- Exibir a resposta na tela da Unihiker K10
Tudo isso utilizando a poderosa API da Groq, que oferece modelos de IA extremamente rápidos.
Como o projeto funciona
O fluxo do sistema é o seguinte:
- O usuário fala a palavra de ativação (“Hi Telly”)
- A Unihiker K10 inicia a gravação de áudio
- O áudio é salvo no cartão SD
- O arquivo é enviado para a API da Groq
- O modelo Whisper realiza a transcrição
- O texto transcrito é enviado para um modelo LLM
- A IA gera uma resposta
- A resposta é exibida na tela
Materiais Utilizados
- Unihiker K10
- Cartão MicroSD
- Conexão Wi-Fi
- Conta gratuita na Groq
- Arduino IDE
Criando sua conta na Groq
Acesse:
Passo 1
Clique em “Sign Up”.
Passo 2
Crie sua conta utilizando:
- Conta Google
- GitHub
Passo 3
Após entrar no painel, clique em:
API Keys
Passo 4
Clique em:
Create API Key
Passo 5
Defina um nome para sua chave.
Exemplo:
AgenteIA-Unihiker
Passo 6
Copie a chave gerada.
Ela terá um formato parecido com:
gsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Guarde essa chave em local seguro.
Configurando o projeto
No código substitua:
const char* ssid = “SEU_WIFI”;
const char* password = “SUA_SENHA_WIFI”;
const char* groqApiKey = “SUA_API_GROQ”;
Pelos seus dados.
Modelos utilizados
Transcrição de Áudio
Modelo:
whisper-large-v3-turbo
Responsável por transformar voz em texto.
Inteligência Artificial
Modelo:
llama-3.1-8b-instant
Responsável por responder às perguntas.
Funcionamento da Transcrição
Quando o áudio é gravado:
music.recordSaveToTFCard(“S:/sound.wav”, 5);
O arquivo WAV é salvo no cartão SD.
Em seguida ele é enviado para:
https://api.groq.com/openai/v1/audio/transcriptions
Utilizando o modelo Whisper.
A resposta recebida possui formato:
{
“text”: “Qual a capital do Brasil?”
}
Funcionamento da IA
Após a transcrição:
String resposta = perguntarIA(texto);
A pergunta é enviada para:
https://api.groq.com/openai/v1/chat/completions
Utilizando:
doc[“model”] = “llama-3.1-8b-instant”;
A IA processa a pergunta e retorna uma resposta curta para ser exibida na tela.
Código do Projeto
Substitua apenas as credenciais de Wi-Fi e a API Key.
const char* ssid = “SEU_WIFI”;
const char* password = “SUA_SENHA_WIFI”;
const char* groqApiKey = “SUA_API_GROQ”;
Código Completo:
#include "asr.h"
#include "unihiker_k10.h"
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <SD.h>
UNIHIKER_K10 k10;
ASR asr;
Music music;
uint8_t screen_dir = 2;
const char* ssid = "SEU_WIFI";
const char* password = "SUA_SENHA_WIFI";
const char* groqApiKey = "SUA_API_GROQ";
String wavPath = "/sound.wav";
String removerAcentos(String texto) {
texto.replace("á", "a"); texto.replace("à", "a"); texto.replace("ã", "a"); texto.replace("â", "a");
texto.replace("é", "e"); texto.replace("ê", "e");
texto.replace("í", "i");
texto.replace("ó", "o"); texto.replace("ô", "o"); texto.replace("õ", "o");
texto.replace("ú", "u");
texto.replace("ç", "c");
texto.replace("Á", "A"); texto.replace("É", "E"); texto.replace("Í", "I");
texto.replace("Ó", "O"); texto.replace("Ú", "U"); texto.replace("Ç", "C");
return texto;
}
void mostrar(String texto) {
texto = removerAcentos(texto);
k10.canvas->canvasClear();
k10.canvas->canvasText("AGENTE IA", 0, 0xFF0000);
int row = 2;
int maxChars = 18;
while (texto.length() > 0 && row < 10) {
String linha;
if (texto.length() > maxChars) {
int corte = texto.lastIndexOf(' ', maxChars);
if (corte <= 0) corte = maxChars;
linha = texto.substring(0, corte);
texto = texto.substring(corte);
texto.trim();
} else {
linha = texto;
texto = "";
}
k10.canvas->canvasText(linha, row, 0x0000FF);
row++;
}
k10.canvas->updateCanvas();
}
String transcreverGroq() {
File audioFile = SD.open(wavPath, FILE_READ);
if (!audioFile) return "Erro ao abrir audio";
String boundary = "----K10Boundary";
String head =
"--" + boundary + "\r\n"
"Content-Disposition: form-data; name=\"model\"\r\n\r\n"
"whisper-large-v3-turbo\r\n"
"--" + boundary + "\r\n"
"Content-Disposition: form-data; name=\"file\"; filename=\"sound.wav\"\r\n"
"Content-Type: audio/wav\r\n\r\n";
String tail = "\r\n--" + boundary + "--\r\n";
int contentLength = head.length() + audioFile.size() + tail.length();
WiFiClientSecure client;
client.setInsecure();
if (!client.connect("api.groq.com", 443)) {
audioFile.close();
return "Erro conexao Groq";
}
client.println("POST /openai/v1/audio/transcriptions HTTP/1.1");
client.println("Host: api.groq.com");
client.print("Authorization: Bearer ");
client.println(groqApiKey);
client.print("Content-Type: multipart/form-data; boundary=");
client.println(boundary);
client.print("Content-Length: ");
client.println(contentLength);
client.println("Connection: close");
client.println();
client.print(head);
uint8_t buffer[1024];
while (audioFile.available()) {
int len = audioFile.read(buffer, sizeof(buffer));
client.write(buffer, len);
}
audioFile.close();
client.print(tail);
String response = "";
unsigned long timeout = millis();
while (client.connected() && millis() - timeout < 25000) {
while (client.available()) {
char c = client.read();
response += c;
timeout = millis();
}
}
client.stop();
int jsonStart = response.indexOf("{");
if (jsonStart < 0) return "Sem JSON";
String json = response.substring(jsonStart);
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeJson(doc, json);
if (error) return "Erro JSON";
String texto = doc["text"].as<String>();
if (texto.length() == 0) return "Sem texto";
return texto;
}
String perguntarIA(String pergunta) {
WiFiClientSecure client;
client.setInsecure();
HTTPClient http;
http.begin(client, "https://api.groq.com/openai/v1/chat/completions");
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", "Bearer " + String(groqApiKey));
DynamicJsonDocument doc(4096);
doc["model"] = "llama-3.1-8b-instant";
doc["temperature"] = 0.4;
doc["max_tokens"] = 120;
JsonArray messages = doc.createNestedArray("messages");
JsonObject systemMsg = messages.createNestedObject();
systemMsg["role"] = "system";
systemMsg["content"] = "Voce e um assistente curto, direto e didatico. Responda em portugues do Brasil com no maximo 3 frases. Nao use acentos.";
JsonObject userMsg = messages.createNestedObject();
userMsg["role"] = "user";
userMsg["content"] = pergunta;
String body;
serializeJson(doc, body);
int httpCode = http.POST(body);
if (httpCode != 200) {
String erro = http.getString();
Serial.println("Erro IA:");
Serial.println(erro);
http.end();
return "Erro IA";
}
String payload = http.getString();
http.end();
DynamicJsonDocument respostaDoc(8192);
DeserializationError error = deserializeJson(respostaDoc, payload);
if (error) return "Erro JSON IA";
String resposta = respostaDoc["choices"][0]["message"]["content"].as<String>();
if (resposta.length() == 0) return "Sem resposta";
return resposta;
}
void setup() {
Serial.begin(115200);
k10.begin();
k10.initScreen(screen_dir);
k10.creatCanvas();
k10.initSDFile();
mostrar("Conectando WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
mostrar("WiFi conectado");
delay(1000);
mostrar("Iniciando voz");
asr.asrInit(CONTINUOUS, EN_MODE, 6000);
while (asr._asrState == 0) {
delay(100);
}
mostrar("Diga Hi Telly");
Serial.println("Diga Hi Telly para fazer uma pergunta");
}
void loop() {
if (asr.isWakeUp()) {
Serial.println("Wake word reconhecida");
mostrar("Pode falar");
delay(700);
mostrar("Gravando");
music.recordSaveToTFCard("S:/sound.wav", 5);
mostrar("Transcrevendo");
String texto = transcreverGroq();
texto = removerAcentos(texto);
Serial.print("Pergunta transcrita: ");
Serial.println(texto);
mostrar("Pensando");
String resposta = perguntarIA(texto);
resposta = removerAcentos(resposta);
Serial.print("Resposta final: ");
Serial.println(resposta);
mostrar(resposta);
// Mantem a resposta na tela ate falar Hi Telly novamente
}
delay(50);
}
Possíveis Melhorias
A partir dessa base você pode criar:
- Assistente pessoal
- Chatbot embarcado
- Automação residencial com voz
- Controle de dispositivos por linguagem natural
- Robôs inteligentes
- Sistemas educacionais
- IA embarcada para indústria
Conclusão
Este projeto mostra como é possível integrar eletrônica, sistemas embarcados e Inteligência Artificial utilizando uma plataforma compacta como a Unihiker K10.
Com poucas linhas de código conseguimos capturar áudio, utilizar reconhecimento de fala, acessar modelos avançados de IA e exibir respostas em tempo real.
Esse tipo de aplicação representa uma das áreas mais promissoras da tecnologia atualmente e demonstra como a combinação entre hardware e IA abre possibilidades praticamente ilimitadas para novos projetos.
Saiba mais sobre a parceria Saravati e Sara Educação
Este “Guia de Montagem” é uma colaboração especial entre a Saravati e a Sara Educação, criado pelo Professor Felipe Rosa. Nosso objetivo é enriquecer a comunidade de entusiastas da eletrônica, IoT e automação com recursos educacionais de alta qualidade. Através dessa parceria, buscamos inspirar e capacitar criadores em seus projetos, disponibilizando esses guias em nosso blog e nas redes sociais.
