Ejercicio 04 — Leer un número (0..255) desde el serie con parseInt, hacer eco de lo…

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

Enunciado

Leer un número (0..255) desde el serie con parseInt, hacer eco de lo recibido y fijar el brillo de un LED por PWM (analogWrite).

Montaje (Arduino UNO)

LED + 220 ohm en el pin 9 (PWM, a GND)

Cómo se resuelve

El reto del módulo, y el más corto de los cuatro: apenas ocho líneas de loop(). Lo interesante es que junta tres cosas que hasta ahora iban por separado: recibir un dato por serie, validarlo y usarlo para gobernar una salida analógica.

Primer cambio, el montaje. El LED ya no va en el pin 8 sino en el pin 9, y el motivo no es capricho: aquí no hay que encender y apagar, hay que graduar el brillo, y eso requiere PWM. En el Arduino UNO solo algunos pines saben hacer PWM, y son los que llevan una tilde ~ impresa al lado del número en la placa. El 9 la lleva; el 8 no. Si dejas el LED en el 8, analogWrite no hace lo que esperas. El resto del montaje es el de siempre: resistencia de 220 Ω en serie, patilla larga hacia la resistencia, corta a GND.

Segundo cambio, cómo se lee. Lo que se espera no es un comando sino una cifra, y para eso existe Serial.parseInt():

int brillo = Serial.parseInt();

parseInt recorre el buffer, se salta lo que no sean dígitos y devuelve el primer número entero que consigue componer. Ya no hace falta leer carácter a carácter ni convertir texto a número a mano: si escribes 128, llegan los tres caracteres '1', '2', '8' y parseInt te devuelve el entero 128. Sigue haciendo falta el if (Serial.available() > 0) de siempre, por la misma razón que en los ejercicios anteriores: no tiene sentido intentar interpretar un buffer vacío.

Conviene saber qué hace parseInt cuando lo que llega no es un número: devuelve 0, sin quejarse. Si escribes “hola”, el LED se apaga y no hay ningún mensaje de error. No es un fallo del sketch, es cómo funciona la función, pero explica un comportamiento que de otro modo desconcierta.

Tercer cambio, y el que de verdad separa un programa cuidadoso de uno descuidado:

brillo = constrain(brillo, 0, 255);

analogWrite espera un valor entre 0 y 255, y parseInt puede devolverte cualquier entero: un 999 porque te sobró una tecla, un -5 porque escribiste un guion. constrain(valor, minimo, maximo) recorta el valor al intervalo: si está por debajo devuelve el mínimo, si está por encima el máximo, y si está dentro lo deja igual. Es la lección general del ejercicio: cuando un dato viene de fuera, no te fíes de él. No importa que seas tú quien lo teclea; el programa no puede saberlo, y validar en la frontera cuesta una línea.

Con el valor ya saneado, aplicarlo es trivial, porque analogWrite es lo que aprendiste en el módulo de PWM:

analogWrite(PIN_LED, brillo);

0 apaga el LED, 255 lo pone al máximo, 128 lo deja a media luz. Merece la pena que pruebes valores bajos (10, 20, 40): verás que el brillo no crece de forma proporcional al número, porque el ojo no percibe la luz linealmente.

Y por último, el eco:

Serial.print("Eco -> brillo = ");
Serial.println(brillo);

Parece redundante (tú acabas de escribir el número, ¿para qué te lo repite?) y es justo lo contrario: es información nueva, porque lo que la placa devuelve no es lo que escribiste, es lo que entendió y aplicó. Escribe 999 y el eco dirá 255, confirmándote que el constrain hizo su trabajo. Escribe hola y el eco dirá 0, y ahí entiendes por qué el LED se apagó. Y si el eco dice 128 pero el LED no cambia, el problema no está en la comunicación: está en el pin, en el cable o en la polaridad del LED.

Esa es la razón de fondo por la que se hace eco en cualquier sistema que reciba órdenes: separa el fallo de comunicación del fallo de ejecución, que desde fuera se parecen mucho y se arreglan en sitios completamente distintos.

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 04 — PRÁCTICA (rellena los TODO)
 * Enunciado: Leer un número (0..255) desde el serie con parseInt, hacer eco
 *            de lo recibido y fijar el brillo de un LED por PWM (analogWrite).
 * Dificultad: amarillo
 * Placa: Arduino UNO    Montaje: LED + 220 ohm en el pin 9 (PWM, a GND)
 * Correr: Arduino IDE / Wokwi (wokwi/ej04) / arduino-cli (ver README)
 *         Escribe un número (p.ej. 128) en el monitor serie y pulsa Enviar.
 */
const int PIN_LED = 9;                   // pin 9 admite PWM (~)
 
void setup() {
    // TODO: configura PIN_LED como salida
    // TODO: abre el puerto serie a 9600 baudios
    // TODO: imprime una instrucción: "Escribe un brillo (0-255):"
}
 
void loop() {
    // TODO: if (Serial.available() > 0) { ... }
    //   TODO: lee un número -> int brillo = Serial.parseInt();
    //   TODO: recorta al rango 0..255 -> brillo = constrain(brillo, 0, 255);
    //   TODO: aplica el brillo -> analogWrite(PIN_LED, brillo);
    //   TODO: haz eco del valor aplicado con Serial.print / Serial.println
}

Solución — cópiala y ejecútala

/*
 * Curso de Arduino — Módulo 05: Comunicación serie
 * Ejercicio 04 — MODELO (resuelto)
 * Enunciado: Leer un número (0..255) desde el serie con parseInt, hacer eco
 *            de lo recibido y fijar el brillo de un LED por PWM (analogWrite).
 * Dificultad: amarillo
 * Placa: Arduino UNO    Montaje: LED + 220 ohm en el pin 9 (PWM, a GND)
 * Correr: Arduino IDE / Wokwi (wokwi/ej04) / arduino-cli (ver README)
 *         Escribe un número (p.ej. 128) en el monitor serie y pulsa Enviar.
 */
const int PIN_LED = 9;                   // pin 9 admite PWM (~)
 
void setup() {
    pinMode(PIN_LED, OUTPUT);
    Serial.begin(9600);
    Serial.println("Escribe un brillo (0-255):");
}
 
void loop() {
    if (Serial.available() > 0) {        // ¿hay datos esperando?
        int brillo = Serial.parseInt();  // extrae el primer número del buffer
        brillo = constrain(brillo, 0, 255); // recorta al rango válido de PWM
        analogWrite(PIN_LED, brillo);    // aplica el brillo
 
        Serial.print("Eco -> brillo = "); // eco de lo que se aplicó
        Serial.println(brillo);
    }
}

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": 140, "attrs": { "color": "red" } },
    { "type": "wokwi-resistor", "id": "r1", "top": -40, "left": 130, "attrs": { "value": "220" } }
  ],
  "connections": [
    [ "uno:9", "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/ej04/. Con la extensión Wokwi instalada y la licencia activada (lo cuenta el onboarding del curso):

make sim EJ=05-comunicacion-serie/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