arduino-sensor-aparcamiento-hcsr04

Cómo hacer un sensor de aparcamiento con Arduino y HC-SR04

  • 8 min

Un sensor de aparcamiento es un sistema que mide la distancia a un obstáculo y avisa de su proximidad mediante señales luminosas o acústicas.

Si en el proyecto del semáforo aprendimos a controlar tiempos, aquí vamos a aprender a medir el mundo físico. No nos limitaremos a encender una luz; nuestro Arduino tendrá que enviar una señal, esperar a que rebote y, basándose en el tiempo que ha tardado, calcular con precisión la distancia a un obstáculo.

Este proyecto es la introducción perfecta a la física de ondas y al uso de sensores de tiempo de vuelo (Time of Flight), principios que se usan desde en submarinos (sonar) hasta en los sensores LiDAR más avanzados.

Cómo medimos la distancia con sonido

Para este proyecto usaremos el omnipresente sensor HC-SR04. Este componente es, en esencia, un pequeño murciélago electrónico.

Su funcionamiento se basa en la ecolocalización. El sensor tiene dos “ojos” (que en realidad son transductores):

  1. Emisor (Trig): Emite una ráfaga de ultrasonidos a 40 kHz (inaudible para el ser humano).
  2. Receptor (Echo): Escucha y espera a recibir el rebote de esa onda.

El principio físico es la cinemática básica. Sabemos que la velocidad es espacio partido por tiempo (v = e / t). Como conocemos la velocidad del sonido en el aire y podemos medir el tiempo, despejamos la distancia.

¿Por qué dividimos entre 2? ¡Crucial! El sonido tiene que ir hasta el obstáculo y volver al sensor. El tiempo que medimos es el del viaje de ida y vuelta. Si no dividimos entre 2, estaríamos calculando el doble de la distancia real.

La velocidad del sonido es aproximadamente 343 m/s (a 20°C). Para facilitar los cálculos en el microcontrolador (que trabaja en microsegundos, ), convertimos esa velocidad: . Por tanto, la fórmula que llevaremos al código será:

Componentes

Vamos a construir un sistema completo: medición (sensor) y aviso (zumbador + LEDs).

  • [1x|blue] Arduino Uno | El cerebro del proyecto
  • [1x|orange] Sensor Ultrasónico HC-SR04 | Mide distancias por ultrasonidos
  • [1x|purple] Zumbador (buzzer) activo | Aviso acústico
  • [1x|green] LED Verde | Zona segura
  • [1x|yellow] LED Amarillo | Precaución
  • [1x|red] LED Rojo | Peligro inminente
  • [3x|gray] Resistencia 220Ω | Limitan corriente de LEDs
  • [Varios|gray] Protoboard y cables | Conexiones

Esquema de conexión

El HC-SR04 tiene 4 pines: VCC, Trig, Echo y GND.

Sensor HC-SR04

El sensor necesita alimentación a 5V y dos señales: Trig para lanzar el pulso, y Echo para medir cuánto tarda en volver.

[ { “from”: “HC-SR04 VCC”, “to”: “5V Arduino”, “color”: “red” }, { “from”: “HC-SR04 GND”, “to”: “GND Arduino”, “color”: “black” }, { “from”: “HC-SR04 Trig”, “to”: “Pin 9”, “color”: “orange”, “note”: “Salida del Arduino” }, { “from”: “HC-SR04 Echo”, “to”: “Pin 10”, “color”: “yellow”, “note”: “Entrada al Arduino” } ]

Buzzer de aviso

El buzzer se activa con los pitidos de proximidad.

[ { “from”: “Buzzer (+)”, “to”: “Pin 6”, “color”: “purple” }, { “from”: “Buzzer (-)”, “to”: “GND Arduino”, “color”: “black” } ]

LEDs indicadores

Los LEDs hacen de semáforo visual para distancia segura, precaución y peligro.

[ { “from”: “LED Rojo + 220Ω”, “to”: “Pin 3”, “color”: “red” }, { “from”: “LED Amarillo + 220Ω”, “to”: “Pin 4”, “color”: “yellow” }, { “from”: “LED Verde + 220Ω”, “to”: “Pin 5”, “color”: “green” }, { “from”: “Cátodos LED”, “to”: “GND Arduino”, “color”: “black” } ]

El código

Vamos a dividir el código en dos partes lógicas: la función que mide y la lógica que avisa.

Para medir el pulso, usaremos la función nativa pulseIn(), que espera a que un pin cambie de estado y cuenta cuánto tiempo ha pasado en microsegundos.

// --- Configuración de Hardware ---
const int pinTrig = 9;
const int pinEcho = 10;
const int pinBuzzer = 6;

// Pines para los LEDs (opcionales, pero recomendados)
const int pinLedVerde = 5;
const int pinLedAmarillo = 4;
const int pinLedRojo = 3;

// Constantes físicas
// Velocidad sonido / 2 = 0.0343 / 2 = 0.01715
const float VELOCIDAD_SONIDO = 0.01715; 

void setup() {
  Serial.begin(9600); // Para depurar por pantalla

  // Configuración de pines
  pinMode(pinTrig, OUTPUT);
  pinMode(pinEcho, INPUT);
  pinMode(pinBuzzer, OUTPUT);
  
  pinMode(pinLedVerde, OUTPUT);
  pinMode(pinLedAmarillo, OUTPUT);
  pinMode(pinLedRojo, OUTPUT);
  
  // Iniciamos con el Trigger apagado
  digitalWrite(pinTrig, LOW);
}
Copied!

El bucle principal y la lógica de aviso

En el loop, tomamos la medida. Según la distancia, haremos que el buzzer suene con diferentes frecuencias (como en un coche real: más cerca = pitidos más rápidos).

void loop() {
  // 1. OBTENER DISTANCIA
  long distancia = medirDistancia();
  
  // Imprimimos para depurar (Debug)
  Serial.print("Distancia: ");
  Serial.print(distancia);
  Serial.println(" cm");

  // 2. LÓGICA DE AVISO (El "Beep Beep")
  // Definimos umbrales de distancia
  if (distancia < 10) {
    // PELIGRO INMINENTE (< 10cm)
    // Pitido continuo y luz roja
    digitalWrite(pinBuzzer, HIGH); // Sonido continuo
    encenderSemaforo(true, false, false); // Solo rojo
  } 
  else if (distancia < 30) {
    // PRECAUCIÓN (< 30cm)
    // Pitidos rápidos y luz amarilla
    alertaIntermitente(100); // Beep rápido
    encenderSemaforo(false, true, false); // Solo amarillo
  } 
  else if (distancia < 60) {
    // ATENCIÓN (< 60cm)
    // Pitidos lentos y luz verde
    alertaIntermitente(300); // Beep lento
    encenderSemaforo(false, false, true); // Solo verde
  } 
  else {
    // ZONA SEGURA (> 60cm)
    digitalWrite(pinBuzzer, LOW); // Silencio
    apagartodo();
  }
  
  delay(50); // Pequeña pausa para estabilidad
}
Copied!

Funciones auxiliares

Aquí es donde encapsulamos la complejidad. La función medirDistancia realiza la secuencia estricta que requiere el sensor HC-SR04 para funcionar.

  1. Mandar un pulso de 10 microsegundos por el pin Trig.
  2. Escuchar el pin Echo.
  3. Aplicar la fórmula.
long medirDistancia() {
  // 1. Generar pulso de disparo (Trigger)
  digitalWrite(pinTrig, LOW);
  delayMicroseconds(2);
  digitalWrite(pinTrig, HIGH);
  delayMicroseconds(10); // El pulso debe durar al menos 10us
  digitalWrite(pinTrig, LOW);
  
  // 2. Medir el tiempo del eco
  // pulseIn espera a que el pin se ponga HIGH y cuenta hasta que baja a LOW
  unsigned long duracion = pulseIn(pinEcho, HIGH, 30000UL);
  
  // 3. Convertir a distancia
  // Si duracion es 0, es que no ha rebotado (fuera de rango)
  if (duracion == 0) return 999; 
  
  return duracion * VELOCIDAD_SONIDO;
}

// Función para hacer el "Beep-Beep"
void alertaIntermitente(int velocidad) {
  digitalWrite(pinBuzzer, HIGH);
  delay(velocidad);
  digitalWrite(pinBuzzer, LOW);
  delay(velocidad);
}

// Helper para gestionar los LEDs limpiamente
void encenderSemaforo(bool r, bool a, bool v) {
    digitalWrite(pinLedRojo, r ? HIGH : LOW);
    digitalWrite(pinLedAmarillo, a ? HIGH : LOW);
    digitalWrite(pinLedVerde, v ? HIGH : LOW);
}

void apagartodo() {
    digitalWrite(pinLedRojo, LOW);
    digitalWrite(pinLedAmarillo, LOW);
    digitalWrite(pinLedVerde, LOW);
}
Copied!

Análisis de problemas comunes

Es probable que al montar esto os encontréis con lecturas extrañas. Es normal, estamos trabajando con sonido en el mundo real.

  • Rebotes falsos: Si el sensor apunta a una superficie blanda (como tela o una esponja), el sonido no rebota bien y el sensor “no ve” nada.
  • Ángulos: Si la superficie está muy inclinada respecto al sensor, el sonido rebota hacia otro lado y nunca vuelve al receptor (como una bola de billar contra una banda).
  • El bloqueo del código: La función alertaIntermitente usa delay. Esto significa que mientras pita, no mide. En un montaje más reactivo usaríamos millis() para pitar y medir sin bloquear el procesador.
  • El tiempo de espera del eco: El tercer parámetro de pulseIn() limita la espera a 30 ms. Sin este límite, una medición sin eco podría bloquear el programa durante mucho más tiempo.

Siguientes pasos

Este proyecto es la base de la robótica móvil. Un robot que no choca es, básicamente, este código montado sobre ruedas.

¿Te atreves a mejorarlo?

  1. Sustituye los LEDs por una Pantalla LCD que muestre la distancia exacta en centímetros.
  2. Usa la función tone() en el buzzer para que el sonido sea más agudo cuanto más cerca esté el objeto, en lugar de solo cambiar la velocidad del pitido.
  3. Intenta implementar la librería NewPing, que optimiza mucho la lectura y evita bloqueos si el sensor no recibe respuesta.