Saltar al contenido
Nivel intermedio

Mostrar las plazas libres en un display de 7 segmentos

Conectar el display de 7 segmentos

El display de 7 segmentos es un componente que representa números encendiendo o apagando siete LED con forma de línea. Cada segmento se identifica con una letra, de la a a la g: por ejemplo, el segmento g es el trazo horizontal del centro. Como cada segmento es un LED, cada uno necesita su resistencia de 220 Ω en serie, y el pin común del display va a GND.

Esquema de conexión del display de 7 segmentos: cada uno de los siete segmentos va, a través de una resistencia de 220 ohm en la protoboard, a un pin digital del Arduino UNO (13, 12, 11, 10, 7, 6, 5); el pin común del display va a GND.
Conexión del display de 7 segmentos (figura original del proyecto): cada segmento llega a una salida digital con su resistencia de 220 Ω y el común va a GND. El diagrama indica solo las conexiones que se agregan para manejar el display.

En el Arduino UNO, los siete segmentos se conectan a los pines a=12, b=13, c=5, d=6, e=7, f=11, g=10 (las constantes del código). Son los mismos pines del esquema original.

En el ESP32, los siete segmentos se conectan a los GPIO a=16, b=17, c=18, d=19, e=21, f=22, g=23 (las constantes del código), todos GPIO de salida seguros. La alimentación del display se toma de 3,3 V y GND.

Programar el display: la tabla de segmentos

Programar el display es igual que encender y apagar LED: para mostrar una cifra hay que prender los segmentos correctos y apagar el resto. Si queremos representar un 8, encendemos los siete; para un 4, solo los segmentos b, c, f y g.

Cada carácter tiene su combinación de segmentos prendidos y apagados. En lugar de escribir el encendido a mano para cada número, conviene guardar esa correspondencia en una tabla dentro del código: una fila por cada cifra (del 0 al 9) y una columna por cada segmento (a, b, c, d, e, f, g), con un 1 si el segmento va encendido y un 0 si va apagado. Esa tabla se parece mucho a la de lápiz y papel donde marcamos, para cada número, qué segmentos se dibujan.

Escribir cualquier cifra con escribir_numero()

Con la tabla lista, necesitamos una función que reciba un número y encienda o apague los segmentos que le corresponden. La llamamos escribir_numero(): recibe un valor (por ejemplo, 2) y usa la fila de la tabla de ese número para escribir cada segmento. Así, en vez de repetir siete instrucciones cada vez, con una sola línea —escribir_numero(2)— mostramos el 2 en el display.

Como prueba, se puede recorrer del 0 al 9 con una demora de un segundo entre cada número: el display irá mostrando la cuenta y, al terminar, volverá a empezar. Ese ejercicio confirma que la tabla y la función están bien antes de conectarlas al estacionamiento.

Incorporar el display al estacionamiento

Ahora conectamos el display al sistema del nivel inicial para que muestre cuántas plazas libres quedan y reemplace a los dos LED verde y rojo. La lógica de las barreras y el conteo es la misma: lo único que cambia es que, cada vez que lugares sube o baja, llamamos a escribir_numero(lugares) para actualizar la pantalla. La variable arranca en 8, así que al encender el display muestra un 8.

Ver el código completo · contador-display.ino
contador-display.ino Arduino UNO
// Estacionamiento automatizado — Nivel Intermedio (Arduino UNO).
//
// Igual que el nivel inicial (dos barreras + contador de lugares), pero los dos
// LED verde/rojo se reemplazan por un DISPLAY DE 7 SEGMENTOS que muestra el
// numero EXACTO de lugares libres (0 a 8), como pide la situacion-problema
// (Juana quiere saber cuantos lugares quedan, no solo si hay o no hay).
//
// Display de 7 segmentos de CATODO COMUN: cada segmento (a..g) se enciende con
// un HIGH en su pin. La tabla segmentos[10][7] define que segmentos van
// prendidos para cada digito, y escribir_numero() la aplica.
//
// Plataforma: Arduino UNO. Proyecto de BAJA TENSION (servos 5 V, display,
// pulsadores): no hay 220 V ni agua, no lleva advertencias electricas.
//
// Nivel intermedio: se permite delay() (fiel a la progresion del original).
//
// Basado en: Fragmentos de codigo del Nivel Intermedio (Pasos 3 y 4) —
// Estacionamiento Automatizado, Saberes Digitales (INET/EDUCAR 2019).
// CORRECCION DE BUG CRITICO (ver README): servoEntrada/servoSalida se
// remapean de los pines 0/1 (RX/TX del USB, que rompen la carga y el serial)
// a los pines 4 y 8.

#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
const int PIN_SERVO_SALIDA  = 8;  // original: pin 1 (TX) = BUG

// --- Pines de los pulsadores (10K como pulldown, del original) ---
const int PIN_PULSADOR_ENTRADA = 2;
const int PIN_PULSADOR_SALIDA  = 3;

// --- Pines del display de 7 segmentos (segmentos a..g), fieles al original ---
const int PIN_A = 12;
const int PIN_B = 13;
const int PIN_C = 5;
const int PIN_D = 6;
const int PIN_E = 7;
const int PIN_F = 11;
const int PIN_G = 10;

// --- 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;

// Vector de 10x7 con la configuracion de los segmentos {a,b,c,d,e,f,g} de cada
// caracter numerico (1 = segmento encendido). Es la tabla del original.
int segmentos[10][7] = { { 1, 1, 1, 1, 1, 1, 0 },   // 0
                         { 0, 1, 1, 0, 0, 0, 0 },   // 1
                         { 1, 1, 0, 1, 1, 0, 1 },   // 2
                         { 1, 1, 1, 1, 0, 0, 1 },   // 3
                         { 0, 1, 1, 0, 0, 1, 1 },   // 4
                         { 1, 0, 1, 1, 0, 1, 1 },   // 5
                         { 1, 0, 1, 1, 1, 1, 1 },   // 6
                         { 1, 1, 1, 0, 0, 0, 0 },   // 7
                         { 1, 1, 1, 1, 1, 1, 1 },   // 8
                         { 1, 1, 1, 1, 0, 1, 1 } }; // 9

Servo servoEntrada;
Servo servoSalida;

// escribir_numero recibe un valor (0 a 9) y enciende/apaga los segmentos
// correspondientes segun la tabla "segmentos".
void escribir_numero(int num) {
  digitalWrite(PIN_A, segmentos[num][0]);
  digitalWrite(PIN_B, segmentos[num][1]);
  digitalWrite(PIN_C, segmentos[num][2]);
  digitalWrite(PIN_D, segmentos[num][3]);
  digitalWrite(PIN_E, segmentos[num][4]);
  digitalWrite(PIN_F, segmentos[num][5]);
  digitalWrite(PIN_G, segmentos[num][6]);
}

void setup() {
  pinMode(PIN_PULSADOR_ENTRADA, INPUT);
  pinMode(PIN_PULSADOR_SALIDA, INPUT);

  pinMode(PIN_A, OUTPUT);
  pinMode(PIN_B, OUTPUT);
  pinMode(PIN_C, OUTPUT);
  pinMode(PIN_D, OUTPUT);
  pinMode(PIN_E, OUTPUT);
  pinMode(PIN_F, OUTPUT);
  pinMode(PIN_G, OUTPUT);

  servoEntrada.attach(PIN_SERVO_ENTRADA);
  servoSalida.attach(PIN_SERVO_SALIDA);
  servoEntrada.write(ANGULO_CERRADA);
  servoSalida.write(ANGULO_CERRADA);

  // Mostramos el valor inicial de lugares (8) en el display.
  escribir_numero(lugares);
}

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;
    escribir_numero(lugares);
  }

  // --- SALIDA: guard lugares < CAPACIDAD evita superar 8 (y un indice fuera
  //     de rango en la tabla segmentos[]) ---
  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;
    escribir_numero(lugares);
  }
}
contador-display.ino ESP32
// Estacionamiento automatizado — Nivel Intermedio (ESP32 DevKit v1).
//
// Igual que el nivel inicial (dos barreras + contador de lugares), pero los dos
// LED verde/rojo se reemplazan por un DISPLAY DE 7 SEGMENTOS que muestra el
// numero EXACTO de lugares libres (0 a 8).
//
// Display de 7 segmentos de CATODO COMUN: cada segmento (a..g) se enciende con
// un HIGH. La tabla segmentos[10][7] define que segmentos van prendidos para
// cada digito y escribir_numero() la aplica.
//
// Plataforma: ESP32 (DevKit v1). Servo con ESP32Servo. 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.
//
// Nivel intermedio: se permite delay() (fiel a la progresion del original).
//
// Basado en: Fragmentos de codigo del Nivel Intermedio (Pasos 3 y 4) —
// Estacionamiento Automatizado, Saberes Digitales (INET/EDUCAR 2019).

#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 del display de 7 segmentos (segmentos a..g) — GPIO del contrato ---
const int PIN_A = 16;
const int PIN_B = 17;
const int PIN_C = 18;
const int PIN_D = 19;
const int PIN_E = 21;
const int PIN_F = 22;
const int PIN_G = 23;

// --- 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;

// Vector de 10x7 con la configuracion de los segmentos {a,b,c,d,e,f,g}.
int segmentos[10][7] = { { 1, 1, 1, 1, 1, 1, 0 },   // 0
                         { 0, 1, 1, 0, 0, 0, 0 },   // 1
                         { 1, 1, 0, 1, 1, 0, 1 },   // 2
                         { 1, 1, 1, 1, 0, 0, 1 },   // 3
                         { 0, 1, 1, 0, 0, 1, 1 },   // 4
                         { 1, 0, 1, 1, 0, 1, 1 },   // 5
                         { 1, 0, 1, 1, 1, 1, 1 },   // 6
                         { 1, 1, 1, 0, 0, 0, 0 },   // 7
                         { 1, 1, 1, 1, 1, 1, 1 },   // 8
                         { 1, 1, 1, 1, 0, 1, 1 } }; // 9

Servo servoEntrada;
Servo servoSalida;

void escribir_numero(int num) {
  digitalWrite(PIN_A, segmentos[num][0]);
  digitalWrite(PIN_B, segmentos[num][1]);
  digitalWrite(PIN_C, segmentos[num][2]);
  digitalWrite(PIN_D, segmentos[num][3]);
  digitalWrite(PIN_E, segmentos[num][4]);
  digitalWrite(PIN_F, segmentos[num][5]);
  digitalWrite(PIN_G, segmentos[num][6]);
}

void setup() {
  pinMode(PIN_PULSADOR_ENTRADA, INPUT);
  pinMode(PIN_PULSADOR_SALIDA, INPUT);

  pinMode(PIN_A, OUTPUT);
  pinMode(PIN_B, OUTPUT);
  pinMode(PIN_C, OUTPUT);
  pinMode(PIN_D, OUTPUT);
  pinMode(PIN_E, OUTPUT);
  pinMode(PIN_F, OUTPUT);
  pinMode(PIN_G, OUTPUT);

  servoEntrada.attach(PIN_SERVO_ENTRADA);
  servoSalida.attach(PIN_SERVO_SALIDA);
  servoEntrada.write(ANGULO_CERRADA);
  servoSalida.write(ANGULO_CERRADA);

  escribir_numero(lugares);
}

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;
    escribir_numero(lugares);
  }

  // --- SALIDA: guard lugares < CAPACIDAD evita superar 8 (indice fuera de
  //     rango en segmentos[]) ---
  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;
    escribir_numero(lugares);
  }
}
Estacionamiento con display: las dos barreras y el conteo funcionan igual que en el nivel inicial, pero ahora el display de 7 segmentos muestra el número exacto de plazas libres cada vez que un auto entra o sale, en lugar de los LED.

Podés ver el comportamiento —los autos entrando y saliendo y el display mostrando la cuenta— en el simulador:

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.

Cierre del nivel

Al terminar este nivel, el estacionamiento ya no solo dice si hay lugar: muestra cuántos. En el camino aprendiste a manejar un display de 7 segmentos, a guardar datos en una tabla y a encapsular la lógica en una función reutilizable. Pero la información sigue estando solo en el lugar: para saber si hay plazas hay que ir hasta el estacionamiento y mirar el display. En el nivel avanzado vamos a publicar esa información en internet, para poder consultarla a distancia desde un dispositivo móvil.

Evidencia de cierre

Al terminar este nivel, esto tiene que estar funcionando:

  • El display de 7 segmentos está conectado: cada segmento (a–g) a su salida digital con una resistencia de 220 Ω, y el común a GND.
  • Entendés cómo se representa una cifra encendiendo y apagando segmentos, y podés escribir cualquier número de 0 a 9 con la función escribir_numero() apoyada en la tabla de segmentos.
  • El display reemplaza a los dos LED del nivel inicial y muestra en todo momento la cantidad exacta de plazas libres, que baja al entrar un auto y sube al salir.