Vas pedaleando de noche y, en vez de un reflectante, tu rueda delantera muestra un logo, una calavera o un arcoíris que parece flotar dentro de los rayos. No hay pantalla: son seis tiras de LED que se encienden y se apagan en el instante justo mientras la rueda gira. Este proyecto se basa en una guía de Erin St Blaine para Adafruit, y aquí lo ordenamos por bloques (concepto, hardware, software y pruebas) para que entiendas cada decisión antes de soldar.
Al terminar vas a saber:
- por qué la persistencia de la visión funciona y qué le exige a los LED;
- cómo se cablean seis tiras APA102 (DotStar) en tres pares que comparten un solo reloj;
- cómo instalar CircuitPython en un RP2040 y probar cada rayo con un código de colores;
- qué cambia si usas una Raspberry Pi Pico en vez de la Feather RP2040 del original, y un sensor Hall A3144 en vez del TMAG5273.
Ojo: no es un proyecto para principiantes. Hay soldadura fina sobre tiras que después van a girar, vibrar y mojarse.
El concepto: dibujar con luz en movimiento
La persistencia de la visión es el efecto por el que tu ojo retiene una imagen durante una fracción de segundo después de que desaparece. Si una columna de LED cambia de color cientos de veces por vuelta, el cerebro junta esos destellos y ve una imagen completa, como cuando agitas una bengala y "escribes" en el aire.
Haz el cálculo para dimensionar el problema. Una rueda de 26 pulgadas tiene cerca de 2 metros de perímetro; a 20 km/h da unas 2,7 vueltas por segundo, o sea, una vuelta cada 370 ms aproximadamente. Si quieres dibujar 180 columnas por vuelta, cada columna dura unos 2 ms. En ese tiempo el microcontrolador tiene que mandar los datos de todos los LED del rayo y la tira tiene que mostrarlos sin parpadeo visible.
Por qué APA102 y no WS2812
Aquí está la razón técnica de usar tiras APA102 (Adafruit las vende con el nombre DotStar) en lugar de las populares WS2812 o NeoPixel:
- Tienen línea de reloj propia. El protocolo de la WS2812 depende de tiempos muy precisos en un solo cable; la APA102 usa dos líneas (datos y reloj, tipo SPI), así que el microcontrolador puede mandar los bits tan rápido o tan lento como pueda sin que la tira se confunda.
- Su PWM interno es mucho más rápido. Cuando una WS2812 atenúa el brillo, el LED parpadea a una frecuencia baja que, en movimiento, se ve como una línea punteada. La APA102 parpadea a una frecuencia muy superior y el trazo se ve continuo. En un POV eso es la diferencia entre una imagen limpia y una imagen "rayada".
- Un LED solo cambia de color cuando recibe un cuadro válido. Cada LED espera un encabezado de 32 ceros y después cuadros de 32 bits que empiezan con tres unos. Esa estructura es la que permite compartir el reloj entre varias tiras, como vas a ver en el código.
Hardware: tres rayos de doble cara
La guía arma una rueda con tres rayos de luz, y cada rayo tiene dos caras: una tira mirando a la izquierda de la bicicleta y otra mirando a la derecha. Son seis tramos de tira en total, de 36 LED cada uno (con tira de 144 LED/m, cada tramo mide 25 cm). Las dos tiras de cada par se cablean idéntico, así que ambos lados muestran la misma imagen; una vez unidas, trátalas como si fueran una sola tira de doble cara.
Antes de soldar, pasa termorretráctil transparente por los dos extremos cortados de cada tira. No lo encojas hasta terminar las pruebas, pero ponlo ahora para no olvidarlo después.

El cableado, línea por línea
Trabaja siempre desde el extremo de entrada de cada tira (las flechas impresas en la tira apuntan alejándose de tus soldaduras). La autora usa cable de silicona de cuatro colores, y conviene respetar el código para no perderse:
| Señal de la tira | Color del cable | Dónde va |
|---|---|---|
| VCC | rojo | todas juntas, al pin VBUS del breakout USB-C |
| GND | negro | todas juntas, al GND del breakout USB-C y al pin G de la Feather |
| CI (reloj) | amarillo | todas juntas, al pin SCK de la Feather |
| DI (datos) | verde | unidas por pares; cada par va a A1, A2 y A3 de la Feather |
El sensor de efecto Hall se enchufa con un cable STEMMA QT en el conector STEMMA de la Feather (sirve cualquiera de los dos puertos del sensor). Ese sensor, junto a un imán fijo en el marco de la bicicleta, le avisa al programa cada vez que la rueda completa una vuelta: con eso el código calcula la velocidad y sabe cuándo dibujar cada columna.
Fíjate en un detalle del diseño: las seis tiras comparten una sola línea de reloj, pero hay tres líneas de datos. Así ahorras pines y simplificas el cableado que cruza el buje, a cambio de escribir un rayo a la vez.
Consumo: el detalle que nadie calcula
Cada LED APA102 puede consumir del orden de 60 mA en blanco a máximo brillo. Con 216 LED (6 tiras de 36), el peor caso teórico supera los 12 A, algo que ninguna batería USB entrega. En la práctica una imagen POV casi nunca es blanca entera, pero conviene que limites el brillo por software y que uses una batería USB-C que entregue al menos 2 A. Si ves que los colores se vuelven anaranjados hacia la punta del rayo o que la placa se reinicia cuando la imagen es muy clara, es caída de voltaje: baja el brillo antes de tocar el cableado.
Feather RP2040 o Raspberry Pi Pico
El original usa una Adafruit Feather RP2040 (en la página del código la guía la llama "RP2040 Prop Maker Feather", que es otra placa de la misma familia; los pines que usa el proyecto existen en ambas). Una Raspberry Pi Pico lleva el mismo microcontrolador RP2040 y corre la misma versión de CircuitPython, así que es una alternativa técnicamente válida, con tres diferencias que tienes que resolver tú:
- Nombres de pines. El código usa
board.SCKyboard.A1,board.A2,board.A3. La Pico no trae el aliasSCK, y suA3es un pin interno que mide el voltaje de alimentación y no sale al conector. En la Pico tienes que elegir pinesGPlibres (por ejemplo, un pin de reloj y tres de datos contiguos) y escribirlos en las dos líneas de configuración que verás más abajo. - No tiene conector STEMMA QT. Para el TMAG5273 necesitas un cable STEMMA QT a pines macho y conectarlo a un par de pines I2C de la Pico, declarando ese bus en el código.
- No trae cargador ni conector de batería. Da lo mismo en este proyecto, porque todo se alimenta desde el breakout USB-C, pero tienes que llevar los 5 V al pin VSYS de la Pico y unir las tierras.
Si prefieres no tocar el código, quédate con la Feather. Si ya tienes una Pico en el cajón, el cambio es de pocas líneas.
Sensor Hall: TMAG5273 o A3144
El original usa un TMAG5273, un magnetómetro Hall 3D lineal que se lee por I2C: entrega la intensidad del campo en tres ejes, así que detecta el imán aunque no quede perfectamente alineado y te deja ajustar el umbral por software.
El A3144 es un sensor Hall de tipo interruptor: su salida digital cambia de estado cuando un polo sur se acerca a su cara marcada. Para contar vueltas basta, pero no es un reemplazo directo, por tres motivos:
- Funciona desde 4,5 V. No lo alimentes con los 3,3 V del RP2040: aliméntalo con los 5 V del bus.
- Su salida es de colector abierto. Necesita una resistencia de pull up (10 kΩ) hacia 3,3 V, o el pull up interno del RP2040. Como la salida solo "tira a tierra", nunca le mete 5 V al pin del microcontrolador.
- Se lee distinto. En vez de la librería del TMAG5273, lees un pin digital con
digitalioy detectas el flanco de bajada. El código final del original está escrito para el TMAG5273, así que esta parte la tienes que adaptar.
Si el A3144 no reacciona, da vuelta el imán: solo responde a un polo.
Software: CircuitPython en el RP2040
CircuitPython es un derivado de MicroPython pensado para aprender y experimentar. No necesitas instalar un entorno en el computador: la placa aparece como un pendrive llamado CIRCUITPY y basta con editar y copiar archivos.
Para instalarlo:
- Descarga el archivo UF2 más reciente de CircuitPython para tu placa desde circuitpython.org (hay una página para la Feather RP2040 y otra para la Pico; no los mezcles).
- Entra al bootloader: mantén apretado el botón BOOT (BOOTSEL) y, sin soltarlo, aprieta y suelta RESET. Sigue sujetando BOOT hasta que aparezca la unidad RPI RP2. Otra forma: con la placa desconectada, mantén BOOTSEL apretado mientras la enchufas por USB.

- Arrastra el archivo UF2 a la unidad RPI RP2.

- La unidad RPI RP2 desaparece y aparece una nueva llamada CIRCUITPY. Listo.

Si la unidad RPI RP2 nunca aparece, revisa primero el cable: muchos cables USB solo cargan y no transmiten datos, y es la causa más común de frustración en este paso.
Modo seguro y "nuke"
Si algún día no puedes editar code.py (la unidad quedó de solo lectura, o la desactivaste desde boot.py), entra al modo seguro: al encender o resetear, la placa espera 1 segundo; si aprietas RESET dentro de ese segundo, arranca sin ejecutar boot.py ni code.py y sin recarga automática. Piénsalo como un doble clic lento en RESET (el doble clic rápido entra al bootloader). En modo seguro el LED de estado parpadea en amarillo tres veces y la consola serial lo confirma con un mensaje. Corriges lo que haga falta y sales con un reset.
Si la placa queda tan mal que CIRCUITPY no aparece ni reinstalando, Adafruit ofrece un UF2 de borrado total ("nuke") que limpia la memoria flash. Pierdes todos los archivos de la placa, pero la recuperas; después reinstalas CircuitPython como arriba.
Prueba de los rayos antes de montar nada
Antes de llevar las tiras a la rueda, conviene un código que encienda cada par de un color fijo: rojo, verde y azul. Te sirve para comprobar que todas las soldaduras funcionan y para no confundir el orden de los pares durante el armado. El código y sus librerías vienen en el Project Bundle de la guía original (botón "Download Project Bundle").
# SPDX-FileCopyrightText: 2026 Erin St Blaine for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""Simple three-spoke DotStar color test using the adafruit_dotstar library."""
import time
import adafruit_dotstar
import board
NUM_PIXELS = 36
CLOCK_PIN = board.SCK
DATA_PINS = (board.A1, board.A2, board.A3)
COLORS = (
(255, 0, 0), # Red
(0, 255, 0), # Green
(0, 0, 255), # Blue
)
class SpokeDotStar(adafruit_dotstar.DotStar):
"""DotStar strip that keeps its pixels lit when its pins are released.
All three spokes share one clock pin, so only one strip can own the pins
at a time. The stock ``deinit`` blanks the strip before releasing the
pins; this version releases them and leaves the last colors showing.
"""
def deinit(self) -> None:
if self._spi:
self._spi.deinit()
else:
self.dpin.deinit()
self.cpin.deinit()
def write_dotstar(data_pin, color):
"""Fill one DotStar strip with a solid color."""
with SpokeDotStar(CLOCK_PIN, data_pin, NUM_PIXELS) as strip:
strip.fill(color)
while True:
for strip_pin, strip_color in zip(DATA_PINS, COLORS):
write_dotstar(strip_pin, strip_color)
time.sleep(1)
Lo interesante está en la clase SpokeDotStar. Como los tres rayos comparten el pin de reloj, solo un objeto DotStar puede "ser dueño" de ese pin a la vez. Por eso write_dotstar crea el objeto, pinta el rayo y lo libera al salir del bloque with. El problema es que el deinit de la librería apaga la tira antes de soltar los pines; la subclase lo reemplaza por uno que suelta los pines y deja encendidos los últimos colores. Y las otras dos tiras no se borran cuando el reloj se mueve para su vecina, porque un LED APA102 solo cambia de color al recibir un cuadro válido por su propia línea de datos.
Para cargarlo, conecta la placa al computador con un cable USB de datos, descomprime el Project Bundle y copia a la unidad CIRCUITPY la carpeta lib y el archivo code.py. Debería quedar así:

Si tus tiras no tienen 36 LED, o soldaste a otros pines (por ejemplo, porque usas una Pico), estas son las líneas que tienes que cambiar:
NUM_PIXELS = 36
CLOCK_PIN = board.SCK
DATA_PINS = (board.A1, board.A2, board.A3)
Montaje en la bicicleta
El montaje físico es la parte que más tiempo toma. Además de la electrónica, la guía pide cinta de silicona autofusionante transparente, termorretráctil transparente de media pulgada, pistola de silicona caliente, pistola de calor, amarras plásticas y el equipo de soldadura. Los conectores JST SM de 2 y 3 pines permiten desconectar la electrónica de la rueda sin cortar cables, algo que agradecerás cuando tengas que sacar la rueda para cambiar una cámara.
La guía original sigue con el armado de la electrónica, la fijación a la rueda, el código final del POV y la preparación de tus propias imágenes. Ese código final no venía completo en el material que revisamos, así que para la versión con sensor Hall descárgalo del Project Bundle de la guía original en vez de copiarlo a mano.
Tres consejos de durabilidad que el uso real te va a agradecer:
- Alivio de tensión en cada soldadura. La rueda vibra todo el tiempo; un cable rígido termina cortándose justo en el punto de soldadura. El cable de silicona y el termorretráctil existen para eso.
- Balancea la rueda. La batería y la placa agregan peso en un solo punto. Si la rueda "salta" a velocidad, reparte el peso o pon un contrapeso al lado opuesto.
- Protege del agua. La cinta autofusionante sella mejor que la cinta aislante común y no deja residuos al retirarla.
Errores comunes
- Un rayo no enciende: revisa la línea de datos de ese par (verde) y que estés soldando en el extremo de entrada de la tira.
- Ningún rayo enciende: sospecha del reloj compartido (amarillo) o de la tierra común entre la placa y el breakout USB-C.
- Colores cambiados (rojo sale azul): algunas tiras APA102 usan otro orden de color; la librería
adafruit_dotstaracepta un parámetro de orden de píxeles. - La imagen se ve estirada o comprimida: el cálculo de velocidad depende del sensor Hall; si pierde pulsos, acerca el imán o ajusta el umbral.
- Datos erráticos con 5 V: la APA102 alimentada a 5 V suele aceptar la lógica de 3,3 V del RP2040, pero si los cables de datos son largos un convertidor de nivel como el 74AHCT125 elimina los errores.
Variantes y mejoras
- Rueda trasera sincronizada. Con una segunda placa y otro sensor Hall puedes mostrar una animación distinta atrás, o la misma imagen desfasada para un efecto de movimiento.
- Cambio de imagen desde el celular. Si usas una placa RP2040 con WiFi, como la Raspberry Pi Pico W, puedes cambiar de imagen desde el celular sin desmontar nada. Ojo: la Pico W es otra placa y necesita su propio UF2 de CircuitPython.
- Velocímetro de luz. Ya que el sensor Hall mide las vueltas, puedes dibujar la velocidad en km/h dentro de la rueda o cambiar de color según qué tan rápido vas.
- Modo de seguridad. Cuando la rueda se detiene (sin pulsos del sensor durante unos segundos), haz que los rayos parpadeen en rojo o blanco para que te vean estando detenido en un semáforo.
Personalización para Chile
En Chile consigues lo principal para este montaje en MechatronicStore:
- Raspberry Pi Pico: el microcontrolador del proyecto. Tiene el mismo RP2040 de la Feather del original y corre CircuitPython; recuerda cambiar los nombres de pines en el código.
- Tira LED APA102 (la misma familia que Adafruit vende como DotStar): para los tres rayos de doble cara. Busca una densidad alta, como la de 144 LED/m del original, para que la imagen tenga resolución.
- Sensor de efecto Hall A3144: detecta cada vuelta de la rueda. Es un interruptor digital, no un magnetómetro lineal como el TMAG5273 del original, así que aliméntalo con 5 V, ponle pull up y adapta la lectura en el código.
- Imán de neodimio: va fijo en el marco o la horquilla, frente al sensor.
- Cable de silicona, termorretráctil y cautín: para soldaduras flexibles que aguanten la vibración.
Si en el tutorial original usan la "Adafruit Feather RP2040", la Raspberry Pi Pico cumple la misma función con los ajustes de pines descritos arriba.
Recursos
- Tutorial original (inglés): CircuitPython POV Bike Wheel, de Erin St Blaine para Adafruit. Esta versión está basada en esa guía.
- Guía completa en PDF: circuitpython pov bike wheel.pdf
- Repositorio de código de las guías de Adafruit: Adafruit_Learning_System_Guides
- CircuitPython para Feather RP2040: circuitpython.org/board/adafruit_feather_rp2040
- CircuitPython para Raspberry Pi Pico: circuitpython.org/board/raspberry_pi_pico
- Documentación de la librería DotStar: adafruit_dotstar
Versión chilena con componentes en stock local en MechatronicStore.





