Hace un tiempo probé usar AtomVM, una máquina virtual ligera que permite ejecutar aplicaciones Elixir y Erlang directamente en microcontroladores como el ESP32-S3. La primera vez me apresuré y no comprendí bien algunos detalles, especialmente la preparación del firmware.
En esta ocasión vuelvo al inicio para entender y documentar el flujo correcto, enfocándome en empezar con AtomVM usando una imagen de firmware precompilada. La idea es simplificar la puesta en marcha sin compilar nada desde el código fuente.
Este artículo no entra en funciones avanzadas. Es una guía práctica para poner tu placa ESP32-S3 a funcionar con AtomVM y ejecutar código Elixir en hardware real lo antes posible.
Entorno y dispositivos objetivo
Placa objetivo: Seeed Studio XIAO ESP32-S3. LED integrado en GPIO 21 activo en nivel bajo.
Equipo anfitrión: Linux basado en Debian LMDE6, Elixir 1.17 con Erlang OTP 27, AtomVM v0.6.6 firmware precompilado, esptool 5.0 para flasheo, picocom 3.1 para monitor serie, Python 3.13 requerido por esptool.
Notas: esptool es una herramienta Python y requiere Python 3.x. Como usaremos una imagen precompilada de AtomVM no necesitas instalar ESP-IDF. Para compatibilidad de versiones de Elixir y OTP consulta las notas de versión.
Instalación de esptool
esptool es la utilidad oficial de línea de comandos para flashear firmware en placas ESP32. Recomendado instalar con pip para gestionar actualizaciones de forma sencilla. Comando sugerido: pip install esptool==5.0
La versión 5.x introduce opciones con guion en lugar de la sintaxis antigua con guion bajo. Verifica tener Python 3.x instalado.
Comprobar el puerto serie
Al conectar tu ESP32-S3 por USB en Linux aparecerá un dispositivo serie como por ejemplo dev ttyACM0 o dev ttyUSB0. Puedes averiguarlo con: dmesg | grep tty
Si ves algo como cdc_acm 1-1.4:1.0: ttyACM0: USB ACM device, usa dev ttyACM0.
Verificar esptool y la conexión con la placa
Comprueba que esptool está instalado y que se comunica con la placa: esptool.py version y luego esptool.py -p /dev/ttyACM0 flash-id. Si ambas operaciones funcionan, puedes flashear el firmware.
Descargar y flashear el firmware de AtomVM
Usaremos el binario precompilado desde GitHub Releases de AtomVM, así que no es necesario compilar. Imagen recomendada para ESP32-S3 v0.6.6.
Descarga de la imagen. Crea carpeta y entra: mkdir -p $HOME/Projects/atomvm && cd $_. Descarga con: curl -LO https://github.com/atomvm/AtomVM/releases/download/v0.6.6/AtomVM-esp32s3-elixir-v0.6.6.img
Borrar la flash recomendado: esptool.py --chip auto --port /dev/ttyACM0 --baud 921600 erase-flash
Escribir el firmware: esptool.py --chip auto --port /dev/ttyACM0 --baud 921600 write_flash 0x0 $HOME/Projects/atomvm/AtomVM-esp32s3-elixir-v0.6.6.img. Según la documentación de AtomVM el offset de arranque para ESP32-S3 es 0x0.
Construir y flashear una aplicación Elixir
Con AtomVM corriendo en tu ESP32-S3, ya puedes desplegar una app Elixir. Usaremos el clásico Blinky para flashear un archivo .avm que hace parpadear el LED integrado.
Obtener el proyecto de ejemplo: cd ~/Projects/atomvm y luego git clone https://github.com/atomvm/atomvm_examples.git y cd atomvm_examples/elixir/Blinky. Instala dependencias con mix deps.get.
Ajustar el pin GPIO para XIAO ESP32-S3: por defecto el ejemplo usa GPIO 2, pero el LED integrado de XIAO va al GPIO 21 y es activo en bajo. En lib blinky.ex establece @pin 21, configura :gpio.set_pin_mode(@pin, :output), inicia el bucle con nivel :low para encender el LED al ser activo en bajo, alterna con una función toggle entre :low y :high cada 1000 ms usando Process.sleep(1000), y escribe el nivel con :gpio.digital_write(pin, level). También puedes imprimir con :io.format para ver el estado del pin en el monitor serie.
Configurar mix.exs con el offset de la app: define en la sección atomvm el flash_offset 0x250000 junto al módulo de inicio. Sin este valor el ESP32-S3 no reconocerá tu app al arrancar.
Empaquetar la app: ejecuta mix atomvm.packbeam. Se generan archivos .avm como Blinky.avm, deps.avm y priv.avm.
Flashear la app: mix atomvm.esp32.flash --port /dev/ttyACM0. Esto escribe los .avm en la ubicación correcta sin tocar el firmware de AtomVM.
Deberías ver el LED parpadeando. Puedes visualizar un ejemplo animado desde este enlace: ver demostración del parpadeo.
Ver registros por el puerto serie
La app Blinky no solo enciende el LED, también imprime mensajes por serie. Para monitorizar en tiempo real usa picocom. Abre la consola con: picocom /dev/ttyACM0 --baud 115200. De inmediato verás líneas mostrando el pin y el nivel alternando cada segundo. Para salir de picocom pulsa Ctrl+A y luego Ctrl+X.
Cierre
Hemos recorrido el proceso completo para preparar una placa ESP32-S3 y ejecutar código Elixir con AtomVM, sin compilar firmware propio. Este enfoque facilita experimentar con Elixir embebido sin profundizar en ESP-IDF ni en los detalles internos de AtomVM. Como próximos pasos, prueba integrar sensores, mostrar datos o conectarte a la nube vía MQTT. Si estás pensando en llevar un prototipo IoT a producción y necesitas aplicaciones a medida para edge y backend, o quieres desplegar la telemetría en la nube, considera nuestros servicios cloud AWS y Azure.
Enlaces
AtomVM en GitHub. Guía de inicio de AtomVM. Notas de versión de AtomVM. Ejemplo Blinky. Seeed Studio XIAO ESP32-S3. Documentación de Elixir.