G019 Arduino y el sensor de ultrasonidos HC-SR04

Descripción                                                                                
Ecolocalización consiste en emitir unos sonidos muy agudos y después recoger los ecos de rebote, para localizar un objeto u obstáculo.  Sabiendo la velocidad a la que viaja el sonido, si emitimos un pulso corto, y medimos el tiempo que tardamos en escucha el eco, podemos calcular la distancia a la que se encuentra el objeto en el que ha rebotado la señal.


El radar funciona de forma similar pero con ondas de radiofrecuencias muy cortas y con una problemática propia descomunal. Un pulso de radiofrecuencia se emite desde una antena y se recoge el eco que vuelve a la velocidad de la luz.

El oído humano no oye por encima de los 20KHz, por eso a las ondas de mayor frecuencia se les llama ULTRASONIDOS, Los sensores de ultrasonido funcionan sobre los 40KHz.

Vamos a utilizar un sensor de ultrasonido HC-SR04 que nos permite enviar pulso ultrasónicos y escuchar el eco de retorno, y midiendo el tiempo que tarda el eco, podemos calcular la distancia a la que está el obstáculo.  Estos sensores no son perfectos, les influye la temperatura, la humedad y los materiales en los que se reflejan, pero son baratos y funcionan bastante bien con un alcance efectivo de unos 3 metros en condiciones normales, si la precisión no es un problema importante.

Materiales
Placa de Arduino
1 Resistencia 330
1 LED de 5mm
1 HC-SR04 emisor-detector de ultrasonidos
Protoboard, cables de conexión, cable USB para conectar arduino al PC y que sirve además de cable de alimentación.

Esquema
Vamos a conectar uno HC-SR04 a ardunino.  El detector tiene 4 patillas dos de alimentación, una tercera que es el trigger, disparador o emisor, y la patilla echo que es por donde llega la señal de que se ha recibido el eco.  Vamos a instalar un LED con su resistencia, para que podamos visualizar cuando se está detectando un objeto.





















Montaje


Código
Con este primer código vamos a utilizar el módulo de ultrasonido como detector de movimiento, con un alcance determinado que activará una alarma, en nuestro caso encenderá un LED.
#define trigPin 13
#define echoPin 12
#define led 2

void setup(){
  Serial.begin(115200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(led, OUTPUT);
}

void loop(){
  long duracion, distancia;
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duracion = pulseIn(echoPin, HIGH);
  distancia = duracion /2/29,1 ;
  Serial.println(String(distancia)+"cm.");
  int Limite = 50;
  if(distancia < Limite){
    digitalWrite(led, HIGH);
  }else{
    digitalWrite(led, LOW);
    delay(100);
  }
}
Para empezar vamos a definir el pin 13 como pin emisor, el pin 12 como pin receptor del eco, y el pin 2 como pin de salida al LED. En lugar de declara variables y asignarles los pines como valor, hemos utilizado la directiva #define, viene a ser lo mismo, pero no ocupa memoria.

En el void setup, lo primero es establecer el contacto por el puerto serie con Serial.begin, a una velocidad de 9600.  Luego vamos a establecer los pines del disparador y del LED, trigPin y led como salida y el pin receptor del eco echoPin, como entrada con la instrucción pinMode.

A continuación declaramos dos variable locales tipo long llamadas duración y distancia.

Estableceremos  el trigPin en LOW y esperaremos 2 microsegundos para asegurarnos. Luego escribiremos en el disparador o trigPin un HIGH durante 10 microsegundos, que será la señal que vamos a lanzar  y pasará a LOW, para poder escuchar su eco de retorno.

Hasta ahora habíamos visto la instrucción delay(milisegundos) pero cuando se necesita un periodo de tiempo inferior, tenemos la instrucción  delayMicroseconds(microsegundos).  Para escuchar el eco de retorno, hemos utilizado la variable duracion, y le hemos asignado la función pulseIn, cuyos parámetros de entrada es la variable echoPin, pin 12 de entrada, y le hemos dicho que notifique solo cuando reciba un HIGH en la entrada, y calcula el tiempo en microsegundos que tarda la señal en ir y volver.

La variable distancia, nos calcula la distancia del objeto contra el que ha rebotado la señal. Para ello conociendo la velocidad el sonido 343 m/s nos da 1/343 = 0,00291 microsegundo es lo que tarda el sonido en recorre un metro.  Para utilizar una medida más cómoda podemos pasa a microsegundo/ centímetro y nos queda 29,1 microsegundo /centímetro.

Como el eco mide el tiempo que tarda en ir y volver la señal, la distancia será la mitad.

distancia = (duracion/29,1) * (1/2) pero con esto no funciona, pon tal y como viene en el código.

y esta es la operación asignada a la variable distancia.

Serial.println, se encarga de imprimir la distancia en centímetros en el monitor del puerto serie cada medio segundo.

La variable tipo entero  Límite tiene asignada un valor de 200 cm que es la distancia dentro de la cual cualquier objeto será detectado, a una distancia superior el objeto no será detectado, o mejor dicho, no se encenderá el led.


El if dice que si la distancia es inferior al Límite escribirá un HIGH en el pin led y si es superior escribirá un LOW, luego esperará medio segundo y vuelta a empezar.

Si en el  monitor serie aparecen valores negativos, eso significa que el sensor está fuera de rango.  Bien porque no le llega la señal de rebote, porque el objeto está demasiado lejos o porque el objeto está demasiado cerca.vamos a hacer el mismo programa pero usando una librería externa, que alguien se ha molestado en escribir, paras esas pocas personas que no disfrutan de los problemas de ciencias y que así, podamos ver la diferencia.

Aquí dejo otra variante del código que es interesante 
int trig = 13;
int eco = 12;
int led = 2;
int duracion;
int distancia;

void setup(){
  pinMode(trig, OUTPUT);
  pinMode(eco, OUTPUT);
  pinMode(led, OUTPUT);
  Serial.begin(115200);
}

void loop(){
  digitalWrite(trig, HIGH);
  delay(1);
  digitalWrite(trig, LOW);
  duracion = pulseIn(eco, HIGH);
  distancia= duracion/58.2;
  Serial.println(distancia + "cm");
  delay(200);
}

En este código se declara las variables, las tres primeras son para indicar que los respectivos pines son pines de salida que se activan como tal en la función setup(), las otras dos variables son para guardar los respectivos valores, para hacer cálculos más tarde.

Se activa la comunicación serie de arduino con el PC usando la función Serial.begin.

Luego en la función loop() se activa el disparador con Trig en alto, se espera un milisegundo y luego se desactiva el disparado,  el tiempo que tarda en recibise la señal de vuelta se guarda en la variable duración.  Para conocer la distancia dividimos la duración entre 58.2, este valor no es arbitrario, sino que lo da el fabricante en las especificaciones. El resultado es en centímetros. Que lo vamos a mostrar en pantalla a través de monitor serie, con Serial. Println y luego esperamos 0,2 segundo para que nos de tiempo de leer los valores.

int trig = 13;
int eco = 12;
int led = 2;
int duración;
int distancia;

void setup(){
  pinMode(trig, OUTPUT);
  pinMode(eco, OUTPUT);
  pinMode(led, OUTPUT);
  Serial.begin(115200);
}

void loop(){
  digitalWrite(trig, HIGH);
  delay(1);
  digitalWrite(trig, LOW);
  duracion = pulseIn(eco, HIGH);
  distancia= duracion/58.2;
  Serial.println(distancia+” cm”);
  Delay(200);
  If (distancia <= 20 && distancia >= 0){
  digitalWrite(Led, HIGH);
  delay(distancia*10);
  digitalWrite(led, LOW);
  }
}
Con estas dos nuevas líneas el led se encenderá y apagará cada vez más rápido si el objeto se acerca al sensor o más lento si se aleja.  Si en lugar del led y la resistencia, ponemos un zumbador, entonces se oirá un pitido intermitente

#include<NewPing.h>
#define TRIGGER_PIN 13
#define ECHO_PIN 12
#define MAX_DISTANCE 200

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE );

void setup(){
  Serial.begin(115200);
  }

void loop(){
  delay(500);
  unsigned int uS=sonar.ping();
  Serial.print("Ping: ");
  Serial.print(uS/ US_ROUNDTRIP_CM);
  Serial.println(" cm.");
}

Para empezar hay que descargar e instalar la librería NewPing. Una vez instalada, hay que llamarla en el código para utilizarla.


Como veréis la librería se encarga de inicializar los pines necesarios, enviar los pulsos, escuchar el eco de retorno  y de hacer los cálculos. No está mal

Veamos el código, incluimos la librería NewPing, definimos los tres pines. Creamos un objeto tipo NewPing, al que llamamos sonar y le asignamos el pin disparador, el pin receptor del eco y la distancia máxima.

En el setup, establecemos la comunicación serie, fíjate que las comunicaciones son más rápidas a 115200, con lo que lo tendrás que cambiar en el monitor del puerto serie.

En el loop se empieza con una pausa de medio segundo y a continuación declaramos una variable local tipo entero sin signo, llamada uS a la que asignamos el objeto sonar.ping()

A continuación se imprime en el monitor del puerto serie "Ping : " con el siguiente Serial.print, se imprimirá el resultado de dividir el valor de la variable uS entre una función conversora, de tiempo en distancia y el resultado serán centímetros, que será la distancia donde esta el objeto contra el que rebotó el pulso de ultrasonido y con el siguiente 
Serial.println se imprime "cm" y se hará su salto de línea.  Todo el proceso se repetirá cada medio segundo.