← Índice Valentina Tech
Laboratorio 6 · Curso de Programación · CircuitPython

Máquinas de estados: la placa recuerda en qué modo está

Objetivos

En esta primera parte aprenderás a:


Material necesario


Introducción

Hasta ahora tus programas tomaban decisiones con if: si hay poca luz, pon azul. Pero
todos tenían algo en común: no se acordaban de nada. Cada vuelta empezaban de cero,
como si nunca hubiera pasado nada antes.

En la vida real, muchas cosas sí se acuerdan de en qué modo están:

Esa memoria de "en qué modo estoy" es justo lo que le vamos a dar a la placa. A esa
forma de pensar los ingenieros le llaman máquina de estados.


🧠 La gran idea: la máquina de estados

⚙️ Máquina de estados: una forma de programar en la que la placa siempre está en
uno (y solo uno) de varios modos
, y cambia de modo con reglas fijas cuando pasa
algo. Se arma con tres piezas.

Las tres piezas, con el ejemplo de ti mismo durmiendo:

👉 La idea poderosa: el mismo evento hace cosas distintas según el estado en que estés.
Si suena la alarma y estás dormido, la acción es despertar; si ya estás despierto, no
pasa gran cosa. Un if suelto, sin memoria, no puede explicar eso. Una máquina de estados,
sí.

🌎 Esto se usa de verdad: las máquinas de estados están por todos lados.

  • Las puertas automáticas de una tienda (cerrada → abriendo → abierta → cerrando).
  • Los elevadores (subiendo, bajando, con la puerta abierta, esperando).
  • Los videojuegos (tu personaje está quieto, corriendo, saltando o herido).
  • Los cajeros automáticos, los semáforos, hasta el microondas.

🔦 La app que vamos a operar: la lámpara automática

Vas a operar una placa que se comporta como esas lámparas de jardín que se prenden solas
al anochecer
y se apagan al amanecer. Adentro tiene una máquina de estados con dos
estados
:

Y cambia de un modo a otro con dos eventos que dependen del sensor de luz:

💡 Curiosidad: esto de verdad existe y se llama fotocelda. Los faroles de la
calle la usan para prenderse solos cuando cae la tarde. ¡Nadie va apagándolos uno por uno!


🗺️ El diagrama de estados

Antes de operarla, mira el "mapa" de la máquina. Cada burbuja es un estado; cada
flecha es una transición y dice qué evento la dispara. La acción que hace la
placa al entrar a un modo va en el recuadro punteado que cuelga de ese estado
(apagar en DÍA, prender en NOCHE).

inicio 🌙 anochece ☀️ amanece acción apagar luces acción prender luces ☀️ DÍA luces apagadas 🌙 NOCHE luces encendidas
El diagrama de la lámpara — se imprime en grande, en una hoja aparte, para el juego.

📋 La tabla de transiciones

La misma máquina, escrita como tabla. Léela de izquierda a derecha: estando en… si
pasa… hago… y quedo en…
. Es casi el pseudocódigo del programa.

Estado actual ¿Qué evento pasa? Acción Nuevo estado
☀️ DÍA anochece (poca luz) prender las luces 🌙 NOCHE
🌙 NOCHE amanece (mucha luz) apagar las luces ☀️ DÍA

🧠 La conexión con el código: cada renglón de esta tabla es un if dentro de un
modo del programa. Cuando en la siguiente sección escribas tú la máquina de estados,
vas a estar traduciendo esta tabla a Python. Lo que hoy haces con la ficha, lo hará
la variable estado.


🎲 Actividad — Opera la lámpara y sigue la máquina con tu ficha

Aquí viene lo divertido. Vas a hacer dos cosas a la vez: operar la placa con tu
dedo y, como en un juego de mesa, mover una ficha por el diagrama para ver en qué
estado estás en cada momento.

Prepara el tablero:

  1. Ten a la mano la hoja del diagrama de estados (las dos burbujas, DÍA y NOCHE).
  2. Consigue una ficha (moneda, botón, gomita…).
  3. Corre el programa en tu CPX y ponla junto al tablero.
  4. Con la luz normal del salón las luces están apagadas: estás en DÍA. Coloca ahí
    tu ficha, donde apunta la flecha de inicio.

A jugar (opera la placa y sigue con la ficha):

  1. Tapa el sensor de luz 👁️ con el dedo (el ojito junto a los LEDs). En un segundo…
    ✨ se prenden las luces cálidas: se produce el evento anochece y la placa se fue
    a NOCHE. Mueve tu ficha por la flecha de arriba hasta NOCHE y di en voz alta:

    "Estaba en DÍA. Se produce el evento anochece. Hago la acción prender y me
    muevo a NOCHE."

  2. Destapa el sensor. Las luces se apagan: se produce el evento amanece y
    vuelves a DÍA.
    Regresa tu ficha por la flecha de abajo y di la frase del otro lado.

  3. Repite tapando y destapando. Tu ficha y la placa deben estar siempre en el mismo
    estado.
    Abre la consola y verás el letrero dia / noche cambiar justo cuando mueves
    tu ficha. Si tu ficha y la placa se despegan, ¡encontraste un error… en el jugador! 😄

❓ Para pensar: si tapas el sensor y lo dejas tapado, ¿la placa se queda prendida
o se apaga sola? Pruébalo. (Pista: mientras siga oscuro, sigue de noche. La placa
recuerda su estado hasta que pase el evento contrario.)


Resumen de la sección

En esta primera parte descubriste que:

👉 En la siguiente parte subimos de nivel: una máquina con tres estados —la alarma de
un coche
— y te tocará a ti descubrir sus eventos y acciones.


🚗 Segunda parte: la alarma de un coche

La lámpara tenía dos estados. Ahora sube el reto: vas a conocer una máquina con tres
estados, como la alarma de un coche. Tu placa ya trae cargado el programa de la alarma;
tú vas a descubrir cómo piensa y a completar su diagrama.

🔦 Los tres estados

🌎 Esto se usa de verdad: es igualito a la alarma de un coche. Con el control la
armas al alejarte y la desarmas al volver; si alguien la mueve mientras está
armada, se dispara.

🎛️ ¿Qué la hace cambiar? (los eventos)

Tu placa solo tiene tres formas de enterarse de que pasó algo:

Uno de esos eventos arma la alarma, otro la desarma y otro la dispara. ¿Cuál
hace cada cosa? Eso lo vas a averiguar tú, operando la placa.

🎬 Y cada cambio hace algo (las acciones)

Igual que la lámpara prendía o apagaba, la alarma reacciona con luces y sonidos
cada vez que cambia de estado: hay destellos de color y pitidos distintos. Tu trabajo es
fijarte bien y describir qué hace en cada cambio.

✏️ Actividad — Completa el diagrama de la alarma

Manos a la obra con la hoja "La alarma del coche" (se imprime aparte). Trae los tres
estados escritos, pero las flechas (eventos) y los recuadros (acciones) están en
blanco: los llenas tú.

  1. Ten a la mano la hoja para completar y un lápiz.
  2. Corre el programa de la alarma en tu CPX, con la placa quieta sobre la mesa.
  3. Pulsa el Botón A. ¿Qué viste y oíste? Escríbelo como acción del estado al que
    llegaste, y anota el evento (qué botón) en la flecha que usaste.
  4. Con la alarma armada, mueve la placa. ¿Qué pasó? Completa esa flecha y su acción.
  5. Pulsa el Botón B. ¿Qué hizo? Completa su flecha y su acción. Pruébalo también
    mientras suena la alarma.
  6. Repite hasta llenar las cuatro flechas y los tres recuadros.

❓ Para pensar: el Botón B aparece en dos flechas. ¿Hace lo mismo estando
activada que estando en alarma? ¿Y el Botón A serviría para apagar la alarma? Pruébalo
y verás por qué el mismo botón puede tener sentido en un estado y en otro no. ¡Es la
misma gran idea de la lámpara!

📋 Revisa tu diagrama

Cuando termines, compáralo con esta tabla. Cada renglón es una flecha de tu diagrama:

Estado actual ¿Qué evento pasa? Acción Nuevo estado
⚪ DESACTIVADO Botón A bip-bip + dos destellos verdes 🔵 ACTIVADO
🔵 ACTIVADO mueves la placa luces en rojo + sirena 🔴 ALARMA
🔵 ACTIVADO Botón B un bip + un destello cian ⚪ DESACTIVADO
🔴 ALARMA Botón B un bip + un destello cian ⚪ DESACTIVADO

🧩 Fíjate en los dos últimos renglones: el Botón B siempre lleva a DESACTIVADO,
venga de activada o de alarma. En cambio el movimiento solo hace algo si estás
activada: si la placa está desactivada, moverla no dispara nada. ¡La máquina
recuerda en qué modo está!

Resumen de la segunda parte

🏁 ¡Felicidades! Ya sabes leer, seguir y completar máquinas de estados: la forma de
pensar con la que funcionan desde una lámpara de jardín hasta la alarma de un coche.

👉 Hasta aquí, cada placa trabajaba sola. En la última parte vas a lograr que dos
placas se hablen
por un cable… ¡pasándose datos de una a la otra!


📡 Tercera parte: mandar información por un cable (UART)

Tu lámpara y tu alarma pensaban solas. Pero las máquinas más interesantes se comunican:
tu control le habla a la tele, tu celular al WiFi. Vamos a dar el primer paso para que
una placa le mande información a otra.

🔌 ¿Cómo se hablan dos placas por un cable?

La forma más segura de que dos placas se pasen datos es unirlas con un cable y mandar la
información número por número por ese hilo. A esa manera de platicar los ingenieros la
llaman puerto serie o UART.

El nombre UART viene del inglés Universal Asynchronous Receiver-Transmitter, que quiere
decir "Transmisor-Receptor Universal": un aparatito que transmite y recibe datos
uno por uno. ¡Por eso los pads de la placa se llaman TX (de transmite) y RX (de
recibe)!

Piensa en el clásico teléfono de latas: dos latas unidas por un hilo tenso. Hablas en una
lata y tu voz viaja por el hilo hasta la otra. UART es igual, pero en vez de voz, por el hilo
viajan números.

🌎 Esto se usa de verdad (y ya lo usabas): el cable USB que conecta tu placa a la
computadora y la consola serial donde salen tus print son exactamente esto: la placa
le habla a la compu por un puerto serie. Ahora vas a hacer que dos placas se hablen entre
ellas de la misma forma.

🔗 Conecta las dos placas (tres cablecitos)

Necesitas dos placas y tres caimanes (cables con pinza). Vas a unir tres pads del
borde de una placa con los de la otra:

Placa 1 Placa 2
pad TX → pad RX
pad RX → pad TX
pad GND → pad GND

Fíjate que TX y RX van cruzados. En cada placa, TX (transmito) es como la persona
que habla
y RX (recibo) como la persona que escucha. Para entenderse, el que
habla en una placa (TX) tiene que conectarse con el que escucha en la otra
(RX). Si conectas a dos que hablan al mismo tiempo, nadie escucha a nadie.

¿Y el cable de GND para qué sirve? Los números viajan por el cable como pequeños cambios
de electricidad
(voltaje), y cada placa decide si llegó un 0 o un 1 comparándolo con su
GND, que es su nivel "cero". El cable de GND une el cero de las dos placas en uno
solo
, para que ambas midan desde el mismo punto y se pongan de acuerdo en qué es alto y qué
es bajo. Sin ese cero común, lo que para una placa es un 1 para la otra sería un revoltijo, y
el mensaje no se entendería.

Dos Circuit Playground Express conectadas por cable: el TX de una placa va al RX de la otra (cruzado) y un GND se une con el otro.
El TX de una placa va al RX de la otra (cruzado), y un GND se une con el otro.

🔢 Lo más sencillo: mandar un número

Empezaremos por lo más simple: mandar un solo número (del 0 al 255) de una placa a la
otra. Una palabra o un color no son más que varios números seguidos, pero eso
viene después.

Sea cual sea el mensaje, la comunicación siempre tiene tres pasos:

  1. Abrir la conexión — preparar el puerto serie (UART).
  2. Enviar el dato — la placa emisora escribe el número en el cable.
  3. Recibir el dato — la placa receptora lo lee del cable.

📤 El emisor — manda un número

Corre este programa en la primera placa (la que habla):

import time
import board
import busio

# ---- ABRIR LA CONEXION: preparar el puerto serie (UART) por el cable ----
uart = busio.UART(board.TX, board.RX, baudrate=9600)

# El dato que vamos a mandar: un solo numero (de 0 a 255)
numero = 7

while True:
    # ---- ENVIAR EL DATO: mandamos el numero como un byte por el cable ----
    uart.write(bytes([numero]))
    print("Envie:", numero)
    time.sleep(1)

📥 El receptor — recibe un número

Corre este otro en la segunda placa (la que escucha):

import board
import busio

# ---- ABRIR LA CONEXION: preparar el puerto serie (UART) por el cable ----
uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=0.5)

while True:
    print("En espera de un mensaje...")
    # ---- RECIBIR EL DATO: leemos un byte del cable ----
    dato = uart.read(1)
    if dato:                    # si llego algo...
        print("Recibi:", dato[0])

🎯 Pruébalo

  1. Conecta las dos placas con los tres cables (TX↔RX cruzados y GND↔GND).
  2. Carga el emisor en una placa y el receptor en la otra.
  3. Abre la consola serial de la placa receptora.
  4. En la consola del receptor debería aparecer, una y otra vez: Recibi: 7. ✨

❓ Para pensar: si quitas el cable de GND, o cruzas mal TX y RX, ¿sigue llegando el
número? (Sin el "piso común" o con la conexión al revés, el mensaje no llega bien: por eso
el protocolo del cable importa tanto.)

Resumen de la tercera parte


🔗 Cuarta parte (proyecto final): dos placas que siguen un protocolo

Ya sabes mandar un número por el cable. Pero para que dos placas se entiendan de verdad
no basta con lanzar datos sueltos: tienen que ponerse de acuerdo en las reglas. A esas
reglas se les llama protocolo de comunicación.

🤝 ¿Qué es un protocolo?

Un protocolo es el acuerdo de reglas que siguen dos que se comunican para entenderse.
Lo usas todos los días sin pensarlo:

Fíjate que siempre hay tres momentos: una señal de inicio, el contenido y una
señal de fin. Sin esas señales, quien recibe no sabría dónde empieza ni dónde acaba el
mensaje.

📨 Nuestro protocolo por el cable

Para pasar un color de una placa a otra mandamos cinco números seguidos por el cable,
con este acuerdo:

Orden Número Qué es
1º Start (170) "ahí te va" (empiezo)
2º, 3º, 4º el color rojo, verde y azul
5º End (85) "terminé"

👉 El Start y el End son marcas para que quien recibe sepa dónde empieza y dónde
acaba
el color dentro del chorro de números que van llegando por el cable. Como el color son
siempre los tres números que vienen justo después del Start, quien recibe nunca se
confunde.

🗺️ El diagrama de estados es el protocolo

Aquí se junta todo el laboratorio. Ese protocolo se dibuja y se programa como una
máquina de estados —la del diagrama "Máquina de estados de la comunicación" (la tienes
aquí abajo; también se imprime aparte, a página completa, para usarla como tablero)—. Es una
sola máquina, igual en las dos placas
:

inicio presionaBotón A envíaStart envíaEnd recibeStart recibeEnd envía valorcolor[i] recibecolor[i] Escuchando Preparando genera tres coloresR, G, B Enviando Recibiendo al recibir los tresvalores R, G, B,prende los LEDs
Rama ámbar = la placa que envía; rama turquesa = la que recibe. Es la misma máquina en las dos.

🧠 ¿Por qué hace falta una máquina de estados? Porque el mismo número significa cosas
distintas según en qué momento de la conversación estés: el 170 es "empiezo" si estabas
escuchando, pero los números que llegan cuando ya estás recibiendo son "el color". La
máquina recuerda en qué punto va la charla. ¡Es la misma gran idea de la lámpara y la
alarma, ahora entre dos placas!

🎲 Actividad — Simula la conversación como juego de mesa

Antes de programarlo, vas a actuar el protocolo con un compañero, como un juego de mesa
—igual que hiciste con la lámpara, pero ahora entre dos—. Así ves la máquina de estados
funcionando antes de que la hagan las placas.

Preparen el tablero (en parejas):

  1. Cada quien toma su propia hoja del diagrama "Máquina de estados de la comunicación"
    (una por jugador) y una ficha (moneda, gomita…).
  2. Consigan unos crayones o papelitos de colores: serán el color que se
    manda.
  3. Hagan dos papelitos más: uno que diga "Start" y otro "End" (las marcas del
    protocolo).
  4. Los dos empiezan con su ficha en Escuchando.

A jugar (uno envía, el otro recibe):

  1. Jugador 1 "aprieta el Botón A" (dilo en voz alta). Se produce el evento presiona
    Botón A
    : mueve tu ficha de Escuchando → Preparando.
  2. En Preparando, elige un color (toma un crayón): esa es la acción genera el color.
  3. Pasa a Enviando y manda a tu compañero, cruzando la mesa y uno por uno: primero
    el papelito "Start", luego el color y luego "End". Mueve tu ficha por las
    flechas envía Start, envía valor color[i] y envía End; al terminar regresa a Escuchando.
  4. Jugador 2, estabas en Escuchando. En cuanto te llega el "Start" se produce el
    evento recibe Start: mueve tu ficha a Recibiendo.
  5. Cuando te llega el color, quédate con ese color (evento recibe color[i]);
    cuando te llega el "End", se produce recibe End y regresas a Escuchando.
  6. ¡Los dos volvieron a Escuchando! Ahora cambien los papeles: el Jugador 2 aprieta su
    Botón A y el 1 recibe. Es la misma máquina en las dos hojas.

❓ Para pensar: ¿qué pasa si al Jugador 2 le llega el color pero nunca le llega el
"End"? (Se queda atorado en Recibiendo, esperando. Por eso el protocolo necesita la
marca de fin: sin ella, quien recibe no sabe que la conversación terminó.)

Cuando les salga fluido, ya entendieron el protocolo. Ahora sí, que lo hagan las placas.

💻 El código (el mismo en las dos placas)

Carga este mismo programa en ambas placas:

import time
import random
import board
import busio
from adafruit_circuitplayground import cp

# ---- ABRIR LA CONEXION: puerto serie (UART) por el cable ----
uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=0.05)

# Protocolo: mandamos 5 numeros seguidos por el cable ->  START, R, G, B, END
# START y END son las MARCAS que envuelven al color.
START = 170  # 0b10101010
END = 85     # 0b01010101

cp.pixels.brightness = 0.4
estado = "escuchando"
print("Estado: " + estado)

while True:

    # ===== ESCUCHANDO (o hablo yo, o me hablan a mi) =====
    if estado == "escuchando":
        if cp.button_a:  # Boton A: hablo yo
            estado = "preparando"
            print("EVENTO: Boton A -> preparando")
            while cp.button_a:
                time.sleep(0.01)
        else:
            marca = uart.read(1)  # me hablan: leo un numero del cable
            if marca and marca[0] == START:
                estado = "recibiendo"
                print("EVENTO: llego Start -> recibiendo")

    # ===== PREPARANDO (prepara el color y lo muestra 2 segundos) =====
    elif estado == "preparando":
        r = random.randint(0, 255)
        g = random.randint(0, 255)
        b = random.randint(0, 255)
        cp.pixels.fill((r, g, b))  # prende sus pixeles con el color
        time.sleep(2)              # lo deja ver 2 segundos
        cp.pixels.fill((0, 0, 0))  # y los apaga
        estado = "enviando"

    # ===== ENVIANDO (manda Start, el color y End por el cable) =====
    elif estado == "enviando":
        uart.write(bytes([START, r, g, b, END]))
        print("Envie color:", r, g, b)
        estado = "escuchando"
        print("---> Estado: escuchando")

    # ===== RECIBIENDO (lee el color, lo muestra 2 segundos y espera el End) =====
    elif estado == "recibiendo":
        color = uart.read(3)  # el DATO: 3 numeros (R, G, B)
        if color and len(color) == 3:
            r, g, b = color[0], color[1], color[2]
            cp.pixels.fill((r, g, b))  # se pinta del color recibido
            print("Recibi color:", r, g, b)
            time.sleep(2)              # lo deja ver 2 segundos
            cp.pixels.fill((0, 0, 0))  # y los apaga
        fin = uart.read(1)  # la marca de END
        if fin and fin[0] == END:
            estado = "escuchando"
            print("---> Estado: escuchando")

    time.sleep(0.02)

🎯 Pruébalo

  1. Conecta las dos placas con los tres cables (TX↔RX cruzados y GND↔GND).
  2. Carga este programa en las dos placas y ábreles la consola serial.
  3. Aprieta el Botón A en una: se pinta de un color al azar unos 2 segundos,
    se apaga y lo manda.
  4. La otra placa se pinta del mismo color por 2 segundos. ✨ ¡Le pasó el color por el
    cable!
  5. Ahora aprieta el Botón A en la otra: los papeles se invierten (es la misma máquina).

Resumen del proyecto

🏆 ¡Terminaste el Laboratorio 6! Pasaste de una máquina de un estado que no recordaba
nada, a dos placas que conversan con un protocolo. Así piensan de verdad las máquinas.

Valentina Tech · Circuit Playground Express · CircuitPython