Sistrix Led Ticker - Montaje de Raspberry Pi + LED Matrix Panel

Llevo desde 2014 trabajando con SISTRIX como consultor SEO. Es la herramienta que abro cada mañana para ver cómo van los proyectos de mis clientes. Y un día, buscando un regalo para un amigo nerd en Etsy, vi paneles LED con los stock de bolsa y de cripto, y pensé: ¿y si tuviera un panel LED en mi escritorio que me mostrara la visibilidad de mis clientes rotando automáticamente?

Era técnicamente posible, pero también sabía que me iba a meter en un marrón, hace años ya hice proyectos con la Raspberry, con ESP32 e incluso me he hecho mods para el Flipper, pero eran un dolor de cabeza. Así que la idea se quedó en el cajón durante años, cogiendo polvo junto con esos juguetitos.

Hasta que empecé a trabajar con Claude Code en noviembre.

Qué hace el panel

Un panel LED RGB de 64x32 píxeles controlado por una Raspberry Pi 4, que se conecta a la API de SISTRIX y va rotando dominios mostrando: label, valor de visibilidad, cambio porcentual, país, modo (weekly/daily) y una sparkline con la evolución. Además de una brand card personalizable con logo en pixel art y mensaje con scroll animado.

Sistrix led ticker raspberry pi + led matrix panel

Todo se gestiona desde un panel web accesible en tu red local. El panel incluye un simulador LED que replica exactamente lo que se ve en la pantalla física, así que puedes probarlo todo sin hardware.

Algunas cosas que me gustan:

  • Editor visual de layout: arrastra y redimensiona cada elemento directamente sobre el simulador
  • Caché inteligente: minimiza créditos API (weekly cacheado 24h, daily 6h)
  • Sincronización web <-> LED: slide actual y estado on/off sincronizados en tiempo real
  • Botón físico para encender/apagar sin sacar el móvil
  • 6 idiomas, responsive, accesible (WCAG 2.1 AA)
  • Colores: hex, rainbow y degradados de dos colores — todo configurable

Todo el código va en dos archivos Python: display.py (driver LED, ~1.000 líneas) y web_panel.py (panel web con simulador, ~3.700 líneas). Sin frameworks, sin npm, es vanilla JS puro. El frontend va inline dentro del Flask. Si el proyecto fuera más grande ya me lo replantearía por mantenimiento.

El hardware: Raspberry Pi + LED Matrix Panel

Llevan enlaces son de afiliado de Amazon, si compras a través de ellos me llevo una pequeña comisión, que me lo he currado 😀

Materiales panel led matrix waveshare raspberry pi

Imprescindible

Opcional (pero recomendado)

  • Botón pulsador Gebildet 12mm - Acero inoxidable con LED azul. Encender/apagar sin tocar el móvil.
  • Kit de soldador 60W- Para soldar los cables del botón a los pines GPIO.
  • Broca escalonada Flintronic - Para agujeros limpios en la carcasa sin partir el plástico.
  • Carcasa impresa en 3D - Pedí a un amigo que me imprimiera una a medida (192x96mm, profundidad 13-15mm). Si no tienes impresora, busca en Etsy "64x32 P3 LED panel case".
  • Juego de tornillos M3 (560 piezas) - Viene de todo: varios largos, tuercas y arandelas. Así que da igual la profundidad de tu caja, seguro que hay alguno que encaja.

Montaje paso a paso

1. Prepara la carcasa: usa la broca escalonada para los agujeros. Yo hice uno de 12mm para el botón y otro más pequeño para el cable flat y la alimentación. La escalonada para mí es clave porque una broca normal parte el plástico, esta va ajustando el diámetro poco a poco. También se podría hacer con un hierro caliente o un soldador, pero no es lo mismo.

Taladrar carcasa matriz led broca escalonada

2. Encaja el Bonnet en la Pi: presiona hasta que encaje en los pines GPIO.

Adafruit RGB Matrix Bonnet to raspberry pi

3. Cablea el botón (opcional): un terminal a GPIO 19 (pin 35), el otro a cualquier GND. No importa la polaridad. Yo lo puse en el pin 39 después de 2 fallos como se puede observar (resulta que la matrix tiene ocupados casi todos los pins).

Soldar boton pulsador gebildet 12mm gpio 19 pin 35 gnd pin 39

4. Conecta el cable flat: del panel al conector HUB75 del Bonnet. Solo hay una orientación (tiene muesca).

Conecta cable flat waveshare to matrix bonnet

5. Conecta la alimentación del panel: fuente 5V al barrel jack del Bonnet. Yo no tenía adaptador barrel jack de la potencia que necesita el panel, así que me monté uno con un cargador USB de un Meizu antiguo de 5V 3A, un cable barrel jack 5.5x2.1mm que corté de otra fuente de 12V que no usaba, y un cable USB ↔ micro USB que también corté y soldé. Funciona perfecto y me ahorré el dinero y esperar al envío. Si no te va hacer el MacGyver, compra la fuente directamente.

Alimentacion 5v 3a barrel jack 5,5m

6. Enciende la Pi: USB-C. Si todo está bien, el panel se enciende en segundos.

Conecta fuente alimentacion 5v al barrel jack del bonnet

7. Fija el panel a la caja: una vez todo funciona desconecta los cables y pásalos por los agujeros. Atornilla con tornillos M3 por las esquinas.

Cómo instalarlo

El proyecto es open source y está en GitHub. Si quieres montarlo:

  1. Instala Raspberry Pi OS Lite 64-bit en tu Pi 4
  2. Clona el repositorio y ejecuta bash setup.sh
  3. Instala el driver LED desde hzeller/rpi-rgb-led-matrix
  4. Abre http://raspberrypi.local:5001 desde cualquier dispositivo en tu red
  5. Configura tu API key de SISTRIX, añade dominios, y ya está

Sin hardware, puedes probar solo el simulador:

pip install flask pillow requests
python3 web_panel.py

Abre http://localhost:5001 y listo.

Problemas que me encontré

El drama del botón y los GPIO

Conecté el botón al GPIO 26. Sin el panel LED funcionaba perfecto. Pero en cuanto arranqué el driver del panel... dejó de funcionar. El Bonnet usa casi todos los GPIO, y el 26 es una línea del multiplexor. Probé el 25 y mismo problema.

Al final, el GPIO 19 (pin 35) estaba libre. Pero no acabó ahí... el botón apagaba y encendía inmediatamente, o solo funcionaba una vez. El problema era la detección por nivel y la solución fue detección por flanco de subida (transición LOW->HIGH al soltar), que genera exactamente un evento por pulsación.

El blanco que salía naranja

En el simulador web los textos se veían blancos puros. En el LED, anaranjados. Los LEDs rojos y verdes de estos paneles tienen más brillo que los azules. La solución que apliqué fue la corrección de color selectiva solo para blancos y grises (reduce R un 10%, G un 8%). Mientras que los colores saturados no se tocan.

El brillo y los PWM

Con brillo a 60, muchos píxeles del mismo número se veían más brillantes y un shimmer visible en dígitos grandes. El punto ideal que he encontrado es brillo 42, PWM bits 8 (pwm_lsb_nanoseconds 300). Degradados suaves, sin shimmer, y suficiente brillo de día sin deslumbrar de noche. Quizás con un panel más profesional habría que cambiar estos ajustes.

El SSH que se rompió solo

Un día el SSH se colgaba al conectar y el .bashrc imprimía texto en sesiones no interactivas, rompiendo SCP/SFTP. Tuve que conectar monitor y teclado a la Pi para ver que ocurría. Así que lo mejor es envolver los echos de tu .bashrc en if [[ $- == *i* ]].

La sincronización

Esto parece trivial pero fue lo más difícil de resolver. Hay dos procesos independientes: el display.py que controla el panel LED (corre como root para acceder a GPIO) y el web_panel.py que sirve el simulador en el browser. Cada uno tiene su propio loop de rotación, su propio estado, su propia idea de qué slide está mostrando. Los problemas fueron apareciendo uno a uno:

  • Cambios que tardaban 60 minutos: quitabas un dominio en la web y el LED no se enteraba hasta el siguiente refresco API. Ahora detecta cambios en la lista de dominios en cada ciclo y recarga desde caché al instante.
  • Fetch bloqueante: cuando el display hacía una llamada API a SISTRIX, el panel se congelaba durante varios segundos en el último frame (normalmente la brand card). Lo movimos a un thread en background.
  • Rotación desincronizada: el panel web tenía su propio timer de rotación independiente del LED. Ahora el web es "esclavo" del LED cuando el servicio está activo y sigue su slide en tiempo real (3 secs de delay) via un fichero de estado compartido.
  • Edición interrumpida: estabas editando la brand card en el web y de repente el slide cambiaba porque el LED seguía rotando. Ahora el modo edición pausa toda la sincronización.
  • Encendido desincronizado: le dabas a ON y cada uno empezaba por un slide diferente. Ahora ambos arrancan desde el slide 0.
  • Botón muerto en brand card: el botón físico GPIO no respondía mientras se mostraba la brand card, porque el loop de scroll no lo estaba comprobando.

Cada uno de estos bugs parecía simple, pero requería entender el flujo completo entre dos procesos, un fichero de config compartido, un state file, timers de JavaScript, un loop de Python, y un botón físico. La IA resolvía cada bug individualmente, pero no veía el sistema y era como jugar al Whac-A-Mole. Yo tenía que detectar los problemas probando en el hardware real y explicarle qué estaba pasando.

Los bugs de seguridad

Esto me preocupó especialmente porque el código generado por la IA tenía MUCHOS agujeros:

  • API key expuesta: el endpoint /api/config devolvía la clave de SISTRIX al frontend en texto plano.
  • XSS: los nombres de dominio se insertaban sin escapar. Un <script> en el label se ejecutaba.
  • Sin cabeceras de seguridad: ni X-Content-Type-Options, ni X-Frame-Options, ni CSP.
  • Sin validación de entrada: un label podía ser cualquier cosa sin sanitización.

La IA genera código funcional rápido, pero la seguridad NO está en sus prioridades por defecto. ¡Hay que auditarlo todo!

Los caracteres que faltaban (y mi hija)

El panel usa fuentes bitmap propias donde cada carácter es una rejilla de píxeles definida a mano. Claude generó el alfabeto y los números. Todo bien hasta que mi hija mayor (7) quiso poner el nombre de su hermana y ella en la tarjeta personalizada tal que así: "Chloe & Lía".

Con eso vimos que faltaban acentos y $, %,&, (, ), =, #, @... Nos pusimos los dos con papel cuadriculado a diseñar los caracteres de 3x5 y 5x7 píxeles. Ella rellenaba cuadraditos, yo los traducía a bits y al final acabó haciéndolo ella también. Además, corregimos letras como la S, la X y la W que en 5x7 le quedaban horribles a Claude y los corregimos a mano sobre papel.

También fue idea suya lo del color rainbow y de ahí salieron también los degradados de dos colores configurables.

Desarrollar con IA: lo que he aprendido

Llevo usando IA generativa desde que tuve acceso a la beta de GPT-3 en 2020. Este panel lo he desarrollado íntegramente con Claude Code. Es decir, esto no es un experimento ni mi primera vez, es mi forma de trabajar desde hace años. Pero lo que hizo Anthropic con Opus en noviembre del año pasado es un antes y un después. Así que no me habría embarcado este proyecto sin ese salto.

En febrero de 2025, Andrej Karpathy acuñó el término "vibe coding" que significa "aceptar todo lo que genera el modelo sin leer los diffs y olvidarte de que el código existe". Un año después él mismo se desdijo y ahora prefiere "agentic engineering". Normal... porque lo de dejarte llevar por las vibes funciona para proyectos de usar y tirar de fin de semana, no para producción.

A mí el término nunca me gustó. Lo que hago se parece más a lo que Kent Beck llama "augmented coding". En vibe coding te da igual el código, solo quieres que funcione; en augmented coding te importa el código, los tests, la cobertura. La IA amplifica tu visión y tu capacidad de descomponer problemas, pero no reemplaza tu criterio.

Simon Willison, cocreador de Django, lo clava cuando dice que revisar código generado por IA muchas veces es más difícil que escribirlo tú. Tienes que reconstruir la intención y pillar lo que el modelo ha ignorado. Pasas de escritor a supervisor y eso exige de mucho más criterio. Y es justamente lo que ha pasado con este proyecto.

Lo que funciona bien

Claude Code maneja todo el flujo desde la terminal en lenguaje natural. "Sube display.py a la Pi y reinicia el servicio" -> SCP, SSH, systemctl restart. "Haz commit" ->  analiza el diff, escribe un mensaje coherente, ejecuta. "El botón no funciona, mira el log" -> se conecta a la Pi por SSH, lee los logs, identifica el problema, propone solución.

Así resolvimos el GPIO, el debounce, la detección por flancos... Yo no sabía qué pines del Bonnet estaban ocupados y él analizó el pinout y los encontró. Sin IA esto habría sido un verdadero infierno.

Lo que falla

CSS y diseño responsive: cada cambio en la interfaz rompía algo. Movía un padding y se descuadraba el mobile. Cambiaba un color y dejaba ilegible un botón. No tenía manera de ver lo que hacía.

La solución que se me ocurrió hace unos meses para no gastar tokens de Computer Use fue meterle un Puppeteer a Claude Code. Un script para hacer capturas en desktop (1280x900) y mobile (390x844), y que Claude hacía con cada subida y que revisaba a cada cambio visual antes de subirlo. Las intervenciones por mi parte se redujeron un 80%.

Design system: el panel tiene tokens CSS (espaciado, colores, bordes) y Claude por defecto metía valores mágicos en línea como margin-top: 13px, color: #3a7fc2 ... en vez de usar las variables. Tenía que estar encima constantemente.

Cambios no pedidos: le dices "cambia el color del texto" y de paso te mueve los números, te cambia un layout que funcionaba, o te "optimiza" algo que no estaba roto.

Usabilidad: la IA desarrolla funcionalidades, pero no piensa en la persona que las va a usar. Control de estados, mensajes de confirmación, flujos lógicos... nada de eso le sale solo. Si un botón debería deshabilitarse mientras se carga, no lo hace. Si una acción destructiva necesita confirmación, no la pone. Si el orden de los pasos no tiene sentido para un usuario, no lo detecta. Tienes que ser tú quien piense en la experiencia.

El desastre del francés: el i18n va en un objeto JavaScript enorme con las cadenas de 6 idiomas que pusimos al final. Al añadir las traducciones francesas, un acento mal escapado reventó las 3.700 líneas del archivo. Pantalla en blanco, sin errores claros y a Claude no se le ocurre otra que tabular todo el código con una RegEx inutilizando todo proyecto. Suerte que teníamos git y vuelta al estado anterior.

Cuánto habría costado este proyecto sin IA asistida

Usé la calculadora COCOMO de la NASA, el modelo estándar de estimación de esfuerzo en ingeniería de software, para medirlo:

  • 4.883 líneas de código (driver de hardware, renderizado bitmap, caché, GPIO, panel web completo con simulador, editor visual, 6 idiomas, WCAG 2.1 AA)
  • Esfuerzo: 12,3 persona-mes
  • Solo a tiempo completo: ~12 meses
  • Coste equivalente: €100.000–140.000 a tarifa de mercado europeo

Pero COCOMO en realidad está pensado para otra cosa. Sirve para equipos, documentación formal, fases de diseño, QA, gestión de proyecto. Asume que hay coordinación entre personas, reuniones, especificaciones... Nada de eso aplica aquí. Además, buena parte de las líneas son HTML/CSS/JS inline del panel web y no es lo mismo que código de sistemas. Para un proyecto personal de un solo dev, COCOMO lo sobreestima salvajemente.

Una estimación más realista de un desarrollador full-stack con experiencia en hardware, LEDs y Flask tardaría quizás 2-3 meses a tiempo completo sin apoyo de la IA. Yo solo soy un consultor SEO, sé algo de código pero no me dedico a ello, sin experiencia con paneles LED ni GPIO, así que probablemente 4-6 meses si pudiera dedicarme 100% a ello. Al 20-30% de dedicación, más de un año. Así que en la práctica, nunca lo habría terminado. Por eso nunca lo empecé 🙂

Con Claude Code lo he hecho en 3 jornadas. Con bugs, con idas y venidas, con cosas que ha roto y que hemos tenido que arreglar. Pero funciona y creo que es bastante robusto. Pero quizás salte alguna movida que no me ha dado tiempo a ver cuando más gente lo use.

No es que la IA haga el trabajo por ti, es que proyectos que antes no merecían la pena por la relación esfuerzo/resultado, ahora sí la merecen. El umbral de lo que puedes permitirte construir ha bajado drásticamente. Pero tienes que ser tú el control de calidad, revisando cada cambio, tener git al día, auditar la seguridad, y no confiar a ciegas. Para mi esto no es vibe coding. Es ingeniería con un copiloto muy rápido al que no puedes soltar el volante, por lo menos por ahora.

El proyecto es open source. Si lo montas, ¡cuéntamelo! me haría ilusión ver más paneles LED de SISTRIX por ahí.

Natzir Turrado 30 marzo 2026

Compartir

Facebook Linkedin Twitter

Otros artículos

Cómo analizar la tecnología de un sitio web

Antes de empezar un proyecto SEO es importante conocer la tecnología en la que está desarrollado un sitio web. ¿Es SalesForce? ¿Cuándo cambiaron de CMS? ¿Es un portal hecho a medida? ¿Está usando un Framework Javascript? ¿Qué sistemas de caché usa? ¿Tiene Cloudflare o similares para poder usar los workers y resolver las limitaciones de […]

Leer más

SEO para Progressive Web APPs (PWA) y JavaScript

Este artículo es un resumen que hemos hecho Christian Oliveira y yo de la charla que dimos en el Congreso Web (consigue aquí las diapositivas), donde pretendemos explicar esta tecnología (PWA) y cómo tenemos que lidiar con ella SEOs y desarrolladores para hacerla accesible a los buscadores. Nos basamos en la experiencia con clientes que usan […]

Leer más