Saltearse al contenido

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

TipoNombreDescripción
EntradaBotón ADetecta cuándo el usuario presiona el botón A.
EntradaBotón BDetecta cuándo el usuario presiona el botón B.
EntradaAcelerómetroDetecta movimientos como agitación, inclinación o caída.
EntradaSensor de LuzMide la intensidad de la luz ambiental.
SalidaMatriz de LEDsMuestra patrones, texto o imágenes en una matriz de 5x5 LEDs.
SalidaAltavozReproduce sonidos y melodías.
SalidaPines GPIO (digital)Envía señales digitales para controlar LEDs, motores u otros dispositivos.
SalidaBluetoothPermite la comunicación inalámbrica con otros dispositivos.

  1. 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")
  2. 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)
  3. 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

  1. display.show()
    Muestra imágenes o texto en la matriz de LEDs.
    Ejemplo:

    from microbit import *
    display.show(Image.HEART)
  2. 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 0
    sleep(500)
    pin0.write_digital(0) # Apaga el LED
    sleep(500)
  3. 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

  1. Botones A y B son entradas digitales simples para acciones directas.
  2. Logo táctil es una entrada capacitiva, útil para interacciones sin presión física.
  3. Las funciones button_a.is_pressed() y pin_logo.is_touched() son clave para manejar entradas.
  4. 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

  1. 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.
  2. 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.

¿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 textos
while 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

  1. Importación de Módulos:

    • from microbit import *: Importa todas las funciones y clases necesarias para programar el micro:bit.
  2. Bucle Principal:

    • El programa entra en un bucle infinito (while True), lo que significa que se ejecutará continuamente.
  3. 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.
  4. 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.
  5. 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.
  6. 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:

    1. Una cara feliz (Image.HAPPY) durante 2 segundos.
    2. Un corazón (Image.HEART) durante 2 segundos.
    3. El texto “Hola” desplazándose en la pantalla.
    4. Una mariposa (Image.BUTTERFLY) durante 2 segundos.
  • 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 diferentes
while 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

  1. 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ódulo music, que proporciona funciones para generar sonidos y melodías.
  2. Bucle Principal:

    • El programa entra en un bucle infinito (while True), lo que significa que se ejecutará continuamente.
  3. 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.
  4. 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ódulo music.
  • 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

  1. 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)
  2. 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
  3. 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()) en self.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áforo
semaforo = Semaforo()
while True:
semaforo.update() # Actualizar el estado del semáforo
sleep(100) # Pequeña pausa para evitar sobrecarga

Explicación del Código

  1. 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).
  2. 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).
  3. 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.

Funcionamiento del Código

  1. 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.
  2. Estado Verde:

    • El semáforo enciende el LED en (3, 2).
    • Después de 5 segundos, cambia al estado Amarillo.
  3. Estado Amarillo:

    • El semáforo enciende el LED en (2, 2).
    • Después de 2 segundos, vuelve al estado Rojo.

Prueba del Código

  1. 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.
  2. 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) → …

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 = 0
STATE_HAPPY = 1
STATE_SMILE = 2
STATE_SAD = 3
HAPPY_INTERVAL = 1500
SMILE_INTERVAL = 1000
SAD_INTERVAL = 2000
current_state = STATE_INIT
start_time = 0
interval = 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

State Machine Model

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:

  1. 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.
  2. 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 estados
STATE_INIT = 0
STATE_HAPPY = 1
STATE_SMILE = 2
STATE_SAD = 3
# Intervalos de tiempo para cada estado
HAPPY_INTERVAL = 1500 # 1.5 segundos
SMILE_INTERVAL = 1000 # 1 segundo
SAD_INTERVAL = 2000 # 2 segundos
# Variables de estado
current_state = STATE_INIT
start_time = 0
interval = 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 a STATE_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 a STATE_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 a STATE_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

  1. 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.
  2. 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.

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().

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.

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.

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() o audio.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.

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 estados
STATE_CONFIG = 0
STATE_ARMED = 1
STATE_EXPLOSION = 2
STATE_DISARMED = 3
# Variables de estado
current_state = STATE_CONFIG
start_time = 0
countdown_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.

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:

  1. Darle voz: Usar el speaker para susurrar “tic-tac” acelerándose,
  2. Personalidad reactiva: Que el brillo de los LEDs cambie según la presión al tocar los botones, y
  3. 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 utime
import music
# Estados
STATE_CONFIG = 0
STATE_ARMED = 1
STATE_EXPLOSION = 2
# Variables
current_state = STATE_CONFIG
start_time = 0
countdown_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 PruebaAcciónResultado EsperadoResultado ObtenidoCorrecciones
1. Ajuste de tiempo inicialPresionar A (aumentar) 5 vecesTiempo aumenta de 20 a 25 segundos✅ Funcionó correctamenteNinguna
2. Límites de tiempoPresionar B hasta 9 segundosSe detiene en 10 segundos (mínimo)❌ Llegó a 9 (error en condición)Cambiado a max(10, countdown_time - 1)
3. Activación con shakeAgitar el micro:bitMuestra “ARMADA!” y comienza cuenta regresiva✅ Funcionó tras ajustar sensibilidadAñadido delay=100 en scroll
4. Desactivación con touchTocar logo durante cuenta regresivaVuelve a modo configuración (✅)❌ No mostraba feedback visualAñadido Image.YES como confirmación
5. Explosión al llegar a 0Esperar fin de cuenta regresivaAnimación de explosión con sonido❌ Sonido genérico (BA_DING)Reemplazado por music.POWER_UP

Errores Críticos y Soluciones

  1. 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).
  2. Feedback Visual Ausente:

    • Problema: Al desactivar con touch, no había confirmación visual.
    • Solución: Se añadió display.show(Image.YES).
  3. 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

  1. Parpadeo en Últimos 5 Segundos:

    if seconds <= 5:
    display.show(str(seconds)) if utime.ticks_ms() % 1000 < 500 else display.clear()
  2. Optimización de Rendimiento:

    • Se añadió last_display_time para evitar actualizaciones innecesarias del display.
  3. Sonido Más Dramático:

    • Se reemplazó music.BA_DING por music.POWER_UP para la explosión.

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.