Ejercicio 04 — Semáforo

Dificultad: amarillo · Módulo 01 (Fundamentos y GPIO digital)

Enunciado

Semáforo. Rojo 3s Verde 3s Amarillo 1s repetir.

Montaje (Arduino UNO)

Pin 8 220 ohm LED ROJO GND pin 9 220 ohm LED AMARILLO GND pin 10 220 ohm LED VERDE GND

UNO pin 8  ──[220Ω]──►|── GND     (ROJO)
UNO pin 9  ──[220Ω]──►|── GND     (AMARILLO)
UNO pin 10 ──[220Ω]──►|── GND     (VERDE)

Para diagramas “bonitos” (Fritzing/Wokwi) exporta un PNG aquí con el nombre ejNN.png. Hasta entonces, estos esquemas ASCII + la simulación de Wokwi son suficientes para dar clase.

Cómo se resuelve

El reto del módulo. Tres LEDs, tres pines, y una secuencia con tiempos distintos: rojo 3 segundos, verde 3 segundos, amarillo 1 segundo, y vuelta a empezar.

El montaje no tiene misterio: es el del ejercicio 02 por triplicado. Cada LED con su resistencia de 220 Ω, en los pines 8, 9 y 10, todos con la vuelta a GND. Los tres se declaran con nombre, y aquí se puede aprovechar que const int admite declarar varios de una vez:

const int ROJO = 8, AMARILLO = 9, VERDE = 10;

Los tres van a OUTPUT en setup().

Lo que hace interesante este ejercicio es la idea de estado. Un semáforo no está “encendiendo el verde”: está en verde, y estar en verde significa que el verde está encendido y los otros dos apagados. Si solo enciendes el siguiente sin apagar el anterior, los LEDs se van acumulando y acabas con el semáforo entero iluminado. Ese es el error que casi todo el mundo comete la primera vez, y es el que da sentido a la pregunta de la teoría.

Así que cada fase del loop() es lo mismo: dejar los pines como deben estar en ese estado, y esperar.

// ROJO
digitalWrite(ROJO, HIGH); digitalWrite(AMARILLO, LOW); digitalWrite(VERDE, LOW);
delay(3000);
// VERDE
digitalWrite(ROJO, LOW); digitalWrite(VERDE, HIGH);
delay(3000);
// AMARILLO
digitalWrite(VERDE, LOW); digitalWrite(AMARILLO, HIGH);
delay(1000);

La primera fase deja los tres pines explícitos; las otras dos solo tocan lo que cambia, porque el estado anterior ya garantiza el resto (al entrar en verde, el amarillo lleva apagado desde el rojo). Es más corto, pero también más frágil: si mañana insertas una fase nueva en medio, o alguien enciende un LED desde otro sitio, el razonamiento se rompe y aparecen dos luces a la vez. Escribir los tres digitalWrite en cada fase cuesta una línea más y no depende de lo que pasara antes. Merece la pena que pruebes las dos versiones y veas que se comportan igual, porque entender por qué una es más frágil vale más que la línea que ahorra.

Fíjate también en que el amarillo dura 1000 ms y los otros 3000: los tiempos son parte del comportamiento, no un detalle. Y no hace falta ningún estado final que “vuelva al rojo”, porque loop() ya vuelve al principio por sí solo.

Escrito así resulta repetitivo, y esa incomodidad es intencionada: la sientes justo antes de aprender las herramientas que la eliminan. Con arrays y bucles (módulos 03 y 05) esto se escribe en cuatro líneas, y con máquinas de estados se escribe de forma que además puedas atender un botón mientras el semáforo corre, que es lo que delay te impide hoy.

Para practicar — cópialo y complétalo

Pega este esqueleto y completa los TODO. Es la mejor forma de aprender: inténtalo antes de mirar la solución.

/*
 * Curso de Arduino — Módulo 01: Fundamentos y GPIO digital
 * Ejercicio 04 — PRÁCTICA (rellena los TODO)
 * Enunciado: Semáforo. Rojo 3s -> Verde 3s -> Amarillo 1s -> repetir.
 * Dificultad: amarillo
 * Placa: Arduino UNO
 * Montaje: pin 8 -> ROJO, pin 9 -> AMARILLO, pin 10 -> VERDE (cada uno con su 220 ohm a GND).
 */
const int ROJO = 8, AMARILLO = 9, VERDE = 10;
 
void setup() {
    // TODO: configura los tres pines como salida
}
 
void loop() {
    // TODO: enciende solo ROJO durante 3 s
    // TODO: enciende solo VERDE durante 3 s
    // TODO: enciende solo AMARILLO durante 1 s
    // (pista: apaga los que no toquen para que no se queden encendidos)
}

Solución — cópiala y ejecútala

/*
 * Curso de Arduino — Módulo 01: Fundamentos y GPIO digital
 * Ejercicio 04 — MODELO (resuelto)
 * Enunciado: Semáforo. Rojo 3s -> Verde 3s -> Amarillo 1s -> repetir.
 * Dificultad: amarillo
 * Placa: Arduino UNO
 * Montaje: pin 8 -> 220 ohm -> LED ROJO -> GND
 *          pin 9 -> 220 ohm -> LED AMARILLO -> GND
 *          pin 10 -> 220 ohm -> LED VERDE -> GND
 */
const int ROJO = 8, AMARILLO = 9, VERDE = 10;
 
void setup() {
    pinMode(ROJO, OUTPUT);
    pinMode(AMARILLO, OUTPUT);
    pinMode(VERDE, OUTPUT);
}
 
void loop() {
    // ROJO
    digitalWrite(ROJO, HIGH); digitalWrite(AMARILLO, LOW); digitalWrite(VERDE, LOW);
    delay(3000);
    // VERDE
    digitalWrite(ROJO, LOW); digitalWrite(VERDE, HIGH);
    delay(3000);
    // AMARILLO
    digitalWrite(VERDE, LOW); digitalWrite(AMARILLO, HIGH);
    delay(1000);
}

Cómo ejecutar la simulación

Sin instalar nada, en el navegador

  1. Abre wokwi.com y crea un proyecto nuevo de la placa que pide el ejercicio.
  2. Pega la solución (o tu intento) en la pestaña sketch.ino.
  3. Abre la pestaña diagram.json, borra lo que haya y pega el circuito de aquí abajo.
  4. Dale al play. Verás el circuito funcionando: LEDs, pantallas y monitor serie.
Circuito del ejercicio (diagram.json)
{
  "version": 1,
  "author": "ESIBot",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} },
    { "type": "wokwi-led", "id": "ledR", "top": -50, "left": 150, "attrs": { "color": "red" } },
    { "type": "wokwi-led", "id": "ledY", "top": -50, "left": 220, "attrs": { "color": "yellow" } },
    { "type": "wokwi-led", "id": "ledG", "top": -50, "left": 290, "attrs": { "color": "green" } },
    { "type": "wokwi-resistor", "id": "r1", "top": 100, "left": 150, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r2", "top": 140, "left": 150, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "r3", "top": 180, "left": 150, "attrs": { "value": "220" } }
  ],
  "connections": [
    [ "uno:8", "r1:1", "green", [] ],
    [ "r1:2", "ledR:A", "green", [] ],
    [ "ledR:C", "uno:GND.1", "black", [] ],
    [ "uno:9", "r2:1", "green", [] ],
    [ "r2:2", "ledY:A", "green", [] ],
    [ "ledY:C", "uno:GND.2", "black", [] ],
    [ "uno:10", "r3:1", "green", [] ],
    [ "r3:2", "ledG:A", "green", [] ],
    [ "ledG:C", "uno:GND.3", "black", [] ]
  ],
  "dependencies": {}
}

En VS Code, con el repo del curso

El paquete de simulación de este ejercicio está en practica/01-fundamentos/wokwi/ej04/. Con la extensión Wokwi instalada y la licencia activada (lo cuenta el onboarding del curso):

make sim EJ=01-fundamentos/ej04

y después, en VS Code, Ctrl+Shift+PWokwi: Start Simulator. La extensión no compila: simula un firmware ya compilado, y de compilarlo se encarga ese make.

Cómo usarlo

Con placa: abre el .ino en el Arduino IDE, elige placa y puerto y pulsa Subir. Sin placa: simulalo en Wokwi con cualquiera de las dos vias de arriba. Antes de mirar la solucion, intenta completar tu el esqueleto: es la mejor forma de aprender.

Conexiones