🤖 Arduino • L298N • HC-SR04 • Servo

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.

DriverL298N
SensoreHC-SR04
ScansioneServo 0°–180°
In poche parole: il robot avanza finché davanti trova più di 30 cm liberi. Quando incontra un ostacolo si ferma, ruota HC-SR04 con il servo, misura lo spazio disponibile a destra e a sinistra e sceglie automaticamente dove girare.

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 Arduino con L298N servo e HC-SR04

Robot car con sensore ultrasonico montato sul servomotore.

Materiale necessario

🔌 Arduino Uno
🚗 Chassis robot a 2 ruote
⚙️ 2 motori DC
🔁 Modulo L298N Dual H-Bridge
📡 Sensore HC-SR04
🦾 Servomotore SG90 9g
🔋 Batteria ricaricabile adatta ai motori
🔘 Interruttore
🔗 Cavetti di collegamento
🧩 Breadboard

🧰 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 consigliato

Link 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 Arduino

Link di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.

Schema di collegamento

Schema robot Arduino L298N servo HC-SR04

Schema completo del robot. L’immagine mantiene una larghezza massima di 686 px.

Collegamenti Arduino

FunzionePin Arduino
HC-SR04 TRIGD2
HC-SR04 ECHOD3
Servo SG90D5
L298N ENBD6 PWM
L298N IN4D7
L298N IN3D8
L298N IN2D9
L298N IN1D10
L298N ENAD11 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:

  1. ferma entrambi i motori;
  2. porta il sensore verso destra, a 0°;
  3. misura la distanza;
  4. se c’è spazio gira a destra;
  5. altrimenti porta il sensore verso sinistra, a 180°;
  6. se trova spazio gira a sinistra;
  7. se entrambi i lati sono occupati, esegue una rotazione più ampia per allontanarsi.
Concetto chiave: il servomotore trasforma un solo HC-SR04 in una piccola testa di scansione, permettendo al robot di confrontare più direzioni prima di scegliere il movimento.

Codice Arduino commentato

Robot evita ostacoli – L298N + servo + HC-SR04
/*
  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:

Velocità motori
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.

Regolare velocità motore Arduino L298N

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.

Esempio: se il robot tende verso destra o sinistra durante l’avanzamento, prova piccoli valori di gap e verifica il comportamento su una superficie piana.

Calibrare la rotazione di 90°

Il valore:

Tempo di rotazione
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.

Attenzione: verifica sempre tensione nominale dei motori, configurazione del modulo L298N e alimentazione del servomotore. I motori possono provocare cadute di tensione e reset di Arduino se l’alimentazione è sottodimensionata.

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.