Guías · 16 min de lectura

Coche fantástico Arduino: secuencia de LEDs, circuito y código

Coche fantástico con Arduino: 8 LEDs con 220 Ω, código con array y bucle for, velocidad con potenciómetro, millis, 74HC595, WS2812B, ESP32 y Pico.

El coche fantástico con Arduino es un clásico efecto de LEDs en el que una fila de LEDs se enciende uno tras otro, recorre la fila de un extremo a otro y vuelve, igual que la luz frontal de KITT, el coche que hablaba en la famosa serie de los años 80 El coche fantástico (El auto increíble en Latinoamérica, Knight Rider en inglés). Solo necesitas un Arduino Uno, 6 u 8 LEDs, una resistencia de 220 Ω por cada LED y algunos cables jumper. Si la luz avanza en una sola dirección y vuelve a empezar desde el principio, se llama secuencia de LEDs o luz corrediza. Los dos son proyectos clásicos que se hacen justo después del semáforo y la forma más divertida de aprender dos de las herramientas más importantes de la programación: los arrays y el bucle for.

En esta guía montarás el circuito y escribirás primero el código de la secuencia simple y después el del coche fantástico, que va y vuelve. Luego ajustarás la velocidad con un potenciómetro, añadirás un efecto en el que los LEDs se acumulan en un extremo y harás funcionar el mismo efecto con millis() sin bloquear nunca el código. En las últimas secciones verás cómo controlar 8 LEDs con solo 3 pines usando el chip 74HC595, cómo hacer un coche fantástico con estela desde un único pin con LEDs direccionables WS2812B, las versiones para ESP32 y Raspberry Pi Pico (MicroPython) y las soluciones a los errores más comunes.

LEDs de 5 mm rojos, amarillos, azules, verdes y blancos
Para el aspecto clásico del coche fantástico usa 6 u 8 LEDs de 5 mm del mismo color (mejor rojos); la pata larga es el ánodo (+) y la corta el cátodo (−).

¿Qué es el efecto coche fantástico y en qué se diferencia de una secuencia de LEDs?

En la serie, la luz roja del parachoques delantero de KITT barre sin parar de izquierda a derecha, como un ojo que vigila. En electrónica este efecto también se llama escáner Larson (Larson scanner), por el productor de la serie, Glen A. Larson; los ojos de los robots cylon de su otra serie, Galáctica, funcionan igual. En el escáner real se ve detrás del punto encendido una estela roja que se apaga poco a poco, una cola. En un circuito de LEDs sencillo cada LED está totalmente encendido o totalmente apagado; para imitar la estela hay que bajar el brillo de los LEDs de forma gradual con PWM. Lo haremos más adelante con los WS2812B y el ESP32. La tabla resume los efectos que vas a programar en este artículo y cuántos pasos dura una vuelta con 8 LEDs.

EfectoQué haceUna vuelta con 8 LEDsEn este artículo
Secuencia simpleUna sola luz avanza de izquierda a derecha y vuelve a empezar8 pasosPaso 1
Coche fantásticoUna sola luz va y vuelve entre los dos extremos14 pasosPasos 2 y 3
LEDs que se acumulanCada luz corre hasta el último hueco libre de la derecha y se queda allí36 pasosPaso 4
Encuentro en el centroDos luces llegan desde los extremos al centro y luego se separan8 pasosSección 74HC595
Coche fantástico con estelaEl LED de cabeza brilla al máximo y los de detrás se van apagando14 pasosSecciones WS2812B y ESP32

Materiales y cómo elegir la resistencia

MaterialCantidadNota
Arduino Uno (o Nano)1También vale un ESP32 o una Raspberry Pi Pico
LED de 5 mm6–8Del mismo color y del mismo lote para que brillen igual
Resistencia de 220 Ω6–8Una por LED; 330 Ω en la Pico
Potenciómetro de 10 kΩ (B10K)1Solo para las versiones con velocidad ajustable
Protoboard1Basta con media protoboard (400 puntos)
Cables jumper12–15Macho-macho
74HC595 o tira WS2812B de 8 LEDs1Opcional: para las secciones de ahorro de pines y de efecto con estela

Un LED no limita su propia corriente, así que cada LED lleva una resistencia en serie. El valor se calcula con la ley de Ohm: R = (tensión de alimentación − tensión directa del LED) / corriente. Un LED rojo tiene una tensión directa de unos 2 V, de modo que a 5 V con 220 Ω la corriente es (5 − 2) / 220 ≈ 13,6 mA. Así el LED brilla bastante y te quedas por debajo de los 20 mA recomendados para un pin de Arduino. En el efecto de LEDs que se acumulan, cuando los ocho LEDs están encendidos a la vez, la corriente total es de unos 109 mA, todavía dentro del límite de 200 mA que el Uno admite sumando todos los pines. Para reconocer una resistencia de 220 Ω por sus bandas de color usa la herramienta código de colores de resistencias; para otros colores y tensiones, la calculadora de resistencia para LED.

Conexión del circuito: 8 LEDs y un potenciómetro

La pata larga (ánodo) de cada LED va a través de una resistencia a un pin digital de la placa, y la pata corta (cátodo) a GND. En la protoboard lo más ordenado es unir el pin GND del Arduino a la línea azul (−) y llevar las patas cortas de los ocho LEDs a esa línea. Coloca los LEDs con la misma separación, de izquierda a derecha y en el orden de los pines; así el orden del array en el código coincide con el orden físico de la luz. Las dos patas exteriores del potenciómetro van a 5V y GND, y la pata central (el cursor) a A0. La tabla muestra los pines que usan todos los códigos de este artículo; si usas 6 LEDs, sáltate las dos últimas filas de LEDs y borra los dos últimos pines del array en el código. Puedes ver la distribución de pines de tu placa en la herramienta Pinout.

FunciónArduino UnoESP32Raspberry Pi Pico
LED 1 (extremo izquierdo)D2GPIO 18GP8
LED 2D3GPIO 19GP9
LED 3D4GPIO 21GP10
LED 4D5GPIO 22GP11
LED 5D6GPIO 23GP12
LED 6D7GPIO 25GP13
LED 7D8GPIO 26GP14
LED 8 (extremo derecho)D9GPIO 27GP15
Pata central del potenciómetroA0GPIO 34GP26 (ADC0)
Patas exteriores del potenciómetro5V y GND3V3 y GND3V3(OUT) y AGND
Cátodos de los LEDs (pata corta)GNDGNDGND
Resistencia en serie220 Ω220 Ω330 Ω
No conectes LEDs a los pines D0 y D1: se usan para cargar el código por USB y para el Monitor Serie; con LEDs conectados la carga puede fallar y los LEDs parpadean al azar. Por eso el array empieza en D2. Si no se enciende ningún LED, comprueba primero que la línea azul de la protoboard está realmente conectada al pin GND del Arduino.
Arduino Uno
Arduino Uno
Breadboard
Breadboard
R · Ω
R · Ω
Jumper
Jumper

Paso 1: código de la secuencia de LEDs con array y bucle for

Podrías escribir ocho líneas pinMode y dieciséis líneas digitalWrite para ocho LEDs, pero el código se alarga y cambiar el número de LEDs se vuelve pesado. En su lugar guardas los números de pin en un array y lo recorres en orden con un bucle for. El primer elemento del array es LEDS[0], es decir, D2; el último es LEDS[7], es decir, D9. Así el mismo código funciona sin cambios con 6, 8 o 12 LEDs; solo editas el array. Tienes los fundamentos de arrays y bucles explicados con más detalle en Fundamentos de programación de Arduino.

C++ (Arduino IDE)
1// Yürüyen LED: 8 LED sırayla yanar / Running light: 8 LEDs light up one after another
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};             // LED pinleri / LED pins
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);  // dizideki LED sayısı (8) / number of LEDs (8)
4const int BEKLE = 100;                                  // adım süresi (ms) / step time (ms)
5
6void setup() {
7  for (int i = 0; i < LED_SAYISI; i++) {
8    pinMode(LEDS[i], OUTPUT);                           // tüm LED pinleri çıkış / all LED pins as outputs
9  }
10}
11
12void loop() {
13  for (int i = 0; i < LED_SAYISI; i++) {
14    digitalWrite(LEDS[i], HIGH);                        // sıradaki LED'i yak / light the next LED
15    delay(BEKLE);
16    digitalWrite(LEDS[i], LOW);                         // söndür ve devam et / turn it off and move on
17  }
18}
LíneaQué hace
const int LEDS[] = {2, ..., 9};Array que guarda los pines de los LEDs en orden de izquierda a derecha; LEDS[0] = 2, LEDS[7] = 9
sizeof(LEDS) / sizeof(LEDS[0])Calcula el número de elementos: en el Uno 16 bytes / 2 bytes = 8; se actualiza solo cuando añades o quitas pines
for (int i = 0; i < LED_SAYISI; i++)Cuenta la variable i de 0 a 7; en cada vuelta se procesa un elemento del array
pinMode(LEDS[i], OUTPUT)Configura los ocho pines como salida con un solo bucle
digitalWrite, delay(BEKLE), digitalWriteEnciende el LED, espera BEKLE milisegundos, lo apaga y pasa al siguiente

Con BEKLE (el tiempo de paso) a 100 ms, la luz recorre los ocho LEDs en 0,8 segundos y vuelve a empezar enseguida. Si lo bajas a 30 ms, el recorrido es muy rápido; si lo subes a 300 ms, parece lento, como lámparas que se encienden una a una. Para cargar el código elige la placa y el puerto en el menú Herramientas y pulsa Subir; si la carga falla, repasa la lista de comprobación de Arduino no sube el código.

Paso 2: código del coche fantástico (ida y vuelta)

Para el efecto coche fantástico la luz tiene que dar la vuelta al llegar al extremo derecho. Lo haces con dos bucles: el primero cuenta de izquierda a derecha y el segundo de derecha a izquierda. El detalle importante está en los LEDs de los extremos. Si los dos bucles cuentan completos de 0 a 7 y de 7 a 0, el LED de la derecha se enciende una vez al final del bucle de ida y otra vez al principio del de vuelta; la luz se queda el doble de tiempo en los extremos y el movimiento parece dar tirones. Por eso el bucle de ida se detiene en 6 y el de vuelta en 1. Así cada vuelta dura exactamente 14 pasos y la luz se queda en los extremos lo mismo que en el centro. Además, hemos pasado las tres líneas que encienden y apagan un LED a una pequeña función llamada yakSondur() ("encender y apagar"); el código queda más corto y más fácil de leer.

C++ (Arduino IDE)
1// Karaşimşek (Knight Rider): ışık iki uç arasında gidip gelir / light bounces between the two ends
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int BEKLE = 80;                                   // adım süresi (ms) / step time (ms)
5
6void yakSondur(int i) {
7  digitalWrite(LEDS[i], HIGH);
8  delay(BEKLE);
9  digitalWrite(LEDS[i], LOW);
10}
11
12void setup() {
13  for (int i = 0; i < LED_SAYISI; i++) pinMode(LEDS[i], OUTPUT);
14}
15
16void loop() {
17  for (int i = 0; i < LED_SAYISI - 1; i++) {           // soldan sağa: 0..6 / left to right: 0..6
18    yakSondur(i);
19  }
20  for (int i = LED_SAYISI - 1; i > 0; i--) {           // sağdan sola: 7..1 / right to left: 7..1
21    yakSondur(i);
22  }
23}
La velocidad más parecida a la de la serie es de unos 60–120 ms por paso. Con 8 LEDs y 80 ms, una vuelta de ida y vuelta dura 14 × 80 = 1,12 segundos. Cuando bajas a unos 20 ms, el ojo percibe varios LEDs encendidos a la vez y la luz se convierte en una línea borrosa.

Paso 3: ajustar la velocidad con un potenciómetro

En lugar de cambiar el código y volver a cargarlo cada vez que quieras otra velocidad, puedes usar un potenciómetro. Un potenciómetro es un divisor de tensión: la tensión de la pata central varía entre 0 y 5 V según la posición del eje, y analogRead() la convierte en un número entre 0 y 1023. map(deger, 0, 1023, 400, 20) transforma ese número en un tiempo de paso entre 400 y 20 ms; como el rango está escrito al revés, cuanto mayor es la lectura, más corto es el paso y más rápida va la luz. Hacia qué lado tienes que girar para acelerar depende de qué pata exterior conectaste a 5V; si te parece al revés, intercambia los dos cables exteriores o el 400 y el 20 en map(). Puedes leer cómo funciona un potenciómetro por dentro en ¿Qué es un potenciómetro?.

Potenciómetro de 10 kΩ
Potenciómetro de 10 kΩ: las patas exteriores van a 5V y GND, y la pata central del cursor a A0.
C++ (Arduino IDE)
1// Hız ayarlı karaşimşek: potansiyometre adım süresini belirler / Speed-adjustable Knight Rider: the pot sets the step time
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int POT = A0;                                     // potansiyometrenin orta bacağı / pot wiper
5
6int adimSuresi() {
7  int deger = analogRead(POT);                          // 0–1023
8  return map(deger, 0, 1023, 400, 20);                  // değer büyüdükçe hızlanır / faster as the value rises
9}
10
11void yakSondur(int i) {
12  digitalWrite(LEDS[i], HIGH);
13  delay(adimSuresi());                                  // her adımda yeniden okunur / read again on every step
14  digitalWrite(LEDS[i], LOW);
15}
16
17void setup() {
18  for (int i = 0; i < LED_SAYISI; i++) pinMode(LEDS[i], OUTPUT);
19}
20
21void loop() {
22  for (int i = 0; i < LED_SAYISI - 1; i++) yakSondur(i);   // sağa / to the right
23  for (int i = LED_SAYISI - 1; i > 0; i--) yakSondur(i);   // sola / to the left
24}

En esta versión el tiempo de paso se vuelve a leer en cada LED, así que la velocidad cambia en cuanto giras el eje. Sin embargo, mientras delay() está en marcha, el Arduino no puede hacer nada más: aunque gires el eje en mitad de un paso lento de 400 ms, la nueva velocidad solo se aplica a partir del siguiente paso. Para un efecto con unos pocos LEDs no es un problema, pero cuando añadas un botón para cambiar de modo o lecturas de sensores tendrás que pasar al método con millis() del paso 5.

Paso 4: el efecto de LEDs que se acumulan

En el efecto de LEDs que se acumulan, la primera luz corre hasta el final de la derecha y se queda encendida allí. La segunda luz también corre, pero esta vez se detiene una posición más a la izquierda; en cada vuelta el destino se desplaza un LED a la izquierda hasta que toda la barra se llena. En el código lo haces con dos bucles anidados: el exterior cuenta cuántos LEDs se han acumulado (dolu, "lleno") y el interior cuántos pasos corre la luz en esta vuelta. El LED que llega a su destino (hedef) no se apaga; de eso se encarga precisamente la línea if (i < hedef). Con ocho LEDs, llenar toda la barra lleva 8 + 7 + 6 + ... + 1 = 36 pasos.

C++ (Arduino IDE)
1// Birikerek dolan efekt: her ışık en boş uca kadar gider ve orada kalır / Stacking effect: each light runs to the last free spot and stays
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int BEKLE = 60;
5
6void setup() {
7  for (int i = 0; i < LED_SAYISI; i++) pinMode(LEDS[i], OUTPUT);
8}
9
10void loop() {
11  for (int dolu = 0; dolu < LED_SAYISI; dolu++) {       // dolu: sağda birikmiş LED sayısı / LEDs already stacked on the right
12    int hedef = LED_SAYISI - 1 - dolu;                  // bu turda ışığın duracağı yer / where the light stops this round
13    for (int i = 0; i <= hedef; i++) {
14      digitalWrite(LEDS[i], HIGH);
15      delay(BEKLE);
16      if (i < hedef) digitalWrite(LEDS[i], LOW);        // hedefte yanık kalır / stays lit at the target
17    }
18  }
19  delay(600);                                           // dolu çubuğu göster / show the full bar
20  for (int i = LED_SAYISI - 1; i >= 0; i--) {           // sağdan sola boşalt / empty from right to left
21    digitalWrite(LEDS[i], LOW);
22    delay(BEKLE);
23  }
24  delay(300);
25}

Al final del código la barra llena se muestra durante 0,6 segundos, después los LEDs se apagan uno a uno de derecha a izquierda y el efecto vuelve a empezar. Si quieres una barra que se llena más sencilla, basta con quitar el bucle interior y encender los LEDs en orden sin apagarlos nunca; ese aspecto es ideal para un indicador de carga o una barra de nivel de sonido. Recuerda que en este efecto los ocho LEDs están encendidos a la vez: mientras cada LED tenga su propia resistencia, el brillo no baja.

Paso 5: coche fantástico sin bloqueo con millis()

En el código que usa delay(), el Arduino se congela durante el tiempo indicado en cada paso; aunque alguien pulse un botón mientras tanto, no se entera. millis(), en cambio, devuelve los milisegundos que han pasado desde que se encendió la placa. La lógica es esta: el bucle gira sin parar, en cada vuelta comprueba si ha pasado suficiente tiempo desde el último paso y, si es así, da un solo paso y sale enseguida. En el código siguiente el coche fantástico y el LED integrado funcionan a la vez como dos tareas independientes: mientras la luz recorre la fila a la velocidad que marca el potenciómetro, el LED de D13 parpadea una vez por segundo a su propio ritmo. Para saber más, consulta Arduino millis() y delay().

C++ (Arduino IDE)
1// millis() ile bekletmesiz karaşimşek + potansiyometre / Non-blocking Knight Rider with millis() + pot
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int POT = A0;
5
6int konum = 0;                     // şu an yanan LED / the LED that is lit now
7int yon = 1;                       // +1 sağa, -1 sola / +1 right, -1 left
8unsigned long sonAdim = 0;         // son adımın zamanı / time of the last step
9unsigned long sonBlink = 0;        // dahili LED için / for the onboard LED
10
11void setup() {
12  for (int i = 0; i < LED_SAYISI; i++) pinMode(LEDS[i], OUTPUT);
13  pinMode(LED_BUILTIN, OUTPUT);    // Uno'da D13 / D13 on the Uno
14  digitalWrite(LEDS[konum], HIGH);
15}
16
17void loop() {
18  unsigned long simdi = millis();
19  unsigned long aralik = map(analogRead(POT), 0, 1023, 400, 20);   // adım süresi (ms) / step time (ms)
20
21  // Görev 1: karaşimşek / Task 1: Knight Rider
22  if (simdi - sonAdim >= aralik) {          // taşmaya karşı güvenli / overflow-safe
23    sonAdim = simdi;
24    digitalWrite(LEDS[konum], LOW);
25    konum += yon;
26    if (konum == LED_SAYISI - 1 || konum == 0) yon = -yon;   // uçta yön değiştir / reverse at the ends
27    digitalWrite(LEDS[konum], HIGH);
28  }
29
30  // Görev 2: dahili LED kendi temposunda yanıp söner / Task 2: the onboard LED blinks at its own pace
31  if (simdi - sonBlink >= 500) {
32    sonBlink = simdi;
33    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
34  }
35  // Buraya buton, sensör ya da seri port kodu eklenebilir / button, sensor or serial code can go here
36}

Aquí hay dos detalles importantes. Primero, las variables de tiempo deben ser unsigned long; si usas int, en el Uno el valor se desborda a los 32,7 segundos aproximadamente y la temporización se estropea: el efecto se para o se acelera sin control. Segundo, la comparación se hace con una resta de la forma simdi - sonAdim >= aralik (ahora menos el último paso, comparado con el intervalo); este método sigue funcionando bien incluso cuando millis() vuelve a cero, más o menos cada 49,7 días. Como guardamos la posición y la dirección de la luz en dos variables (konum y yon), ya no hay bucles: en cada paso la posición sube o baja en uno y, al llegar a los extremos, la dirección cambia de signo.

8 LEDs con 3 pines usando el 74HC595

Ocho LEDs ocupan ocho pines del Uno; cuando quieras añadir una pantalla LCD, sensores y botones a tu proyecto, empezarán a faltarte pines. El registro de desplazamiento 74HC595 controla sus ocho salidas con solo tres pines del Arduino (datos, reloj y latch). El estado de cada LED es un bit de un byte: la expresión 1 << i pone a 1 solo el bit i, es decir, enciende un único LED. Con operaciones de bits también es fácil crear patrones: (1 << i) | (0x80 >> i) produce dos luces que llegan a la vez desde los dos extremos hacia el centro. Encadenando dos chips puedes hacer incluso un coche fantástico de 16 LEDs con los mismos tres pines; el encadenado, el control rápido por SPI y el uso con displays de 7 segmentos se explican paso a paso en el artículo Registro de desplazamiento 74HC595.

Pin del 74HC595Conexión (Arduino Uno)
DS (14)D11
SH_CP (11)D13
ST_CP (12)D10
OE (13)GND (salidas siempre activas)
MR (10)5V (reset desactivado)
VCC (16) / GND (8)5V / GND, con un condensador de 100 nF al lado
Q0 (15), Q1–Q7 (1–7)Cada una a través de 470 Ω al ánodo de un LED
Pata central del potenciómetroA0
C++ (Arduino IDE)
1// 74HC595 ile 3 pinden 8 LED: karaşimşek ve ortada buluşma / 8 LEDs from 3 pins with a 74HC595: Knight Rider and meet-in-the-middle
2const int DATA_PIN = 11;    // DS (14)
3const int CLOCK_PIN = 13;   // SH_CP (11)
4const int LATCH_PIN = 10;   // ST_CP (12)
5const int POT = A0;
6
7void yaz595(byte desen) {
8  digitalWrite(LATCH_PIN, LOW);
9  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, desen);   // 8 biti gönder / send the 8 bits
10  digitalWrite(LATCH_PIN, HIGH);                    // çıkışlara aktar / copy to the outputs
11}
12
13void setup() {
14  pinMode(DATA_PIN, OUTPUT);
15  pinMode(CLOCK_PIN, OUTPUT);
16  pinMode(LATCH_PIN, OUTPUT);
17  yaz595(0);                                        // açılışta hepsi sönük / all off at startup
18}
19
20void loop() {
21  int bekle = map(analogRead(POT), 0, 1023, 400, 20);
22
23  for (int i = 0; i < 7; i++) { yaz595(1 << i); delay(bekle); }   // Q0 -> Q7
24  for (int i = 7; i > 0; i--) { yaz595(1 << i); delay(bekle); }   // Q7 -> Q0
25
26  for (int i = 0; i < 4; i++) {                     // uçlardan ortaya / from the ends to the middle
27    yaz595((1 << i) | (0x80 >> i));
28    delay(bekle);
29  }
30  for (int i = 3; i >= 0; i--) {                    // ortadan uçlara / from the middle to the ends
31    yaz595((1 << i) | (0x80 >> i));
32    delay(bekle);
33  }
34}

En las salidas del 74HC595 se recomienda 470 Ω en lugar de 220 Ω: la corriente total que pasa por los pines VCC y GND del chip no debe superar 70 mA. Con 470 Ω circulan unos 6,4 mA por LED e, incluso con los ocho LEDs encendidos, el total se queda en 51 mA. En el coche fantástico solo hay uno o dos LEDs encendidos a la vez, así que los LEDs se siguen viendo bien.

Coche fantástico con estela desde un solo pin con WS2812B

La versión que más se parece al escáner real de KITT se hace con LEDs direccionables WS2812B. Cada WS2812B lleva su propio controlador integrado; por larga que sea la tira, ajustas el color y el brillo de cada LED por separado con un único cable de datos. Para la estela guardamos un array: en cada paso el brillo de todos los LEDs se divide entre tres y el LED de cabeza se pone a 255. Así los LEDs de detrás se apagan rápido pasando por 255, 85, 28 y 9, y aparece una estela natural detrás de la luz. Si divides entre 2 en vez de entre 3, la estela se alarga; con 5, se acorta. Para pasar de 8 a 60 LEDs con el mismo método solo tienes que cambiar el valor de NUM_LEDS.

LED RGB direccionable WS2812B
WS2812B: cada LED tiene su propio controlador dentro; se conecta con DIN, 5V y GND, y DOUT va al siguiente LED.
C++ (Arduino IDE)
1// WS2812B ile kuyruklu karaşimşek (tek veri pini) / Knight Rider with a fading tail on WS2812B (one data pin)
2#include <Adafruit_NeoPixel.h>
3
4const int DATA_PIN = 6;      // DIN, 330 Ω üzerinden / DIN through 330 Ω
5const int NUM_LEDS = 8;      // şerit ya da çubuktaki LED sayısı / LEDs on the strip or stick
6const int POT = A0;
7
8Adafruit_NeoPixel strip(NUM_LEDS, DATA_PIN, NEO_GRB + NEO_KHZ800);
9
10uint8_t seviye[NUM_LEDS];    // her LED'in kırmızı parlaklığı / red brightness of each LED
11int konum = 0;
12int yon = 1;
13
14void setup() {
15  strip.begin();
16  strip.setBrightness(80);   // 0–255; USB için düşük tut / keep it low on USB power
17  strip.show();              // hepsini söndür / all off
18}
19
20void loop() {
21  for (int i = 0; i < NUM_LEDS; i++) seviye[i] = seviye[i] / 3;   // kuyruk söner / the tail fades
22  seviye[konum] = 255;                                            // baştaki LED tam parlak / the head is full brightness
23
24  for (int i = 0; i < NUM_LEDS; i++) {
25    strip.setPixelColor(i, strip.Color(seviye[i], 0, 0));         // yalnız kırmızı / red only
26  }
27  strip.show();
28
29  konum += yon;
30  if (konum == NUM_LEDS - 1 || konum == 0) yon = -yon;            // uçta yön değiştir / reverse at the ends
31  delay(map(analogRead(POT), 0, 1023, 150, 20));
32}
Al conectar los WS2812B, pon una resistencia de 330 Ω en serie con la línea de datos y un condensador de 1000 µF entre 5V y GND, y si usas una fuente externa, une su GND con el del Arduino. Cada LED puede consumir unos 60 mA en blanco a máxima potencia; una tira de 8 LEDs funciona con el USB, pero a partir de 30 LEDs necesitas una fuente de 5 V aparte. Para instalar la librería, el orden de colores y el cálculo de consumo, consulta el artículo LED WS2812B NeoPixel.

Coche fantástico con ESP32: estela por PWM en cada pin

En el Uno es difícil hacer un coche fantástico con estela usando LEDs normales, porque el PWM solo está en los pines 3, 5, 6, 9, 10 y 11, y en nuestro array D2–D9 solo hay cuatro de ellos. En el ESP32, gracias al hardware LEDC, casi cualquier pin de salida puede generar PWM, y el ESP32 clásico tiene 16 canales PWM. Como analogWrite() funciona directamente en el núcleo actual de Arduino para ESP32, puedes aplicar la lógica de la estela de los WS2812B a LEDs normales. Los pines de la tabla son GPIO seguros que no afectan al arranque; el potenciómetro va al GPIO 34 del canal ADC1, que lee bien incluso con el Wi-Fi activo, y como el ADC del ESP32 es de 12 bits el valor va de 0 a 4095. Los pines del ESP32 dan 3,3 V, así que por un LED rojo con 220 Ω circulan unos 6 mA; los LEDs se ven algo más tenues que en el Uno. Para preparar la placa, consulta ¿Qué es el ESP32?.

C++ (Arduino IDE)
1// ESP32: her pinde PWM ile kuyruklu karaşimşek / ESP32: Knight Rider with a PWM tail on every pin
2const int LEDS[] = {18, 19, 21, 22, 23, 25, 26, 27};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int POT = 34;                        // ADC1, yalnızca giriş / ADC1, input only
5
6int parlaklik[LED_SAYISI];                 // 0–255
7int konum = 0;
8int yon = 1;
9unsigned long sonAdim = 0;
10
11void setup() {
12  // analogWrite() pini PWM için kendisi hazırlar / analogWrite() sets the pin up for PWM itself
13}
14
15void loop() {
16  unsigned long aralik = map(analogRead(POT), 0, 4095, 400, 20);   // ESP32 ADC 12 bit: 0–4095
17  if (millis() - sonAdim >= aralik) {
18    sonAdim = millis();
19    for (int i = 0; i < LED_SAYISI; i++) parlaklik[i] /= 3;        // kuyruk söner / the tail fades
20    parlaklik[konum] = 255;
21    for (int i = 0; i < LED_SAYISI; i++) analogWrite(LEDS[i], parlaklik[i]);
22    konum += yon;
23    if (konum == LED_SAYISI - 1 || konum == 0) yon = -yon;
24  }
25}

Coche fantástico con Raspberry Pi Pico y MicroPython

En la Raspberry Pi Pico escribes el mismo efecto en unas pocas líneas de MicroPython. Guardar los objetos Pin en una lista cumple la misma función que el array en Arduino. time.ticks_ms() y time.ticks_diff() son los equivalentes en MicroPython de millis() y de la resta segura frente al desbordamiento. El potenciómetro va a GP26 (ADC0); read_u16() da un valor entre 0 y 65535 y el código lo convierte en 400–20 ms. Se recomienda que la corriente total de todos los GPIO de la Pico no supere los 50 mA; por eso en la tabla elegimos 330 Ω: circulan unos 4 mA por LED e, incluso con los ocho encendidos, el total ronda los 32 mA. El proyecto coche fantástico para Pico de BlueGrays usa 6 LEDs en los pines GP9–GP14; si has montado ese circuito, basta con cambiar la lista PINLER a [9, 10, 11, 12, 13, 14]. Para la instalación y la carga del código con Thonny, consulta ¿Qué es la Raspberry Pi Pico?.

MicroPython
1# Raspberry Pi Pico: potansiyometreyle hız ayarlı karaşimşek / Pico: Knight Rider with pot speed control
2from machine import Pin, ADC
3import time
4
5PINLER = [8, 9, 10, 11, 12, 13, 14, 15]        # GP8–GP15
6leds = [Pin(p, Pin.OUT) for p in PINLER]
7pot = ADC(26)                                   # GP26 = ADC0
8
9def adim_suresi():
10    # read_u16: 0–65535 -> 400–20 ms
11    return 400 - pot.read_u16() * 380 // 65535
12
13konum, yon = 0, 1
14leds[konum].on()
15son = time.ticks_ms()
16
17while True:
18    if time.ticks_diff(time.ticks_ms(), son) >= adim_suresi():   # millis() benzeri / like millis()
19        son = time.ticks_ms()
20        leds[konum].off()
21        konum += yon
22        if konum == len(leds) - 1 or konum == 0:
23            yon = -yon                          # uçta yön değiştir / reverse at the ends
24        leds[konum].on()

Todos los GPIO de la Pico también pueden generar PWM; con machine.PWM y un valor duty_u16() para cada LED puedes llevar el efecto con estela del ESP32 a la Pico. Si quieres usar WS2812B, el módulo neopixel integrado en MicroPython controla una tira desde un único GPIO; pero un WS2812B alimentado a 5 V no siempre lee de forma fiable la señal de datos de 3,3 V de la Pico, así que si los colores fallan, añade un conversor de nivel entre ambos.

Ideas de proyectos con el coche fantástico

  • Vúmetro (indicador de nivel de sonido): decide cuántos LEDs de la barra se encienden según el volumen medido con el sensor de sonido KY-038.
  • Barra de LEDs para sensor de aparcamiento: enciende más LEDs a medida que disminuye la distancia medida con el HC-SR04 y haz que parpadeen todos cuando estés muy cerca.
  • Juego de atrapar la luz: mientras la luz va y viene rápido, intenta pulsar un botón justo cuando se enciende el LED del centro; con cada acierto, acorta el tiempo de paso.
  • Decoración nocturna automática: que el efecto arranque solo cuando un LDR detecte que oscurece.
  • Luz trasera para coche de maqueta o bicicleta: haz un coche fantástico rojo con estela en una tira WS2812B y enciende todos los LEDs al máximo al pulsar el botón de freno.
  • Indicador de nivel: muestra la posición de un potenciómetro o la tensión de una batería como una barra que se llena.
  • Pantallas más grandes: lleva la misma lógica a una matriz de LEDs MAX7219 o a un cubo de LEDs.

Errores comunes y cómo solucionarlos

SíntomaCausaSolución
Los LEDs brillan muy pocoFalta pinMode(OUTPUT); digitalWrite solo activa la resistencia pull-up internaConfigura todos los pines como OUTPUT con un bucle en setup()
Un LED no se enciende nuncaEl LED está al revés, o una resistencia o un cable están desplazados una filaPata larga a la resistencia y al pin, pata corta a GND; prueba el LED solo con 5V y una resistencia
Los LEDs de los extremos se quedan el doble de tiempoLos dos bucles incluyen los LEDs de los extremosUsa i < LED_SAYISI − 1 en el bucle de ida e i > 0 en el de vuelta
Un pin cualquiera parpadea o el programa hace cosas rarasTe sales del array: i <= LED_SAYISICambia la condición a i < LED_SAYISI; no existe el elemento LEDS[8]
El código no sube o los LEDs parpadean durante la cargaHay LEDs conectados a D0 y D1Empieza el array en D2
El potenciómetro no cambia la velocidadA A0 llega una pata exterior en lugar de la central, o el valor se lee una sola vez fuera del bucleConecta la pata central a A0; llama a analogRead en cada paso
El efecto se estropea a los 32 segundos aproximadamenteEl valor de millis() se guarda en una variable intDeclara las variables de tiempo como unsigned long
Los WS2812B no se encienden o salen colores al azarFalta el GND común, falta la resistencia de datos o la tira está conectada por el extremo equivocado (DOUT)Une los GND, añade 330 Ω y conecta por el extremo DIN, donde empiezan las flechas
Antes de montar el circuito, puedes probar el código en Tinkercad con 8 LEDs y un potenciómetro. Si algo falla en el circuito real, carga un código corto que ponga todos los pines en HIGH durante unos segundos para probar los LEDs uno a uno; verás enseguida cuál no se enciende.

El coche fantástico parece sencillo, pero contiene ideas básicas que usarás después en cualquier proyecto: arrays, bucles, lecturas analógicas, map(), temporización sin bloqueo, operaciones de bits y LEDs direccionables. Como siguiente paso, echa un vistazo al proyecto semáforo con Arduino o a la lista de ideas de proyectos con Arduino. En la aplicación BlueGrays encontrarás la secuencia de LEDs, el coche fantástico y sus versiones con velocidad ajustable, los efectos de acumulación y coche fantástico con WS2812B, y los proyectos de secuencia de LEDs con ESP32 y coche fantástico con Pico, cada uno con su esquema paso a paso y el código listo para probar en tu propia placa.

Preguntas frecuentes

¿Cuántos LEDs puedo controlar con un Arduino Uno?

El Uno tiene 20 pines que pueden usarse como salidas digitales, D0–D13 y A0–A5; si dejas libres D0 y D1 para la comunicación serie, puedes controlar 18 LEDs directamente. Pon una resistencia a cada LED y mantén la corriente total por debajo de 200 mA; si los 18 van a estar encendidos a la vez, elige 330 Ω o más. Para más LEDs se usa un registro de desplazamiento 74HC595 o una tira WS2812B, que controla cientos de LEDs con un solo pin.

¿Qué resistencia necesito para una secuencia de LEDs?

En un Arduino Uno de 5 V, 220 Ω va bien para LEDs rojos y da unos 13,6 mA por LED; 330 Ω también sirve, pero los LEDs brillan algo menos. En el ESP32 de 3,3 V se recomiendan 220 Ω y en la Pico 330 Ω. En efectos en los que solo hay un LED encendido funciona también una única resistencia común, pero el brillo baja cuando se encienden varios, así que lo correcto es una resistencia por LED.

¿Se puede hacer el coche fantástico sin Arduino?

Sí, el método clásico es un temporizador 555 y un contador CD4017. El 555 genera los pulsos de reloj y el 4017 pone en HIGH sus 10 salidas una tras otra, lo que por sí solo da una secuencia simple. Para la ida y vuelta las salidas se combinan con diodos: las 10 salidas se conectan a 6 LEDs en el orden 1-2-3-4-5-6-5-4-3-2, y la velocidad se ajusta con un potenciómetro en el 555.

¿Qué diferencia hay entre una secuencia de LEDs y el efecto coche fantástico?

En la secuencia simple la luz avanza en una dirección y, tras el último LED, vuelve a empezar; con 8 LEDs una vuelta son 8 pasos. En el coche fantástico la luz da la vuelta al llegar al extremo y va y viene entre los dos lados; con 8 LEDs una vuelta son 14 pasos. En el código la diferencia también es pequeña: para el coche fantástico añades un segundo bucle que cuenta hacia atrás.

¿Por qué usar millis() en lugar de delay() en una secuencia de LEDs?

Mientras delay() está en marcha el Arduino no puede hacer nada más; se pierde las pulsaciones de botones y no puede leer sensores. Con millis(), en cada vuelta del bucle solo se da un paso cuando ha pasado el tiempo, y en el resto del tiempo se ejecutan otras tareas. Así, mientras la luz recorre la fila, los botones, el potenciómetro o los comandos por el puerto serie responden al instante.

¿Cómo se añade una estela al efecto coche fantástico?

Para la estela hay que bajar poco a poco el brillo de los LEDs que van detrás, y para eso se necesita PWM. En el Uno el PWM solo está en los pines 3, 5, 6, 9, 10 y 11, así que con esos pines puedes hacer un coche fantástico con estela de 6 LEDs. Lo más fácil es usar una tira WS2812B, en la que controlas cada LED por separado, o un ESP32 o una Pico, que tienen PWM en todos los pines.

Ver todos los proyectos
Efecto coche fantástico con LED
#6Intermedio

Efecto coche fantástico con LED

La clásica luz que va y viene: un punto de luz recorre seis LED de un extremo al otro y luego regresa. El Arduino enciende cada LED una décima de segundo antes de pasar al siguiente, da la vuelta en c

4.8(106)
202
Luz secuencial LED
#5Intermedio

Luz secuencial LED

Luces que se encienden una tras otra, como si corrieran. El Arduino enciende seis LED de uno en uno; cada uno brilla un instante y se apaga, así que la luz recorre la fila de principio a fin y vuelve

4.6(85)
207
Efecto coche fantástico con velocidad regulable
#8Intermedio

Efecto coche fantástico con velocidad regulable

Una luz recorre seis LED de un extremo a otro, da la vuelta y vuelve a correr. Girando el mando del potenciómetro cambias al instante la velocidad de esa carrera: con el mando a un lado la luz casi vu

4.5(60)
120
Luz secuencial LED con velocidad regulable
#7Intermedio

Luz secuencial LED con velocidad regulable

Seis LED se encienden uno tras otro y la luz parece correr de un extremo al otro. Al girar el mando del potenciómetro, la velocidad de esa carrera cambia al instante: hacia un lado la luz vuela, hacia

4.6(72)
146
Efecto coche fantástico con WS2812B
#73Intermedio
Premium

Efecto coche fantástico con WS2812B

Un punto de luz roja recorre una tira LED inteligente de un extremo al otro y vuelve, en un vaivén que nunca se detiene. En cada paso el Arduino enciende un solo LED, espera una décima de segundo y pa

4.9(73)
94
Luz secuencial con WS2812B (efecto llenado)
#72Intermedio
Premium

Luz secuencial con WS2812B (efecto llenado)

Una tira de luz que se llena y se vacía como un vaso de agua. El Arduino enciende diez LED de color uno a uno en naranja y los deja encendidos; cuando la tira está llena, los apaga uno a uno en el mis

4.7(50)
65
LED Secuencial ESP32 (Knight Rider)
#108Principiante

LED Secuencial ESP32 (Knight Rider)

6 LEDs moviéndose secuencialmente de izquierda a derecha y de derecha a izquierda (estilo Knight Rider). Ejemplo básico del uso del bucle for y arrays. Enseña la lógica del cambio de dirección.

4.5(19)
32
Raspberry Pi Pico Knight Rider LED Escáner (6 LED Ida-Vuelta)
#154Principiante

Raspberry Pi Pico Knight Rider LED Escáner (6 LED Ida-Vuelta)

¡Efecto escáner LED "Knight Rider" clásico con Pico! 6 LEDs van de izquierda a derecha, luego de derecha a izquierda, indefinidamente. Aprende reversed() y dos bucles for separados para patrón ida-vuelta.

0.0(0)
13