Barreras automáticas y conteo de plazas
Recorrido del nivel
Esa barra de arriba te dice en qué paso estás. Tocala para ver el índice completo y saltar a cualquier paso.
Montar el servomotor de la barrera en la protoboard
El sistema arranca por la barrera. Vamos a controlar su movimiento con un servomotorServomotorMotor que se ubica en un ángulo específico (los comunes, de 0° a 180°) y se mantiene ahí. Se programa indicando el ángulo deseado; tiene tres cables: alimentación (VCC, GND) y señal.: cuando llegue un auto a la entrada, la barrera se levantará con un giro del servo a un ángulo de 90° y luego volverá a bajar a 0°.
El servo tiene tres cables: VCC (alimentación, cable rojo o marrón), GND (masa, cable negro o marrón) y señal (cable naranja o amarillo), que es el que se conecta a una salida digital de la placa y le indica el ángulo. Empezamos conectando un servo (la barrera de entrada); en el paso 4 sumamos el segundo, para la salida.
En el Arduino UNO, el cable de señal del servo de entrada va al pin 4 (la constante
PIN_SERVO_ENTRADA del código), VCC a 5V y GND a GND.
Ojo con un error del material original: el esquema de 2019 conectaba los servos a los pines 0 y 1. Esos dos pines son los que el UNO usa para comunicarse con la computadora por USB (RX y TX): si se los ocupa con los servos, no se puede cargar el programa ni usar el Monitor Serie, y el servo se mueve de forma errática mientras la placa se comunica. Por eso en esta reedición los servos van a pines libres: la barrera de entrada al 4 y la de salida al 8.
En el ESP32, el cable de señal del servo de entrada va al GPIO 25 (la constante
PIN_SERVO_ENTRADA del código). La alimentación del servo conviene tomarla de una fuente de 5 V
aparte (los servos consumen más de lo que el ESP32 entrega con comodidad) y unir siempre el GND
de esa fuente con el GND del ESP32. Para el ESP32 se usa la librería ESP32Servo, que reemplaza
a la Servo.h clásica del UNO.
Programar el movimiento de la barrera
La programación la haremos directamente en el lenguaje de Arduino (C++), con el Arduino IDE
en su versión 2.x, que se descarga gratis desde
arduino.cc/en/software. Un programa de Arduino se llama
sketch y tiene dos bloques: setup(), que se ejecuta una sola vez al encender, y loop(),
que se ejecuta repetidamente después. Todo lo que sigue a // es un comentario: no afecta al
programa, sirve para que el código sea más fácil de leer.
Para mover el servo alcanza con indicarle el ángulo: en el código, una instrucción lleva la
barrera a 90 (levantada) y otra a 0 (baja). Como primera prueba conviene hacer la secuencia
completa —subir la barrera, esperar dos segundos, bajarla, esperar dos segundos— y ver el brazo
moverse. En este primer nivel usamos delay() para las esperas: es lo más simple y hace que el
código se lea igual que su comportamiento (en el nivel avanzado lo cambiaremos, porque el IoT lo
exige).
Accionar la barrera con el pulsador de entrada
Ahora sumamos el pulsadorPulsadorInterruptor que normalmente está abierto y, mientras se lo mantiene presionado, cierra el circuito entre sus patas. Se usa como botón para que el usuario interactúe con el dispositivo, o como sensor de contacto (fin de carrera). de entrada, para que la barrera se accione sola cuando llega un auto. Más adelante lo colocaremos debajo de una plataforma en la entrada: el auto la pisa, el pulsador se presiona y la barrera se levanta.
Un pulsador es un interruptor que normalmente está abierto y, mientras se lo mantiene presionado,
cierra el circuito. En esta reedición lo conectamos directo entre el pin y GND, aprovechando
la resistencia interna de pull-up del microcontrolador (INPUT_PULLUP): así el pin lee un
valor estable en reposo y otro al presionarse, sin necesidad de la resistencia externa de 10 kΩ
que usaba el esquema original.
La lógica que programamos es: cuando se presiona el pulsador de entrada, la barrera se abre (servo a 90°); mientras el auto sigue sobre la plataforma esperamos, y una vez que pasó, esperamos tres segundos y bajamos la barrera (servo a 0°).
En el Arduino UNO, el pulsador de entrada va al pin 2 (la constante PIN_PULSADOR_ENTRADA).
En el ESP32, el pulsador de entrada va al GPIO 32 (la constante PIN_PULSADOR_ENTRADA).
Contar los autos: barrera de salida y variable de lugares
Con una sola barrera no alcanza para llevar la cuenta. Sumamos la barrera de salida con su propio servo y su propio pulsador, iguales a los de la entrada, y una variable que guarde cuántos lugares quedan libres.
Consideramos que el estacionamiento tiene 8 plazas. La variable lugares arranca en 8. Cada
vez que un auto entra, hay un lugar menos: el programa resta 1. Cada vez que un auto
sale, hay un lugar más: suma 1. Así, en todo momento, lugares refleja los espacios
disponibles.
En el Arduino UNO, la barrera de salida usa el servo en el pin 8 (PIN_SERVO_SALIDA) y el
pulsador de salida en el pin 3 (PIN_PULSADOR_SALIDA).
En el ESP32, la barrera de salida usa el servo en el GPIO 26 (PIN_SERVO_SALIDA) y el pulsador
de salida en el GPIO 33 (PIN_PULSADOR_SALIDA).
Indicar la ocupación con dos LED e impedir el ingreso si está lleno
Falta que el sistema avise si hay lugar. Agregamos dos LEDLEDComponente electrónico tipo diodo que emite luz. Tiene polaridad: la pata larga es la positiva y la corta (o el lado plano del encapsulado) la negativa. Conectado al revés no se daña, pero no enciende.: uno verde que se enciende cuando hay al menos una plaza libre y uno rojo que se enciende cuando están todas ocupadas. Cada LED tiene polaridad —la pata larga es la positiva y va al pin de la placa— y una resistenciaResistenciaComponente que se opone al paso de la corriente eléctrica. Su valor se mide en ohm (Ω). Se usa para determinar la cantidad de corriente de una rama del circuito, por ejemplo para evitar que un LED se queme por exceso de corriente. de 220 Ω en serie que limita la corriente.
En el Arduino UNO, el LED verde («hay lugar») va al pin 9 (PIN_LED_VERDE) y el rojo
(«completo») al pin 13 (PIN_LED_ROJO). Como el pin 8 ya lo usa el servo de salida, el LED
rojo se lleva a un pin de salida libre. Recordá que los pines se reasignan según lo que ya tengas
ocupado; lo que manda son las constantes del código, no un número fijo.
En el ESP32, el LED verde va al GPIO 27 (PIN_LED_VERDE) y el rojo al GPIO 14
(PIN_LED_ROJO), dos GPIO de salida libres.
La última pieza de la lógica es impedir el ingreso cuando no hay lugar: para abrir la barrera
de entrada no alcanza con que el pulsador esté presionado, también tiene que haber al menos una
plaza disponible (lugares mayor que 0). La barrera de salida, en cambio, siempre puede abrirse.
Este es el programa completo del nivel inicial: las dos barreras, el conteo con lugares y los
dos LED.
Ver el código completo · barrera-pulsadores.ino
// Estacionamiento automatizado — Nivel Inicial (Arduino UNO).
//
// Maqueta a escala de un estacionamiento de 8 plazas con DOS barreras:
// - Barrera de ENTRADA: un pulsador la abre (servo a 90) SOLO si quedan
// lugares; al pasar el auto, se cierra y se resta un lugar.
// - Barrera de SALIDA: un pulsador la abre; al salir el auto, se cierra y
// se suma un lugar.
// Dos LED indican de un vistazo la ocupacion, como pide la situacion-problema
// de Juana: VERDE = hay lugar, ROJO = estacionamiento completo.
//
// Plataforma: Arduino UNO. Proyecto de BAJA TENSION (servos 5 V, LED,
// pulsadores): no hay 220 V ni agua, no lleva advertencias electricas.
//
// Nivel inicial: se permite delay() (fiel a la progresion del original).
//
// Basado en: Fragmentos de codigo del Nivel Inicial (Pasos 2, 4 y 5) —
// Estacionamiento Automatizado, Saberes Digitales (INET/EDUCAR 2019).
// CORRECCION DE BUG CRITICO (ver README):
// El original ataba servoEntrada al pin 0 y servoSalida al pin 1. Los pines
// 0 y 1 del UNO son el RX/TX del USB/serial de programacion: usarlos para
// los servos ROMPE la carga del sketch y el Monitor Serie. Se remapean a
// los pines 4 (entrada) y 8 (salida), que estan libres.
#if defined(ESP32)
#include <ESP32Servo.h>
#else
#include <Servo.h>
#endif
// --- Capacidad del estacionamiento ---
const int CAPACIDAD = 8;
// --- Pines de las barreras (servos) — REMAPEADOS (bug del original) ---
const int PIN_SERVO_ENTRADA = 4; // original: pin 0 (RX) = BUG, rompe el USB
const int PIN_SERVO_SALIDA = 8; // original: pin 1 (TX) = BUG, rompe el USB
// --- Pines de los pulsadores ---
// El original usa resistencias de 10K como PULLDOWN (estan en los insumos):
// el pulsador lee HIGH cuando se presiona y LOW en reposo.
const int PIN_PULSADOR_ENTRADA = 2;
const int PIN_PULSADOR_SALIDA = 3;
// --- Pines de los LED de estado ---
// Estos dos LED existen SOLO en el nivel inicial. En el nivel intermedio se
// reemplazan por el display de 7 segmentos (que reutiliza estos pines).
const int PIN_LED_VERDE = 9; // encendido = hay lugares disponibles
const int PIN_LED_ROJO = 13; // encendido = estacionamiento completo
// --- Angulos de la barrera ---
const int ANGULO_ABIERTA = 90;
const int ANGULO_CERRADA = 0;
// Tiempo (ms) que se espera, tras liberar el pulsador, a que el auto termine
// de cruzar antes de bajar la barrera.
const unsigned long TIEMPO_PASO_MS = 3000;
// Lugares disponibles. Arranca vacio: 8 lugares libres.
int lugares = CAPACIDAD;
Servo servoEntrada;
Servo servoSalida;
void setup() {
pinMode(PIN_PULSADOR_ENTRADA, INPUT);
pinMode(PIN_PULSADOR_SALIDA, INPUT);
pinMode(PIN_LED_VERDE, OUTPUT);
pinMode(PIN_LED_ROJO, OUTPUT);
servoEntrada.attach(PIN_SERVO_ENTRADA);
servoSalida.attach(PIN_SERVO_SALIDA);
// Ambas barreras arrancan bajas (cerradas).
servoEntrada.write(ANGULO_CERRADA);
servoSalida.write(ANGULO_CERRADA);
}
void loop() {
// --- ENTRADA: solo se abre si hay al menos un lugar libre ---
if (digitalRead(PIN_PULSADOR_ENTRADA) == HIGH && lugares >= 1) {
servoEntrada.write(ANGULO_ABIERTA);
// Mientras el auto sigue sobre el pulsador, esperamos.
while (digitalRead(PIN_PULSADOR_ENTRADA) == HIGH) {
}
delay(TIEMPO_PASO_MS);
servoEntrada.write(ANGULO_CERRADA);
lugares = lugares - 1; // entro un auto: un lugar menos
}
// --- SALIDA: solo tiene sentido si hay algun auto adentro (lugares < 8) ---
// El guard (lugares < CAPACIDAD) evita que el contador supere la capacidad.
if (digitalRead(PIN_PULSADOR_SALIDA) == HIGH && lugares < CAPACIDAD) {
servoSalida.write(ANGULO_ABIERTA);
while (digitalRead(PIN_PULSADOR_SALIDA) == HIGH) {
}
delay(TIEMPO_PASO_MS);
servoSalida.write(ANGULO_CERRADA);
lugares = lugares + 1; // salio un auto: un lugar mas
}
// --- LED de estado ---
if (lugares > 0) {
digitalWrite(PIN_LED_VERDE, HIGH);
digitalWrite(PIN_LED_ROJO, LOW);
} else {
digitalWrite(PIN_LED_VERDE, LOW);
digitalWrite(PIN_LED_ROJO, HIGH);
}
} // Estacionamiento automatizado — Nivel Inicial (ESP32 DevKit v1).
//
// Maqueta a escala de un estacionamiento de 8 plazas con DOS barreras:
// - Barrera de ENTRADA: un pulsador la abre (servo a 90) SOLO si quedan
// lugares; al pasar el auto, se cierra y se resta un lugar.
// - Barrera de SALIDA: un pulsador la abre; al salir el auto, se cierra y
// se suma un lugar.
// Dos LED indican la ocupacion: VERDE = hay lugar, ROJO = completo.
//
// Plataforma: ESP32 (DevKit v1). Servo con la libreria ESP32Servo (la Servo.h
// clasica no funciona en ESP32). Proyecto de BAJA TENSION: sin 220 V ni agua.
// Nota electrica: el ESP32 trabaja a 3,3 V; los servos se alimentan desde 5 V
// con GND comun con la placa.
//
// Nivel inicial: se permite delay() (fiel a la progresion del original).
//
// Basado en: Fragmentos de codigo del Nivel Inicial (Pasos 2, 4 y 5) —
// Estacionamiento Automatizado, Saberes Digitales (INET/EDUCAR 2019).
// Los servos van a GPIO seguros del contrato (25/26); no aplica el bug de los
// pines 0/1 del UNO, pero la eleccion de GPIO evita strapping pins.
#if defined(ESP32)
#include <ESP32Servo.h>
#else
#include <Servo.h>
#endif
// --- Capacidad del estacionamiento ---
const int CAPACIDAD = 8;
// --- Pines de las barreras (servos) — GPIO del contrato ---
const int PIN_SERVO_ENTRADA = 25;
const int PIN_SERVO_SALIDA = 26;
// --- Pines de los pulsadores (con resistencia de 10K como pulldown) ---
const int PIN_PULSADOR_ENTRADA = 32;
const int PIN_PULSADOR_SALIDA = 33;
// --- Pines de los LED de estado (solo en el nivel inicial) ---
// GPIO libres y seguros; en intermedio el display reemplaza a los LED.
const int PIN_LED_VERDE = 27; // encendido = hay lugares disponibles
const int PIN_LED_ROJO = 14; // encendido = estacionamiento completo
// --- Angulos de la barrera ---
const int ANGULO_ABIERTA = 90;
const int ANGULO_CERRADA = 0;
// Espera (ms) a que el auto cruce antes de bajar la barrera.
const unsigned long TIEMPO_PASO_MS = 3000;
// Lugares disponibles. Arranca vacio: 8 lugares libres.
int lugares = CAPACIDAD;
Servo servoEntrada;
Servo servoSalida;
void setup() {
pinMode(PIN_PULSADOR_ENTRADA, INPUT);
pinMode(PIN_PULSADOR_SALIDA, INPUT);
pinMode(PIN_LED_VERDE, OUTPUT);
pinMode(PIN_LED_ROJO, OUTPUT);
servoEntrada.attach(PIN_SERVO_ENTRADA);
servoSalida.attach(PIN_SERVO_SALIDA);
servoEntrada.write(ANGULO_CERRADA);
servoSalida.write(ANGULO_CERRADA);
}
void loop() {
// --- ENTRADA: solo se abre si hay al menos un lugar libre ---
if (digitalRead(PIN_PULSADOR_ENTRADA) == HIGH && lugares >= 1) {
servoEntrada.write(ANGULO_ABIERTA);
while (digitalRead(PIN_PULSADOR_ENTRADA) == HIGH) {
}
delay(TIEMPO_PASO_MS);
servoEntrada.write(ANGULO_CERRADA);
lugares = lugares - 1;
}
// --- SALIDA: guard (lugares < CAPACIDAD) evita superar la capacidad ---
if (digitalRead(PIN_PULSADOR_SALIDA) == HIGH && lugares < CAPACIDAD) {
servoSalida.write(ANGULO_ABIERTA);
while (digitalRead(PIN_PULSADOR_SALIDA) == HIGH) {
}
delay(TIEMPO_PASO_MS);
servoSalida.write(ANGULO_CERRADA);
lugares = lugares + 1;
}
// --- LED de estado ---
if (lugares > 0) {
digitalWrite(PIN_LED_VERDE, HIGH);
digitalWrite(PIN_LED_ROJO, LOW);
} else {
digitalWrite(PIN_LED_VERDE, LOW);
digitalWrite(PIN_LED_ROJO, HIGH);
}
} Podés ver el comportamiento —los autos entrando y saliendo, el conteo y los LED cambiando— en el simulador, antes de armar el circuito real:
Simulación del comportamiento
La misma máquina de estados del firmware, portada a TypeScript, maneja el
comportamiento del dispositivo. No se ejecuta el binario real: la ejecución
del .hex con avr8js está en el roadmap.
Simulación lista. Presioná «Iniciar» para arrancar la secuencia.
Para subir el código a la placa, conectala a la computadora con el cable USB, elegí en el Arduino IDE 2.x la placa y el puertoPuerto COMPuerto de comunicaciones por el cual el sistema operativo se comunica con un dispositivo externo, como la placa. Se asigna automáticamente al conectarla por USB y puede cambiar de número; en el IDE hay que indicar cuál usar. (en el IDE 2.x se eligen juntos en el menú desplegable de la barra superior) y apretá el botón Subir (la flecha →). Al terminar, aparece el mensaje de carga completada en la barra inferior.
Para el Arduino UNO: usá el cable USB tipo B, elegí la placa Arduino UNO y el puerto que se
agregó al conectarla (en Windows es un puerto COM numerado; en Linux suele llamarse
/dev/ttyACM0 o similar). Como ahora los servos están en los pines 4 y 8 (y no en el 0/1), la
carga funciona sin desconectar nada.
Para el ESP32 hay dos pasos previos que se hacen una sola vez: instalar el soporte de placas ESP32 desde el gestor de placas del IDE (buscá “esp32” e instalá el paquete de Espressif) y la librería ESP32Servo desde el gestor de bibliotecas. Después elegí la placa ESP32 Dev Module y el puerto correspondiente. Si al subir el IDE queda esperando en “Connecting…”, mantené apretado el botón BOOT de la placa hasta que empiece la carga.
Verificá
Con el programa cargado, presioná el pulsador de entrada: la barrera de entrada tiene que levantarse, esperar y volver a bajar, y el LED verde debe seguir encendido mientras queden plazas. Repetí hasta “llenar” las 8 plazas: al llegar a cero, el LED verde se apaga, se enciende el rojo y la barrera de entrada ya no se abre aunque presiones. Presioná el pulsador de salida: la barrera de salida se abre, suma un lugar y el LED verde vuelve a encenderse. Si un servo se mueve solo o no podés cargar el programa, revisá que no esté en los pines 0 o 1.
Armar la maqueta del estacionamiento
Con el circuito probado sobre la protoboard, podemos pasar a la maqueta. Una vez que las conexiones funcionan, se puede prescindir de la protoboard soldando cada componente con un cable a la placa y ubicando cada pieza en su lugar dentro de la maqueta.
Para diseñar la planta del estacionamiento con los estudiantes hay que tener en cuenta la ubicación de los dos servomotores con sus barreras (entrada y salida, en calles distintas), la de los dos pulsadores bajo sus plataformas basculantes, la de los LED y la distribución de las 8 plazas.
Esta parte es de fabricación. Los brazos de las barreras y los soportes de los servos (piezas impresas en 3D) y la planta del estacionamiento (corte láser en MDF 3 mm) forman parte de los paquetes de fabricación del proyecto, que se descargan desde su ficha. Mientras tanto, la maqueta puede construirse con materiales simples: una base de cartón o madera con las plazas dibujadas, palitos o cartulina para las barreras encastradas en el brazo del servo y pequeñas plataformas de cartón sobre cada pulsador.
Para el aula
En el nivel intermedio, por la complejidad del cableado del display, el original propone cerrar el proyecto en la protoboard en lugar de pasar a maqueta. Por eso conviene decidir con el grupo: si el recorrido termina en el nivel inicial, vale la pena invertir en una maqueta prolija; si van a seguir a intermedio, quizás convenga dejar la maqueta para el final. Es una buena oportunidad para conversar sobre planificación de un proyecto.
Cierre del nivel
Al terminar este nivel, el estacionamiento de Juana ya se gestiona solo: las barreras se levantan
al llegar un auto, el sistema lleva la cuenta de las plazas con la variable lugares y los LED
avisan si hay lugar o si está completo, bloqueando la entrada cuando no quedan espacios. Además,
corregiste el error del original que conectaba los servos a los pines del USB. Pero los LED solo
dicen “hay / no hay” lugar: no cuántos. En el nivel intermedio vamos a agregar un display de
7 segmentos para ver en pantalla el número exacto de plazas libres.
Evidencia de cierre
Al terminar este nivel, esto tiene que estar funcionando:
- El circuito está montado en la protoboard: dos servomotores (barreras de entrada y de salida), dos pulsadores y los LED verde y rojo, con los servos conectados a pines libres (no a los pines 0 y 1 del USB).
- Sabés subir un programa desde el Arduino IDE 2.x: elegir la placa, elegir el puerto y verificar que quedó cargado.
- Al presionar el pulsador de entrada la barrera se levanta (servo a 90°), espera y vuelve a bajar (0°), y el programa descuenta un lugar; el pulsador de salida hace lo inverso y suma un lugar.
- El LED verde queda encendido mientras hay plazas libres y el rojo cuando el estacionamiento está completo; con el estacionamiento lleno, la barrera de entrada no se abre.
- La maqueta del estacionamiento está armada con sus 8 plazas, las dos barreras, los pulsadores y los LED.