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.
Comprueba cada punto para confirmar que el sistema funciona correctamente. Si algo falla, revisa la seccion de problemas.
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.