Sunteți pe pagina 1din 8

SENSOR DE DISTANCIA HC-SR04 CON ARDUINO

Una de las funciones ms tiles en las aplicaciones de robtica es la


medicin de distancias. Esto puede ser utilizado para evadir
obstculos o para generar una "imagen" del entorno en el que nuestro
robot se est desplazando. En esta entrada explicaremos como utilizar
el sensor HC-SR04 que nos permite estimar distancias a travs de un
eco ultrasonido.

CMO FUNCIONA EL SENSOR?


El eco es ese sonido que parece repetir lo que decimos cuando
hablamos o producimos sonidos en ciertos lugares. Este fenmemo se
origina cuando las ondas de sonido rebotan en una superfcie y
regresan a nosotros generando ese particular sonido de repeticin.
Debido a que el sonido viaja en el aire a una velocidad ms o menos
constante*, es posible estimar la distancia recorrida por un objeto
gracias a una sencilla frmula de fsica:

Donde
es la diferencia en la posicin y
es el tiempo que tard en realizarse
este desplazamiento. Como en este caso no nos interesa la direccin que toman las
ondas sonoras y estamos asumiendo una trayectoria casi recta frente al sensor,
podemos utilizar la siguiente frmula:

Siendo v la velocidad del sonido, d la distancia recorrida por la onda sonora y t el


tiempo transcurrido, haciendo uso de un poco de lgebra:

Para simplificar las cosas, vamos a asumir una velocidad del sonido constante en el
aire de 340 m/s. La distancia la obtendremos entonces, multiplicando dicha
velocidad por el tiempo en que tardemos en recibir el eco.
Sin embargo, la distancia hacia el objeto no es la calculada sino que se hace
necesario dividir este total entre dos, ya que el tiempo medido es el tiempo de ida y
vuelta de la seal ultrasnica hacia el sensor. As que nuestra frmula final es la
siguiente:

El sensor
Una de las ventajas de este sensor es que incluye toda la circuitera necesaria para
la generacin del pulso ultrasnico y su correspondiente recepcin, as que no
tendremos que complicarnos en todos estos detalles tcnicos.
En nuestro sensor vamos a encontrar 4 pines que conectaremos de la siguiente
manera:

1.

VCC

2.

Trig

3.

Echo

4.

GND

El mdulo inicia a trabajar al recibir un pulso positivo en la lnea trg de al menos


10us. Luego de que el mdulo recibe el pulso, este enva una seal ultrasnica y el
mdulo cambia el estado de la lnea "echo" de 0 a 1 y la lnea permanece en 1 hasta
que se recibe el eco o en su defecto hasta que ha pasado el tiempo mximo de
medicin.
Esto ltimo resulta muchsimo ms fcil de visualizarse en el siguiente diagrama:

Como referencia, el rango mximo de este sensor va desde los 3cm hasta
aproximadamente 3.5m. El rango depende esencialmente del material que est
reflejando la seal ultrasnica.
MIDIENDO LA DISTANCIA CON ARDUINO
omencemos conectando el mdulo a nuestro Arduino Mega 2560 de la siguiente manera:

Antes de continuar, debemos recordar que los tiempos de eco para una distancia de
entre 3cm y 3.5m son muy cortos, en el rango de los micro-segundos. Si utilizamos

el loop principal de Arduino para consultar el estado de la lnea puede que


perdamos muchos "ciclos" y no podamos medir tiempo.
La forma ms adecuada de manejar este tipo de situaciones es mediante el uso de
interrupciones, estas responden a "eventos". Para este caso en particular nos
interesa responder al cambio de nivel en el voltaje de la lnea.
El algoritmo que utilizaremos ser el siguiente:

1.

Enviamos un pulso de 10 microsegundos a la lnea "Trg" del mdulo.

2.
Cuando la lnea cambie de 0->1 guardaremos el contador de tiempo transcurrido
de nuestro Arduino.
3.
Cuando la lnea cambie de 1->0 compararemos el tiempo actual contra el que
guardamos en el contador para determinar cuanto tiempo ha transcurrido.
A programar!
Primero definimos algunas constantes y variables a utilizar:

#define SOUND_SPD 320 // Velocidad del sonido


volatile long t_elapsed; // Almacena el tiempo de recorrido
volatile double lastDist; // Almacena la ltima distancia
calculada

Luego inicializamos el puerto serie (para reportar las distancias medidas), configuramos el
pin 21 (interrupcin 2) como entrada y el pin 2 como salida.
Asociamos la interrupcin 2 (lnea 21) a la funcin onChange para que se llame cada vez
que exista un cambio en el valor lgico de la lnea.

void setup() {
Serial.begin(9600);
pinMode(21,INPUT);
pinMode(2,OUTPUT);
attachInterrupt(2,onChange,CHANGE);
digitalWrite(2,LOW);
}

Para iniciar el proceso de medicin, enviamos un pequeo pulso de 10us, para realizar
esto simplemente ponemos la lnea en alto, esperamos 10 microsegundos y volvemos la
lnea a 0, colocamos este cdigo en una funcin aparte para poder llamarlo fcilmente
desde el loop principal

void startMeasure() {
t_start = 0;
lastDist = 0;
Serial.write("Starting measure...\r\n");
digitalWrite(2,HIGH);
delayMicroseconds(10);
digitalWrite(2,LOW);
}

La funcin que realiza el manejo de interrupcin debe de realizar dos tareas, la primera es
guardar el punto en el tiempo actual, y luego a la siguiente llamada cuando el valor de la
lnea cae de 1 a 0 deber calcular la diferencia de tiempo para estimar la distancia.
Es muy importante que el cdigo de manejo de interrupcin sea extremadamente
rpido. El contador de tiempo de arduino ser detenido mientras nos encontremos en el
cdigo de manejo de interrupcin, as que perderemos algunos micro-segundos en lo que
se ejecuta nuestro cdigo que no sern registrados por el contador.

void onChange() {
if(t_start==0) {
t_start = micros();
} else {
lastDist = (((micros()-t_start)/1000000.0)*SOUND_SPD)/2;
Serial.write("Distance: ");
Serial.print(lastDist);
Serial.write("m\r\n");
}
}

A diferencia de la frmula original dividimos entre 1,000,000 para obtener el tiempo en


segundos y poder multiplicarlo por la velocidad del sonido.
Al revisar el cdigo podemos notar como la instruccin que toma registro del tiempo es la
primera luego del if esto es para disminuir el efecto del tiempo perdido por el manejo de la
interrupcin.
Si el contador de tiempo es cero, entonces simplemente guardamos el contador de tiempo
actual en la variable t_start.
Al ser diferente de cero, primero almacenamos el contador del tiempo en una variable
local. Y luego calculamos la diferencia entre los tiempos. En esta parte del cdigo ya no
resulta tan crtico que el cdigo sea considerablemente rpido ya que ha terminado el
perodo de medicin, tanto as que nos podemos tomar la libertad de imprimir en el puerto
serial.
Nota: Recuerden que mientras se ejecute el cdigo de interrupcin se pausar el loop
principal, si su loop principal est realizando una tarea muy importante pueden reducir el
cdigo como se muestra a continuacin:

void onChange() {
if(t_start==0) {
t_start = micros();
} else {
lastDist = (((micros()-t_start)/1000000.0)*SOUND_SPD)/2;
}
}

Y luego desde el cdigo del loop principal podemos leer el valor almacenado en lastDist
con la ltima distancia calculada.
Por ltimo el loop principal simplemente iniciar el proceso de lectura cada segundo y lo
reportar al puerto serial al momento de haber sido calculado:

void loop() {
startMeasure();

delay(1000); // Repetir medicin cada segundo


}
Si te da pereza copiar el cdigo lo puedes descargar desde la siguiente direccin:
http://dev.teubi.co/downloads/sensor_distancia.ino
Si todo ha funcionado bien, debern tener una salida en el puerto serie similar a la
siguiente:

Starting measure...
Distance: 0.01800000m
Starting measure...
Distance: 0.0600000m

Conclusiones
El sensor ultrasnico de distancia es una sencilla solucin para aplicaciones en que sea
requerido estimar distancias o esquivar obstculos. El mdulo HC-SR04 facilita
considerablemente la implementacin de este tipo de funcionalidad ya que nos permite
centrarnos en la parte de medicin de tiempos en vez de los detalles tcnicos de la
generacin de la seal y el procesamiento del eco recibido.

Y no habiendo nada ms que decir por ahora... Hasta


la prxima!

+Fuentes y Recursos
Obtn tu HC-SR04 en la Tienda TeUbi.co

Hoja tcnica del HC-SR04

Manejo de interrupciones con Arduino

*La velocidad del sonido en aire depende de la densidad del mismo. El sonido

viaja ms rpido a nivel del mar que en mayores altitudes. Sin embargo, para
aplicaciones que no requieren de gran precisin, esta diferencia es despreciable.

#define SOUND_SPD 320


volatile long t_star;
volatile double lastDist;
void setup() {
Serial.begin(9600);
pinMode(21,INPUT);
pinMode(2,OUTPUT);
attachInterrupt(2,onChange,CHANGE);
digitalWrite(2,LOW);
}
void onChange() {
if(t_start==0) {
t_start = micros();
} else {
lastDist = (((micros()-t_start)/1000000.0)*SOUND_SPD)/2;
Serial.write("Distance: ");
Serial.print(lastDist);
Serial.write("m\r\n");
}
}
void startMeasure() {
t_start = 0;
Serial.write("Starting measure...\r\n");
digitalWrite(2,HIGH);
delayMicroseconds(10);
digitalWrite(2,LOW);
}
void loop() {
startMeasure();
delay(1000);
}

S-ar putea să vă placă și