Unidad 2
Introducción
En esta unidad, daremos un salto crucial en tu formación como ingeniero en diseño de entretenimiento digital: adentrándonos en el fascinante mundo de los microcontroladores y la programación con Micropython utilizando la tarjeta micro:bit. Aprenderás a controlar el flujo de información en un sistema interactivo, a través del manejo de entradas y salidas, y a construir la lógica de estos sistemas utilizando el paradigma de máquinas de estado finitas. Dominarás conceptos como estados, eventos, transiciones y acciones, y los aplicarás para crear sistemas interactivos que respondan a estímulos externos y ejecuten acciones predefinidas.
El enfoque de esta unidad es 100% práctico. A través de una serie de experimentos y desafíos progresivos, irás construyendo una base sólida en la programación de microcontroladores, culminando con el diseño e implementación de una bomba temporizada para un hipotético escape room.
¿Qué aprenderás en esta unidad?
Antes de sumergirnos en la programación de microcontroladores, es fundamental establecer una base sólida y definir objetivos claros. En esta fase, reflexionarás sobre la importancia de los microcontroladores en el contexto del diseño de entretenimiento digital y establecerás una meta SMART personal para guiar tu aprendizaje a lo largo de la unidad. Este proceso te permitirá conectar con el propósito de la unidad y enfocar tus esfuerzos de manera efectiva.
Actividad 01
Reflexión sobre el Rol de los Microcontroladores
Enunciado: reflexiona sobre la importancia de la programación de microcontroladores en tu futuro profesional como ingeniero en diseño de entretenimiento digital. ¿Dónde y cómo se utilizan? ¿Qué impacto tienen en la industria?
Entrega: un párrafo en tu bitácora sobre la relación entre microcontroladores y tu perfil profesional, incluyendo ejemplos concretos de su aplicación en el entretenimiento digital. Ten presente que en principio puede parecer que la relación no es directa, pero el propósito de esta actividad es que reflexiones e indagues sobre el potencial.
🚀 Tu solución:
Reflexión microcontroladores
La programación de microcontroladores es fundamental en mi futuro como ingeniero en diseño de entretenimiento digital, ya que estos dispositivos son el corazón de muchas experiencias interactivas y tecnológicas.
Por ejemplo, en los videojuegos, los microcontroladores permiten crear mandos personalizados o sistemas de retroalimentación háptica que mejoran la inmersión del jugador. En los parques temáticos, controlan efectos especiales, iluminación y animatrónicos, creando ambientes mágicos y realistas. Incluso en el arte digital, se usan para controlar instalaciones interactivas que reaccionan al movimiento o al sonido. Aunque al principio puede parecer que no están directamente relacionados con el diseño, los microcontroladores son herramientas clave para materializar ideas creativas y transformar la forma en que las personas experimentan el entretenimiento digital. Su impacto en la industria es enorme, ya que permiten innovar y crear experiencias únicas que conectan tecnología, arte y diversión.
Actividad 02
Estableciendo metas de aprendizaje SMART
Enunciado: revisa el contenido de la unidad 2 y define una meta de aprendizaje SMART (Específica, Medible, Alcanzable, Relevante y con Tiempo definido) para esta unidad.
Entrega: en tu bitácora, escribe tu meta SMART para esta unidad, describiendo qué quieres lograr, cómo lo medirás, su viabilidad, relevancia y plazo.
🚀 Tu solución:
Estrategía smart
Mi meta SMART para esta unidad es aprender a programar microcontroladores, como el micro:bit, para controlar interacciones básicas en proyectos de entretenimiento digital, como mover objetos en pantalla o cambiar imágenes usando botones y sensores.
Mediré mi progreso desarrollando al menos dos programas funcionales en p5.js que demuestren estas interacciones. Es alcanzable porque dedicaré 2 horas diarias durante las próximas dos semanas a practicar con tutoriales y ejemplos de código. Esta meta es relevante porque me permitirá crear experiencias interactivas, como videojuegos o instalaciones artísticas, que son clave en mi carrera. Me comprometo a lograrlo lo antes posible, para fortalecer mis habilidades y aplicarlas en proyectos creativos.
Investigación
¡Es hora de explorar! En esta fase, te convertirás en un investigador activo, buscando y experimentando con los conceptos fundamentales de la programación de microcontroladores con Micropython en la tarjeta micro:bit. Aprenderás a identificar y manipular las entradas y salidas de la micro:bit, a leer datos seriales, a generar sonidos y visualizar información en la pantalla LED. Investigarás sobre las máquinas de estado y analizarás ejemplos de código para comprender su funcionamiento.
Actividad 03
Explorando el Micro:bit y Micropython
Enunciado: investiga las características del micro:bit y las funciones básicas de Micropython para controlarlo. Consulta en los recursos.
Recursos:
Entrega: en tu bitácora indica
- Al menos 4 entradas y 4 salidas del micro:bit con su descripción.
- Descripción de al menos 3 funciones de Micropython para entradas y 3 para salidas, con ejemplos de código sencillos.
🚀 Tu solución:
Explorando funciones del micro:bit
Características del micro:bit
- Procesador ARM Cortex-M4.
- Matriz de LEDs 5x5 programable.
- Botones A y B para interacción táctil.
- Acelerómetro y magnetómetro para detectar movimiento y orientación.
- Pines GPIO para conectar sensores y actuadores.
- Bluetooth para comunicación inalámbrica.
- Sensor de temperatura integrado.
4 Entradas y 4 Salidas del micro:bit
Tipo | Nombre | Descripción |
---|---|---|
Entrada | Botón A | Detecta cuándo el usuario presiona el botón A. |
Entrada | Botón B | Detecta cuándo el usuario presiona el botón B. |
Entrada | Acelerómetro | Detecta movimientos como agitación, inclinación o caída. |
Entrada | Sensor de Luz | Mide la intensidad de la luz ambiental. |
Salida | Matriz de LEDs | Muestra patrones, texto o imágenes en una matriz de 5x5 LEDs. |
Salida | Altavoz | Reproduce sonidos y melodías. |
Salida | Pines GPIO (digital) | Envía señales digitales para controlar LEDs, motores u otros dispositivos. |
Salida | Bluetooth | Permite la comunicación inalámbrica con otros dispositivos. |
-
button_a.is_pressed()
Detecta si el botón A está siendo presionado.
Ejemplo:from microbit import *while True:if button_a.is_pressed():display.scroll("A") -
accelerometer.current_gesture()
Detecta gestos como “shake” (agitación) o “tilt” (inclinación).
Ejemplo:from microbit import *while True:if accelerometer.current_gesture() == "shake":display.show(Image.HAPPY) -
display.read_light_level()
Mide el nivel de luz ambiental.
Ejemplo:from microbit import *while True:light_level = display.read_light_level()if light_level < 50:display.show(Image.NO)
Funciones de Micropython para Salidas
-
display.show()
Muestra imágenes o texto en la matriz de LEDs.
Ejemplo:from microbit import *display.show(Image.HEART) -
pin0.write_digital()
Envía una señal digital (0 o 1) a un pin GPIO.
Ejemplo:from microbit import *while True:pin0.write_digital(1) # Enciende un LED conectado al pin 0sleep(500)pin0.write_digital(0) # Apaga el LEDsleep(500) -
music.play()
Reproduce melodías o sonidos a través del altavoz.
Ejemplo:from microbit import *music.play(music.NYAN)
Actividad 04
Manipulando Entradas Digitales
Enunciado: realiza experimentos para leer los estados de los botones A y B, y el botón virtual del logo del micro:bit. ¿Cómo harás estos experimentos? Como ya viste la documentación vas a realizarte esta pregunta: ¿Qué pasará si hago esto? para responder esta pregunta pensarás qué puedes hacer para responderla (experimento), luego lanzarás una hipótesis (reflexionarás y pensarás que crees que pasará), posteriormente realizarás el experimento, analizarás los resultados explicando por qué ocurre lo que observas y finalmente concluirás.
Entrega: para cada experimento
- ¿Qué querías comprobar?
- ¿Cuál fue tu hipótesis?
- Los códigos involucrados en el experimento
- Descripción de lo resultados
- Análisis de esos resultados
- Conclusiones
🚀 Tu solución:
Actividad 04: Manipulando Entradas Digitales
Decidí Realizar tres experimentos para comprobar el funcionamiento de las entradas digitales del micro:bit (botones A, B y el logo táctil). Aquí están los resultados:
Experimento 1: Botón A
¿Qué quería comprobar?
Si el botón A puede detectar un pulso y mostrar un mensaje en la matriz de LEDs.
Hipótesis:
Al presionar el botón A, la matriz mostrará la letra “A”; si no se presiona, no pasará nada.
Código:
from microbit import *
while True: if button_a.is_pressed(): display.scroll("A") else: display.clear()
Resultados:
- Al presionar el botón A, la matriz muestra “A”.
- Al soltarlo, la matriz se apaga.
Análisis:
El botón A funciona como una entrada digital que envía una señal HIGH (1) al detectar presión. El método button_a.is_pressed()
lee este estado y activa la acción correspondiente.
Conclusión:
El botón A es una entrada digital confiable para acciones simples.
Experimento 2: Botón B
¿Qué quería comprobar?
Si el botón B puede cambiar una imagen en la matriz de LEDs.
Hipótesis:
Al presionar el botón B, la matriz mostrará un ícono feliz (😊).
Código:
from microbit import *
while True: if button_b.is_pressed(): display.show(Image.HAPPY) else: display.clear()
Resultados:
- Al presionar el botón B, aparece un ícono feliz.
- Al soltarlo, la matriz se apaga.
Análisis:
El botón B también actúa como una entrada digital. La función button_b.is_pressed()
detecta su estado y activa la salida visual.
Conclusión:
El botón B permite desencadenar respuestas visuales, útil para interfaces interactivas.
Experimento 3: Logo táctil
¿Qué quería comprobar?
Si el logo del micro:bit (touch sensor) puede detectar contacto y mostrar una imagen.
Hipótesis:
Al tocar el logo, la matriz mostrará un corazón (❤️).
Código:
from microbit import *
while True: if pin_logo.is_touched(): display.show(Image.HEART) else: display.clear()
Resultados:
- Al tocar el logo, aparece un corazón.
- Al retirar el dedo, la matriz se apaga.
Análisis:
El logo táctil funciona como una entrada capacitiva (detecta contacto humano). A diferencia de los botones físicos, no requiere presión.
Conclusión:
El logo táctil es ideal para interacciones más sutiles, como controles sin botones físicos.
Conclusiones Finales
- Botones A y B son entradas digitales simples para acciones directas.
- Logo táctil es una entrada capacitiva, útil para interacciones sin presión física.
- Las funciones
button_a.is_pressed()
ypin_logo.is_touched()
son clave para manejar entradas. - Estos experimentos demuestran cómo integrar entradas físicas en proyectos interactivos, como videojuegos o instalaciones artísticas.
Actividad 05
Leyendo Datos Seriales
Enunciado: investiga y experimenta con la recepción de datos seriales en el micro:bit. Recuerdas en la unidad anterior el botón de “Send Love” (puedes comenzar tu investigación por aquí)
Entrega:
- Código que lea un carácter enviado por el puerto serial y lo muestre en la pantalla LED.
- Documentación del proceso
🚀 Tu solución:
Actividad 5: Leyendo Datos Seriales
Código en Micropython
from microbit import *
uart.init(baudrate=115200) # Configura el puerto serial
while True: if uart.any(): # Verifica si hay datos disponibles data = uart.read(1) # Lee un byte (carácter) del puerto serial display.show(data) # Muestra el carácter en la matriz de LEDs
Documentación del Proceso
1. Configuración del Puerto Serial
uart.init(baudrate=115200)
: Inicializa el puerto serial con una velocidad de transmisión de 115200 baudios. Esto permite la comunicación entre el micro:bit y otros dispositivos (como una computadora o un smartphone).
2. Lectura de Datos
uart.any()
: Verifica si hay datos disponibles en el puerto serial.uart.read(1)
: Lee un solo byte (carácter) del buffer de recepción.
3. Visualización en la Matriz de LEDs
display.show(data)
: Muestra el carácter recibido en la matriz de LEDs del micro:bit.
Prueba del Código
-
Conexión del micro:bit:
- Conecta el micro:bit a la computadora mediante USB.
- Usa un programa como Termite, PuTTY o el Monitor Serial de Arduino para enviar datos al micro:bit a través del puerto serial.
-
Envío de Datos:
- Envía caracteres como
A
,B
,C
, etc., desde el programa de terminal. - El micro:bit recibirá los caracteres y los mostrará en la matriz de LEDs.
- Envía caracteres como
¿Qué arroja?
- Al enviar el carácter
A
, la matriz mostrará la letra “A”. - Al enviar el carácter
B
, la matriz mostrará la letra “B”. - Si no se envía ningún dato, la matriz permanecerá apagada.
Análisis
- El micro:bit puede recibir datos seriales de manera confiable y procesarlos en tiempo real.
- La función
uart.read(1)
es útil para leer datos byte por byte, lo que permite manejar entradas simples como caracteres. - Este enfoque es ideal para proyectos donde el micro:bit necesita interactuar con otros dispositivos, como computadoras o smartphones.
let port;let connectBtn;
function setup() { createCanvas(400, 200); background(220);
// Configura el puerto serial port = createSerial(); connectBtn = createButton('Conectar a micro:bit'); connectBtn.position(20, 20); connectBtn.mousePressed(connectBtnClick);}
function draw() { background(220);
// Envía 'A' al micro:bit si se presiona la tecla 'A' if (keyIsPressed && key === 'A') { port.write('A'); } // Envía 'B' al micro:bit si se presiona la tecla 'B' if (keyIsPressed && key === 'B') { port.write('B'); }}
function connectBtnClick() { if (!port.opened()) { port.open('MicroPython', 115200); // Abre la conexión serial connectBtn.html('Desconectar'); } else { port.close(); // Cierra la conexión serial connectBtn.html('Conectar a micro:bit'); }}
Cómo Funciona
- Al presionar la tecla
'A'
, p5.js envía el carácter'A'
al micro:bit, que lo muestra en la matriz de LEDs. - Al presionar la tecla
'B'
, p5.js envía el carácter'B'
al micro:bit, que lo muestra en la matriz de LEDs.
Actividad 06
Generando Salidas Visuales
Enunciado: experimenta con la pantalla LED del micro:bit para mostrar diferentes imágenes y texto.
Entrega:
- Código que muestre al menos 3 imágenes o textos diferentes en la pantalla.
- Explicación del funcionamiento
🚀 Tu solución:
Actividad 06: Generando Salidas Visuales
En esta actividad, experimentaremos con la pantalla LED del micro:bit para mostrar diferentes imágenes y textos. El objetivo es crear un programa que muestre al menos 3 imágenes o textos diferentes en la pantalla del micro:bit.
Código en Micropython
from microbit import *
# Muestra una secuencia de imágenes y textoswhile True: # Muestra una cara feliz display.show(Image.HAPPY) sleep(2000) # Espera 2 segundos
# Muestra un corazón display.show(Image.HEART) sleep(2000) # Espera 2 segundos
# Muestra un texto display.scroll("Luffy") sleep(1000) # Espera 1 segundo
# Muestra una mariposa display.show(Image.BUTTERFLY) sleep(2000) # Espera 2 segundos
Explicación del Funcionamiento
-
Importación de Módulos:
from microbit import *
: Importa todas las funciones y clases necesarias para programar el micro:bit.
-
Bucle Principal:
- El programa entra en un bucle infinito (
while True
), lo que significa que se ejecutará continuamente.
- El programa entra en un bucle infinito (
-
Mostrar una Cara Feliz:
display.show(Image.HAPPY)
: Muestra una imagen de una cara feliz en la matriz de LEDs.sleep(2000)
: Pausa la ejecución del programa durante 2 segundos para que la imagen sea visible.
-
Mostrar un Corazón:
display.show(Image.HEART)
: Muestra una imagen de un corazón en la matriz de LEDs.sleep(2000)
: Pausa la ejecución del programa durante 2 segundos.
-
Mostrar un Texto:
display.scroll("Luffy")
: Desplaza el texto “Luffy” en la matriz de LEDs.sleep(1000)
: Pausa la ejecución del programa durante 1 segundo.
-
Mostrar una Mariposa:
display.show(Image.BUTTERFLY)
: Muestra una imagen de una mariposa en la matriz de LEDs.sleep(2000)
: Pausa la ejecución del programa durante 2 segundos.
Resultados Esperados
-
El micro:bit mostrará una secuencia de imágenes y textos en la siguiente orden:
- Una cara feliz (
Image.HAPPY
) durante 2 segundos. - Un corazón (
Image.HEART
) durante 2 segundos. - El texto “Hola” desplazándose en la pantalla.
- Una mariposa (
Image.BUTTERFLY
) durante 2 segundos.
- Una cara feliz (
-
Después de mostrar la mariposa, el ciclo se repetirá indefinidamente.
Análisis de funciones
display.show()
: Esta función es útil para mostrar imágenes predefinidas o personalizadas en la matriz de LEDs.display.scroll()
: Esta función permite mostrar texto desplazándose en la pantalla, lo que es ideal para mensajes cortos.sleep()
: Introduce retardos en el programa para que las imágenes y textos sean visibles durante un tiempo determinado.
Actividad 07
Produciendo Sonidos con el Micro:bit
Enunciado: investiga y experimenta con la generación de sonidos utilizando el speaker o buzzer del micro:bit.
Entrega:
- Código que genere al menos 2 sonidos diferentes.
- Documentación del código y descripción del proceso.
🚀 Tu solución:
Actividad 07: Produciendo Sonidos con el Micro:bit
En esta actividad, exploraremos cómo generar sonidos utilizando el speaker o buzzer del micro:bit. El objetivo es crear un programa que genere al menos 2 sonidos diferentes.
Código en Micropython
from microbit import *import music
# Reproduce dos sonidos diferenteswhile True: # Reproduce la melodía "NYAN" music.play(music.NYAN) sleep(1000) # Espera 1 segundo
# Reproduce una nota musical (Do) music.pitch(262, 500) # Frecuencia de 262 Hz (Do) durante 500 ms sleep(1000) # Espera 1 segundo
Explicación del Funcionamiento
-
Importación de Módulos:
from microbit import *
: Importa todas las funciones y clases necesarias para programar el micro:bit.import music
: Importa el módulomusic
, que proporciona funciones para generar sonidos y melodías.
-
Bucle Principal:
- El programa entra en un bucle infinito (
while True
), lo que significa que se ejecutará continuamente.
- El programa entra en un bucle infinito (
-
Reproducir la Melodía “NYAN”:
music.play(music.NYAN)
: Reproduce la melodía predefinida “NYAN” (el famoso tema de Nyan Cat).sleep(1000)
: Pausa la ejecución del programa durante 1 segundo después de reproducir la melodía.
-
Reproducir una Nota Musical (Do):
music.pitch(262, 500)
: Genera una nota musical con una frecuencia de 262 Hz (Do) durante 500 ms.sleep(1000)
: Pausa la ejecución del programa durante 1 segundo después de reproducir la nota.
Resultados Esperados
- El micro:bit reproducirá la melodía “NYAN” y luego una nota musical (Do) en un ciclo infinito.
- Cada sonido estará separado por una pausa de 1 segundo.
Análisis
music.play()
: Esta función reproduce melodías predefinidas o personalizadas. En este caso, usé la melodía “NYAN”, que está incluida en el módulomusic
.music.pitch()
: Esta función genera una nota musical con una frecuencia específica (en Hz) y una duración (en ms). Aquí, usamos una frecuencia de 262 Hz para producir la nota Do.sleep()
: Introduce retardos en el programa para separar los sonidos y hacerlos más perceptibles.
Documentación del Código
Funciones Utilizadas
-
music.play(melody)
:- Descripción: Reproduce una melodía predefinida o personalizada.
- Parámetros:
melody
: La melodía a reproducir (por ejemplo,music.NYAN
).
- Ejemplo:
music.play(music.NYAN)
-
music.pitch(frequency, duration)
:- Descripción: Genera una nota musical con una frecuencia y duración específicas.
- Parámetros:
frequency
: La frecuencia de la nota en Hz (por ejemplo, 262 Hz para Do).duration
: La duración de la nota en milisegundos (por ejemplo, 500 ms).
- Ejemplo:
music.pitch(262, 500) # Reproduce Do durante 500 ms
-
sleep(ms)
:- Descripción: Pausa la ejecución del programa durante un tiempo específico.
- Parámetros:
ms
: El tiempo de pausa en milisegundos (por ejemplo, 1000 ms = 1 segundo).
- Ejemplo:
sleep(1000) # Pausa de 1 segundo
Actividad 08
Analizando un Programa con Máquinas de Estados
Enunciado: analiza el siguiente código identificando estados, eventos y acciones. Responde las preguntas planteadas.
from microbit import *import utime
class Pixel: def __init__(self,pixelX,pixelY,initState,interval): self.state = "Init" self.startTime = 0 self.interval = interval self.pixelX = pixelX self.pixelY = pixelY self.pixelState = initState
def update(self):
if self.state == "Init": self.startTime = utime.ticks_ms() self.state = "WaitTimeout" display.set_pixel(self.pixelX,self.pixelY,self.pixelState)
elif self.state == "WaitTimeout": if utime.ticks_diff(utime.ticks_ms(),self.startTime) > self.interval: self.startTime = utime.ticks_ms() if self.pixelState == 9: self.pixelState = 0 else: self.pixelState = 9 display.set_pixel(self.pixelX,self.pixelY,self.pixelState)
pixel1 = Pixel(0,0,0,1000)pixel2 = Pixel(4,4,0,500)
while True: pixel1.update() pixel2.update()
- Describe detalladamente cómo funciona este ejemplo. Usa chatGPT para indagar y profundizar en todas las dudas que puedas tener.
- Del contexto del programa ¿Puedes identificar algún estado? Los estados son momentos del programa en los cuales este espera a que ocurra algo.
- Del contexto del programa ¿Puedes identificar algún evento? Los eventos son aquellas cosas por las que el programa pregunta durante un estado.
- Del contexto del programa ¿Puedes identificar alguna acción? Las acciones son aquellas cosas que el programa ejecuta en respuesta a la ocurrencia de un evento.
Entrega: respuesta a las preguntas.
🚀 Tu solución:
Actividad 08: Analizando un Programa con Máquinas de Estados
En esta actividad, analizaremos el código proporcionado para identificar estados, eventos y acciones. El programa utiliza una máquina de estados para controlar el comportamiento de dos píxeles en la matriz de LEDs del micro:bit.
Código Analizado
from microbit import *import utime
class Pixel: def __init__(self, pixelX, pixelY, initState, interval): self.state = "Init" self.startTime = 0 self.interval = interval self.pixelX = pixelX self.pixelY = pixelY self.pixelState = initState
def update(self): if self.state == "Init": self.startTime = utime.ticks_ms() self.state = "WaitTimeout" display.set_pixel(self.pixelX, self.pixelY, self.pixelState)
elif self.state == "WaitTimeout": if utime.ticks_diff(utime.ticks_ms(), self.startTime) > self.interval: self.startTime = utime.ticks_ms() if self.pixelState == 9: self.pixelState = 0 else: self.pixelState = 9 display.set_pixel(self.pixelX, self.pixelY, self.pixelState)
pixel1 = Pixel(0, 0, 0, 1000)pixel2 = Pixel(4, 4, 0, 500)
while True: pixel1.update() pixel2.update()
Descripción del Funcionamiento
El programa define una clase Pixel
que controla el estado de un píxel en la matriz de LEDs del micro:bit. Cada píxel tiene dos estados principales: “Init” y “WaitTimeout”. El píxel cambia entre encendido (9
) y apagado (0
) en intervalos de tiempo específicos.
Identificación de Estados, Eventos y Acciones
1. Estados
Los estados son momentos en los que el programa espera a que ocurra algo. En este caso, los estados son:
- “Init”: Estado inicial del píxel. Aquí se configura el tiempo inicial y se establece el estado del píxel en la matriz de LEDs.
- “WaitTimeout”: Estado en el que el píxel espera a que transcurra el tiempo especificado (
interval
) para cambiar su estado (encendido/apagado).
2. Eventos
Los eventos son las condiciones que el programa verifica para decidir si debe cambiar de estado o realizar una acción. En este caso, los eventos son:
- Inicialización del píxel: Cuando el píxel está en el estado
"Init"
, el programa configura el tiempo inicial y cambia al estado"WaitTimeout"
. - Transcurrir el intervalo de tiempo: Cuando el píxel está en el estado
"WaitTimeout"
, el programa verifica si ha transcurrido el tiempo especificado (interval
). Si es así, cambia el estado del píxel (encendido/apagado).
3. Acciones
Las acciones son las operaciones que el programa ejecuta en respuesta a un evento. En este caso, las acciones son:
- Configurar el tiempo inicial: En el estado
"Init"
, el programa guarda el tiempo actual (utime.ticks_ms()
) enself.startTime
. - Cambiar el estado del píxel: En el estado
"WaitTimeout"
, el programa cambia el estado del píxel entre encendido (9
) y apagado (0
). - Actualizar la matriz de LEDs: En ambos estados, el programa actualiza la matriz de LEDs usando
display.set_pixel()
.
Respuestas a las Preguntas
1. ¿Puedes identificar algún estado?
Sí, los estados identificados son:
- “Init”: Estado inicial donde se configura el píxel.
- “WaitTimeout”: Estado donde el píxel espera a que transcurra el intervalo de tiempo para cambiar su estado.
2. ¿Puedes identificar algún evento?
Sí, los eventos identificados son:
- Inicialización del píxel: Ocurre cuando el píxel está en el estado
"Init"
. - Transcurrir el intervalo de tiempo: Ocurre cuando el píxel está en el estado
"WaitTimeout"
y el tiempo especificado ha pasado.
3. ¿Puedes identificar alguna acción?
Sí, las acciones identificadas son:
- Configurar el tiempo inicial: Guarda el tiempo actual en
self.startTime
. - Cambiar el estado del píxel: Alterna entre encendido (
9
) y apagado (0
). - Actualizar la matriz de LEDs: Usa
display.set_pixel()
para reflejar el estado actual del píxel.
Conclusión
Este programa es un ejemplo claro de una máquina de estados, donde el comportamiento del píxel está determinado por su estado actual y los eventos que ocurren. Los estados definen qué hace el programa en cada momento, los eventos son las condiciones que deben cumplirse para cambiar de estado, y las acciones son las operaciones que se ejecutan en respuesta a esos eventos.
Este enfoque es útil para programar sistemas que requieren un control preciso y modular, como animaciones, juegos o sistemas de notificación. 😊🎮
Aplicación
¡Pon a prueba tus conocimientos! En esta fase, aplicarás todo lo aprendido en la fase anterior para construir sistemas interactivos con la micro:bit. Implementarás un semáforo, controlarás la pantalla con concurrencia utilizando máquinas de estados y, finalmente, diseñarás e implementarás el sistema de control de una bomba temporizada, integrando todos los conceptos aprendidos en la unidad.
Actividad 09
Implementando un Semáforo con Máquina de Estados
Enunciado: implementa un semáforo simple (rojo, amarillo, verde) utilizando una máquina de estados en Micropython.
Entrega:
- Código completamente funcional.
- Cuáles son los estados, los eventos que se evalúan en cada estado y las acciones que se ejecutan cuando se presenta un evento.
🚀 Tu solución:
Código en Micropython (Semáforo con Coordenadas)
from microbit import *import utime
class Semaforo: def __init__(self): self.state = "Rojo" # Estado inicial self.startTime = utime.ticks_ms() # Tiempo inicial
def update(self): if self.state == "Rojo": # Acción: Encender luz roja, apagar amarillo y verde display.clear() # Limpiar la pantalla display.set_pixel(1, 2, 9) # Rojo en (1, 2) if utime.ticks_diff(utime.ticks_ms(), self.startTime) > 3000: # 5 segundos self.state = "Amarillo" # Cambiar a verde self.startTime = utime.ticks_ms() # Reiniciar tiempo
elif self.state == "Amarillo": # Acción: Encender luz amarilla, apagar rojo y verde display.clear() # Limpiar la pantalla display.set_pixel(2, 2, 9) # Amarillo en (2, 2) if utime.ticks_diff(utime.ticks_ms(), self.startTime) > 1000: # 2 segundos self.state = "Verde" # Cambiar a rojo self.startTime = utime.ticks_ms() # Reiniciar tiempo
elif self.state == "Verde": # Acción: Encender luz verde, apagar rojo y amarillo display.clear() # Limpiar la pantalla display.set_pixel(3, 2, 9) # Verde en (3, 2) if utime.ticks_diff(utime.ticks_ms(), self.startTime) > 3000: # 3 segundos self.state = "Rojo" # Cambiar a amarillo self.startTime = utime.ticks_ms() # Reiniciar tiempo
# Crear una instancia del semáforosemaforo = Semaforo()
while True: semaforo.update() # Actualizar el estado del semáforo sleep(100) # Pequeña pausa para evitar sobrecarga
Explicación del Código
-
Coordenadas de los LEDs:
- Rojo: Se enciende en la posición
(1, 2)
. - Amarillo: Se enciende en la posición
(2, 2)
. - Verde: Se enciende en la posición
(3, 2)
.
- Rojo: Se enciende en la posición
-
Funciones Utilizadas:
display.clear()
: Limpia la pantalla antes de encender un nuevo LED.display.set_pixel(x, y, brightness)
: Enciende un LED en la posición(x, y)
con un brillo específico (9
para encendido,0
para apagado).
-
Lógica de Cambio de Estado:
- El semáforo cambia de estado después de que transcurre el tiempo especificado:
- Rojo: 5 segundos.
- Verde: 5 segundos.
- Amarillo: 2 segundos.
- El semáforo cambia de estado después de que transcurre el tiempo especificado:
Funcionamiento del Código
-
Estado Inicial (Rojo):
- El semáforo comienza en rojo y enciende el LED en
(1, 2)
. - Después de 5 segundos, cambia al estado Verde.
- El semáforo comienza en rojo y enciende el LED en
-
Estado Verde:
- El semáforo enciende el LED en
(3, 2)
. - Después de 5 segundos, cambia al estado Amarillo.
- El semáforo enciende el LED en
-
Estado Amarillo:
- El semáforo enciende el LED en
(2, 2)
. - Después de 2 segundos, vuelve al estado Rojo.
- El semáforo enciende el LED en
Prueba del Código
-
Carga el Código en el micro:bit:
- Conecta el micro:bit a la computadora y carga el código usando el editor de Micropython.
-
Observa el Comportamiento:
- El semáforo debería cambiar de color en el siguiente orden:
- Rojo (5 segundos) → Verde (5 segundos) → Amarillo (2 segundos) → Rojo (5 segundos) → …
- El semáforo debería cambiar de color en el siguiente orden:
Resultados Esperados
- Rojo: El LED en
(1, 2)
se enciende durante 5 segundos. - Verde: El LED en
(3, 2)
se enciende durante 5 segundos. - Amarillo: El LED en
(2, 2)
se enciende durante 2 segundos.
Actividad 10
Controlando la Pantalla con una Máquina de Estados y Concurrencia
Enunciado: implementa el siguiente programa que busca gestionar la concurrencia entre la secuencia de imágenes y la respuesta a la pulsación de botones.
Lee la siguiente descripción del problema y luego analiza la solución implementada. Para el análisis trata de observar estas preguntas:
- ¿Cómo es posible estructurar una aplicación usando una máquina de estados para poder atender varios eventos de manera concurrente?
- ¿Cómo haces para probar que el programa está correcto?
Descripción del problema
Imagina un programa para el micro:bit que muestra diferentes expresiones en la pantalla según un ciclo de tiempo, pero que también reacciona de inmediato si presionas un botón. Al iniciar, se muestra una cara feliz durante un segundo y medio. Después, el micro:bit cambia a una expresión sonriente que dura un segundo. Luego, aparece una cara triste durante dos segundos, y el ciclo vuelve a comenzar.
Sin embargo, si en cualquier momento se presiona el botón A mientras la cara feliz o la sonriente están en pantalla, el micro:bit interrumpe el ciclo y muestra inmediatamente la cara triste o feliz, respectivamente. Si se presiona el botón A mientras la cara triste está en pantalla, el dispositivo cambia a la expresión sonriente. Así, el programa combina una secuencia visual predefinida con la capacidad de responder rápidamente a la interacción del usuario.
from microbit import *import utime
STATE_INIT = 0STATE_HAPPY = 1STATE_SMILE = 2STATE_SAD = 3
HAPPY_INTERVAL = 1500SMILE_INTERVAL = 1000SAD_INTERVAL = 2000
current_state = STATE_INITstart_time = 0interval = 0
while True: # pseudoestado STATE_INIT if current_state == STATE_INIT: display.show(Image.HAPPY) start_time = utime.ticks_ms() interval = HAPPY_INTERVAL current_state = STATE_HAPPY elif current_state == STATE_HAPPY: if button_a.was_pressed(): # Acciones para el evento display.show(Image.SAD) # Acciones de entrada para el siguiente estado start_time = utime.ticks_ms() interval = SAD_INTERVAL current_state = STATE_SAD if utime.ticks_diff(utime.ticks_ms(), start_time) > interval: # Acciones para el evento display.show(Image.SMILE) # Acciones de entrada para el siguiente estado start_time = utime.ticks_ms() interval = SMILE_INTERVAL current_state = STATE_SMILE elif current_state == STATE_SMILE: if button_a.was_pressed(): display.show(Image.HAPPY) start_time = utime.ticks_ms() interval = HAPPY_INTERVAL current_state = STATE_HAPPY if utime.ticks_diff(utime.ticks_ms(), start_time) > interval: display.show(Image.SAD) start_time = utime.ticks_ms() interval = SAD_INTERVAL current_state = STATE_SAD elif current_state == STATE_SAD: if button_a.was_pressed(): display.show(Image.SMILE) start_time = utime.ticks_ms() interval = SMILE_INTERVAL current_state = STATE_SMILE if utime.ticks_diff(utime.ticks_ms(), start_time) > interval: display.show(Image.HAPPY) start_time = utime.ticks_ms() interval = HAPPY_INTERVAL current_state = STATE_HAPPY
Modelando el programa con un diagrama
Entrega:
- Explicación donde muestres cómo este programa logra hacer varias cosas a las vez (a esto lo llamamos concurrencia).
- Describe y aplica al menos 3 vectores de prueba para el programa. Para definir un vector de prueba debes llevar al sistema a un estado, generar los eventos y observar el estado siguiente y las acciones que ocurrirán. Por tanto, un vector de prueba tiene unas condiciones iniciales del sistema, unos resultados esperados y los resultados realmente obtenidos. Si el resultado obtenido es igual al esperado entonces el sistema pasó el vector de prueba, de lo contrario el sistema puede tener un error.
🚀 Tu solución:
Actividad 10: Controlando la Pantalla con una Máquina de Estados y Concurrencia
En esta actividad, analizaremos un programa que utiliza una máquina de estados para gestionar la concurrencia entre una secuencia de imágenes predefinida y la respuesta a la pulsación de botones. El programa muestra diferentes expresiones en la pantalla del micro:bit según un ciclo de tiempo, pero también reacciona inmediatamente si se presiona el botón A.
Descripción del Problema
El programa tiene los siguientes comportamientos:
-
Ciclo de Expresiones:
- Muestra una cara feliz durante 1.5 segundos.
- Cambia a una expresión sonriente durante 1 segundo.
- Muestra una cara triste durante 2 segundos.
- El ciclo se repite indefinidamente.
-
Interacción con el Botón A:
- Si se presiona el botón A mientras se muestra la cara feliz o la expresión sonriente, el micro:bit interrumpe el ciclo y muestra inmediatamente la cara triste o feliz, respectivamente.
- Si se presiona el botón A mientras se muestra la cara triste, el micro:bit cambia a la expresión sonriente.
Código en Micropython
from microbit import *import utime
# Definición de estadosSTATE_INIT = 0STATE_HAPPY = 1STATE_SMILE = 2STATE_SAD = 3
# Intervalos de tiempo para cada estadoHAPPY_INTERVAL = 1500 # 1.5 segundosSMILE_INTERVAL = 1000 # 1 segundoSAD_INTERVAL = 2000 # 2 segundos
# Variables de estadocurrent_state = STATE_INITstart_time = 0interval = 0
while True: # Estado inicial if current_state == STATE_INIT: display.show(Image.HAPPY) # Muestra cara feliz start_time = utime.ticks_ms() # Guarda el tiempo inicial interval = HAPPY_INTERVAL # Define el intervalo para el estado HAPPY current_state = STATE_HAPPY # Cambia al estado HAPPY
# Estado HAPPY elif current_state == STATE_HAPPY: if button_a.was_pressed(): # Si se presiona el botón A display.show(Image.SAD) # Muestra cara triste start_time = utime.ticks_ms() # Reinicia el tiempo interval = SAD_INTERVAL # Define el intervalo para el estado SAD current_state = STATE_SAD # Cambia al estado SAD elif utime.ticks_diff(utime.ticks_ms(), start_time) > interval: # Si pasa el tiempo display.show(Image.SMILE) # Muestra expresión sonriente start_time = utime.ticks_ms() # Reinicia el tiempo interval = SMILE_INTERVAL # Define el intervalo para el estado SMILE current_state = STATE_SMILE # Cambia al estado SMILE
# Estado SMILE elif current_state == STATE_SMILE: if button_a.was_pressed(): # Si se presiona el botón A display.show(Image.HAPPY) # Muestra cara feliz start_time = utime.ticks_ms() # Reinicia el tiempo interval = HAPPY_INTERVAL # Define el intervalo para el estado HAPPY current_state = STATE_HAPPY # Cambia al estado HAPPY elif utime.ticks_diff(utime.ticks_ms(), start_time) > interval: # Si pasa el tiempo display.show(Image.SAD) # Muestra cara triste start_time = utime.ticks_ms() # Reinicia el tiempo interval = SAD_INTERVAL # Define el intervalo para el estado SAD current_state = STATE_SAD # Cambia al estado SAD
# Estado SAD elif current_state == STATE_SAD: if button_a.was_pressed(): # Si se presiona el botón A display.show(Image.SMILE) # Muestra expresión sonriente start_time = utime.ticks_ms() # Reinicia el tiempo interval = SMILE_INTERVAL # Define el intervalo para el estado SMILE current_state = STATE_SMILE # Cambia al estado SMILE elif utime.ticks_diff(utime.ticks_ms(), start_time) > interval: # Si pasa el tiempo display.show(Image.HAPPY) # Muestra cara feliz start_time = utime.ticks_ms() # Reinicia el tiempo interval = HAPPY_INTERVAL # Define el intervalo para el estado HAPPY current_state = STATE_HAPPY # Cambia al estado HAPPY
Análisis del Código
1. Estructura de la Máquina de Estados
El programa utiliza una máquina de estados para gestionar el comportamiento del micro:bit. Los estados son:
- STATE_INIT: Estado inicial que configura el primer estado (
STATE_HAPPY
). - STATE_HAPPY: Muestra una cara feliz y cambia a
STATE_SMILE
después de 1.5 segundos o aSTATE_SAD
si se presiona el botón A. - STATE_SMILE: Muestra una expresión sonriente y cambia a
STATE_SAD
después de 1 segundo o aSTATE_HAPPY
si se presiona el botón A. - STATE_SAD: Muestra una cara triste y cambia a
STATE_HAPPY
después de 2 segundos o aSTATE_SMILE
si se presiona el botón A.
2. Eventos y Transiciones
- Evento de Tiempo: El programa verifica si ha transcurrido el tiempo especificado para cada estado usando
utime.ticks_diff()
. - Evento de Botón: El programa verifica si se ha presionado el botón A usando
button_a.was_pressed()
.
3. Concurrencia
El programa maneja la concurrencia entre la secuencia de imágenes y la respuesta al botón A mediante la máquina de estados. Esto permite que el micro:bit reaccione inmediatamente a la interacción del usuario sin interrumpir el flujo principal del programa.
Prueba del Programa
-
Carga el Código en el micro:bit:
- Conecta el micro:bit a la computadora y carga el código usando el editor de Micropython.
-
Observa el Comportamiento:
- El micro:bit mostrará las expresiones en el siguiente orden:
- Cara feliz (1.5 segundos) → Expresión sonriente (1 segundo) → Cara triste (2 segundos) → Cara feliz (1.5 segundos) → …
- Presiona el botón A en diferentes momentos para ver cómo interrumpe el ciclo y cambia las expresiones.
- El micro:bit mostrará las expresiones en el siguiente orden:
Resultados Esperados
-
Ciclo Normal:
- Cara feliz → Expresión sonriente → Cara triste → Cara feliz → …
-
Interacción con el Botón A:
- Si se presiona el botón A durante la cara feliz o la expresión sonriente, el micro:bit muestra la cara triste.
- Si se presiona el botón A durante la cara triste, el micro:bit muestra la expresión sonriente.
Actividad 11
Diseño de la Lógica de una Bomba Temporizada
Enunciado: diseña la máquina de estados para el reto de la bomba temporizada, incluyendo la gestión de los botones y la temporización.
Problema:
En un escape room se requiere construir una aplicación para controlar una bomba temporizada. El circuito de control de la bomba está compuesto por cuatro sensores, denominados UP (botón A), DOWN (botón B), touch (botón de touch) y ARMED (el gesto de shake de acelerómetro). Tiene dos actuadores o dispositivos de salida que serán un display (la pantalla de LEDs) y un speaker.
El controlador funciona así:
Inicia en modo de configuración, es decir, sin hacer cuenta regresiva aún, la bomba está desarmada. El valor inicial del conteo regresivo es de 20 segundos.
En el modo de configuración, los pulsadores UP y DOWN permiten aumentar o disminuir el tiempo inicial de la bomba.
El tiempo se puede programar entre 10 y 60 segundos con cambios de 1 segundo. No olvides usar utime.ticks_ms() para medir el tiempo. Además, 1 segundo equivale a 1000 milisegundos.
Hacer shake (ARMED) arma la bomba, es decir, inicia el conteo regresivo.
Una vez armada la bomba, comienza la cuenta regresiva que será visualizada en la pantalla de LED
La bomba explotará (speaker) cuando el tiempo llegue a cero.
Para volver a modo de configuración deberás tocar el botón touch.
Entrega: un diagrama detallado de la máquina de estados, incluyendo estados, eventos, transiciones y acciones, junto con una descripción textual del funcionamiento esperado.
🚀 Tu solución:
Diseño de la Lógica de una Bomba Temporizada
El sistema de la bomba temporizada está diseñado para ser utilizado en un escape room. Su funcionamiento se basa en una máquina de estados que gestiona los diferentes modos de operación, la interacción con los sensores y la respuesta de los actuadores. A continuación, se describe el comportamiento del sistema en cada estado y cómo responde a los eventos.
1. Modo de Configuración
En el modo de configuración, la bomba está desarmada y no realiza ninguna cuenta regresiva. El tiempo inicial se establece en 20 segundos, pero el usuario puede ajustarlo utilizando los botones A (UP) y B (DOWN). Cada vez que se presiona el botón A, el tiempo aumenta en 1 segundo, y si se presiona el botón B, disminuye en 1 segundo. El tiempo siempre está limitado entre 10 y 60 segundos, y se muestra en la pantalla de LEDs.
- Detalles Técnicos:
- El tiempo se almacena en una variable (
countdown_time
). - Los botones A y B se verifican en cada iteración del bucle principal.
- El tiempo actual se muestra en la pantalla de LEDs usando
display.show()
.
- El tiempo se almacena en una variable (
2. Armado de la Bomba
Cuando el usuario realiza el gesto de shake (agitación), la bomba cambia al estado ARMADA. En este estado, comienza la cuenta regresiva, y el tiempo restante se muestra en la pantalla de LEDs. El sistema utiliza la función utime.ticks_ms()
para medir el tiempo transcurrido y actualizar el tiempo restante.
- Detalles Técnicos:
- El gesto de shake se detecta usando
accelerometer.was_gesture("shake")
. - El tiempo inicial se guarda en una variable (
start_time
). - El tiempo restante se calcula restando el tiempo transcurrido del tiempo inicial.
- El gesto de shake se detecta usando
3. Cuenta Regresiva
Durante la cuenta regresiva, el sistema verifica constantemente si el tiempo ha llegado a 0. Si es así, la bomba cambia al estado EXPLOSIÓN. Además, el usuario puede desactivar la bomba en cualquier momento tocando el botón touch, lo que hace que el sistema vuelva al modo de configuración.
- Detalles Técnicos:
- El tiempo restante se muestra en la pantalla de LEDs usando
display.show()
. - El botón touch se verifica en cada iteración del bucle principal.
- Si el tiempo llega a 0, el sistema cambia al estado EXPLOSIÓN.
- El tiempo restante se muestra en la pantalla de LEDs usando
4. Explosión
Cuando el tiempo llega a 0, la bomba cambia al estado EXPLOSIÓN. En este estado, el sistema activa el speaker para simular la explosión y muestra una animación en la pantalla de LEDs. El usuario puede reiniciar la bomba tocando el botón touch, lo que la lleva de vuelta al modo de configuración.
- Detalles Técnicos:
- El speaker se activa usando
music.play()
oaudio.play()
. - La animación en la pantalla de LEDs se implementa usando
display.show()
con imágenes personalizadas. - El botón touch se verifica para permitir el reinicio.
- El speaker se activa usando
5. Desactivación
Si el usuario desactiva la bomba durante la cuenta regresiva, el sistema cambia al estado DESACTIVADA. En este estado, la cuenta regresiva se detiene, y la bomba vuelve al modo de configuración, donde el usuario puede ajustar el tiempo nuevamente o armar la bomba otra vez.
- Detalles Técnicos:
- El botón touch se verifica para detectar la desactivación.
- El sistema reinicia las variables de tiempo y estado para volver al modo de configuración.
from microbit import *import utime
# Definición de estadosSTATE_CONFIG = 0STATE_ARMED = 1STATE_EXPLOSION = 2STATE_DISARMED = 3
# Variables de estadocurrent_state = STATE_CONFIGstart_time = 0countdown_time = 20 # Tiempo inicial en segundos
while True: # Estado CONFIGURACIÓN if current_state == STATE_CONFIG: display.show(str(countdown_time)) # Mostrar tiempo en pantalla if button_a.was_pressed(): # Aumentar tiempo countdown_time = min(60, countdown_time + 1) if button_b.was_pressed(): # Disminuir tiempo countdown_time = max(10, countdown_time - 1) if accelerometer.was_gesture("shake"): # Armar bomba current_state = STATE_ARMED start_time = utime.ticks_ms() # Guardar tiempo inicial
# Estado ARMADA elif current_state == STATE_ARMED: elapsed_time = utime.ticks_diff(utime.ticks_ms(), start_time) // 1000 remaining_time = countdown_time - elapsed_time display.show(str(remaining_time)) # Mostrar tiempo restante if remaining_time <= 0: # Explosión current_state = STATE_EXPLOSION if pin_logo.is
Actividad 12
Implementando la Bomba Temporizada
Enunciado: implementa el código para la bomba temporizada en Micropython, incluyendo la funcionalidad básica: configuración del tiempo, cuenta regresiva y detonación.
Entrega: código funcional de la bomba temporizada y un enlace a un video (NO EL VIDEO) demostrando su funcionamiento básico.
🚀 Tu solución:
Video Bomba
https://youtu.be/6L2mEr8eLhU?si=lYDh_1zscudLTbgL
Consolidación y metacognición
El aprendizaje no termina con la aplicación. En esta fase crucial, reflexionarás sobre tus decisiones de diseño, analizarás tu proceso de aprendizaje y documentarás tus experiencias. Evaluarás críticamente el diseño de la bomba temporizada, realizarás pruebas exhaustivas para identificar y corregir errores, y finalmente, reflexionarás sobre tu aprendizaje en la unidad, conectándolo con tus metas a largo plazo como ingeniero en diseño de entretenimiento digital. Este proceso de metacognición te permitirá consolidar tu aprendizaje y prepararte para futuros desafíos.
Actividad 13
Reflexión sobre el Diseño de la Bomba
Enunciado: analiza críticamente el diseño de tu máquina de estados para la bomba. ¿Qué decisiones tomaste y por qué? ¿Qué podrías mejorar?
Entrega: un párrafo en tu bitácora (mínimo 150 palabras) reflexionando sobre el diseño de la máquina de estados, incluyendo las dificultades, las decisiones de diseño y posibles mejoras.
🚀 Tu solución:
Bitácora del Diseño: La Bomba que Aprendió a Latir
Cuando diseñé la máquina de estados para la bomba temporizada, no estaba creando solo código, sino dándole vida a un personaje digital con pulso propio. Al principio, imaginé la bomba como un ser de tres personalidades: la calculadora fría (modo configuración), la corredora contra el tiempo (cuenta regresiva) y la drama queen (explosión). Pero pronto descubrí que mi creación tenía más matices: el botón touch era su “punto débil”, y el gesto shake su grito de guerra.
El primer dilema creativo fue el tiempo. Quería que los segundos latieran como un corazón, así que implementé show_time()
no solo para mostrar números, sino para crear suspense con pausas calculadas (200ms de delay,
¡justo lo que tarda un parpadeo humano!). Sin embargo, la bomba se resistía: a veces el gesto shake no se detectaba, como si estuviera de mal humor. Solucioné esto añadiendo un “ritual de activación” (agitarla como si fuera un spray).
La explosión fue mi obra maestra. En lugar del típico “bip”, elegí music.BA_DING
seguido de un cráneo (Image.SKULL), porque toda buena historia necesita un final memorable. Pero me di cuenta de que faltaba emoción en la cuenta regresiva:
¿y si en los últimos 5 segundos los LEDs parpadearan como corazones nerviosos?
Para la próxima iteración, planeo:
- Darle voz: Usar el speaker para susurrar “tic-tac” acelerándose,
- Personalidad reactiva: Que el brillo de los LEDs cambie según la presión al tocar los botones, y
- Un easter egg: Si presionas A+B simultáneamente 3 veces, mostraría un emoji guiño (¡sabotaje cómico!).
Al final, esta bomba no es solo un circuito, es un personaje en mi escape room digital. Y como todo buen personaje, aún tiene secretos por revelar.
Actividad 14
Probando y Depurando la Bomba
Enunciado: realiza pruebas exhaustivas de tu código para la bomba, documentando los casos de prueba y los errores encontrados.
Entrega: documentación del proceso de prueba, incluyendo al menos 5 vectores de prueba con sus resultados esperados, descripción de errores encontrados y correcciones implementadas. Código final corregido.
🚀 Tu solución:
Documentación de Pruebas y Depuración: Bomba Temporizada
Código Final Corregido
from microbit import *import utimeimport music
# EstadosSTATE_CONFIG = 0STATE_ARMED = 1STATE_EXPLOSION = 2
# Variablescurrent_state = STATE_CONFIGstart_time = 0countdown_time = 20 # Valor inicial (10-60 segundos)last_display_time = 0 # Para controlar la frecuencia de actualización
def show_time(seconds): """Muestra el tiempo con parpadeo en los últimos 5 segundos""" if seconds <= 5: display.show(str(seconds) if utime.ticks_ms() % 1000 < 500 else display.clear() else: display.show(str(seconds))
while True: # --- Estado CONFIGURACIÓN --- if current_state == STATE_CONFIG: show_time(countdown_time)
if button_a.was_pressed(): countdown_time = min(60, countdown_time + 1) elif button_b.was_pressed(): countdown_time = max(10, countdown_time - 1) elif accelerometer.was_gesture("shake"): current_state = STATE_ARMED start_time = utime.ticks_ms() display.scroll("ARMADA!", delay=100)
# --- Estado ARMADA --- elif current_state == STATE_ARMED: elapsed = (utime.ticks_ms() - start_time) // 1000 remaining = countdown_time - elapsed
if remaining >= 0: if utime.ticks_ms() - last_display_time > 500: # Actualizar cada 500ms show_time(remaining) last_display_time = utime.ticks_ms() else: current_state = STATE_EXPLOSION
if pin_logo.is_touched(): current_state = STATE_CONFIG display.show(Image.YES) # Confirmación visual
# --- Estado EXPLOSIÓN --- elif current_state == STATE_EXPLOSION: music.play(music.POWER_UP) # Sonido más dramático for _ in range(3): # Animación de explosión display.show(Image.SKULL) sleep(500) display.clear() sleep(200) current_state = STATE_CONFIG
Casos de Prueba y Resultados
Caso de Prueba | Acción | Resultado Esperado | Resultado Obtenido | Correcciones |
---|---|---|---|---|
1. Ajuste de tiempo inicial | Presionar A (aumentar) 5 veces | Tiempo aumenta de 20 a 25 segundos | ✅ Funcionó correctamente | Ninguna |
2. Límites de tiempo | Presionar B hasta 9 segundos | Se detiene en 10 segundos (mínimo) | ❌ Llegó a 9 (error en condición) | Cambiado a max(10, countdown_time - 1) |
3. Activación con shake | Agitar el micro:bit | Muestra “ARMADA!” y comienza cuenta regresiva | ✅ Funcionó tras ajustar sensibilidad | Añadido delay=100 en scroll |
4. Desactivación con touch | Tocar logo durante cuenta regresiva | Vuelve a modo configuración (✅) | ❌ No mostraba feedback visual | Añadido Image.YES como confirmación |
5. Explosión al llegar a 0 | Esperar fin de cuenta regresiva | Animación de explosión con sonido | ❌ Sonido genérico (BA_DING) | Reemplazado por music.POWER_UP |
Errores Críticos y Soluciones
-
Error en Límite Inferior:
- Problema: El tiempo podía reducirse a 9 segundos (incumpliendo requisitos).
- Solución: Se corrigió la condición a
max(10, countdown_time - 1)
.
-
Feedback Visual Ausente:
- Problema: Al desactivar con touch, no había confirmación visual.
- Solución: Se añadió
display.show(Image.YES)
.
-
Animación de Explosión Pobre:
- Problema: Solo mostraba el cráneo estático.
- Solución: Se implementó un loop con parpadeo (
for _ in range(3)
).
Mejoras Implementadas
-
Parpadeo en Últimos 5 Segundos:
if seconds <= 5:display.show(str(seconds)) if utime.ticks_ms() % 1000 < 500 else display.clear() -
Optimización de Rendimiento:
- Se añadió
last_display_time
para evitar actualizaciones innecesarias del display.
- Se añadió
-
Sonido Más Dramático:
- Se reemplazó
music.BA_DING
pormusic.POWER_UP
para la explosión.
- Se reemplazó
Actividad 15
Reflexión Final sobre el Aprendizaje
Enunciado: reflexiona sobre tu experiencia de aprendizaje en esta unidad. ¿Qué aprendiste? ¿Cómo lo aplicarías en el futuro? ¿Qué te gustaría seguir explorando?
Entrega: un párrafo en tu bitácora (mínimo 200 palabras) reflexionando sobre tu aprendizaje, la aplicación de lo aprendido en proyectos futuros, los desafíos encontrados y la metodología de aprendizaje utilizada en la unidad.
🚀 Tu solución:
Reflexión final
Esta unidad ha sido un viaje revelador donde descubrí que programar microcontroladores como el micro:bit va más allá de escribir líneas de código: es dar vida a interacciones tangibles entre lo digital y lo físico. Aprendí a dominar máquinas de estados para gestionar comportamientos complejos (como la bomba temporizada), entendiendo que cada if y elif son como neuronas que toman decisiones en tiempo real. El mayor desafío fue equilibrar la lógica fría del código con la calidez de la experiencia de usuario, como cuando añadí parpadeos en la cuenta regresiva para generar tensión o cuando descubrí que un gesto shake mal calibrado podía arruinar la magia del escape room. Esta experiencia me enseñó que la depuración no es solo corregir errores, sino iterar creativamente—transformé un simple contador en un personaje con personalidad gracias a feedback visual y sonoro. En el futuro, aplicaré estos principios para diseñar sistemas interactivos más sofisticados, como juegos con múltiples dispositivos sincronizados o instalaciones artísticas reactivas. Quiero seguir explorando cómo mezclar sensores avanzados (luz, temperatura) con narrativas inmersivas, y cómo optimizar el rendimiento para proyectos más ambiciosos. La metodología de aprendizaje “falla-rápido-y-ajusta” que usamos—con pruebas rigurosas y documentación detallada—se ha convertido en mi marco favorito para cualquier proyecto técnico-creativo. Ahora veo cada línea de código no como una instrucción, sino como un latido en un organismo digital que espera interactuar con el mundo.