Radar con Arduino: HC-SR04, servo SG90 e schermo in Processing
Radar con Arduino passo passo: collegamento di HC-SR04 e servo SG90, codice per angolo e distanza, schermo radar verde in Processing, mini radar OLED ed errori.
Un radar con Arduino è un progetto che monta un sensore a ultrasuoni HC-SR04 su un servomotore SG90 e lo fa ruotare tra 0 e 180 gradi per misurare sia la direzione sia la distanza degli oggetti vicini, mostrando il risultato sul computer come uno schermo radar verde, proprio come nei film. A ogni angolo Arduino esegue una misura e invia sulla porta seriale una riga nel formato "angolo,distanza"; un piccolo programma Processing in esecuzione sul computer legge questi numeri e disegna la linea di scansione che ruota e gli oggetti rilevati come linee rosse.
In questa guida trovi ogni passaggio spiegato, dall'elenco dei componenti e dallo schema di collegamento fino al codice Arduino e allo schermo radar in Processing. Vediamo anche un mini radar su display OLED che non ha bisogno del computer, le versioni per ESP32 e Raspberry Pi Pico, come regolare la velocità di scansione e la precisione delle misure e come risolvere gli errori più comuni della porta seriale. È economico, si finisce in un pomeriggio ed è uno dei progetti Arduino che attirano più attenzione nelle presentazioni a scuola.




Come funziona un radar con Arduino?
Il cuore del sistema è l'HC-SR04. Uno dei due cilindri del sensore (T) emette un breve impulso sonoro a 40 kHz che l'orecchio umano non sente; quando il suono colpisce un oggetto e torna indietro, l'altro (R) capta l'eco. Arduino misura questo tempo di andata e ritorno in microsecondi. Il suono viaggia nell'aria a circa 343 m/s, quindi impiega circa 29 microsecondi per percorrere un centimetro; dato che il percorso viene fatto due volte, andata e ritorno, la formula diventa distanza (cm) = tempo (µs) / 58. Il servo ruota il sensore passo dopo passo e a ogni passo la misura viene ripetuta. Alla fine sai "a quale angolo e a quanti centimetri c'è qualcosa", cioè una coordinata polare. Per disegnarla sullo schermo, angolo e distanza vengono convertiti in una posizione in pixel con x = distanza × cos(angolo) e y = distanza × sin(angolo).
| Componente | Funzione | Valori chiave |
|---|---|---|
| HC-SR04 | Misura della distanza a ultrasuoni | 40 kHz, 2–400 cm, angolo di misura di circa 15°, 5 V, 15 mA |
| Servo SG90 | Ruota il sensore da 0 a 180° | 0,1 s/60° (4,8 V), coppia 1,8 kg·cm, 4,8–6 V, 9 g |
| Arduino Uno | Misura, muove il servo e invia i dati | 16 MHz, livello logico 5 V, porta seriale USB |
| Processing | Disegna lo schermo radar sul computer | Gratuito, basato su Java, libreria Serial inclusa |
| OLED SSD1306 (opzionale) | Mini schermo radar senza computer | 128×64 pixel, I2C, indirizzo 0x3C |
Componenti per il radar con Arduino
- Arduino Uno o Nano e un cavo USB che trasmetta dati (i cavi di sola ricarica non compaiono come porta sul computer).
- Sensore di distanza a ultrasuoni HC-SR04.
- Micro servo SG90 e le squadrette di plastica incluse nella confezione.
- Una breadboard e 8–10 cavetti jumper maschio-maschio e maschio-femmina.
- Un condensatore elettrolitico da 470 µF (almeno 10 V): evita che la tensione crolli quando il servo si muove.
- Nastro biadesivo, colla a caldo o un piccolo supporto stampato in 3D per fissare il sensore al servo.
- Opzionale: un display OLED I2C da 0,96 pollici (per la versione senza computer) e un alimentatore esterno da 5 V 2 A.
Schema di collegamento del radar con Arduino
| Collegamento | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| HC-SR04 VCC | 5V | VIN (5 V) | VBUS (pin 40) |
| HC-SR04 GND | GND | GND | GND |
| HC-SR04 Trig | D10 | GPIO 26 | GP14 |
| HC-SR04 Echo | D11 | GPIO 27 (con partitore) | GP13 (con partitore) |
| SG90 marrone (GND) | GND | GND | GND |
| SG90 rosso (+5 V) | 5V | VIN (5 V) | VBUS (pin 40) |
| SG90 arancione (segnale) | D9 | GPIO 13 | GP15 |
Sull'Uno il cablaggio è più ordinato se colleghi i fili 5 V e GND del sensore e del servo alle linee positiva e negativa della breadboard, e queste linee ai pin 5V e GND di Arduino. Inserisci il condensatore da 470 µF sulle stesse linee, con la gamba lunga (+) sui 5 V e la gamba corta, indicata dalla striscia sul corpo, su GND. Su alcuni servo i fili sono nero, rosso e bianco: in questo caso il nero è GND e il bianco il segnale. Per verificare dove si trovano i pin sulla tua scheda, usa lo strumento pinout.
Montare il sensore sul servo

Prima di montare la squadretta, porta il servo a 90 gradi: basta caricare un breve sketch di prova con radarServo.write(90) e lasciare il servo in quella posizione. Poi monta la squadretta in modo che il sensore guardi dritto davanti a sé. Così 0° punta a destra, 90° in avanti e 180° a sinistra, e le direzioni sullo schermo di Processing corrispondono esattamente al mondo reale. Quando incolli l'HC-SR04 alla squadretta con biadesivo o colla a caldo, assicurati che i due cilindri restino paralleli al pavimento; se il sensore è inclinato verso il basso, scambierà il piano del tavolo per un oggetto. Lascia ai cavi abbastanza gioco perché non si tendano durante la rotazione di 180 gradi e fissa il servo a una base pesante o a una scatola; una struttura che traballa a ogni passo rovina le misure.
Costruire il radar con Arduino passo passo
- Collega i componenti secondo la tabella qui sopra, non dimenticare il condensatore e monta il sensore sul servo.
- Apri l'IDE di Arduino; la libreria Servo è già inclusa, non devi installare altro.
- Carica il codice del radar qui sotto. Se hai problemi con la scelta della scheda o della porta, leggi Arduino non carica lo sketch.
- Apri il Monitor seriale a 9600 baud; se scorrono righe di angolo e distanza come "30,45", la parte Arduino è pronta. Poi chiudi assolutamente il Monitor seriale.
- Installa Processing 4 sul computer, apri un nuovo sketch e incolla il codice dello schermo radar.
- Premi Run; nella console in basso compare l'elenco delle porte e si apre la finestra del radar. Muovendo la mano davanti al sensore dovrebbero comparire delle linee rosse.
Codice del radar con Arduino
1#include <Servo.h>
2
3const byte SERVO_PIN = 9; // SG90 turuncu kablo / SG90 orange wire
4const byte TRIG_PIN = 10; // HC-SR04 Trig
5const byte ECHO_PIN = 11; // HC-SR04 Echo
6const int MIN_ANGLE = 0; // tarama başlangıcı / sweep start
7const int MAX_ANGLE = 180; // tarama sonu / sweep end
8const int STEP = 2; // adım başına derece / degrees per step
9const int STEP_DELAY = 40; // ölçümden önce bekleme (ms) / wait before measuring (ms)
10
11Servo radarServo;
12int angle = MIN_ANGLE;
13int dir = STEP;
14
15int measureCm() {
16 digitalWrite(TRIG_PIN, LOW);
17 delayMicroseconds(2);
18 digitalWrite(TRIG_PIN, HIGH); // 10 µs tetik darbesi / 10 µs trigger pulse
19 delayMicroseconds(10);
20 digitalWrite(TRIG_PIN, LOW);
21 unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL); // en çok 30 ms bekle / wait at most 30 ms
22 if (us == 0) return 0; // yankı yok = menzil dışı / no echo = out of range
23 return us / 58; // gidiş-dönüş süresi → cm / round-trip time → cm
24}
25
26void setup() {
27 Serial.begin(9600);
28 pinMode(TRIG_PIN, OUTPUT);
29 pinMode(ECHO_PIN, INPUT);
30 radarServo.attach(SERVO_PIN);
31 radarServo.write(angle);
32 delay(500); // başlangıç konumuna gitsin / reach the start position
33}
34
35void loop() {
36 radarServo.write(angle); // servoyu yeni açıya döndür / move the servo to the new angle
37 delay(STEP_DELAY); // titreşim geçsin / let the vibration settle
38 int distance = measureCm();
39
40 Serial.print(angle); // biçim: açı,mesafe / format: angle,distance
41 Serial.print(',');
42 Serial.println(distance);
43
44 if (angle + dir > MAX_ANGLE || angle + dir < MIN_ANGLE) dir = -dir; // uçta yön değiştir / reverse at the ends
45 angle += dir;
46}Spiegazione del codice
| Parte del codice | Cosa fa? |
|---|---|
| STEP e STEP_DELAY | Stabiliscono di quanti gradi ruota il servo a ogni passo e quanto si aspetta prima di misurare; con queste due costanti regoli la velocità di scansione. |
| measureCm() | Invia un impulso di 10 µs al pin Trig, misura con pulseIn per quanto tempo il pin Echo resta HIGH e divide per 58 per ottenere i centimetri. |
| pulseIn(..., 30000UL) | Aspetta al massimo 30 ms e restituisce 0 se non arriva nessuna eco. Senza questo timeout, puntando nel vuoto la funzione potrebbe bloccarsi fino a 1 secondo. |
| radarServo.write(angle) | Porta il servo all'angolo richiesto; la libreria converte il valore 0–180 in un impulso di 544–2400 µs. |
| Serial.print ... println | Invia ogni misura come un'unica riga "angolo,distanza"; il fine riga segnala a Processing che il dato è completo. |
| dir = -dir | Inverte la direzione quando l'angolo arriva a 180 o a 0, così il servo scansiona avanti e indietro senza sosta. |
C'è un motivo se i dati sono così semplici: una sola riga separata da una virgola si legge comodamente nel Monitor seriale e si divide con una riga di codice in Processing, Python o Excel. Una distanza pari a 0 significa "nulla entro la portata a questo angolo" e Processing non disegna questi valori. Se apri gli stessi dati nel Plotter seriale dell'IDE di Arduino, vedrai l'angolo salire e scendere a dente di sega e la distanza fare un salto ogni volta che il sensore passa davanti a un oggetto. Per questo progetto delay va benissimo; se vuoi leggere un pulsante o accendere un LED mentre il radar lavora, riscrivi il ciclo con millis().
Lo schermo radar verde con Processing
Processing è un software gratuito basato su Java pensato per la programmazione visuale, e la sua interfaccia somiglia molto all'IDE di Arduino: scrivi il codice e premi Run. La libreria Serial, necessaria per la comunicazione seriale, è inclusa in Processing; puoi aggiungerla dal menu Sketch > Import Library o affidarti semplicemente alla riga import all'inizio del codice. Il codice seguente va incollato in Processing, non nell'IDE di Arduino.
1// Processing 4 çizimi: Arduino IDE'ye değil, Processing'e yapıştır / Processing 4 sketch: paste into Processing, not the Arduino IDE
2import processing.serial.*; // Serial kütüphanesi / Serial library
3
4Serial port;
5int angle = 0; // son açı / last angle
6int distance = 0; // son mesafe (cm) / last distance (cm)
7final int MAX_CM = 100; // ekrandaki en uzak mesafe / farthest distance on screen
8float R; // radar yarıçapı (piksel) / radar radius (pixels)
9
10void setup() {
11 size(1200, 700);
12 R = width * 0.45;
13 printArray(Serial.list()); // portları konsola yaz / print the ports to the console
14 String portName = Serial.list()[0]; // gerekirse [1] ya da "COM4" yaz / use [1] or "COM4" if needed
15 port = new Serial(this, portName, 9600); // Arduino ile aynı baud / same baud as the Arduino
16 port.bufferUntil('\n'); // satır sonunu bekle / wait for the end of a line
17 background(0);
18}
19
20void draw() {
21 noStroke();
22 fill(0, 12); // yarı saydam siyah: solan iz / translucent black: fading trail
23 rect(0, 0, width, height);
24 translate(width / 2, height - 60); // radar merkezi alt ortada / radar centre at the bottom middle
25 drawGrid();
26 drawSweep();
27 drawObject();
28 drawLabels();
29}
30
31void drawGrid() {
32 noFill();
33 strokeWeight(2);
34 stroke(98, 245, 31);
35 for (int i = 1; i <= 4; i++) {
36 float d = 2 * R * i / 4;
37 arc(0, 0, d, d, PI, TWO_PI); // 25-50-75-100 cm yayları / 25-50-75-100 cm arcs
38 }
39 for (int a = 0; a <= 180; a += 30) {
40 line(0, 0, R * cos(radians(a)), -R * sin(radians(a))); // 30 derecelik çizgiler / 30-degree lines
41 }
42}
43
44void drawSweep() {
45 strokeWeight(5);
46 stroke(30, 250, 60);
47 line(0, 0, R * cos(radians(angle)), -R * sin(radians(angle))); // tarama çizgisi / sweep line
48}
49
50void drawObject() {
51 if (distance <= 0 || distance > MAX_CM) return; // menzil dışı / out of range
52 float p = R * distance / MAX_CM; // cm → piksel / cm → pixels
53 float c = cos(radians(angle));
54 float s = sin(radians(angle));
55 strokeWeight(7);
56 stroke(255, 10, 10);
57 line(p * c, -p * s, R * c, -R * s); // nesneden dışa kırmızı çizgi / red line from the object outwards
58}
59
60void drawLabels() {
61 resetMatrix();
62 noStroke();
63 fill(0);
64 rect(0, height - 40, width, 40); // yazı şeridi / text strip
65 fill(98, 245, 31);
66 textSize(20);
67 for (int i = 1; i <= 4; i++) {
68 text(MAX_CM * i / 4 + " cm", width / 2 + R * i / 4 + 4, height - 66); // yay etiketleri / arc labels
69 }
70 String d = (distance > 0 && distance <= MAX_CM) ? distance + " cm" : "-";
71 text("Açı / Angle: " + angle + "°", 40, height - 12);
72 text("Mesafe / Distance: " + d, width / 2, height - 12);
73}
74
75void serialEvent(Serial p) {
76 String msg = p.readStringUntil('\n'); // "açı,mesafe" satırı / "angle,distance" line
77 if (msg == null) return;
78 String[] parts = split(trim(msg), ',');
79 if (parts.length == 2) {
80 angle = int(parts[0]);
81 distance = int(parts[1]);
82 }
83}La parte più importante del codice è la funzione serialEvent(). Grazie a bufferUntil('\n'), Processing accumula i dati in arrivo finché non arriva un fine riga e poi chiama automaticamente questa funzione con una riga completa. La riga viene ripulita dagli spazi e dal carattere \r con trim(), divisa in due alla virgola con split() e convertita in numeri con int(). draw(), invece, viene eseguita circa 60 volte al secondo: prima dipinge sullo schermo un rettangolo nero semitrasparente (fill(0, 12)), poi ridisegna la griglia, la linea di scansione e l'oggetto. Dato che le linee vecchie si scuriscono un po' a ogni fotogramma, l'effetto scia che svanisce, tipico dei radar veri, nasce da solo.
| Impostazione | Dove? | A cosa serve? |
|---|---|---|
| MAX_CM = 100 | Processing | La distanza massima coperta dallo schermo; l'arco esterno vale 100 cm, quelli interni indicano 25, 50 e 75 cm. |
| Serial.list()[0] | Processing | Sceglie la prima porta seriale del computer; se il tuo Arduino è più in basso nell'elenco, cambia l'indice o scrivi direttamente il nome, per esempio "COM4". |
| 9600 | Entrambi | Velocità in baud; il valore di Serial.begin su Arduino e quello in Processing devono coincidere. |
| fill(0, 12) | Processing | Velocità di dissolvenza; 5 dà una scia lunga, 30 un'immagine quasi senza scia. |
| size(1200, 700) | Processing | Dimensione della finestra; riducila se non entra nel tuo schermo. Il raggio dipende dalla larghezza, quindi tieni l'altezza superiore a metà della larghezza. |
Regolare la velocità del servo e la durata della scansione
Secondo il datasheet, l'SG90 ruota di 60 gradi in 0,1 secondi a 4,8 V, quindi completa un passo di 2 gradi in pochi millisecondi. A determinare davvero la durata della scansione non è il servo, ma l'attesa e la misura a ogni passo. Quando il servo si ferma, squadretta e sensore oscillano per un attimo; se misuri in quel momento, le distanze saltano. Inoltre il produttore dell'HC-SR04 consiglia di lasciare circa 60 ms tra due misure, perché gli echi dell'impulso precedente che rimbalzano nella stanza possono finire nella misura successiva. In pratica, un totale di 50–60 ms per passo (attesa + misura) è un buon compromesso. Una scansione completa dura circa (180 / passo + 1) × durata di un passo.
| Passo | STEP_DELAY | Una scansione (0→180°) | Risultato |
|---|---|---|---|
| 1° | 20 ms | circa 7 s | Immagine più fluida ma lenta; lo stesso oggetto viene misurato molte volte. |
| 2° | 40 ms | circa 5 s | Impostazione consigliata: fluida e stabile. |
| 3° | 50 ms | circa 4 s | Più veloce; grazie al fascio di 15° del sensore nessun oggetto sfugge. |
| 5° | 70 ms | circa 3,5 s | Lo schermo appare a scatti; con passi grandi le oscillazioni aumentano e l'attesa deve essere più lunga. |
Per un movimento più morbido, tieni il passo piccolo e l'attesa breve; se vuoi velocità, aumenta il passo e allunga un po' l'attesa. Limitare la scansione alla zona che ti interessa (per esempio 45–135°) dimezza anche il tempo. Se il servo dà strattoni da solo, Arduino ogni tanto si riavvia e Processing perde la connessione, il problema non è la velocità ma l'alimentazione: l'SG90 può assorbire circa 100–250 mA in movimento e fino a 600 mA sotto sforzo. Aggiungi il condensatore e, se serve, alimenta il servo con un alimentatore esterno da 5 V con GND in comune con Arduino.
Migliorare la precisione delle misure
Anche se sulla carta l'HC-SR04 promette una risoluzione di 3 mm, in un radar la precisione dipende da tre fattori: larghezza del fascio, velocità del suono e tipo di superficie. Il fascio sonoro del sensore si allarga come un cono di circa 15 gradi. Per questo una penna sottile a 50 cm non appare sullo schermo come un punto, ma come un arco di 15–20 gradi; la risoluzione angolare del radar la decide questo fascio, non il passo del servo, e la direzione reale dell'oggetto è al centro dell'arco. La velocità del suono cambia con la temperatura e si calcola con v = 331,3 + 0,606 × T (m/s, T in °C). Il numero 58 nel codice corrisponde a circa 22 °C; in un garage freddo le misure risultano più lunghe di qualche punto percentuale.
| Temperatura | Velocità del suono | Andata e ritorno per 1 cm | Oggetto a 100 cm (con /58) |
|---|---|---|---|
| 0 °C | 331,3 m/s | 60,4 µs | circa 104 cm |
| 10 °C | 337,4 m/s | 59,3 µs | circa 102 cm |
| 20 °C | 343,4 m/s | 58,2 µs | circa 100 cm |
| 30 °C | 349,5 m/s | 57,2 µs | circa 99 cm |
| 40 °C | 355,5 m/s | 56,3 µs | circa 97 cm |
Puoi misurare la temperatura ambiente con un DHT11 o un DS18B20 e tenere conto della velocità del suono, e scartare le letture sbagliate isolate prendendo la mediana di tre misure. Ti basta aggiungere le due funzioni qui sotto al codice principale e sostituire la chiamata a measureCm() dentro loop() con una delle due. Dato che il filtro a mediana fa tre misure a ogni passo, rallenta un po' la scansione.
1// Ana radar koduna eklenecek fonksiyonlar / functions to add to the main radar sketch
2
3// Sıcaklığa göre düzeltilmiş ölçüm / temperature-compensated reading
4int measureCmTemp(float tempC) {
5 digitalWrite(TRIG_PIN, LOW);
6 delayMicroseconds(2);
7 digitalWrite(TRIG_PIN, HIGH);
8 delayMicroseconds(10);
9 digitalWrite(TRIG_PIN, LOW);
10 unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL);
11 if (us == 0) return 0; // yankı yok / no echo
12 float v = 331.3 + 0.606 * tempC; // ses hızı (m/s) / speed of sound (m/s)
13 return (int)(us * v / 20000.0 + 0.5); // µs × (m/s) / 20000 = cm
14}
15
16// Üç ölçümün ortancası: tek seferlik sıçramaları atar / median of three: drops one-off spikes
17int medianCm() {
18 int a = measureCm(); delay(20);
19 int b = measureCm(); delay(20);
20 int c = measureCm();
21 return max(min(a, b), min(max(a, b), c));
22}
23
24// loop() içinde kullanım / use inside loop():
25// int distance = medianCm();
26// int distance = measureCmTemp(18.5); // sıcaklık DHT11'den gelebilir / temperature can come from a DHT11- Le superfici morbide (tende, tessuti, spugna) assorbono il suono; un oggetto potrebbe non comparire dove si trova.
- Le superfici inclinate deviano il suono; una scatola piatta ruotata di oltre 45° rispetto al sensore può essere letta come spazio vuoto.
- Gli oggetti a meno di 2 cm non si possono misurare; in pratica considera poco affidabile ogni valore sotto i 3–4 cm.
- Gli angoli della stanza creano riflessioni multiple e possono generare "fantasmi" lontani che non esistono; fai le prove in uno spazio libero e ampio.
- Portata: il datasheet indica 400 cm, ma con oggetti piccoli le misure stabili arrivano di solito a circa 2 metri; scegli MAX_CM di conseguenza.
Mini radar su display OLED (senza computer)
Se vuoi che il radar diventi un dispositivo portatile a batteria che non dipende dal computer, puoi usare un display OLED da 0,96 pollici al posto di Processing. Il punto centrale del bordo inferiore dello schermo 128×64 con driver SSD1306 diventa il centro del radar; ci vengono disegnati un semicerchio con raggio di 60 pixel, la linea di scansione e dei punti che mostrano l'ultimo oggetto misurato a ogni angolo. Per il collegamento del display (SDA → A4, SCL → A5) e l'installazione delle librerie, consulta la guida display OLED SSD1306; HC-SR04 e servo si collegano come sopra.

1#include <Wire.h>
2#include <Adafruit_GFX.h>
3#include <Adafruit_SSD1306.h>
4#include <Servo.h>
5
6const byte SERVO_PIN = 9; // SG90 sinyal / SG90 signal
7const byte TRIG_PIN = 10; // HC-SR04 Trig
8const byte ECHO_PIN = 11; // HC-SR04 Echo
9const int MAX_CM = 50; // ekrandaki en uzak mesafe / farthest distance on screen
10const int STEP = 3; // adım başına derece / degrees per step
11const int CX = 64, CY = 63, R = 60; // radar merkezi ve yarıçapı (piksel) / radar centre and radius (px)
12
13Adafruit_SSD1306 display(128, 64, &Wire, -1);
14Servo radarServo;
15uint8_t dist[180 / STEP + 1]; // her açının son ölçümü (cm) / last reading per angle (cm)
16int angle = 0;
17int dir = STEP;
18
19int measureCm() {
20 digitalWrite(TRIG_PIN, LOW);
21 delayMicroseconds(2);
22 digitalWrite(TRIG_PIN, HIGH);
23 delayMicroseconds(10);
24 digitalWrite(TRIG_PIN, LOW);
25 unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL);
26 if (us == 0) return 0; // yankı yok / no echo
27 return us / 58;
28}
29
30void setup() {
31 pinMode(TRIG_PIN, OUTPUT);
32 pinMode(ECHO_PIN, INPUT);
33 radarServo.attach(SERVO_PIN);
34 if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
35 for (;;); // ekran bulunamadı / display not found
36 }
37 display.setTextColor(SSD1306_WHITE);
38}
39
40void loop() {
41 radarServo.write(angle);
42 delay(20); // çizim de zaman aldığı için kısa / short, drawing takes time too
43 int d = measureCm();
44 dist[angle / STEP] = (d > 255) ? 255 : d; // byte'a sığdır / fit into a byte
45
46 display.clearDisplay();
47 display.drawCircle(CX, CY, R, SSD1306_WHITE); // dış yay, alt yarısı ekran dışında / outer arc, lower half off-screen
48 display.drawCircle(CX, CY, R / 2, SSD1306_WHITE); // orta yay = MAX_CM / 2 / middle arc = MAX_CM / 2
49 for (int i = 0; i <= 180 / STEP; i++) {
50 if (dist[i] > 0 && dist[i] <= MAX_CM) {
51 float rad = radians(i * STEP);
52 int r = map(dist[i], 0, MAX_CM, 0, R); // cm → piksel / cm → pixels
53 display.fillCircle(CX + r * cos(rad), CY - r * sin(rad), 1, SSD1306_WHITE);
54 }
55 }
56 float rad = radians(angle);
57 display.drawLine(CX, CY, CX + R * cos(rad), CY - R * sin(rad), SSD1306_WHITE); // tarama çizgisi / sweep line
58 display.setCursor(0, 0);
59 display.print(angle); // açı / angle
60 display.setCursor(98, 0);
61 display.print(d); // mesafe / distance
62 display.print(F("cm"));
63 display.display();
64
65 if (angle + dir > 180 || angle + dir < 0) dir = -dir; // uçta yön değiştir / reverse at the ends
66 angle += dir;
67}In questa versione le distanze vengono salvate per angolo nell'array dist, così i punti restano sullo schermo anche dopo il passaggio della linea di scansione e vengono aggiornati al giro successivo. Il centro del cerchio si trova sul bordo inferiore del display, quindi la sua metà inferiore esce dallo schermo e la libreria non la disegna: resta un semicerchio pulito. Inviare un fotogramma al display richiede circa 25 ms con I2C a 400 kHz, perciò l'attesa è stata ridotta a 20 ms e il passo portato a 3 gradi; una scansione dura circa 4–5 secondi. Su uno schermo piccolo una scala di 50 cm è più leggibile, quindi MAX_CM vale 50. Metà dei 2 KB di memoria dell'Uno va al buffer del display, per questo è importante tenere l'array in byte (uint8_t).
Radar con ESP32
Sull'ESP32 la libreria Servo di Arduino non funziona; devi installare la libreria ESP32Servo dal Gestore librerie. Il resto del codice è quasi identico. Dato che l'ESP32 lavora a 3,3 V, non dimenticare il partitore di tensione sulla linea Echo dell'HC-SR04; l'impulso a 3,3 V sulla linea Trig, invece, basta a far scattare la maggior parte dei sensori. Questo codice usa 115200 baud, quindi cambia anche il 9600 nel codice Processing in 115200. Grazie al Wi-Fi dell'ESP32, in seguito potrai inviare i dati del radar a una pagina web sul telefono invece che al computer; se l'ESP32 è una novità per te, parti da Cos'è l'ESP32.
1#include <ESP32Servo.h> // Kütüphane Yöneticisi: ESP32Servo / Library Manager: ESP32Servo
2
3const int SERVO_PIN = 13; // SG90 sinyal / SG90 signal
4const int TRIG_PIN = 26; // HC-SR04 Trig
5const int ECHO_PIN = 27; // 1k/2k bölücüden / through the 1k/2k divider
6const int STEP = 2; // adım başına derece / degrees per step
7const int STEP_DELAY = 40; // ölçümden önce bekleme (ms) / wait before measuring (ms)
8
9Servo radarServo;
10int angle = 0;
11int dir = STEP;
12
13int measureCm() {
14 digitalWrite(TRIG_PIN, LOW);
15 delayMicroseconds(2);
16 digitalWrite(TRIG_PIN, HIGH);
17 delayMicroseconds(10);
18 digitalWrite(TRIG_PIN, LOW);
19 unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL);
20 if (us == 0) return 0; // yankı yok / no echo
21 return us / 58;
22}
23
24void setup() {
25 Serial.begin(115200); // Processing'de de 115200 / 115200 in Processing too
26 pinMode(TRIG_PIN, OUTPUT);
27 pinMode(ECHO_PIN, INPUT);
28 radarServo.setPeriodHertz(50); // standart servo 50 Hz / standard servo 50 Hz
29 radarServo.attach(SERVO_PIN, 500, 2400); // SG90 darbe aralığı (µs) / SG90 pulse range (µs)
30 radarServo.write(angle);
31 delay(500);
32}
33
34void loop() {
35 radarServo.write(angle);
36 delay(STEP_DELAY);
37 int distance = measureCm();
38 Serial.printf("%d,%d\n", angle, distance); // açı,mesafe / angle,distance
39 if (angle + dir > 180 || angle + dir < 0) dir = -dir; // uçta yön değiştir / reverse at the ends
40 angle += dir;
41}Radar con Raspberry Pi Pico e MicroPython
Sul Pico non serve una libreria apposita per il servo: basta impostare la larghezza dell'impulso di un segnale PWM a 50 Hz con duty_ns(). Il tempo dell'eco si misura con machine.time_pulse_us(), che in caso di timeout restituisce un numero negativo. Anche i pin del Pico lavorano a 3,3 V, quindi il partitore sulla linea Echo è obbligatorio. Salva il codice sul Pico come main.py con Thonny e poi chiudi Thonny; altrimenti la porta resta occupata e Processing non riesce a collegarsi. Poiché il Pico apre una porta seriale virtuale via USB, il valore dei baud in Processing non conta: lo stesso schermo radar funziona senza modifiche.
1from machine import Pin, PWM, time_pulse_us
2import time
3
4servo = PWM(Pin(15)) # SG90 sinyal / SG90 signal
5servo.freq(50) # standart servo 50 Hz / standard servo 50 Hz
6trig = Pin(14, Pin.OUT)
7echo = Pin(13, Pin.IN) # bölücüden gelir / comes through the divider
8
9def set_angle(a):
10 # 0° = 500 µs, 180° = 2400 µs darbe / pulse
11 servo.duty_ns(500000 + a * 1900000 // 180)
12
13def measure_cm():
14 trig.value(0)
15 time.sleep_us(2)
16 trig.value(1) # 10 µs tetik / 10 µs trigger
17 time.sleep_us(10)
18 trig.value(0)
19 t = time_pulse_us(echo, 1, 30000) # en çok 30 ms bekle / wait at most 30 ms
20 if t < 0:
21 return 0 # yankı yok / no echo
22 return t // 58
23
24angle, step = 0, 2
25set_angle(angle)
26time.sleep_ms(500)
27
28while True:
29 set_angle(angle)
30 time.sleep_ms(40) # servo otursun / let the servo settle
31 print("{},{}".format(angle, measure_cm())) # açı,mesafe / angle,distance
32 if angle + step > 180 or angle + step < 0:
33 step = -step # uçta yön değiştir / reverse at the ends
34 angle += stepErrori comuni e soluzioni
| Sintomo o messaggio di errore | Causa | Soluzione |
|---|---|---|
| Error opening serial port COM3: Port busy | Il Monitor seriale o il Plotter seriale dell'IDE di Arduino, Thonny o una seconda finestra di Processing stanno occupando la porta. | Chiudi il Monitor seriale e gli altri programmi e riavvia lo sketch di Processing; se serve, scollega e ricollega il cavo USB. |
| ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0 | Serial.list() è vuoto: la scheda non è collegata, il cavo è di sola ricarica o manca il driver CH340. | Usa un cavo dati e installa il driver; se l'IDE di Arduino vede la porta, la vedrà anche Processing. |
| La finestra si apre ma la linea di scansione non si muove | È stata scelta la porta sbagliata (su Windows COM1 è spesso la prima dell'elenco) oppure i baud non coincidono. | Trova la posizione di Arduino nell'elenco della console, cambia in Serial.list()[1] o simile e imposta gli stessi baud da entrambe le parti. |
| The package “processing.serial” does not exist. You might be missing a library. | La libreria Serial non viene trovata; il pacchetto di installazione di Processing 4.4.8 ne era privo. | Aggiorna Processing a una versione più recente oppure usa la 4.4.7, e controlla che la riga import sia scritta correttamente. |
| Error opening serial port /dev/ttyACM0: Permission denied | Su Linux il tuo utente non ha il permesso di accedere alla porta seriale. | Aggiungi il tuo utente al gruppo dialout (sudo usermod -a -G dialout $USER), poi esci e rientra nella sessione. |
| Con Processing aperto lo sketch non si carica su Arduino | La porta è occupata da Processing. | Prima di caricare, ferma lo sketch di Processing con il pulsante Stop. |
| La distanza è sempre 0 o dà valori assurdi | Trig ed Echo sono invertiti, il sensore non è alimentato o l'oggetto è fuori portata. | Controlla i collegamenti con la tabella e prova prima con uno sketch semplice che misura solo la distanza. |
| Il servo vibra e Arduino si riavvia da solo | La porta USB non fornisce la corrente richiesta dal servo e la tensione cala. | Aggiungi un condensatore da 470 µF o alimenta il servo con un alimentatore esterno da 5 V con GND in comune. |
| Destra e sinistra invertite sullo schermo radar | Il servo o il sensore sono montati al contrario. | In Processing scrivi angle = 180 - int(parts[0]); oppure togli la squadretta e rimontala girata. |
Idee per sviluppare il progetto radar
- Radar di sicurezza con allarme: quando un oggetto si avvicina a meno di 30 cm, fai suonare un buzzer e accendi un LED rosso; abbinalo alle idee di sistema di allarme con Arduino.
- Robot che evita gli ostacoli: metti il radar sulla parte anteriore di un robot; quando si ferma, scansiona a destra e a sinistra e gira verso la direzione più libera. Dettagli in robot evita ostacoli.
- Mappa della stanza: salva i dati della scansione su un modulo scheda SD e disegnali sul computer come nuvola di punti.
- Radar wireless: invia le misure da un ESP32 via Wi-Fi a una pagina web sul telefono; con un web server ESP32 puoi disegnare in tempo reale.
- Mappa più nitida: usa un sensore laser (ToF) a fascio stretto al posto dell'HC-SR04; trovi le alternative nel confronto tra sensori di distanza.
- Bastone intelligente: costruisci un bastone che avvisa le persone non vedenti della presenza di ostacoli con un sensore di distanza e un motorino a vibrazione: progetto bastone intelligente.
Poiché unisce sensore di distanza, controllo del servo, comunicazione seriale e grafica sul computer in un unico progetto, il radar con Arduino è un ottimo passo successivo per chi inizia. Per consolidare le basi, dai un'occhiata anche alle guide sul sensore di distanza HC-SR04 e sul servomotore. Nell'app BlueGrays trovi, passo passo e con schemi elettrici e codice commentato, i progetti di misura della distanza con l'HC-SR04, sensore di parcheggio, uso del servomotore e robot che evita gli ostacoli.
Domande frequenti
Il radar con Arduino è un vero radar?
Tecnicamente no, è un sonar. I radar veri emettono onde radio, mentre questo progetto usa le onde sonore a 40 kHz dell'HC-SR04. Si chiama "radar con Arduino" perché il principio è lo stesso (emettere un'onda, misurare il tempo dell'eco e disegnarla con la sua direzione) e la schermata somiglia a quella di un radar.
Fino a che distanza rileva un radar con Arduino?
Secondo il datasheet l'HC-SR04 misura da 2 a 400 cm. Superfici grandi e piatte come una parete vengono rilevate fino a 3–4 metri, ma con oggetti come la gamba di una sedia o una persona la portata affidabile è in genere di 1,5–2 metri. Impostare MAX_CM nel codice Processing su questa portata dà l'immagine più chiara.
Quali componenti servono per un radar con Arduino?
Bastano un Arduino Uno o Nano, un sensore a ultrasuoni HC-SR04, un servo SG90, una breadboard, qualche cavetto jumper e un condensatore da 470 µF per il servo. Lo schermo radar lo disegna sul computer il programma gratuito Processing; per la versione senza computer si aggiunge un display OLED da 0,96 pollici.
Si può fare un radar con Arduino senza Processing?
Sì. Con un display OLED SSD1306 puoi disegnare il radar direttamente su Arduino e trasformarlo in un dispositivo portatile a batteria. Anche senza display puoi seguire angolo e distanza come grafico nel Plotter seriale dell'IDE di Arduino.
Come si risolve l'errore "Port busy" in Processing?
Questo errore indica che un altro programma sta usando la porta seriale. Chiudi il Monitor seriale e il Plotter seriale dell'IDE di Arduino, Thonny o qualsiasi altro sketch di Processing rimasto aperto e riprova. Se il problema persiste, scollega il cavo USB e ricollegalo.
Perché il servo vibra e Arduino si riavvia?
L'SG90 assorbe picchi di corrente quando si muove e la linea a 5 V di un Arduino alimentato via USB cala per un istante. Un condensatore da 470 µF sull'alimentazione del servo di solito risolve; altrimenti alimenta il servo con un alimentatore esterno da 5 V con GND in comune con Arduino.
Progetti da realizzare dopo questo articolo
Vedi tutti i progetti
HC-SR04 Misura della distanza (display seriale)
Il sensore HC-SR04 funziona come un pipistrello che trova la strada al buio: manda un suono che non puoi sentire, ne ascolta l'eco e misura quanto è lontano l'oggetto davanti a sé. L'Arduino scrive qu

Utilizzo del servomotore
Il braccio di un piccolo servomotore ruota a turno in tre posizioni: tutto all'inizio, esattamente a metà e tutto alla fine, aspettando due secondi a ogni fermata. L'Arduino dice al motore a quale ang

SG90 Servocomando angolare con potenziometro
Controllo del servomotore (SG90) con il potenziometro L'obiettivo principale di questo progetto è controllare con precisione la posizione angolare di un servomotore in tempo reale utilizzando un'unità di ingresso analogica, il potenziometro. Il progetto è un esempio di ingegneria di base per comprendere la logica della conversione analogico-digitale (ADC) e la mappatura dei segnali. Logica di funzionamento: Lettura dei dati analogici: Quando l'utente ruota il potenziometro, un segnale di tensio

Sensore di parcheggio con HC-SR04
Una versione in miniatura del sensore di parcheggio delle auto: più qualcosa si avvicina, più i bip accelerano. Il sensore di distanza misura l'oggetto davanti a sé; se è a più di 20 centimetri resta

Robot che evita gli ostacoli
Che ne dite di costruire un veicolo intelligente che trova la propria strada? L'Obstacle Avoiding Robot scruta costantemente l'ambiente circostante grazie al sensore a ultrasuoni posto davanti a lui.

ESP32 HC-SR04 Misuratore di distanza a ultrasuoni
Il sensore a ultrasuoni HC-SR04 calcola la distanza misurando il tempo di volo (Time of Flight) dell'onda sonora che emette dopo aver colpito un oggetto e essere rimbalzata indietro. In questo progetto invieremo un impulso di 10 microsecondi dall'ESP32 al pin TRIG del sensore e leggeremo il tempo di eco proveniente dal pin ECHO con `pulseIn()`. Visualizziamo la distanza calcolata in cm su un display LCD I2C 16x2. Poiché l'HC-SR04 funziona a 5V, è necessario un **divisore di tensione** sul pin EC

Sensore di parcheggio ESP32 (HC-SR04 + barra a 5 LED + cicalino + OLED)
La versione ESP32 del sensore di parcheggio per auto! Grazie al sensore a ultrasuoni HC-SR04 misuriamo la distanza dall'oggetto davanti al veicolo. Man mano che la distanza diminuisce, la barra composta da 5 LED si riempie (da verde → giallo → rosso) e l'intervallo tra i bip del cicalino si accorcia. Quando ci si avvicina troppo (meno di 10 cm), l'allarme suona ininterrottamente e tutti i LED si accendono. Sul display OLED SSD1306 vengono visualizzati in caratteri grandi il valore istantaneo in

Misurazione della distanza tramite display LCD
Uno strumento che misura le distanze senza righello: muovi la mano avanti e indietro davanti al sensore e guarda il numero cambiare. L'HC-SR04 manda un'onda sonora e ascolta l'eco, e l'Arduino calcola
Altri articoli
App BlueGrays
Costruisci questo circuito passo passo sul telefono
Schema, codice ed elenco componenti in un’unica schermata. Oltre 160 progetti Arduino, ESP32 e Pico da realizzare.
Inquadra con il telefono
Punta la fotocamera sul codice: si apre lo store del tuo telefono.
oppure apri lo store

