Unidad 3
Introducción 📜
Sección titulada «Introducción 📜»En esta unidad vas a seguir explorando la integración entre micro:bit y p5.js, al tiempo que profundizarás en la técnica de programación con máquinas de estado. Volverás a practicar dicha técnica con el micro:bit, pero también en p5.js.
Te preguntarás ¿Por qué tanta insistencia del profe con esta técnica? Y la razón es que ella te permitirá lograr en tus aplicaciones escalabilidad, en términos de concurrencia, es decir, permitirá que una aplicación tenga múltiples TAREAS haciendo al mismo tiempo varias cosas.
Rúbrica de evaluación de la unidad 📝
Sección titulada «Rúbrica de evaluación de la unidad 📝»Requisito de salida (condición necesaria)
Sección titulada «Requisito de salida (condición necesaria)»Rúbrica analítica
Sección titulada «Rúbrica analítica»| Criterio (peso) | Cumple plenamente (5.0) | Se cumple medianamente (4.0) | Problemas importantes (3.0) | Falta comprensión básica (2.0) | No hay evidencia (0.0) |
|---|---|---|---|---|---|
| 1. Aplicación + bitácora (40%) | La app se ejecuta sin fallos en el entorno acordado. Evidencia completa y verificable en bitácora. Todo consistente con lo mostrado en la demo. | La app funciona y cumple lo esencial. La bitácora permite verificar, pero hay 1–2 vacíos menores | La app funciona parcialmente o depende de condiciones no declaradas. Bitácora con vacíos importantes o incompleta. | La app no corre o no demuestra lo requerido. La bitácora no permite verificación de la app. | No se entregaron evidencias o no se puede acceder a ellas |
| Evaluación | |||||
| 2. Sustentación (60%) | Responde a las preguntas con precisión, conectando: (a) lo que se ve, (b) cómo está hecho, y (c) por qué. Usa su bitácora para justificar decisiones. Reconoce límites/errores y propone cómo probar/mejorar. | Respuestas correctas pero con imprecisiones menores o justificación superficial. Usa parcialmente la bitácora para sustentar. | Responde solo “qué hizo” pero le cuesta explicar “cómo” o “por qué”. Necesita guía para conectar con su propia evidencia/bitácora. | No logra responder de forma coherente o responde sin relación con lo presentado/documentado. Evidencia falta de comprensión básica del trabajo entregado. | No se entregaron evidencias o no se puede acceder a ellas |
| Evaluación |
Set: ¿Qué aprenderás en esta unidad? 💡
Sección titulada «Set: ¿Qué aprenderás en esta unidad? 💡»Vas a seguir practicando la técnica de programación con máquinas de estado y a transferirla a p5.js.
Actividad 01
Sección titulada «Actividad 01»Regresemos a la actividad del semáforo de la unidad anterior. Te pediré que hagas las siguientes modificaciones:
-
Si el botón A se presiona el semáforo debe cambiar a modo “peatonal”. En este modo el semáforo se pone en rojo, pero antes debe pasar por amarillo para darle tiempo a los autos a detenerse.
-
Si el botón B se presiona el semáforo pasa a modo nocturno. En este modo el semáforo parpadea en amarillo. Si el botón A se presiona en este modo, el semáforo vuelve a modo normal.
Actividad 02
Sección titulada «Actividad 02»Vas a modificar el código del temporizador de la unidad anterior así:
-
Si está corriendo el temporizador, al presionar el botón A se debe pausar el conteo. Si se vuelve a presionar el botón A, el conteo se reanuda en donde se había pausado.
-
Si el temporizador está corriendo, si se presiona una secuencia de botones A-B-A, el temporizador debo volver a modo de configuración.
Te dejo el proyecto base para modificar si no tienes tu propia versión
main.py:
from microbit import *from fsm import FSMTask, ENTRY, EXITfrom utils import FILLimport utimeimport music
class Temporizador(FSMTask): def __init__(self): super().__init__() self.event_queue = [] self.timers = [] self.counter = 20 self.myTimer = self.add_timer("Timeout",1000) self.estado_actual = None self.transition_to(self.estado_config)
def estado_config(self, ev): if ev == ENTRY: self.counter = 20 display.show(FILL[self.counter]) self.myTimer.start() if ev == "A": if self.counter > 15: self.counter -= 1 display.show(FILL[self.counter]) if ev == "B": if self.counter < 25: self.counter += 1 display.show(FILL[self.counter]) if ev == "S": self.transition_to(self.estado_armed)
def estado_armed(self, ev): if ev == ENTRY: self.myTimer.start() if ev == "Timeout": if self.counter > 0: self.counter -= 1 display.show(FILL[self.counter]) if self.counter == 0: self.transition_to(self.estado_timeout) else: self.myTimer.start()
def estado_timeout(self, ev): if ev == ENTRY: display.show(Image.SKULL) music.play(music.FUNERAL) if ev == "A": music.stop() self.transition_to(self.estado_config)
temporizador = Temporizador()
while True:
if button_a.was_pressed(): temporizador.post_event("A") if button_b.was_pressed(): temporizador.post_event("B") if accelerometer.was_gesture("shake"): temporizador.post_event("S")
temporizador.update() utime.sleep_ms(20)fsm.py:
import utime
ENTRY = "ENTRY"EXIT = "EXIT"
class Timer: def __init__(self, owner, event_to_post, duration): self.owner = owner self.event = event_to_post self.duration = duration self.start_time = 0 self.active = False
def start(self, new_duration=None): if new_duration is not None: self.duration = new_duration self.start_time = utime.ticks_ms() self.active = True
def stop(self): self.active = False
def update(self): if self.active and utime.ticks_diff(utime.ticks_ms(), self.start_time) >= self.duration: self.active = False self.owner.post_event(self.event)
class FSMTask: def __init__(self): self._q = [] self._timers = [] self._state = None
def post_event(self, ev): self._q.append(ev)
def add_timer(self, event, duration): t = Timer(self, event, duration) self._timers.append(t) return t
def transition_to(self, new_state): if self._state: self._state(EXIT) self._state = new_state self._state(ENTRY)
def update(self): for t in self._timers: t.update() while self._q: ev = self._q.pop(0) if self._state: self._state(ev)utils.py:
from microbit import Image
def make_fill_images(on='9', off='0'): imgs = [] for n in range(26): rows = [] k = 0 for y in range(5): row = [] for x in range(5): row.append(on if k < n else off) k += 1 rows.append(''.join(row)) imgs.append(Image(':'.join(rows))) return imgs
FILL = make_fill_images()# Para mostrar usas display.show(FILL[n]) donde n será# un valor de 0 a 25Seek: Investigación 🔎
Sección titulada «Seek: Investigación 🔎»Actividad 03
Sección titulada «Actividad 03»Ahora vamos a analizar juntos la implementación del temporizador en p5.js usando la técnica de máquinas de estado. Para esto necesito que abras este repositorio de GitHub y sigamos juntos las instrucciones.
Apply: Aplicación 🛠
Sección titulada «Apply: Aplicación 🛠»Actividad 04
Sección titulada «Actividad 04»Vas a modificar el código anterior adicionando:
- Si está corriendo el temporizador, al presionar la tecla A se debe pausar el conteo. Si se vuelve a presionar la tecla A, el conteo se reanuda en donde se había pausado.
- Si el temporizador está corriendo, si se presiona una secuencia de teclas A-B-A, el temporizador debo volver a modo de configuración.
- Vas a controlar el temporizador que está funcionando en p5.js usando el micro:bit, además de las teclas del computador. Recuerda que solo deberás usar del micro:bit los botones A y B y el acelerómetro.
Reflect: Consolidación y metacognición 🤔
Sección titulada «Reflect: Consolidación y metacognición 🤔»Actividad 05
Sección titulada «Actividad 05»En este punto ya tienes una aplicación de temporizador funcionando en p5.js. Para esta actividad de reflexión, vas a reproducir lo que ya tienes de la actividad 4, es decir, el temporizador en p5.js con las modificaciones implementadas y controlado por un micro:bit local. Ahora te pediré que te juntes con un compañero o compañera y que adiciones la posibilidad de controlar el temporizador en p5.js de manera remota usado otro micro:bit. Es decir, cada grupo tendrá dos micro:bits, uno para controlar el temporizador localmente y otro para controlarlo de manera remota.
Te pediré que NO modifiques la implementación de la máquina de estados del temporizador en p5.js. Esta deberá seguir recibiendo por serial los mismos comandos que recibía antes, solo que ahora el micro:bit local se comnicará con el micro:bit remoto y servirá como puente para enviar los comandos del micro:bit remoto a p5.js.
¿Por dónde puedes comenzar a investigar para resolver este problema? En el editor de micro:bit ingresa a la sección Reference y luego busca allí la sección Radio. Encontrarás que cada pareja de micro:bits deben definir un radio group para poder comunicarse entre sí. Este radio group no puede repetirse con el de otras parejas, así que cada grupo deberá elegir un número de radio group diferente.