Un modelo de generación de imágenes que corre entero dentro de un microcontrolador, sin internet, sin GPU y sin nube: eso es Pico Faces. Son 1,5 millones de parámetros. unas 5.000 veces menos que un modelo de generación de imágenes convencional. produciendo caras de 128x128 píxeles en un chip que cuesta lo que un almuerzo.

En esta guía vas a poner a funcionar el port de Pico Faces para la placa Adafruit Fruit Jam, con salida de video DVI por HDMI y control desde los botones de la placa. Hay dos caminos: el rápido, copiar un archivo UF2 y listo, y el largo, compilar desde el código fuente para modificar el comportamiento. Al final vas a entender qué hace realmente el modelo, qué significan los parámetros que controlas con los botones, y qué parte de todo esto puedes replicar con una Raspberry Pi Pico 2, que es el RP2350 que sí se consigue fácil en Chile.

Qué es lo que está corriendo en el chip

Pico Faces implementa un transformer de difusión en espacio latente (latent flow DiT). La idea general es la misma de los modelos grandes de generación de imágenes: se parte de ruido puro y se lo va "limpiando" en pasos sucesivos hasta que aparece una imagen coherente. La diferencia está en la escala y en los atajos.

Dos decisiones son las que hacen que esto quepa en un microcontrolador:

  1. El modelo no trabaja sobre píxeles, trabaja sobre un espacio latente comprimido. En vez de refinar 128x128x3 valores en cada paso, refina una representación mucho más pequeña, y recién al final un decodificador la expande a la imagen. El costo por paso baja en órdenes de magnitud.
  2. Los pesos viven en flash, no en RAM. El archivo model.bin se compila dentro del firmware. El RP2350 tiene 520 KB de SRAM, que no alcanzarían para mantener el modelo completo en memoria, pero sí para los tensores intermedios de un paso. Por eso el UF2 pesa bastante más que un firmware normal y por eso la copia al bootloader demora 30 a 60 segundos.

El RP2350 aporta lo suyo: dos núcleos Cortex-M33 con unidad de punto flotante por hardware. Un DiT es esencialmente una pila de multiplicaciones de matrices en punto flotante, y hacerlas por software. como habría que hacer en el RP2040, que no tiene FPU. sería órdenes de magnitud más lento.

La otra pieza propia del RP2350 es el HSTX, un periférico serializador de alta velocidad. Es lo que permite generar una señal DVI válida casi sin intervención de la CPU. En el RP2040 la salida DVI se lograba haciendo bit banging con los PIO, lo que consumía un núcleo completo; acá el video sale por hardware y los dos núcleos quedan libres para el modelo.

El proyecto original de cpldcpu soportaba dos salidas: enviar la imagen por serie USB para renderizarla en un PC con la Python Imaging Library, o sacarla por VGA con la Pimoroni Pico VGA Demo Base. El port de Adafruit agrega la Fruit Jam con salida HSTX/DVI y, de yapa, un modo de grilla 2x2 de colores inspirado en la serigrafía de Andy Warhol.

Camino rápido: copiar un UF2 y nada más

No necesitas compilador ni SDK para probar la demo. El RP2350 arranca como pendrive cuando entras a su bootloader, y ahí basta con arrastrar un archivo.

Entra al bootloader. Mantén apretado el botón BOOT/BOOTSEL, y sin soltarlo, presiona y suelta el botón de reset. Sigue sosteniendo BOOT hasta que aparezca la unidad. También funciona con la placa desconectada: aprietas BOOTSEL, conectas el USB con el botón apretado y sueltas cuando la unidad aparezca.

Placa Fruit Jam con los botones de reset y boot destacados

Acá hay una trampa clásica que vale la pena decir en voz alta: si usas un cable USB de solo carga, no va a pasar absolutamente nada. La placa se enciende, pero el computador no la ve. Es el problema número uno de la gente que se queda pegada en este paso. Usa un cable que sepas que transfiere datos.

Verifica que aparezca la unidad. En el explorador de archivos tiene que salir un disco llamado RP2350.

Explorador de archivos mostrando la unidad de bootloader RP2350

Copia el firmware. Arrastra el archivo pico_faces_fruit_jam.uf2 a esa unidad. Demora entre 30 y 60 segundos porque el archivo es grande. recuerda que ahí adentro van los pesos del modelo. . Cuando termina, la placa se reinicia sola.

Unidad RP2350 con el archivo pico_faces_fruit_jam.uf2 ya copiado

Conecta la pantalla. Con un cable HDMI a un monitor o TV compatible con DVI, y alimentación por USB-C. Al arrancar aparece la grilla de caras generadas.

Grilla 2x2 de caras de colores generadas por el modelo en la demo de Pico Faces

Los tres botones: qué controla cada uno

Toda la demo se maneja desde la placa, sin computador. Cada botón responde distinto a una pulsación corta y a una mantenida.

Botón 1. refresco. Una pulsación corta genera una cara nueva. Mantenerlo apretado alterna entre modo manual y automático; en automático genera una cara nueva cada 15 segundos. Arranca en manual.

Placa Fruit Jam con el botón 1 destacado

Botón 2. color. Pulsaciones cortas van rotando entre los estilos de color de la grilla. Mantenerlo apretado activa o desactiva el modo grilla: al desactivarlo, se muestra la cara tal como sale del modelo, sin el tratamiento de color.

Placa Fruit Jam con el botón 2 destacado

Botón 3. configuración del modelo. Este es el interesante, porque toca directamente los parámetros de inferencia. Hay 8 presets; el actual se muestra como fracción en la esquina inferior izquierda. Pulsación corta avanza, mantenido retrocede.

Placa Fruit Jam con el botón 3 destacado

# Nombre K Clase w
1 soft K2 w4 rnd 2 aleatoria 4
2 strong K8 w8 rnd 8 aleatoria 8
3 unconditional 4 nula 0
4 sketch K1 1 nula 0
5 female neutral 4 femenina, neutra 6
6 female smiling 4 femenina, sonriente 6
7 male neutral 4 masculina, neutra 6
8 male smiling 4 masculina, sonriente 6

Vale la pena entender qué significan las columnas, porque son los mismos conceptos que gobiernan cualquier modelo de difusión:

  • K es la cantidad de pasos de Euler que usa el solver para ir del ruido a la imagen. Es un cambio directo de tiempo por calidad: con K=1 (el preset "sketch") la cara sale en un abrir y cerrar de ojos pero apenas esbozada; con K=8 demora bastante más y sale claramente más definida. Si quieres ver la diferencia con tus propios ojos, pasa del preset 4 al 2 y compara.
  • La clase es hacia qué tipo de cara se guía la generación: las cuatro combinaciones de femenino/masculino con neutro/sonriente, más la clase nula, que deja al modelo generar sin guía.
  • w es la fuerza de la guía. Mientras más alto, más se empuja el resultado hacia la clase pedida. Un w alto da resultados más "obedientes" pero menos variados. Con clase nula, w no hace nada: no hay hacia dónde guiar.

Los dos primeros presets eligen la clase al azar en cada generación, que es lo más entretenido para dejarlo funcionando como pieza decorativa.

Camino largo: compilar desde el código fuente

Si quieres modificar el comportamiento, cambiar los estilos de color o usar la generación para otra cosa, tienes que compilar. Hay dos ramas relevantes:

  • fruit_jam: lo mínimo para correr Pico Faces en la Fruit Jam con salida DVI, controlado por serie USB. No dibuja nada al arrancar; para generar una cara te conectas por serie y mandas una G mayúscula seguida de Enter. Es la rama de la que partir si quieres construir algo distinto sobre la generación de imágenes.
  • color_grid_mode: la demo completa con la grilla 2x2 y el control por botones. Genera la primera cara al encender. Es la rama de la que partir si quieres personalizar la demo o crear estilos de color propios.

Clona la rama que te sirva:

Bash
git clone -b color_grid_mode https://github.com/adafruit/pico-faces.git

Después necesitas el SDK de la Pico junto con el submódulo de TinyUSB:

Bash
git clone https://github.com/raspberrypi/pico-sdk.git

cd pico-sdk
git submodule update --init lib/tinyusb
cd ../

Y con eso ya puedes configurar y compilar:

Bash
export PICO_SDK_PATH=~/pico-sdk/

# building on x86_64
cmake -S firmware -B build/fruitjam -G "Unix Makefiles" -DPICO_BOARD=adafruit_fruit_jam -DRF_DVI=1 -DRF_VGA=0 -DMODEL_BIN=$PWD/checkpoints/m3_decD_deep_full/model.bin -DCMAKE_BUILD_TYPE=Release -DPICOTOOL_FORCE_FETCH_FROM_GIT=1

# building on ARM like RPi
# cmake -S firmware -B build/fruitjam -DCMAKE_BUILD_TYPE=Release -DRF_DVI=1 -DRF_VGA=0 -DPICO_BOARD=adafruit_fruit_jam -DMODEL_BIN=$PWD/checkpoints/m3_decD_deep_full/model.bin

cmake --build build/fruitjam -j4

El resultado queda en build/fruitjam/pico_faces.uf2, listo para copiar al bootloader igual que el UF2 precompilado.

Un par de notas sobre este proceso que ahorran tiempo:

  • PICO_SDK_PATH tiene que apuntar al repositorio del SDK que clonaste. Si lo dejaste en otro lado que no sea ~/pico-sdk/, corrige la ruta o el cmake va a fallar en la configuración, no en la compilación, así que el error se ve antes de que empiece lo lento.
  • Las banderas -DRF_DVI=1 -DRF_VGA=0 son las que seleccionan la salida de video. Son mutuamente excluyentes: RF_VGA=1 compila para la base VGA de Pimoroni del proyecto original.
  • -DMODEL_BIN= apunta al checkpoint que se va a empaquetar dentro del firmware. Cambiar de checkpoint es cambiar de modelo, y es el punto donde intervendrías si entrenaras uno propio.
  • La variante para compilar en ARM (por ejemplo, sobre una Raspberry Pi) está comentada en el mismo bloque. Es la misma línea sin el generador explícito de Makefiles.

Variantes y mejoras

Hazlo correr en una Raspberry Pi Pico 2. La Pico 2 monta el mismo RP2350, así que el modelo corre igual de bien. Lo que no tiene es el hardware de video de la Fruit Jam ni su definición de placa. El camino realista es compilar desde la rama fruit_jam desactivando la salida de video y quedarte con el modo original de serie USB: la Pico 2 genera la imagen y la manda por el puerto serie, y un script en Python con Pillow la arma en la pantalla del computador. Pierdes la autonomía, pero es la forma más barata de tener este modelo corriendo en hardware que se consigue acá.

Sácalo por una pantalla SPI en vez de HDMI. Si quieres autonomía sin depender de un monitor, la imagen es de 128x128 píxeles: cabe entera y sobra en una pantalla TFT ST7789 de 240x240. Hay que reemplazar la capa de salida DVI por escrituras SPI al controlador, que es un cambio acotado porque el resto del pipeline no se toca. Como bonus, el consumo baja bastante respecto de mantener una señal DVI activa.

Crea tus propios estilos de color. El modo grilla 2x2 aplica paletas sobre la salida en escala de grises del modelo. Partiendo de color_grid_mode, agregar una paleta nueva es tocar una tabla de colores, no el modelo. Es la modificación de menor esfuerzo y mayor efecto visual, y un buen primer cambio para familiarizarte con el código antes de meterte con la inferencia.

Mide los tiempos de verdad. El proyecto no publica cuánto demora cada preset. Instrumentar la generación con time_us_64() antes y después de la inferencia, e imprimir el resultado por serie, te da la curva real de tiempo contra K en tu placa. Es un dato que no está en ninguna parte y que te sirve para decidir con qué preset dejarlo funcionando.

Personalización para Chile

Acá hay que ser derecho: la Adafruit Fruit Jam no está en el catálogo de MechatronicStore, y traerla importada con el gabinete y la pantalla HDMI de 7" del proyecto original supera con facilidad los 200 dólares antes de envío. Vale la pena saber qué parte del proyecto sí es alcanzable localmente y cuál no.

Lo que sí consigues acá:

  • Raspberry Pi Pico 2. es el mismo chip RP2350, con la misma FPU y la misma capacidad de correr el modelo. Es la pieza clave y la que hace viable el proyecto en Chile. La diferencia con la Fruit Jam es todo lo que la rodea (conector HDMI, audio, botones, ranura microSD), no el procesador. Ojo: tiene que ser Pico 2, no Pico ni Pico W originales, que montan el RP2040 sin FPU.
  • Cable USB-A a USB-C o micro USB según tu placa. y que sea de datos, no de solo carga. Con la Pico 2, además, este cable es el canal por el que llega la imagen generada.
  • Pantalla TFT SPI ST7789 de 240x240. la ruta para tener salida de video autónoma sin HDMI, con el cambio de código descrito más arriba.
  • Protoboard 830 puntos y jumpers macho hembra 20cm si vas por la pantalla SPI y necesitas cablear.

Lo que no vas a encontrar en catálogo local y tendrías que importar: la Fruit Jam propiamente tal y la pantalla HDMI de 7" del montaje original. Ninguna de las dos es imprescindible si tomas la ruta Pico 2.

Una nota sobre el cable HDMI: si vas por la Fruit Jam importada, cualquier cable HDMI estándar sirve. La señal DVI del RP2350 es eléctricamente compatible con HDMI y la mayoría de los monitores y televisores la aceptan sin configurar nada.

Recursos

Versión chilena, inspirada en el port de Adafruit, con la ruta alternativa sobre hardware que se consigue en stock local.