CORAMO — COlaborativo Reprogramable Autónomo MOdular
Robot de doble brazo diseñado para asistir en tareas domésticas e industriales. Controlado por voz con IA completamente local, sin dependencias de la nube. Basado en Raspberry Pi 5 con GPUs discretas AMD RX 580.
| Componente | Detalle |
|---|---|
| SBC | Raspberry Pi 5 Model B (8GB) |
| OS | Ubuntu 24.04.4 LTS aarch64 |
| Kernel | 6.6.70-v8-16k+ (Coreforge, GPU patched) |
| GPU x2 | AMD Radeon RX 580 2048SP (8GB VRAM cada una) |
| Expansión PCIe | Suptronics X1011 M.2 PCIe Multiplexer |
| WiFi USB | MediaTek MT7921U (antena externa) |
| Audio | USB PnP Sound Device (PCM2902) |
| Microcontrolador | Arduino Mega 2560 (CH340) vía USB |
Pipeline completo de voz a voz con control de hardware:
Micrófono → Silero VAD (CPU, detecta habla)
→ whisper small (GPU 1, ~5s transcripción)
→ check "coramo" en texto → descarta si no está
→ Qwen3-4B Q4_K_M (GPU 0, ~1s inferencia)
→ tool_choice=required → mover_dedo/gesto/responder
→ Arduino Mega → PCA9685 → mano robótica (5 servos) [si acción física]
→ Piper TTS (CPU, es_ES-davefx) [si respuesta verbal]
→ Altavoz
Wake words: "coramo", "hola coramo", "hey coramo", "oye coramo"
Ejemplos:
- "coramo abre la mano" → gesto: todos los dedos a 0°
- "coramo cierra la mano" → gesto: todos los dedos a 180°
- "coramo mueve el índice a 90 grados" → mover_dedo(1, 90)
Optimizaciones de latencia:
- Streaming LLM→TTS — empieza a hablar en cuanto termina la primera oración, sin esperar la respuesta completa.
- Silero VAD — corta la grabación en cuanto el usuario deja de hablar (~1s de silencio), eliminando las esperas fijas de 8–14s.
- Overlap transcripción+grabación — mientras se graba la continuación (VAD, CPU), la transcripción del chunk inicial (GPU 1) corre en paralelo via
ThreadPoolExecutor, reduciendo ~1-3s de latencia. - KV cache warmup — al arrancar, el system prompt se pre-calienta en el KV cache. Las peticiones al LLM solo procesan los tokens del usuario.
- Sin TTS para comandos físicos — los gestos y movimientos de dedo se ejecutan sin síntesis de voz, eliminando ~2s de latencia por comando.
- tool_choice=required + tool responder() — el LLM siempre llama una tool, eliminando el fallo intermitente finish_reason=stop.
Parámetros añadidos a /boot/firmware/cmdline.txt:
amdgpu.num_kcq=0 amdgpu.lockup_timeout=180000
amdgpu.num_kcq=0— desactiva los async compute rings. Necesario porque las GPUs corren a PCIe x1 (multiplexor ASM1184e) — los compute rings tienen timeouts en GPU 1 sin este parámetro.amdgpu.lockup_timeout=180000— extiende el timeout del ringgfxa 3 minutos. Sin esto, el ringgfxde GPU 0 hace timeout durante inferencia LLM y el servidor llama-server cae conErrorDeviceLost.
- 01 - Conectividad de red
- 02 - Alimentación por DC jack
- 03 - GPU AMD RX 580 en RPi5
- 04 - Salida de video
- 05 - Whisper.cpp con GPU
- 06 - Asistente de voz
| Archivo | Descripción |
|---|---|
scripts/coramo-assistant.py |
Asistente de voz principal |
scripts/arduino.py |
Comunicación serial con Arduino (mover_dedo, gesto) |
arduino/coramo_servo.ino |
Sketch Arduino — PCA9685, 5 servos, comandos JSON |
scripts/debug_mano.py |
Debug interactivo de hardware de la mano robótica |
scripts/whisper-stream.sh |
Transcripción en tiempo real |
scripts/fix-firmware-zst.sh |
Descomprimir firmwares para kernel 6.6.x |
scripts/network-check.sh |
Verificar estado de red y failover |
config/coramo-assistant.service |
Servicio systemd del asistente |
- Conectividad de red con failover WiFi USB (fix: NM dispatcher desactiva powersave tras reconexión)
- Alimentación por DC jack sin advertencias
- Kernel con soporte amdgpu
- Dos GPU RX 580 operativas
- Salida de video por GPU
- Whisper small en GPU 1 (~5s transcripción)
- Pipeline simplificado: VAD → Whisper → check "coramo" → LLM (sin openWakeWord)
- LLM Qwen3-4B Q4_K_M con GPU 0 (~1s inferencia)
- Piper TTS en español
- Function calling → mano robótica 5 dedos via Arduino Mega + PCA9685
- Gestos: abre/cierra mano y control de dedo individual
- Silero VAD para detección de fin de habla
- amdgpu.lockup_timeout=180000 para prevenir crash de llama-server por ring gfx timeout
- Overlap transcripción+grabación (ThreadPoolExecutor) para reducir latencia
- KV cache warmup del system prompt al arrancar
- Eliminado TTS para comandos físicos exitosos (menor latencia)
- tool_choice=required + tool responder() — LLM siempre llama una tool, sin finish_reason=stop
- Fuzzy fallback en extract_question — "coramos" → extrae correctamente el comando