Robot evita ostacoli con Arduino, L298N, servo e HC-SR04
Costruiamo un robot car autonomo capace di guardare davanti, a destra e a sinistra con il sensore HC-SR04 montato su un servomotore, scegliendo automaticamente dove muoversi.
Perché usare il modulo L298N
Il modulo L298N integra due ponti H e permette di controllare due motori DC in modo molto più completo rispetto a un semplice transistor. Oltre ad accendere e spegnere i motori, possiamo gestire il verso di rotazione e regolare la velocità attraverso gli ingressi Enable.
Nel progetto i pin ENA ed ENB vengono pilotati in PWM, mentre IN1–IN4 determinano il verso di rotazione dei due motori.
Robot car con sensore ultrasonico montato sul servomotore.
Materiale necessario
🧰 Kit Arduino consigliato
Un kit completo è utile per avere breadboard, cavetti, resistenze, sensori e molti componenti di base per sperimentare con 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. All’interno troverai spiegazioni semplici, schemi chiari e molti progetti pratici pensati per chi parte da zero.
👉 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 di collegamento
Schema completo del robot. L’immagine mantiene una larghezza massima di 686 px.
Collegamenti Arduino
| Funzione | Pin Arduino |
|---|---|
| HC-SR04 TRIG | D2 |
| HC-SR04 ECHO | D3 |
| Servo SG90 | D5 |
| L298N ENB | D6 PWM |
| L298N IN4 | D7 |
| L298N IN3 | D8 |
| L298N IN2 | D9 |
| L298N IN1 | D10 |
| L298N ENA | D11 PWM |
Come decide dove andare
Il servo tiene normalmente HC-SR04 rivolto in avanti a 90°. Se la distanza supera 30 cm, il robot continua ad avanzare.
Quando davanti trova un ostacolo:
- ferma entrambi i motori;
- porta il sensore verso destra, a 0°;
- misura la distanza;
- se c’è spazio gira a destra;
- altrimenti porta il sensore verso sinistra, a 180°;
- se trova spazio gira a sinistra;
- se entrambi i lati sono occupati, esegue una rotazione più ampia per allontanarsi.
Codice Arduino commentato
/*
ROBOT CAR EVITA OSTACOLI CON ARDUINO,
L298N, SERVOMOTORE SG90 E HC-SR04
HC-SR04:
TRIG -> D2
ECHO -> D3
Servo:
segnale -> D5
L298N:
ENA -> D11
IN1 -> D10
IN2 -> D9
IN3 -> D8
IN4 -> D7
ENB -> D6
*/
#include <Servo.h>
Servo servo1;
// Posizione richiesta e posizione precedente del servo
int pos = 0;
int posprec = 0;
// Parametri del movimento del servo
int gradi = 0;
int incremento = 1;
// Pin L298N
const int ENA = 11;
const int IN1 = 10;
const int IN2 = 9;
const int IN3 = 8;
const int IN4 = 7;
const int ENB = 6;
// Correzione tra i due motori
int gap = 0;
// Velocità PWM dei motori
// Nel montaggio di esempio è consigliato un intervallo 120-255
int velocita = 255;
// Tempo indicativo per una rotazione di circa 90°
int rotazione90 = 500;
// Distanza letta dal sensore
float cm = 0;
// ----------------------------------------------------------
// AVANTI
// ----------------------------------------------------------
void avanti() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, constrain(velocita + gap, 0, 255));
analogWrite(ENB, constrain(velocita, 0, 255));
}
// ----------------------------------------------------------
// ROTAZIONE A SINISTRA
// ----------------------------------------------------------
void sx90() {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, constrain(velocita + gap, 0, 255));
analogWrite(ENB, constrain(velocita, 0, 255));
delay(rotazione90);
// Arresta i motori al termine della rotazione
analogWrite(ENA, 0);
analogWrite(ENB, 0);
}
// ----------------------------------------------------------
// ROTAZIONE A DESTRA
// ----------------------------------------------------------
void dx90() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, constrain(velocita + gap, 0, 255));
analogWrite(ENB, constrain(velocita, 0, 255));
delay(rotazione90);
analogWrite(ENA, 0);
analogWrite(ENB, 0);
}
// ----------------------------------------------------------
// MUOVE IL SERVO E MISURA LA DISTANZA
// ----------------------------------------------------------
void sensore() {
gradi = posprec;
incremento = 1;
// Se dobbiamo spostarci verso un angolo minore,
// il servo deve procedere al contrario
if (pos <= posprec) {
incremento = -1;
}
// Movimento progressivo del servo
for (posprec = gradi; posprec != pos; posprec += incremento) {
servo1.write(posprec);
delay(15);
}
// Impulso di trigger HC-SR04
digitalWrite(2, LOW);
delayMicroseconds(2);
digitalWrite(2, HIGH);
delayMicroseconds(10);
digitalWrite(2, LOW);
// Conversione della durata dell'eco in centimetri
unsigned long durata = pulseIn(3, HIGH, 30000UL);
if (durata == 0) {
cm = 999.0; // nessun eco valido entro il timeout
} else {
cm = durata / 58.0;
}
}
void setup() {
// Breve attesa all'accensione
delay(3000);
// Servo al centro
servo1.attach(5);
servo1.write(90);
posprec = 90;
// L298N
pinMode(ENA, OUTPUT);
pinMode(ENB, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
// HC-SR04
pinMode(2, OUTPUT);
pinMode(3, INPUT);
// Motori fermi all'avvio
analogWrite(ENA, 0);
analogWrite(ENB, 0);
}
void loop() {
// Guarda davanti
pos = 90;
sensore();
// Se davanti ci sono più di 30 cm liberi, avanza
if (cm > 30) {
avanti();
}
else {
// Ostacolo: ferma i motori
analogWrite(ENA, 0);
analogWrite(ENB, 0);
// Guarda a destra
pos = 0;
sensore();
if (cm > 30) {
dx90();
}
else {
// Guarda a sinistra
pos = 180;
sensore();
if (cm > 30) {
sx90();
}
else {
// Nessuno spazio sufficiente:
// esegue due rotazioni a sinistra
sx90();
sx90();
}
}
}
}
Come funziona il codice
1. Funzione avanti()
Imposta IN1–IN4 in modo che i due motori ruotino nel verso necessario per procedere in avanti. ENA ed ENB ricevono il valore PWM della velocità.
2. Funzioni dx90() e sx90()
Le due funzioni fanno girare i motori in versi opposti, consentendo al telaio di ruotare. Il tempo rotazione90 stabilisce quanto dura la manovra.
3. Funzione sensore()
Muove gradualmente il servo verso l’angolo richiesto e poi effettua una misura con HC-SR04.
4. Logica principale
Il loop() controlla prima lo spazio davanti. Se è insufficiente esegue le misure laterali e decide la direzione da prendere.
Regolare la velocità dei motori
La velocità è impostata con la variabile:
int velocita = 255;
Il valore PWM può variare tra 0 e 255. Nel montaggio mostrato viene suggerito di lavorare indicativamente tra 120 e 255, perché sotto una certa soglia i motoriduttori potrebbero non avere abbastanza coppia per partire.
Parametro utilizzato per regolare la velocità dei motori.
Correggere un robot che tende da un lato
Due motoriduttori apparentemente identici possono girare a velocità leggermente diversa. La variabile gap permette di compensare una piccola differenza applicando più PWM a un motore.
gap e verifica il comportamento su una superficie piana.Calibrare la rotazione di 90°
Il valore:
int rotazione90 = 500;
è soltanto un punto di partenza. La rotazione effettiva dipende da batteria, peso, diametro delle ruote, attrito e velocità dei motori. Regolalo fino a ottenere una sterzata vicina ai 90°.
Alimentazione del robot
I motori devono ricevere corrente attraverso il driver L298N e un’alimentazione adeguata. Evita di alimentare i motori direttamente dai pin Arduino.
Controllare il verso dei motori
Prima di poggiare il robot a terra, solleva le ruote e verifica il movimento. Se durante il comando avanti una ruota gira nel verso sbagliato, puoi invertire i due fili del relativo motore oppure correggere la logica IN1–IN4.
Scarica lo sketch
⬇️ Scarica arduino_robot_con_servo_hc-sr04.ino
Debug rapido
- controlla che TRIG sia su D2 ed ECHO su D3;
- verifica che il servo sia collegato a D5;
- controlla ENA su D11 ed ENB su D6;
- verifica IN1–IN4 sui pin D10, D9, D8 e D7;
- se il robot non gira abbastanza, aumenta
rotazione90; - se gira troppo, riduci
rotazione90; - se tende da un lato, regola
gap; - se Arduino si resetta, controlla alimentazione e assorbimento di motori e servo.
Varianti del progetto
- aggiungere sensori laterali fissi;
- aggiungere un buzzer quando viene rilevato un ostacolo;
- aggiungere fari LED;
- memorizzare distanze e direzioni sul Monitor Seriale;
- aggiungere controllo Bluetooth manuale;
- usare encoder alle ruote per rotazioni più precise;
- sostituire L298N con un driver più efficiente per motori a bassa tensione.
Cosa devi ricordare
- L298N controlla direzione e velocità di due motori DC.
- HC-SR04 è montato sul servo e può guardare in più direzioni.
- Il robot avanza se davanti ci sono più di 30 cm liberi.
- In presenza di un ostacolo misura prima destra e poi sinistra.
- ENA ed ENB vengono pilotati in PWM.
- Velocità, gap e tempo di rotazione devono essere calibrati sul telaio reale.
Domande frequenti
Perché il robot va storto?
I due motori possono avere velocità leggermente diverse. Puoi correggere il comportamento modificando la variabile gap.
Perché la rotazione non è esattamente di 90°?
Il codice usa una rotazione temporizzata. Il risultato dipende da batteria, motori, ruote e superficie, quindi rotazione90 deve essere calibrato.
Perché il robot si ferma ma non sceglie bene la direzione?
Controlla che il servo raggiunga realmente gli angoli 0°, 90° e 180° e che HC-SR04 restituisca misure affidabili nelle tre posizioni.
Posso usare un altro driver al posto dell’L298N?
Sì. Il principio resta lo stesso, ma collegamenti e codice devono essere adattati al driver scelto.

