Radar con Arduino y Processing
Introducción
En este artículo vamos a tratar de realizar un radar, utilizando Arduino para obtener las señales correspondientes, y Processing para procesarlas.
Si queréis modificar las proporciones del radar graficado con Processing a vuestro gusto necesitaréis tener conocimientos básicos de trigonometría, por lo que intentaré ser claro y conciso a la hora de explicar el código.
Materiales
Para la realización de nuestro radar vamos a necesitar los siguientes materiales:
- x1 Arduino UNO (Aunque serviría otra versión también)
- x1 ServoMotor
- x1 Sensor Ultrasónico HC-SR04
(Ni que decir tiene que necesitaremos el cable USB y una protoboard para realizar las conexiones)
Esquema
Como alimentación de nuestro Arduino UNO en mi caso utilizaré el cable USB conectado directamente al PC, pero también podéis alimentarlo conectándolo a alguna batería portátil o por su puerto DC Jack.
#include <Servo.h>
#include <NewPing.h>
// Trigger pin del sensor ultrasónico conectado a Arduino
#define TRIGGER_PIN 8
// Echo pin del sensor ultrasonico conectado a Arduino
#define ECHO_PIN 9
// Distancia maxima que queremos detectar (en cm). El maximo del sensor ronda entre 400-500cm.
#define MAX_DISTANCE 200
// Inicialización del sensor ultrasónico
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
Servo radar;
void setup() {
Serial.begin(9600); // Inicializamos el puerto Serial
radar.attach(2); // Indicamos que usaremos el pin 2 para mover el servo (radar)
radar.write(0); // Lo colocamos en la posicion de 0 grados
delay(2000); // Esperamos 2 segundos
}
// Bucle for que mueve el servo desde los 0 grados hasta los 180
for (int i = 0; i <= 180; i++) {
radar.write(i); // Movemos el servo
int ms = sonar.ping_median(2); // Obtenemos la media de microsegundos de 2 pulsos
int distancia = sonar.convert_cm(ms); // Convertimos la media de microsegundos en distancia en cm
delay(10);
// Enviamos los datos con formato 'Angulo,Distancia.'
Serial.print(i);
Serial.print(",");
Serial.print(distancia);
Serial.println(".");
}
// Bucle for que mueve el servo desde los 180 grados hasta los 0
for (int i = 179; i >= 0; i--) {
radar.write(i); // Movemos el servo
int ms = sonar.ping_median(2); // Obtenemos la media de microsegundos de 2 pulsos
int distancia = sonar.convert_cm(ms); // Convertimos la media de microsegundos en distancia en cm
delay(10);
// Enviamos los datos con formato 'Angulo,Distancia.'
Serial.print(i);
Serial.print(",");
Serial.print(distancia);
Serial.println(".");
}
radar_arduino.ino
#include <Servo.h>
#include <NewPing.h>
// Trigger pin del sensor ultrasónico conectado a Arduino
#define TRIGGER_PIN 8
// Echo pin del sensor ultrasonico conectado a Arduino
#define ECHO_PIN 9
// Distancia maxima que queremos detectar (en cm). El maximo del sensor ronda entre 400-500cm.
#define MAX_DISTANCE 200
// Inicialización del sensor ultrasónico
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
Servo radar;
void setup() {
Serial.begin(9600); // Inicializamos el puerto Serial
radar.attach(2); // Indicamos que usaremos el pin 2 para mover el servo (radar)
radar.write(0); // Lo colocamos en la posicion de 0 grados
delay(2000); // Esperamos 2 segundos
}
void loop() {
for (int i = 0; i <= 180; i++) {
radar.write(i); // Movemos el servo
int ms = sonar.ping_median(2); // Obtenemos la media de microsegundos de 2 pulsos
int distancia = sonar.convert_cm(ms); // Convertimos la media de microsegundos en distancia en cm
delay(10);
// Enviamos los datos con formato 'Angulo,Distancia.'
Serial.print(i);
Serial.print(",");
Serial.print(distancia);
Serial.println(".");
}
delay(50);
for (int i = 179; i >= 0; i--) {
radar.write(i); // Movemos el servo
int ms = sonar.ping_median(2); // Obtenemos la media de microsegundos de 2 pulsos
int distancia = sonar.convert_cm(ms); // Convertimos la media de microsegundos en distancia en cm
delay(10);
// Enviamos los datos con formato 'Angulo,Distancia.'
Serial.print(i);
Serial.print(",");
Serial.print(distancia);
Serial.println(".");
}
delay(50);
}
Processing
En este apartado no me detendré a explicar trozo a trozo la funcionalidad del código, ya que es bastante largo y algunas partes son algo complejas. Sin embargo, me he encargado de comentar con el mayor nivel de detalle posible el código, para que la comprensión del mismo resulte más sencillo y a la vez no tenga que extenderme mucho. Éste sería el resultado del código para el radar en Processing:
radar_processing.pde
import processing.serial.*;
Serial myPort;
String angle=""; // Variable que almacenara el angulo en el que se encuentra el servo en String
String distance=""; // Variable usada para almacenar la distancia en cm del objeto al sensor en String
String data=""; // Variable que almacena el mensaje enviado desde el Arduino a traves del Serial
String noObject; // Texto que mostrara si el/los objeto/s detectado/s estan en rango o no
float pixsDistance; // Variable que almacenara la distancia convertida de cm a px
int iAngle, iDistance; // Variables que almacenaran las variables 'angle' y 'distance' convertidas de String a int
int index1; // Variable que almacenara el index del splitter (separador) del mensaje enviado desde Arduino (',')
int rc = 10; // Codigo ASCII del retorno de carro, sera usado para guardar el mensaje de Arduino hasta el salto de linea
void setup() {
// Aqui se especifican las dimensiones de la ventana
size(1920, 1080);
//println(Serial.list()); // Lista todos los puertos series
myPort = new Serial(this, Serial.list()[1], 9600); // Establece un puerto serie
myPort.bufferUntil(rc); // Almacena en el bufer hasta llegar un retorno de carro
}
void draw() {
// Simula desenfoque de movimiento (motion blur) y decoloracion lenta (slow fade) de la linea de movimiento verde
noStroke();
fill(0, 2.5);
rect(0, 0, width, height-height*0.05);
drawRadar(); // Dibuja las lineas del radar
drawLine(); // Dibuja las lineas verdes del radar
drawObject(); // Dibuja las lineas rojas del radar en base a si se ha detectado un objeto y su distancia de nosotros
drawText(); // Dibuja el texto del radar
println(iAngle + " " + iDistance); // Imprime por consola el angulo y distancia del objeto con formato 'Angulo Distancia'
}
// Obtenemos los valores del puerto Serial
void serialEvent (Serial myPort) {
data = myPort.readStringUntil(rc); // Leemos el mensaje enviado desde Arduino con formato 'Angulo,Distancia.'
data = data.substring(0,data.length()-1); // Eliminamos el '.' del mensaje
index1 = data.indexOf(','); // Almacenamos la posicion del splitter (',')
angle= data.substring(0, index1); // Almacenamos los caracteres desde la posicion 0 hasta el splitter (sin incluir)
distance= data.substring(index1+1, data.length()); // Almacenamos los caracteres desde la posicion del splitter+1 hasta el final
// Convertimos los Strings obtenidos en Integers
iAngle = int(angle);
iDistance = int(distance);
}
void drawRadar() {
pushMatrix();
translate(width/2,height-height*0.074); // Movemos la matriz al punto desde el que se dibujaran las lineas y arcos del radar
noFill();
strokeWeight(0.1);
stroke(98,245,31); // Color verde
// Dibujamos 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);
// Dibujamos las lineas de los angulos
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();
}
void drawObject() {
pushMatrix();
translate(width/2, height-height*0.074); // Movemos la matriz al punto desde el que se dibujaran las lineas rojas del radar del objeto detectado (si se ha detectado)
strokeWeight(12.5);
stroke(255, 10, 10); // Color rojo
pixsDistance = iDistance*((height-height*0.1666)*0.025); // Convertimos la distancia del sensor de cm a px
// Limitamos el rango de deteccion del sensor a 40cm
if (iDistance<=40) {
// Dibujamos el objeto en base al angulo y la distancia
line(pixsDistance*cos(radians(iAngle)), -pixsDistance*sin(radians(iAngle)), (width-width*0.505)*cos(radians(iAngle)), -(width-width*0.505)*sin(radians(iAngle)));
}
popMatrix();
}
void drawLine() {
pushMatrix();
strokeWeight(11);
stroke(88, 255, 109); // Color verde
translate(width/2, height-height*0.074); // Movemos la matriz al punto desde el que se dibujaran las lineas verdes del radar
line(0, 0, (height-height*0.12)*cos(radians(iAngle)), -(height-height*0.12)*sin(radians(iAngle))); // Dibujamos la linea verde en base al angulo
popMatrix();
}
void drawText() {
pushMatrix();
if (iDistance>40) {
// Si la distancia excede de 40cm cambiamos el valor del String noObject a 'Fuera de Rango'
noObject = "Fuera de Rango";
}
else {
// Sino significa que el objeto esta en rango por lo que el String contendra 'En Rango'
noObject = "En Rango";
}
fill(0);
noStroke();
rect(0, height-height*0.072, width, height);
fill(98, 245, 31);
/********************* Dibujamos todo el texto que aparece en la ventana *********************/
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);
// Tamaño del texto para el pie de programa (objeto, angulo, distancia)
textSize(15);
text("Objeto: " + noObject, width-width*0.975, height-height*0.0277);
text("Ángulo: " + iAngle +"°", width-width*0.525, height-height*0.0277);
text("Distancia: ", width-width*0.1, height-height*0.0277);
if (iDistance<200) {
text(iDistance +" cm", width-width*0.04, height-height*0.0277);
}
// Tamaño del texto para los numeros del radar
//textSize(15);
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();
}
Recursos
Tenéis disponibles los recursos del post en el siguiente enlace, ¡espero que os haya gustado!
NOTA: Si usáis el radar en una habitación algo pequeña y/o con muchos objetos es posible que el radar dé falsos positivos.
Esto se debe a que los ultrasonidos rebotan de más en la habitación y en los objetos, provocando que colisionen ondas entre sí y, por ende, ocasionando malas lecturas.
Frontend Engineer en Reveni.
Autodidacta, apasionado de las nuevas tecnologías y de los proyectos DIY.




que tal amigo. quiero enpezar un proyecto muy bueno avanzado.. radar para detectar amenaza a kilometro. masa corporal anti enemigo. con mal intencion. indentificando ´por ponsentaja de 100 muy alto de 20 a 15 cero a menasa. puedo hacerlo ya que tengo demaciadas idea. como puedo descargar los programa. para tenerlo en mi computadora. espero algun comentasrio bueno
¡Hola, Mario!
Al final del post tienes una sección llamada Recursos donde hay un enlace que te lleva a todos los archivos del proyecto.
Muchas suerte con tu proyecto, espero que te sirva de ayuda.
Saludos!
Hola me gusto el procedimiento de como hiciste para desarrollar este tipo de radar y tengo una pregunta, es posible implementar un Shield Lcd Tft 3.5» Touch Arduino Uno Mega2560 480×320 para proyectar las ondas al proyecto? porque yo quería hacerlo de una forma que se pueda llevar en todo momento en la mano pero la verdad es que no tengo idea de como hacerlo.
Hola Iván, gracias por tu proyecto que me parece muy interesante.
Soy alumno de FP y estoy muy interesado en hacer un proyecto semejante al que tú propones, pero no lo entiendo todo bien porque no tengo muchos conocimientos aún.
Todo lo que explicas en la primera parte está fenomenal, pero con el procesing no se qué hacer, si pegarlo a continuación o qué.
¿No puedes enviarme el código completo? o al menos explicarme mejor como acabarlo, porque me he quedado atrancado.
Muchas gracias anticipadas.
Un saludo, Jorge