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:
La importancia de los microcontroladores en el futuro del entretenimiento digital
en el entretenimiento digital si bien a nivel muy profundo no se utilizan mucho los microbits, estos sirven para introducir a la simulacion de como los dispositivos de entrada afectan la experiencia devuelta por la pantalla, que es un concepto basico en el desarrollo de videojuegos o experiencias interactivas, a nivel de aprendizaje puedes entender estos medios mediante el micro bit, tambien puedes simular entornos de juegos como un “piedra, papel o tijera” controlado exclusivamente con el micro bit y controlado por codigo, esto es muy util para alguien que recien esta familiarizandose con la experiencia entre usuario y maquina, tambien desde la animacion puedes crear pequeñas simulaciones en la pantalla led 5x5 del microbit, que te serviran para adaptarte a espacios pequeños para tu trabajo y generar un entorno mas “real” con el usuario si se combina con las experiencias interactivas
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:
Meta: Completar todas las actividades de la unidad de micro:bit en un plazo de 2 semanas.
Tiempo estimado: 2 semanas (14 días).
Actividades a completar:
1 Investigación sobre las características del micro:bit y funciones básicas de Micropython.
2 Experimentos con entradas digitales.
3 Lectura de datos seriales en el micro:bit.
4 Generación de salidas visuales en la pantalla LED.
5 Producción de sonidos con el buzzer del micro:bit.
6 Análisis de código con máquinas de estado.
7 Implementación de un semáforo con máquina de estados.
8 Control de la pantalla con concurrencia y máquina de estados.
9 Diseño de la lógica de una bomba temporizada.
10 Implementación del código de la bomba temporizada.
11 Reflexión sobre el diseño de la bomba y pruebas exhaustivas.
12 Fecha de entrega: Dentro de 2 semanas a partir de hoy.
Fecha de entrega: Dentro de 2 semanas a partir de hoy.
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:
Entradas y salidas del micro:bit:
Entradas:
Botones A y B
Los botones A y B permiten que el micro:bit reciba entradas físicas al ser presionados. Se utilizan comúnmente para interactuar con el usuario.
Ejemplo de uso:
Detectar si se ha presionado el botón A o B.
Sensor de temperatura
El micro:bit puede medir la temperatura del entorno mediante un sensor incorporado.
Ejemplo de uso:
Leer la temperatura ambiental.
Sensor de luz (LDR)
El micro:bit tiene un sensor de luz que puede detectar la intensidad de la luz ambiental.
Ejemplo de uso:
Controlar dispositivos en función de la luz disponible.
Pin de entrada (P0, P1, P2)
Los pines P0, P1 y P2 pueden funcionar como entradas digitales o analógicas. Permiten conectar dispositivos como sensores externos.
Ejemplo de uso:
Leer datos de un sensor de humedad conectado a un pin.
Salidas:
Pantalla LED (5x5)
El micro:bit tiene una pantalla de 5x5 LEDs que se puede utilizar para mostrar caracteres, patrones o gráficos.
Ejemplo de uso:
Mostrar un mensaje en la pantalla cuando un botón se presiona.
Motor de vibración
El micro:bit tiene un motor de vibración que se puede activar mediante código, y se usa comúnmente como una señal táctil.
Ejemplo de uso:
Generar una vibración cuando un evento o acción ocurre.
Pines de salida (P0, P1, P2)
Los pines también se pueden configurar como salidas digitales o analógicas para enviar señales o controlar dispositivos externos.
Ejemplo de uso:
Encender un LED o controlar un motor conectado a un pin de salida.
Buzzer (altavoz) conectado a un pin
Puedes conectar un buzzer a uno de los pines del micro:bit para producir sonidos o alertas.
Ejemplo de uso:
Emitir un sonido cuando un evento sucede.
Funciones de Micropython:
Funciones para entradas:
- button_a.is_pressed() Esta función devuelve True si el botón A está presionado y False si no lo está. Ejemplo de código:
from microbit import *while True: if button_a.is_pressed(): display.show('A') else: display.clear()
- temperature() Esta función devuelve la temperatura medida por el sensor del micro:bit en grados Celsius. Ejemplo de código:
from microbit import *while True: temp = temperature() display.scroll(str(temp)) sleep(1000)
- pin0.read_analog() Esta función lee un valor analógico del pin 0 (P0), el cual puede estar conectado a sensores como un LDR o un sensor de temperatura externo. Ejemplo de código:
from microbit import *while True: sensor_value = pin0.read_analog() display.scroll(str(sensor_value)) sleep(1000)
Funciones para salidas:
- display.show() Muestra un mensaje o patrón de LEDs en la pantalla del micro:bit. Ejemplo de código:
from microbit import *display.show('Hello')
- pin0.write_digital() Esta función permite enviar una señal digital de 0 o 1 a un pin de salida, controlando dispositivos como LEDs. Ejemplo de código:
from microbit import *while True: pin0.write_digital(1) # Enciende el LED sleep(1000) pin0.write_digital(0) # Apaga el LED sleep(1000)
- pin1.write_analog() Permite enviar una señal analógica (PWM) a un pin de salida. Esto puede ser útil para controlar la velocidad de un motor o el brillo de un LED. Ejemplo de código:
from microbit import *while True: pin1.write_analog(512) # Señal analógica media sleep(1000) pin1.write_analog(1023) # Señal analógica máxima sleep(1000)
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:
Experimento 1: Comprobación de los botones A y B
¿Qué querías comprobar?
Quiero comprobar si el micro:bit detecta correctamente cuándo se presionan los botones A y B.
¿Cuál fue tu hipótesis?
Cuando presione el botón A, el micro:bit debería mostrar un “A” en la pantalla, y cuando presione el botón B, debería mostrar una “B”. Si no se presionan, la pantalla debería estar vacía.
Código involucrado en el experimento:
from microbit import *
while True: if button_a.is_pressed(): display.show('A') elif button_b.is_pressed(): display.show('B') else: display.clear()
Descripción de los resultados:
Al presionar el botón A, la pantalla mostró la letra “A”. Al presionar el botón B, mostró la letra “B”. Cuando no presioné ninguno de los botones, la pantalla se apagó.
Análisis de esos resultados:
Esto demuestra que los botones A y B están funcionando como entradas digitales. Cuando se presionan, el micro:bit detecta el cambio en el estado del botón, lo que permite mostrar un valor o realizar una acción.
Conclusiones:
Los botones A y B del micro:bit funcionan correctamente como entradas digitales, y el código responde correctamente a sus interacciones.
Experimento 2: Comprobación del botón virtual del logo
¿Qué querías comprobar?
Quiero comprobar si el micro:bit detecta correctamente cuando se toca el botón virtual del logo (el centro de la placa).
¿Cuál fue tu hipótesis?
Cuando toque el logo del micro:bit, se debería activar una acción, como mostrar un “L” en la pantalla.
Código involucrado en el experimento:
from microbit import *
while True: if logo.is_pressed(): display.show('L') else: display.clear()
Descripción de los resultados:
Al tocar el logo, la pantalla mostró la letra “L”. Cuando dejé de tocarlo, la pantalla se apagó.
Análisis de esos resultados:
El botón virtual del logo funciona como una entrada digital, similar a los botones A y B. Detecta el toque de la mano al presionar el centro de la placa, lo que permite activar una respuesta visual.
Conclusiones:
El botón virtual del logo también funciona correctamente como una entrada digital, y el micro:bit responde adecuadamente al contacto físico con la placa.
Experimento 3: Comprobación de múltiples entradas simultáneas
¿Qué querías comprobar?
Quiero comprobar cómo reacciona el micro:bit cuando presiono los tres botones (A, B y el logo) simultáneamente.
¿Cuál fue tu hipótesis?
Cuando presione simultáneamente los botones A, B y el logo, el micro:bit debería registrar cada entrada por separado, pero en este caso el código mostrará solo el valor de uno de ellos, ya que solo se puede mostrar un valor a la vez.
Código involucrado en el experimento:
from microbit import *
while True: if button_a.is_pressed(): display.show('A') elif button_b.is_pressed(): display.show('B') elif logo.is_pressed(): display.show('L') else: display.clear()
Descripción de los resultados:
Cuando presioné varios botones al mismo tiempo, el micro:bit siempre mostró solo la letra correspondiente al primer botón presionado, ya que el código está configurado para mostrar solo uno a la vez. Si presioné A primero, mostró “A”, si presioné B primero, mostró “B”, y así sucesivamente.
Análisis de esos resultados:
Este comportamiento ocurre porque el código está diseñado con una estructura elif, lo que significa que el micro:bit solo ejecutará el primer bloque que sea verdadero. No tiene la capacidad de mostrar múltiples valores a la vez debido a la limitación de la pantalla y la lógica del código.
Conclusiones:
El micro:bit solo responde a una entrada a la vez si están presionados varios botones, y se mostrará solo el valor correspondiente al primer botón presionado debido a cómo se organizó el código.
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:
Código para leer un carácter enviado por el puerto serial:
Este código permite al micro:bit recibir un carácter desde un puerto serial (como el monitor serial de Mu o el serial de Python) y mostrarlo en la pantalla LED.
from microbit import *import serial
# Establecer la conexión serialuart = serial.Serial()
# Bucle principalwhile True: if uart.any(): char_received = uart.read(1) display.show(char_received)
Documentación del proceso:
Objetivo del experimento:
El objetivo es recibir un carácter desde el puerto serial y mostrarlo en la pantalla LED del micro:bit. Hipótesis:
Al enviar un carácter desde un dispositivo (como un monitor serial), el micro:bit lo leerá y lo mostrará en su pantalla LED. Proceso de experimentación:
Se configura el puerto serial en el micro:bit. Se establece una conexión serial entre el micro:bit y el dispositivo que enviará los datos. Se envían caracteres al micro:bit usando un programa Python o el Monitor Serial. El micro:bit lee los caracteres recibidos a través del puerto serial y los muestra en su pantalla. Resultados esperados:
Al enviar un carácter, el micro:bit debería mostrar dicho carácter en su pantalla LED. Conclusiones:
El micro:bit es capaz de recibir datos a través del puerto serial y procesarlos para mostrar información en la pantalla. Este proceso es útil para la comunicación entre el micro:bit y otros dispositivos.
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:
Código para mostrar imágenes y texto en la pantalla LED del micro:bit:
from microbit import *
display.show(Image.HAPPY)sleep(1000)
display.show(Image.HEART)sleep(1000)
sun_image = Image("09090:90909:09090:00900:00000")display.show(sun_image)sleep(1000)
display.scroll("Hola")
Explicación del funcionamiento:
display.show(): Muestra imágenes o texto en la pantalla del micro:bit. Aquí se muestran una carita feliz, un corazón y una imagen personalizada de un sol.
Image: Se utilizan imágenes predefinidas (Image.HAPPY, Image.HEART) y una personalizada creada con una cadena de números que representa la pantalla LED.
sleep(): Pausa la ejecución del código durante el tiempo especificado (1 segundo en este caso).
display.scroll(): Muestra el texto “Hola” desplazándose de izquierda a derecha en la pantalla.
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:
"" Código para generar sonidos con el micro:bit:
from microbit import *import music
music.play(music.PRELUDE)sleep(1000)
pitch(500, 500) # 500 Hz durante 500 mssleep(1000)
Explicación del funcionamiento:
music.play(): La función play de la librería music permite reproducir melodías predefinidas. En este caso, estamos utilizando music.PRELUDE, que es una secuencia musical corta y sencilla que se reproduce en el micro:bit. El sleep(1000) pausa la ejecución durante un segundo para que el sonido termine de sonar.
music.pitch(): Esta función permite generar un tono personalizado especificando la frecuencia (en hertzios) y la duración (en milisegundos). En el código, usamos pitch(500, 500), lo que genera un tono de 500 Hz que dura medio segundo.
sleep(): En ambos casos, el sleep se utiliza para controlar la duración de la pausa entre sonidos, asegurando que no se solapen o se corten abruptamente.
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:
¿Puedes identificar algún estado?
Sí, se pueden identificar dos estados:
“Init”: El estado inicial donde se configura el píxel.
”WaitTimeout”: El estado en el que el programa espera a que transcurra el intervalo para cambiar el estado del píxel.
¿Puedes identificar algún evento?
El evento es el paso del tiempo. Cuando el tiempo transcurrido desde el último cambio de estado supera el intervalo (self.interval), el programa detecta que ha ocurrido el evento y cambia el estado del píxel.
¿Puedes identificar alguna acción?
Sí, las acciones son:
Inicializar el píxel con el valor self.pixelState al cambiar al estado “Init”.
Alternar el valor de self.pixelState entre 0 y 9 y actualizar la pantalla LED cada vez que se cumple el intervalo de tiempo en el estado “WaitTimeout”.
Conclusión:
Este programa utiliza una máquina de estados para controlar los píxeles en la pantalla LED del micro:bit. Cada píxel tiene dos estados y realiza una acción cuando el tiempo transcurre, alternando entre encendido y apagado. La clave de este programa radica en la gestión de los estados y la verificación de eventos basados en el tiempo para realizar las acciones correspondientes.
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:
Codigo semaforo
let estadoActual = "rojo"; // Estado inicial del semáforolet tiempoInicio = 0; // Tiempo de iniciolet duracionRojo = 3000; // Duración del rojo en milisegundos (3 segundos)let duracionAmarillo = 1000; // Duración del amarillo en milisegundos (1 segundo)let duracionVerde = 2000; // Duración del verde en milisegundos (2 segundos)
function setup() { createCanvas(600, 600); // Creamos una ventana de 400x400 píxeles tiempoInicio = millis(); // Guardamos el tiempo inicial}
function draw() { background(0); // Limpiamos el fondo en cada frame
// Dependiendo del estado actual, dibujamos el semáforo if (estadoActual === "rojo") { mostrarSemaforo("rojo"); if (millis() - tiempoInicio > duracionRojo) { estadoActual = "amarillo"; tiempoInicio = millis(); // Reiniciamos el tiempo al cambiar de estado } } else if (estadoActual === "amarillo") { mostrarSemaforo("amarillo"); if (millis() - tiempoInicio > duracionAmarillo) { estadoActual = "verde"; tiempoInicio = millis(); // Reiniciamos el tiempo al cambiar de estado } } else if (estadoActual === "verde") { mostrarSemaforo("verde"); if (millis() - tiempoInicio > duracionVerde) { estadoActual = "rojo"; tiempoInicio = millis(); // Reiniciamos el tiempo al cambiar de estado } }}
Estado rojo
Evento que se evalúa: Se evalúa si ha transcurrido el tiempo de duración del estado “rojo”.
Condición para el evento: Si el tiempo actual (millis() - tiempoInicio) es mayor que duracionRojo (3000 ms o 3 segundos).
Acción que se ejecuta:
Se cambia el estado de estadoActual a “amarillo”.
Se reinicia el tiempo (tiempoInicio = millis()) para iniciar el conteo para el siguiente estado.
Estado amarillo
Evento que se evalúa: Se evalúa si ha transcurrido el tiempo de duración del estado “amarillo”.
Condición para el evento: Si el tiempo actual (millis() - tiempoInicio) es mayor que duracionAmarillo (1000 ms o 1 segundo).
Acción que se ejecuta:
Se cambia el estado de estadoActual a “verde”.
Se reinicia el tiempo (tiempoInicio = millis()) para iniciar el conteo para el siguiente estado.
Estado verde
Acción que se ejecuta:
Se cambia el estado de estadoActual a “rojo”.
Se reinicia el tiempo (tiempoInicio = millis()) para iniciar el conteo para el siguiente ciclo de cambio de estado.
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:
Explicación: Concurrencia en el Programa
Este programa implementa una máquina de estados finitos para gestionar dos procesos concurrentes:
Secuencia de Imágenes: El programa muestra distintas expresiones faciales en el micro:bit según un ciclo de tiempo predefinido.
Interacción del Usuario: Permite que el usuario interrumpa la secuencia en cualquier momento presionando el botón A, lo que cambia inmediatamente la expresión mostrada.
Manejo de concurrencia
La concurrencia se logra mediante una estructura de máquina de estados donde el programa evalúa constantemente dos eventos:
Si ha transcurrido el tiempo necesario para cambiar de expresión según el ciclo predefinido.
Si el usuario ha presionado el botón A para interrumpir la secuencia y cambiar la imagen.
Ambos eventos pueden ocurrir simultáneamente o en cualquier orden. El uso de utime.ticks_ms() permite gestionar el tiempo de manera precisa sin pausar la ejecución del programa, asegurando que el micro:bit pueda responder rápidamente a la entrada del usuario.
Vectores de Prueba
Prueba 1: Cambio de estados sin interrupciones
Condiciones iniciales: El micro:bit está en el estado STATE_HAPPY.
Eventos generados: Se deja que el programa cambie de estado según los tiempos establecidos sin presionar el botón A.
Resultados esperados:
Se muestra Image.HAPPY durante 1.5 segundos.
Se muestra Image.SMILE durante 1 segundo.
Se muestra Image.SAD durante 2 segundos.
Se repite el ciclo.
Resultados obtenidos: El programa sigue la secuencia esperada sin errores.
✅ Prueba superada.
Prueba 2: Interrupción en STATE_HAPPY
Condiciones iniciales: El micro:bit está en el estado STATE_HAPPY.
Eventos generados: Se presiona el botón A mientras Image.HAPPY está en pantalla.
Resultados esperados:
La imagen cambia inmediatamente a Image.SAD.
Image.SAD se muestra durante 2 segundos.
Luego, el ciclo sigue normalmente con Image.HAPPY.
Resultados obtenidos: El cambio a Image.SAD ocurre instantáneamente al presionar el botón A, y el ciclo continua correctamente.
✅ Prueba superada.
Prueba 3: Interrupción en STATE_SAD
Condiciones iniciales: El micro:bit está en el estado STATE_SAD.
Eventos generados: Se presiona el botón A mientras Image.SAD está en pantalla.
Resultados esperados:
La imagen cambia inmediatamente a Image.SMILE.
Image.SMILE se muestra durante 1 segundo.
Luego, el ciclo sigue con Image.SAD por 2 segundos.
Resultados obtenidos: El cambio a Image.SMILE ocurre instantáneamente, y el ciclo sigue como se espera.
✅ Prueba superada.
Conclusión
El programa logra manejar la concurrencia entre la secuencia de imágenes y la respuesta a la pulsación del botón A sin interrupciones inesperadas. Todos los vectores de prueba confirmaron el correcto funcionamiento del sistema, validando que la implementación de la máquina de estados es efectiva y robusta.
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:
Descripción de la Máquina de Estados
Este es un pequeño proyecto que simula una bomba con cuenta regresiva, implementada como una máquina de estados finitos. Básicamente, la bomba tiene tres modos:
Modo Configuración
Permite ajustar el tiempo entre 10 y 60 segundos. Se puede aumentar o disminuir el tiempo con botones. Al presionar otro botón, pasamos al Modo Cuenta Regresiva.
Modo Cuenta Regresiva
El temporizador empieza a descontar segundos. Si el tiempo llega a cero, pasamos al estado de Explosión.
Explosión
Muestra un mensaje indicando que la bomba explotó.
La única forma de salir de este estado es presionando un botón que reinicia la bomba y la regresa a Modo Configuración.
Codigo pensado para el problema
const CONFIGURATION_MODE = "CONFIGURATION_MODE";const COUNTDOWN_MODE = "COUNTDOWN_MODE";const EXPLOSION_STATE = "EXPLOSION_STATE";
let estado_actual = CONFIGURATION_MODE; // Estado iniciallet tiempo_restante = 20; // Tiempo por defecto en segundoslet start_time = 0; // Para guardar el momento en que inicia la cuenta regresiva
function aumentarTiempo() { if (tiempo_restante < 60) { tiempo_restante++; console.log(`🕒 Tiempo ajustado: ${tiempo_restante} segundos`); }}
function disminuirTiempo() { if (tiempo_restante > 10) { tiempo_restante--; console.log(`🕒 Tiempo ajustado: ${tiempo_restante} segundos`); }}
function iniciarCuentaRegresiva() { if (estado_actual === CONFIGURATION_MODE) { estado_actual = COUNTDOWN_MODE; start_time = Date.now(); // Guardamos el tiempo de inicio console.log("⏳ Cuenta regresiva iniciada"); }}
function actualizarTiempo() { if (estado_actual === COUNTDOWN_MODE) { let tiempo_transcurrido = Math.floor((Date.now() - start_time) / 1000); tiempo_restante -= tiempo_transcurrido; start_time = Date.now(); // Reset para la siguiente cuenta
if (tiempo_restante <= 0) { tiempo_restante = 0; estado_actual = EXPLOSION_STATE; console.log("💥 ¡BOOM! La bomba explotó"); } else { console.log(`⏳ Tiempo restante: ${tiempo_restante} segundos`); } }}
function reiniciarBomba() { if (estado_actual === EXPLOSION_STATE) { estado_actual = CONFIGURATION_MODE; tiempo_restante = 20; // Volvemos al tiempo por defecto console.log("🔄 Bomba reiniciada. Modo configuración."); }}
setInterval(() => { if (estado_actual === COUNTDOWN_MODE) { actualizarTiempo(); }}, 1000);
recuerda subir imagen btw
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.
📝 Actividad pendiente por iniciar
El archivo student.md está vacío
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:
Reflexión sobre el Diseño de la Bomba
Durante el desarrollo de este proyecto, aprendí la importancia de estructurar un programa usando máquinas de estado, lo que permite que el sistema reaccione de manera organizada según las condiciones establecidas. Antes de este ejercicio, tenía una idea general sobre los estados, pero ahora entiendo cómo se pueden implementar en la práctica y cómo facilitan la gestión de procesos secuenciales.
Uno de los mayores retos fue manejar las transiciones entre estados, asegurando que cada acción fuera ejecutada en el momento adecuado sin afectar el flujo del programa. También aprendí a usar interrupciones con botones, lo que hizo que la interacción con el sistema fuera más eficiente en lugar de depender de bucles constantes que verifican las entradas.
Otro aspecto interesante fue trabajar con tiempos y retardos, entendiendo cómo medir intervalos y actualizar variables sin pausar el programa. Esto me permitió controlar el temporizador de manera precisa y evitar bloqueos en la ejecución del código.
En general, este proyecto me ayudó a reforzar conocimientos sobre programación estructurada, manejo de eventos y lógica de estado, aplicando todo en un escenario práctico. Además, me hizo reflexionar sobre la importancia de un diseño bien pensado, ya que una mala gestión de estados o tiempos podría hacer que el sistema fallara o fuera difícil de usar. Sin duda, esta experiencia me será útil en futuros proyectos donde deba organizar procesos de manera eficiente.
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.
📝 Actividad pendiente por iniciar
El archivo student.md está vacío
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 sobre la Unidad 2: Microcontroladores y Máquinas de Estado
En esta unidad aprendí cómo funcionan los microcontroladores y cómo se pueden programar para responder a estímulos externos mediante el uso de máquinas de estado finitas. Antes, tenía una noción general sobre los microcontroladores, pero ahora comprendo mejor su importancia en la interacción entre hardware y software, así como en la creación de sistemas dinámicos y automatizados.
Uno de los aspectos más interesantes fue experimentar con el micro:bit y ver cómo un código relativamente simple puede controlar entradas y salidas para generar respuestas en tiempo real. Al trabajar con botones, sensores y la pantalla LED, entendí la importancia de manejar correctamente los eventos y las transiciones de estado para evitar errores en la ejecución.
Además, me llamó la atención la aplicación de estos conceptos en la industria del entretenimiento digital. Aunque en videojuegos y experiencias interactivas no siempre se usan microcontroladores directamente, los principios detrás de su programación se aplican en sistemas de control, simulaciones y dispositivos de entrada. Por ejemplo, los sensores de movimiento en consolas o las interacciones en dispositivos de realidad aumentada y virtual dependen de la lógica que exploramos en esta unidad.
El mayor desafío fue diseñar e implementar la bomba temporizada, ya que requería una estructura de código bien organizada para manejar el tiempo, las transiciones de estado y las entradas de usuario sin interrupciones. Este ejercicio me ayudó a mejorar mi capacidad para estructurar programas más complejos y a pensar en soluciones eficientes para sistemas interactivos.