Ejercicio 02 — Leer un carácter desde el monitor serie y controlar un LED

Dificultad: verde · Módulo 05 (Comunicacion serie)

Enunciado

Leer un carácter desde el monitor serie y controlar un LED: ‘1’ enciende el LED, ‘0’ lo apaga.

Montaje (Arduino UNO)

LED + 220 ohm en el pin 8 (a GND)

Cómo se resuelve

En el ejercicio anterior la placa hablaba y tú escuchabas. Aquí se invierte el sentido: escribes tú y la placa obedece. Es el primer dato que viaja del PC a la placa en todo el curso, y con él aparecen dos conceptos nuevos, el buffer y Serial.available().

El montaje es el mínimo para que la orden tenga un efecto visible: un LED con su resistencia de 220 Ω en el pin 8, con la vuelta a GND, exactamente como en el módulo 01. El LED no tiene nada que ver con el serie; está para que puedas ver con los ojos que lo que escribiste llegó.

setup() mezcla las dos preparaciones, la del pin y la del canal:

pinMode(PIN_LED, OUTPUT);
Serial.begin(9600);
Serial.println("Escribe 1 (ON) o 0 (OFF):");

Ese tercer println es una buena costumbre que merece la pena copiar: un programa que espera órdenes debería decir al arrancar qué órdenes acepta. Quien abra el monitor serie sin haber leído el código sabrá inmediatamente qué hacer.

El loop() entero es este patrón, y lo vas a repetir en todos los ejercicios que quedan:

if (Serial.available() > 0) {
    char c = Serial.read();
    ...
}

La razón de ese if es la pieza conceptual del ejercicio. Los caracteres que envías desde el PC no llegan cuando al loop() le viene bien: llegan cuando pulsas Enviar, y hasta que el programa los recoja se quedan guardados en el buffer, una pequeña memoria de espera. Serial.available() te dice cuántos caracteres hay ahí dentro esperando, y Serial.read() saca uno y lo elimina del buffer.

Piensa en los números: el loop() da del orden de un millón de vueltas por segundo, y tú escribes algo cada varios segundos. En la práctica totalidad de las vueltas el buffer está vacío. Si leyeras sin preguntar, Serial.read() devolvería -1 (su forma de decir “no había nada”) y el programa estaría tomando decisiones millones de veces por segundo sobre un dato que nunca existió. El if convierte eso en lo correcto: solo se lee cuando hay algo que leer.

El otro detalle importante está en las comillas de las comparaciones:

if (c == '1') { ... } else if (c == '0') { ... }

Serial.read() devuelve un char, un carácter, no un número. Cuando pulsas la tecla 1 no llega el valor 1, llega el carácter '1', que en la tabla de códigos es el 49. Comparar con 1 a secas no funcionaría, y como el compilador no protesta (un char es un número para él), es un fallo que puede costar un rato encontrar. Comillas simples para caracteres: '1', '0'.

Cada rama hace dos cosas: mueve el pin con digitalWrite e informa por serie con Serial.println("LED encendido") o "LED apagado". Esa confirmación es la versión sencilla del eco que se explota en el ejercicio 04. Sirve para distinguir dos fallos distintos que desde fuera se parecen: si el monitor dice “LED encendido” y el LED sigue apagado, el problema está en el cableado o en la polaridad del LED; si el monitor no dice nada, el carácter ni siquiera llegó.

Queda una sutileza en el comentario final del modelo: cualquier otro carácter (incluido '\n') se ignora. Si el monitor serie está configurado para añadir salto de línea al enviar, cuando escribas 1 llegarán en realidad dos caracteres al buffer, el '1' y el '\n'. El loop() los procesará en dos vueltas seguidas: la primera enciende el LED, y en la segunda el '\n' no coincide con ninguna de las dos ramas y simplemente no hace nada. Esa estructura de if/else if sin else es lo que hace el programa robusto: todo lo que no reconoce lo descarta en silencio, en vez de liarse.

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 05: Comunicación serie
 * Ejercicio 02 — PRÁCTICA (rellena los TODO)
 * Enunciado: Leer un carácter desde el monitor serie y controlar un LED:
 *            '1' enciende el LED, '0' lo apaga.
 * Dificultad: verde
 * Placa: Arduino UNO    Montaje: LED + 220 ohm en el pin 8 (a GND)
 * Correr: Arduino IDE / Wokwi (wokwi/ej02) / arduino-cli (ver README)
 *         Escribe 1 o 0 en el monitor serie y pulsa Enviar.
 */
const int PIN_LED = 8;                   // LED en el pin 8
 
void setup() {
    // TODO: configura PIN_LED como salida -> pinMode(PIN_LED, OUTPUT)
    // TODO: abre el puerto serie a 9600 baudios
    // TODO: imprime una instrucción para el usuario con Serial.println(...)
}
 
void loop() {
    // TODO: comprueba si hay datos -> if (Serial.available() > 0) { ... }
    //   TODO: lee un carácter -> char c = Serial.read();
    //   TODO: si c == '1' enciende el LED (digitalWrite HIGH) e informa
    //   TODO: si c == '0' apaga el LED (digitalWrite LOW) e informa
}

Solución — cópiala y ejecútala

/*
 * Curso de Arduino — Módulo 05: Comunicación serie
 * Ejercicio 02 — MODELO (resuelto)
 * Enunciado: Leer un carácter desde el monitor serie y controlar un LED:
 *            '1' enciende el LED, '0' lo apaga.
 * Dificultad: verde
 * Placa: Arduino UNO    Montaje: LED + 220 ohm en el pin 8 (a GND)
 * Correr: Arduino IDE / Wokwi (wokwi/ej02) / arduino-cli (ver README)
 *         Escribe 1 o 0 en el monitor serie y pulsa Enviar.
 */
const int PIN_LED = 8;                   // LED en el pin 8
 
void setup() {
    pinMode(PIN_LED, OUTPUT);            // el pin del LED como salida
    Serial.begin(9600);                 // puerto serie a 9600 baudios
    Serial.println("Escribe 1 (ON) o 0 (OFF):");
}
 
void loop() {
    if (Serial.available() > 0) {       // ¿hay al menos un carácter recibido?
        char c = Serial.read();         // lee UN carácter del buffer
        if (c == '1') {
            digitalWrite(PIN_LED, HIGH); // enciende
            Serial.println("LED encendido");
        } else if (c == '0') {
            digitalWrite(PIN_LED, LOW);  // apaga
            Serial.println("LED apagado");
        }
        // cualquier otro carácter (incluido '\n') se ignora
    }
}

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": "led1", "top": -110, "left": 130, "attrs": { "color": "red" } },
    { "type": "wokwi-resistor", "id": "r1", "top": -40, "left": 120, "attrs": { "value": "220" } }
  ],
  "connections": [
    [ "uno:8", "r1:1", "green", [ "v0" ] ],
    [ "r1:2", "led1:A", "green", [ "v0" ] ],
    [ "led1:C", "uno:GND.1", "black", [ "v0" ] ]
  ],
  "dependencies": {}
}

En VS Code, con el repo del curso

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

make sim EJ=05-comunicacion-serie/ej02

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