RADAR POR ULTRASONIDOS
INTEGRANTES
- Javier García Borrego
- Alex Gisbet Lizaga
- Ana Hernando Jiménez
INTRODUCCIÓN
En esta pequeña entrada se resume toda la información necesaria para comprender como hemos realizado nuestro proyecto que, como el título indica, se trata de un radar por ultrasonidos capaz de detectar objetos. Su objetivo, aparte de detectar objetos cercanos, es también determinar a qué distancia se encuentran.
Su funcionamiento es bastante simple, el radar únicamente envía un pulso de sonido de alta frecuencia, despreciable para nosotros, el cual rebota en cualquier objeto cercano volviendo al radar, que se encargará de estimar la distancia del objeto observando el tiempo entre pulsos y conociendo la velocidad del sonido.
LISTA DE MATERIALES
Material | Utilidad | Coste | Enlace de compra |
---|---|---|---|
Sensor ultrasónico | Medir la distancia entre el sensor y los objetos | 4,49€ | https://www.amazon.es/dp /B07TKVPPHF |
Placa de Arduino uno | Donde se realizan partes de las conexiones esenciales para el funcionamiento correcto. | 0€ | Caja universidad Rey Juan Carlos |
Servo | Otorga un movimiento de rotación del sensor para poder visualizar más espacio. | 0€ | Caja universidad Rey Juan Carlos |
Protoboard | Ayuda a pequeñas conexiones entre la placa de Arduino, el servo y el sensor. | 0€ | Otorgada por Javier García Borrego |
Pequeña protoboard | Se utiliza como soporte entre el servo y el sensor, para que el sensor pueda apoyarse y rotar, es decir, funciona como una pequeña tabla. | 0€ | Caja universidad Rey Juan Carlos |
Conjunto de cables | Como todo cable, se utiliza para unir los diferentes enlaces, en este caso, entre el Arduino, la placa protoboard, el servo y el sensor. | 0€ | Caja universidad Rey Juan Carlos |
Dos gomas | Se utilizan para sujetar el sensor a la pequeña protoboard y así otorgar una estabilidad decente. | 0€ | Caja universidad Rey Juan Carlos |
IMPLEMENTACIÓN DEL HARDWARE
En cuanto al aspecto de la implementación del hardware, hemos usado como elemento principal un sensor ultrasonidos que se encarga de captar la posición del objeto. Para poder abarcar un radio mayor al que tiene predeterminado el sensor (15 grados aproximadamente), hemos añadido un servomotor ubicado debajo de la protoboard. Este servomotor se encarga de girar en un ángulo comprendido entre 15 y 165 grados (vuelve a su estado inicial para completar el recorrido) sumando así 180 grados en los que el sensor capta los objetos. Además, la distancia a la que detecta los objetos sin errores está en 40 cm, a partir de este límite el sensor comienza a fallar.
En cuanto a la conexión de los pines de cada sistema, el servomotor está formado por tres cables, los cuales (según nuestro modelo) el negro/marrón indica tierra, el naranja debe de estar conectado a la fuente de alimentación, que en este caso son los 5 voltios que proporciona el Arduino y, por último, el amarillo el cuál es conectado al pin del Arduino para su correcto funcionamiento y programación (pin 12). Por parte del sensor ultrasonidos, está compuesto por cuatro pines. Tal y como viene en la parte posterior, el pin de la izquierda indica la puesta a tierra, el del otro extremo es al que se le tiene que conectar a la fuente de alimentación, que siguen siendo los 5 voltios que proporciona el Arduino. Los dos pines de en medio, son los que desempeñan las funciones de mandar un pulso de ultrasonidos (trigger) y el que se encarga de recoger esos datos (echo). El pin trigger va conectado al pin 10 mientras que el echo va al pin 11. Como ya se ha dicho anteriormente el servomotor está situado debajo de la protoboard a la que está conectada el sensor. Mientras que en la otra protoboard está conectado el Arduino, haciendo puente con el Arduino y el sensor.
CÓDIGO
Como nuestro proyecto no genera nada físicamente, si no que la funcionalidad se tiene que mostrar por pantalla, hemos tenido que implementar dos códigos.
El primero es el del Arduino en sí, es decir, lo primero que se ejecuta para poner en funcionamiento todo el proyecto y donde está toda la funcionalidad de este (el sensor, el sesgo, etc.).
El segundo código consiste, en su mayoría, en el dibujo que se imprime por pantalla, para que los valores obtenidos tengan sentido y sean visualmente aceptables. Se visualiza una simulación de un radar con los diferentes grados y distancias, véase imagen 1. A su vez, muestra una línea que va “barriendo” de un extremo a otro, en representación del sensor, para detectar objetos cercanos. Estos objetos se destacan por un color rojo al aparecer en el rango límite estimado de 40 cm como se muestra en la imagen 2.
A continuación, se muestran los códigos implementados:
//CÓDIGO DEL ARDUINO #include <Servo.h> //Definición de variables. trigPin y echoPin hacen referencia a la entrada y salida del sensor. const int trigPin = 10; const int echoPin = 11; long duracion; int distanciacalculada; Servo Servo1; //Definimos la función de los pines e iniciamos la comunicación por serial y el servo. void setup() { pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); Serial.begin(9600); Servo1.attach(12); } //Función donde se ejecuta todo el arduino void loop() { // Función para rotar el servo de 15 a 165 grados for(int i=15;i<=165;i++){ Servo1.write(i); delay(30); // Función que calcula la distancia para cada grado distanciacalculada = calcularladistancia(); Serial.print(i); Serial.print(","); Serial.print(distanciacalculada); Serial.print("."); //(Angulo,distancia.) para comunicación con processing. } //fin del for for(int i=165;i>15;i--){ // Devolver el servo de 165 a 15 grados Servo1.write(i); delay(30); distanciacalculada = calcularladistancia(); Serial.print(i); Serial.print(","); Serial.print(distanciacalculada); Serial.print("."); } //fin del for } //fin de loop //Función independiente para calcular la distancia y que se utiliza en la parte loop(). int calcularladistancia() { //Enviamos una señar alta entre dos bajas para medir el tiempo que tarda la señal en volver y así calcular la distancia. //Pulso en low 2 microseg digitalWrite(trigPin, LOW); delayMicroseconds(2); // Pulso en high 10 microseg digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duracion = pulseIn(echoPin, HIGH); //Medir tiempo entre pulsos distanciacalculada= duracion*0.034/2; //Distancia(cm) = Tiempo * Duracion /2 return distanciacalculada; }
//CÓDIGO DE LA PANTALLA import processing.serial.*; // Librería para comunicación import java.awt.event.KeyEvent; // Para leer la información de la comunicación import java.io.IOException; Serial Puerto; //Variables globales String angulo=""; String distancia=""; String datos=""; String EstadoObjeto; float DistanciaPix; int iAngulo, iDistancia; int Index=0; PFont Arial; void setup() { size (1360, 768); // cambiar para resolución optima (width, height) smooth(); //no crear dientes de sierra en las líneas Puerto = new Serial(this,"COM3", 9600); //comunicación serial con el puerto(para recibir los datos de Arduino IDE) Puerto.bufferUntil('.'); //Se lee hasta el punto (Angulo,distancia.) Arial = createFont("Arial",20); // Fuente a usar } void draw() { fill(98,245,31); //establece un color, en este caso verde, para las llamadas posteriores. textFont(Arial); // simular blur y desvanecimiento de la linea noStroke(); fill(0,4); //color de fondo rect(0, 0, width, height-height*0.065); fill(98,245,31); // verde //Dibujamos todos los elementos que forman nuestro radar visual. DibujarRadar(); Linea(); LineaObjeto(); DibujarTexto(); } //fin draw //Función para la comunicación processing void serialEvent (Serial Puerto) { //Se lee hasta el punto y se mete en un string datos = Puerto.readStringUntil('.'); datos = datos.substring(0,datos.length()-1); //(angulo,distancia.) //Se lee hasta la coma y se mete su valor en index1. Index = datos.indexOf(","); angulo= datos.substring(0, Index); // Se lee de 0 hasta la posición de index1 (ángulo). distancia= datos.substring(Index+1, datos.length()); // Se lee de index+1 hasta el final del string(distancia). // Convertir a entero. iAngulo = int(angulo); iDistancia = int(distancia); }//fin serialEvent //Función para dibujar los arcos y las líneas que forman el radar. void DibujarRadar() { pushMatrix(); // Mover de coordenadas 0,0 a sus coordenadas correspondientes. translate(width/2,height-height*0.074); noFill(); strokeWeight(2); stroke(98,245,31); // dibujar los arcos del radar arc(0,0,(width-width*0.0625),(width-width*0.0625),PI,TWO_PI); arc(0,0,(width-width*0.27),(width-width*0.27),PI,TWO_PI); arc(0,0,(width-width*0.479),(width-width*0.479),PI,TWO_PI); arc(0,0,(width-width*0.687),(width-width*0.687),PI,TWO_PI); // dibujar las líneas que cortan los arcos line(-width/2,0,width/2,0); line(0,0,(-width/2)*cos(radians(30)),(-width/2)*sin(radians(30))); line(0,0,(-width/2)*cos(radians(60)),(-width/2)*sin(radians(60))); line(0,0,(-width/2)*cos(radians(90)),(-width/2)*sin(radians(90))); line(0,0,(-width/2)*cos(radians(120)),(-width/2)*sin(radians(120))); line(0,0,(-width/2)*cos(radians(150)),(-width/2)*sin(radians(150))); line((-width/2)*cos(radians(30)),0,width/2,0); popMatrix(); }//fin DibujarRadar //Función que dibuja al objeto detectado void LineaObjeto() { pushMatrix(); translate(width/2,height-height*0.074); strokeWeight(9); stroke(255,10,10); // red color // Conversor de cm a pixeles DistanciaPix = iDistancia*((height-height*0.1666)*0.025); // Limitar rango a 40 cm (maximo del radar) if(iDistancia<40){ // Se dibuja el objeto dependiendo de su ángulo y distancia line(DistanciaPix*cos(radians(iAngulo)),DistanciaPix*sin(radians(iAngulo)), (width-width*0.505)*cos(radians(iAngulo)), -(width-width*0.505)*sin(radians(iAngulo))); } popMatrix(); } //fin LineaObjeto //Función que dibuja la línea representando al sensor void Linea() { pushMatrix(); strokeWeight(9); stroke(30,250,60); //otro tono de verde. translate(width/2,height-height*0.074); line(0,0,(height-height*0.12)*cos(radians(iAngulo)),-(height-height*0.12)*sin(radians(iAngulo))); // Dibuja la línea según el ángulo. popMatrix(); } //fin Linea //Función que dibuja todo el texto que aparece. void DibujarTexto() { pushMatrix(); //Si detecta un objeto a menos de 40 cm, cambia de enunciado. if(iDistancia>40) { EstadoObjeto = "Fuera de rango"; } else { EstadoObjeto = "En rango"; } fill(0,0,0); //Negro noStroke(); rect(0, height-height*0.0648, width, height); fill(98,245,31); textSize(25); //Distancia que representan los arcos text("10cm",width-width*0.3854,height-height*0.0833); text("20cm",width-width*0.281,height-height*0.0833); text("30cm",width-width*0.177,height-height*0.0833); text("40cm",width-width*0.0729,height-height*0.0833); //Atributos destacables cuando se detecta un objeto textSize(40); text("Objeto: " + EstadoObjeto, width-width*1, height-height*0.0277); text("Angulo: " + iAngulo +" °", width-width*0.55, height-height*0.0277); text("Distancia: ", width-width*0.23, height-height*0.0277); if(iDistancia<40) { text(" " + iDistancia +" cm", width-width*0.16, height-height*0.0277); } //Los grados que representan las líneas que cortan los arcos textSize(25); fill(98,245,60); translate((width-width*0.4994)+width/2*cos(radians(30)),(height-height*0.0907)-width/2*sin(radians(30))); rotate(-radians(-60)); text("30°",0,0); resetMatrix(); translate((width-width*0.503)+width/2*cos(radians(60)),(height-height*0.0888)-width/2*sin(radians(60))); rotate(-radians(-30)); text("60°",0,0); resetMatrix(); translate((width-width*0.507)+width/2*cos(radians(90)),(height-height*0.0833)-width/2*sin(radians(90))); rotate(radians(0)); text("90°",0,0); resetMatrix(); translate(width-width*0.513+width/2*cos(radians(120)),(height-height*0.07129)-width/2*sin(radians(120))); rotate(radians(-30)); text("120°",0,0); resetMatrix(); translate((width-width*0.5104)+width/2*cos(radians(150)),(height-height*0.0574)-width/2*sin(radians(150))); rotate(radians(-60)); text("150°",0,0); popMatrix(); } //fin DibujarTexto
Hay que destacar la importancia de la herramienta Processing en este proyecto, ya que nos ha servido para poder utilizar los paquetes de java referentes al diseño y así poder diseñar una interfaz básica pero funcional.
Dicha herramienta se puede descargar en el siguiente enlace: https://processing.org/download/
CASOS DE USO
En nuestro caso, al ser un radar que detecta objetos, hemos determinado dos casos de uso diferentes. Estos son:
- Detección de objetos. En este caso se determina si el sensor detecta un objeto, debido a que es un sensor sin mucha potencia, la máxima distancia a la que detecta un objeto correctamente, es aproximadamente 40 cm. Además, al ampliar el rango mediante un servomotor, hemos implementado que te diga qué grados está captando. Al detectar un objeto, en la pantalla, las varillas verdes que indican los grados o la posición del sensor cambian a rojo y un indicador en la parte inferior de la pantalla, nos indica a que distancia se encuentra el objeto del sensor. También nos determina si el objeto es de gran tamaño o no, ya que un objeto de gran tamaño ocupa más varillas que uno de menor tamaño. Por último, en la esquina inferior izquierda nos indica si el objeto está a rango. Véase imagen 2.
- No detección del objeto. En este caso el sensor no detecta ningún objeto en su rango, ya sea por su lejanía o porque no está ubicado en un rango de 180 grados. Al no detectar ningún objeto, el servomotor sigue girando y se siguen mostrando los grados, pero no la distancia y las varillas que determinan si hay o no un objeto, serán verdes completamente y en la esquina inferior izquierda saldrá que el objeto no está a rango. Véase imagen 1.
PROBLEMAS Y SOLUCIONES ENCONTRADAS
Uno de los mayores problemas que hemos tenido ha sido la de no poder hacer este proyecto en un ambiente de trabajo como un laboratorio cómo se hace en otros años debido a la situación a la que nos estamos enfrentando todos. Esto ha hecho que tengamos que trabajar de forma online con los integrantes del grupo para poder desarrollar correctamente el proyecto. Debido a que cada integrante del grupo debe hacer un video explicando el funcionamiento, el hardware y el código, teníamos que disponer del material del trabajo y debido a que ha habido confinamientos por zonas y una reducción de movilidad, decidimos adquirir material adicional para así no tener problemas en cuanto a ese aspecto. Por ejemplo, en el video del funcionamiento, se añaden materiales para su correcto funcionamiento, tal y como se explica correctamente en el vídeo.
En cuanto a problemas que han aparecido durante el desarrollo del proyecto, uno de los más destacados ha sido el implementar el código de la representación del radar en la pantalla. Debido a que ha consistido en picar mucho código, jugando con las alturas, las distancias (que ha sido otro de los problemas a los que nos hemos enfrentado), etc. Solucionando esto mediante ensayo y error y mucho tiempo.
Debido a que había que dibujar sobre la pantalla el radar, hemos usado processing, permitiéndonos usar java para facilitar el desarrollo del código y de esta forma poder pintar por pantalla la salida correcta.
Para concluir, el tema del movimiento del servomotor. Este problema radica en determinar cómo debe de girar el servomotor para que no vaya ni muy rápido ni muy lento y que, gracias a este movimiento, el sensor sea capaz de capturar correctamente el objeto que se encuentra en su ángulo de medición. Determinamos que el delay del servomotor debía de ser 30 ms y debería de girar en un radio entre 15 y 165 grados, para que así el sensor pueda captar 180 grados.
VIDEO EXPLICATIVO