Cómo obtener mejores resultados con HCSR04.

Cómo funciona el sensor ultrasónico.

El sensor ultrasónico utiliza un sonar para determinar la distancia a un objeto. Esto es lo que sucede:

  • El transmisor (pin trig) envía una señal: un sonido de alta frecuencia.
  • Cuando la señal encuentra un objeto, se refleja y …
  • … El transmisor (pin de eco) lo recibe.

El tiempo entre la transmisión y la recepción de la señal nos permite calcular la distancia a un objeto. Esto es posible porque conocemos la velocidad del sonido en el aire.

Configuración de pines del sensor ultrasónico HC-SR04

Patas

  • VCC: + 5 VCC
  • Trig: Trigger (INPUT)
  • Eco: Eco (SALIDA)
  • GND: GND

Código estándar:

La parte principal del código es una función que mide el tiempo después de la señal en el pin Trigger hasta el momento en que la señal en el pin Echo baja.

digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Read the signal from the sensor: a HIGH pulse whose
// duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
//With measured time we calculate the distance in cm:
cm = (duration/2) * 0.034;

¡Y todo parece estar bien! Pero no funciona.

¿Qué pasa con el código estándar?

Después de recopilar algunos datos, trazamos un gráfico con él. Muestra el tiempo que tardó el sonido en viajar desde el sensor hasta el obstáculo a una distancia de 30 cm y hacia atrás.

Como puede ver, es un desastre absoluto. Puede decir que es solo la inexactitud del sensor, pero encontré una solución para esto. El problema no está en el sensor sino en Arduino. Cuando Arduino funciona, ejecuta el código que escribiste, pero no solo. A veces, el procesador recibe una señal para congelar su código y hacer otra cosa y luego de eso, reanuda lo que congeló. Esa situación se llama manejo de una interrupción y es muy común en Arduino. El problema es que la interrupción congela nuestro temporizador (función PulseIn) y, por lo tanto, nuestras lecturas se estropean. Arreglar esto es bastante fácil. Son solo dos líneas en código estándar:

noInterrupts();
duration = pulseIn(echoPin, HIGH);
interrupts();

Sin interrupciones, nuestras lecturas se ven mucho mejor, pero aún así, vemos que algunas lecturas son 25 µs más altas y pocas son incluso 50 µs más de lo normal. Entonces, ¿por qué es así? ¿Quizás esta es la precisión del sensor? Aún no.

Picos de 25 µs.

La frecuencia del sonido en el sensor es de 40 kHz y el sensor registra la onda de sonido al regresar. La onda de sonido se emite durante 200 µs y esto significa que contiene 8 picos de onda. A veces, el primer pico que regresa no es lo suficientemente fuerte como para activar el sensor.

Onda sonora de retorno, primer pico no registrado. Gráficos realizados con osciloscopio.

¿Cómo arreglar esto?

No es tan fácil como con las interrupciones y no tengo un código exacto para solucionarlo. Solo una idea de cómo debería funcionar esa corrección.La primera idea es tomar una media de un gran número de mediciones pero esto significa que siempre tendremos resultados más altos que los reales.La segunda opción es dividir los resultados en dos grupos y calcular la media de la inferior. Entonces, primero calcule la media de todas las mediciones y luego tome el promedio de los resultados que estaban debajo de ella.

La precisión real de HCSR04.

Ola mal medida.
Ola mal medida.
Ola mal medida.
Ola mal medida.
Onda correctamente medida.
Onda correctamente medida.

El HCSR04 espera a que vuelva la ola y verifica una vez cada 3 µs si ese es el caso. El problema es que esto significa que nuestro tiempo medido es más alto que el real en hasta 3 µs. Y no hará nada al respecto sin cambiar el sensor. Pero aún así, 3 µs significa una precisión de 1,02 mm.