les vencimos · offline

L27. Estados y funciones

Pensar en el tiempo (70–84%)

Maestro

Cuando el programa crece, loop se vuelve una bolsa de if. La salida es poner nombre a cada modo y nombre a cada gesto. Un estado es una variable: apagado, encendido, aviso. Una función es un trozo con nombre: encender, apagar, medir. loop solo pregunta en qué estado estás y llama. No hace el trabajo menudo.

Sin estados, cada sensor añade condiciones cruzadas y un día el LED enciende por dos razones a la vez. Con estados, solo hay un modo vigente. Pasas de apagado a encendido cuando llega el botón. Pasas a aviso cuando el sensor cruza el umbral. Cada modo sabe qué pinta en los pines. Los otros modos no se cuelan.

Una función void encender() agrupa los digitalWrite. Se llama desde donde haga falta y no se copia. Si mañana el LED cambia de pin, lo cambias en un sitio. El nombre tiene que decir el gesto, no un número suelto.

El sketch de abajo es mínimo: estado 0 apagado, estado 1 encendido. El pin 2 cambia de uno a otro, con una espera corta de rebote. La función aplicar escribe el LED. loop no sabe de pines. Eso es el orden que vas a necesitar en el semáforo y en la alarma.

Montaje

estado 0LED apagadoun flanco lo cambiaestado 1LED encendidootro flanco vuelve
Un solo botón en el 2 cambia de estado. El LED no copia el dedo: copia la memoria.

Pines de esta lección

Uno R3 · 5 V · mira la serigrafía, no la memoria2un flanco13según estado0apagado1encendido
El 2 sigue a GND con pull-up. El 13 muestra estado, no el nivel instantáneo.

Por qué

Un estado es un recuerdo con nombre. Aquí vale 0 o 1. El dedo no pone el LED: el dedo pide un cambio, y la función aplicar traduce el recuerdo a HIGH o LOW. Si mañana el estado 1 también enciende un zumbador, lo añades en aplicar, no repartes digitalWrite por todo el loop.

Hace falta el flanco y luego esperar a que suelten. Si cambias de estado mientras el pin sigue LOW, la siguiente vuelta del loop lo cambia otra vez, y el LED parpadea a toda velocidad con el dedo quieto. El while que espera la suelta es una forma simple. Bloquea, sí, pero solo durante el dedo, que es corto.

Los nombres 0 y 1 son pobres y bastan. Cuando haya tres situaciones, rojo, ámbar y verde, el estado será 0, 1 y 2 y aplicar pondrá tres pines. La idea no cambia: una variable, un sitio que la aplica, un sitio que la cambia.

Inicializar importa. estado = 0 y aplicar dentro de setup dejan el LED apagado al cargar, no en un recuerdo de la vez anterior. El chip no guarda la variable al quitar el USB. Al volver, setup manda.

Práctica

  1. Un pulsador en el 2, LED en el 13.
  2. Carga el sketch del estado.
  3. Al arrancar, LED apagado.
  4. Un golpe. LED encendido, y se queda al soltar.
  5. Otro golpe. LED apagado. Diez golpes: acaba apagado, porque empezó apagado y diez es par.
  6. Mantén el dedo. No debe oscilar. Si oscila, el while de la suelta no está.
  7. Pulsa RESET. Tiene que volver a apagado, el estado inicial, no al último.

Anota el montaje

Escribe qué cable va a qué pin, o qué has entendido del paso. Se guarda en este aparato.

Ejemplos resueltos

Oscila mientras aprietas

Se cambia el estado en cada vuelta en la que el pin está LOW. Un dedo de medio segundo son cientos de cambios. Al soltar, el LED queda al azar.

Después de cambiar, se espera a que digitalRead vuelva a HIGH. Un gesto, un cambio. El delay de 30 ms sigue ahí para el rebote del golpe.

Aplicar está copiado en dos sitios y no coincide

En un sitio el estado 1 enciende el LED. En otro, un arreglo rápido lo deja apagado. Según por dónde entres, el recuerdo y la luz mienten.

Una sola función aplicar. Quien cambie el estado no toca el pin. Quien toca el pin no decide el estado.

En la mesa

Golpea y suelta, diez veces, contando solo clics. El LED debe quedar como empezó si empezó apagado y diez es par. Si queda al azar, estás cambiando de estado durante todo el tiempo que el dedo está abajo. Mira el while de la suelta. Sin él, esta lección es la del rebote otra vez, no la de la memoria.

Pulsa RESET. Tiene que volver a apagado, el estado inicial, no acordarse del último golpe. El chip no tiene diario. Si se acuerda, no has reiniciado: has pulsado otra cosa. Usa el botón de RESET de la placa y míralo.

Di la función aplicar en una frase: aquí se entera el LED, y en ningún otro sitio. Si encuentras otro digitalWrite del 13 suelto, bórralo o mételo dentro. Dos sitios, dos verdades, un LED mentiroso.

Sketch

int estado = 0;

void aplicar() {
  digitalWrite(13, estado == 1 ? HIGH : LOW);
}

void setup() {
  pinMode(13, OUTPUT);
  pinMode(2, INPUT_PULLUP);
  aplicar();
}

void loop() {
  if (digitalRead(2) == LOW) {
    delay(30);
    if (estado == 0) estado = 1;
    else estado = 0;
    aplicar();
    while (digitalRead(2) == LOW) {
      delay(10);
    }
  }
}

Ejercicio

Añade un estado 2, aviso, que parpadee usando millis, no un delay largo. Entras con el pin 3. Si te lías, vuelve a dejar solo dos estados: mejor pocos y claros.

Autoevaluación

1. ¿Qué problema tiene un loop lleno de if cruzados?

2. ¿Para qué sirve una función con nombre?

3. ¿Cuántos estados mandan a la vez?