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.