Arduino sonar radar con HC-SR04 e Processing
Costruiamo un sonar a scansione con sensore ultrasonico HC-SR04 montato su servomotore e visualizziamo angolo, distanza e ostacoli sul PC con Processing.
angolo,distanza.. Processing riceve questi dati e disegna una visualizzazione in stile radar.Come funziona il progetto
Il sensore HC-SR04 è montato sul servomotore. Il servo esegue una scansione da 15° a 165° e poi torna indietro, permettendo al sensore di controllare progressivamente l’area davanti al circuito.
Per ogni posizione Arduino misura la distanza dell’ostacolo e associa il valore all’angolo corrente. I due dati vengono poi inviati al computer tramite la porta seriale.
Montaggio del sonar radar con HC-SR04 e servomotore.
Materiale necessario
🧰 Kit Arduino consigliato
Un kit completo è utile per avere a disposizione breadboard, cavetti, sensori e altri componenti utilizzati nei progetti Arduino.
👉 Guarda il kit Arduino consigliatoLink di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.
📘 Vuoi imparare Arduino passo dopo passo?
Se vuoi approfondire e realizzare progetti più completi, puoi dare un’occhiata anche ai miei libri dedicati ad Arduino.
👉 Scopri i miei libri su ArduinoLink di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.
Schema del circuito
Schema di collegamento del sensore HC-SR04 e del servomotore.
Collegamenti principali
| Componente | Pin Arduino |
|---|---|
| HC-SR04 TRIG | D10 |
| HC-SR04 ECHO | D11 |
| Segnale servomotore | D12 |
Codice Arduino
Il programma sposta il servo grado per grado, calcola la distanza e invia i dati alla porta seriale.
#include <Servo.h>
const int trigPin = 10;
const int echoPin = 11;
long duration;
int distance;
Servo myServo;
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600);
myServo.attach(12);
}
void loop() {
for (int i = 15; i <= 165; i++) {
myServo.write(i);
delay(30);
distance = calculateDistance();
Serial.print(i);
Serial.print(",");
Serial.print(distance);
Serial.print(".");
}
for (int i = 165; i > 15; i--) {
myServo.write(i);
delay(30);
distance = calculateDistance();
Serial.print(i);
Serial.print(",");
Serial.print(distance);
Serial.print(".");
}
}
int calculateDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration * 0.034 / 2;
return distance;
}
Come viene calcolata la distanza
Il pin TRIG genera un impulso di 10 microsecondi. Il sensore invia un’onda ultrasonica e misura il tempo necessario perché l’eco ritorni.
distance = duration * 0.034 / 2;
Formato dei dati seriali
Arduino trasmette angolo e distanza separati da una virgola e termina ogni coppia con un punto:
45,23.
46,22.
47,22.
Processing
Processing legge i dati seriali inviati da Arduino e li utilizza per disegnare archi, scala delle distanze, linea di scansione e posizione degli ostacoli.
new Serial(this,"COM8",9600). Sostituisci COM8 con la porta effettivamente utilizzata da Arduino sul tuo computer.Codice Processing
/* Arduino Radar Project
*
* Updated version. Fits any screen resolution!
* Just change the values in the size() function,
* with your screen resolution.
*
* by Dejan Nedelkovski,
* www.HowToMechatronics.com
*
*/
import processing.serial.*; // imports library for serial communication
import java.awt.event.KeyEvent; // imports library for reading the data from the serial port
import java.io.IOException;
Serial myPort; // defines Object Serial
// defubes variables
String angle="";
String distance="";
String data="";
String noObject;
float pixsDistance;
int iAngle, iDistance;
int index1=0;
int index2=0;
PFont orcFont;
void setup() {
size (1920, 1080); // ***CHANGE THIS TO YOUR SCREEN RESOLUTION***
smooth();
myPort = new Serial(this,"COM8", 9600); // starts the serial communication
myPort.bufferUntil('.'); // reads the data from the serial port up to the character '.'. So actually it reads this: angle,distance.
orcFont = loadFont("OCRAExtended-30.vlw");
}
void draw() {
fill(98,245,31);
textFont(orcFont);
// simulating motion blur and slow fade of the moving line
noStroke();
fill(0,4);
rect(0, 0, width, height-height*0.065);
fill(98,245,31); // green color
// calls the functions for drawing the radar
drawRadar();
drawLine();
drawObject();
drawText();
}
void serialEvent (Serial myPort) { // starts reading data from the Serial Port
// reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
data = myPort.readStringUntil('.');
data = data.substring(0,data.length()-1);
index1 = data.indexOf(","); // find the character ',' and puts it into the variable "index1"
angle= data.substring(0, index1); // read the data from position "0" to position of the variable index1 or thats the value of the angle the Arduino Board sent into the Serial Port
distance= data.substring(index1+1, data.length()); // read the data from position "index1" to the end of the data pr thats the value of the distance
// converts the String variables into Integer
iAngle = int(angle);
iDistance = int(distance);
}
void drawRadar() {
pushMatrix();
translate(width/2,height-height*0.074); // moves the starting coordinats to new location
noFill();
strokeWeight(2);
stroke(98,245,31);
// draws the arc lines
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);
// draws the angle lines
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); // moves the starting coordinats to new location
strokeWeight(9);
stroke(255,10,10); // red color
pixsDistance = iDistance*((height-height*0.1666)*0.025); // covers the distance from the sensor from cm to pixels
// limiting the range to 40 cms
if(iDistance<40){
// draws the object according to the angle and the distance
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(9);
stroke(30,250,60);
translate(width/2,height-height*0.074); // moves the starting coordinats to new location
line(0,0,(height-height*0.12)*cos(radians(iAngle)),-(height-height*0.12)*sin(radians(iAngle))); // draws the line according to the angle
popMatrix();
}
void drawText() { // draws the texts on the screen
pushMatrix();
if(iDistance>40) {
noObject = "Out of Range";
}
else {
noObject = "In Range";
}
fill(0,0,0);
noStroke();
rect(0, height-height*0.0648, width, height);
fill(98,245,31);
textSize(25);
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);
textSize(40);
text("Object: " + noObject, width-width*0.875, height-height*0.0277);
text("Angle: " + iAngle +" °", width-width*0.48, height-height*0.0277);
text("Distance: ", width-width*0.26, height-height*0.0277);
if(iDistance<40) {
text(" " + iDistance +" cm", width-width*0.225, height-height*0.0277);
}
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();
}
Risoluzione della finestra
Lo sketch Processing utilizza una finestra impostata a 1920×1080:
size(1920, 1080);
Se il monitor utilizza una risoluzione differente, modifica i valori della funzione size().
Errore del font OCRAExtended-30.vlw
Il programma utilizza il font OCRAExtended-30.vlw. Se Processing segnala che il font non può essere caricato, crea il font tramite Processing e assicurati che il file sia disponibile nella cartella data dello sketch.
orcFont = loadFont("OCRAExtended-30.vlw");
Risultato sul PC
Visualizzazione radar generata da Processing.
Scarica i file
⬇️ Scarica lo sketch Processing
Debug rapido
- controlla TRIG su D10 ed ECHO su D11;
- controlla il servo sul pin D12;
- verifica che la comunicazione seriale sia a 9600 baud;
- imposta la porta COM corretta in Processing;
- controlla il font OCRAExtended-30.vlw se la grafica non parte;
- verifica che il servo riesca a muoversi correttamente tra 15° e 165°.
Varianti del progetto
- modificare il limite grafico di 40 cm;
- ridurre l’ampiezza della scansione;
- aggiungere un buzzer per gli ostacoli vicini;
- registrare angolo e distanza su file;
- realizzare una grafica Processing personalizzata;
- sostituire il PC con un display TFT.
Cosa devi ricordare
- Il servo esegue la scansione angolare.
- L’HC-SR04 misura la distanza.
- Arduino invia
angolo,distanza.tramite seriale. - Processing trasforma i dati in una grafica radar.
- Porta COM e baud rate devono essere configurati correttamente.
Domande frequenti
Perché Processing non riceve dati?
Verifica la porta COM e assicurati che Arduino e Processing utilizzino entrambi 9600 baud.
Perché vengono visualizzati solo oggetti entro 40 cm?
Lo sketch Processing limita la rappresentazione degli oggetti con la condizione iDistance < 40.
Posso cambiare la risoluzione?
Sì. Modifica i valori della funzione size() nel programma Processing.
Perché compare l’errore relativo a OCRAExtended-30.vlw?
Il font richiesto non è disponibile nella cartella dati dello sketch Processing. Crealo da Processing e salvalo nel progetto.

