Una barrera automatizada que se abre con un pulsador y se cierra de emergencia si el sensor de choque detecta un impacto. Aprende maquinas de estados y control de servo.
Estos son los componentes necesarios para este proyecto. Haz clic en cada uno para ir a su guia completa.
Conecta cada componente a la placa de expansion del micro:bit siguiendo esta tabla. Usa colores de cable diferentes para no confundirte.
Codigo completo con comentarios detallados. Elige tu entorno y copia el codigo en tu editor. Recuerda instalar la extension OLED en MakeCode antes de programar.
// Sistema de acceso con servo y máquina de estados // Estados: CERRADO, ABRIENDO, ABIERTO, CERRANDO, EMERGENCIA // Constantes de estado let CERRADO = 0 let ABRIENDO = 1 let ABIERTO = 2 let CERRANDO = 3 let EMERGENCIA = 4 let estado = CERRADO let tiempoAbierto = 5000 // ms que permanece abierto // Inicializar OLED.init(128, 64) pins.servoWritePin(AnalogPin.P1, 0) // Barrera cerrada function actualizarOLED() { OLED.clear() OLED.writeString("=== ACCESO ===") if (estado == CERRADO) { OLED.writeString("ESTADO: Cerrado") OLED.writeString("Pulsa A para abrir") } else if (estado == ABRIENDO) { OLED.writeString("ESTADO: Abriendo...") } else if (estado == ABIERTO) { OLED.writeString("ESTADO: ABIERTO") OLED.writeString("Cierra en 5s") } else if (estado == CERRANDO) { OLED.writeString("ESTADO: Cerrando...") } else if (estado == EMERGENCIA) { OLED.writeString("!!! EMERGENCIA !!!") OLED.writeString("Impacto detectado") } } basic.forever(function () { // Leer sensores let botonPulsado = pins.digitalReadPin(DigitalPin.P0) let choquePulsado = pins.digitalReadPin(DigitalPin.P2) // Detectar emergencia desde cualquier estado if (choquePulsado == 1 && estado != EMERGENCIA) { estado = EMERGENCIA pins.servoWritePin(AnalogPin.P1, 0) // Cerrar inmediatamente actualizarOLED() basic.pause(3000) estado = CERRADO } // Máquina de estados if (estado == CERRADO) { actualizarOLED() if (botonPulsado == 1) { estado = ABRIENDO } } else if (estado == ABRIENDO) { actualizarOLED() pins.servoWritePin(AnalogPin.P1, 90) // Abrir barrera basic.pause(500) estado = ABIERTO } else if (estado == ABIERTO) { actualizarOLED() basic.pause(tiempoAbierto) // Permanecer abierto estado = CERRANDO } else if (estado == CERRANDO) { actualizarOLED() pins.servoWritePin(AnalogPin.P1, 0) // Cerrar barrera basic.pause(500) estado = CERRADO } basic.pause(100) })
from microbit import *
import ssd1306
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# Estados
CERRADO = 0
ABRIENDO = 1
ABIERTO = 2
CERRANDO = 3
EMERGENCIA = 4
estado = CERRADO
TIEMPO_ABIERTO = 5000 # ms
def mover_servo(angulo):
# Convertir ángulo (0-180) a PWM (0-1023)
# 0° = 26, 90° = 77, 180° = 128 (aproximado)
pwm = int(26 + (angulo / 180) * 102)
pin1.write_analog(pwm)
def actualizar_oled():
oled.fill(0)
oled.text("=== ACCESO ===", 0, 0)
if estado == CERRADO:
oled.text("Cerrado", 0, 20)
oled.text("Pulsa boton", 0, 36)
elif estado == ABRIENDO:
oled.text("Abriendo...", 0, 20)
elif estado == ABIERTO:
oled.text("ABIERTO", 0, 20)
oled.text("Cierra en 5s", 0, 36)
elif estado == CERRANDO:
oled.text("Cerrando...", 0, 20)
elif estado == EMERGENCIA:
oled.text("!EMERGENCIA!", 0, 20)
oled.text("Impacto!", 0, 36)
oled.show()
# Posición inicial: cerrado
mover_servo(0)
while True:
boton = pin0.read_digital()
choque = pin2.read_digital()
# Emergencia
if choque == 1 and estado != EMERGENCIA:
estado = EMERGENCIA
mover_servo(0)
actualizar_oled()
sleep(3000)
estado = CERRADO
# Máquina de estados
if estado == CERRADO:
actualizar_oled()
if boton == 1:
estado = ABRIENDO
elif estado == ABRIENDO:
actualizar_oled()
mover_servo(90)
sleep(500)
estado = ABIERTO
elif estado == ABIERTO:
actualizar_oled()
sleep(TIEMPO_ABIERTO)
estado = CERRANDO
elif estado == CERRANDO:
actualizar_oled()
mover_servo(0)
sleep(500)
estado = CERRADO
sleep(100)
En lugar de un montón de if anidados, usamos una variable de estado que solo puede tener un valor a la vez. Cada ciclo del loop comprueba en que estado estamos y que hacer. La emergencia tiene prioridad absoluta — se comprueba ANTES de la maquina de estados. Esto hace el codigo predecible y facil de ampliar.
Cuatro retos progresivos para ampliar el proyecto. No hay solucion unica — experimenta y prueba tus ideas.
tiempoAbierto a 10000 (10 segundos) y observa el comportamiento. Luego prueba con 2000 (2 segundos). ¿Que valor te parece mas realista para una barrera de parking?estado == ABIERTO.Si algo no funciona como esperas, revisa estos casos. La mayoria de los problemas tienen una causa sencilla.
estado = ABIERTO al final del bloque de ABRIENDO. Sin esa linea, el estado nunca cambia y el loop repite el mismo bloque infinitamente.choque == 1 por choque == 0 en la condicion de emergencia.OLED.clear() como primera linea de la funcion actualizarOLED.Ideas para convertir este proyecto en algo mas complejo. Son punto de partida — investiga como implementarlas.