Macchinina robot Arduino: costruzione e controllo Bluetooth
Macchinina robot Arduino passo passo: materiali e costi, collegamenti L298N e HC-05, batterie 18650, codice, controllo da smartphone, deriva e reset risolti.
Costruire una macchinina con Arduino è uno dei modi più divertenti per imparare elettronica e programmazione in un unico progetto. Con due motoriduttori, un driver per motori L298N, due batterie 18650, un modulo Bluetooth HC-05 e un Arduino Uno puoi realizzare in un fine settimana una macchinina robot da guidare con lo smartphone. Lungo la strada vedrai di persona perché i motori non si collegano direttamente ad Arduino, perché la scelta della batteria è così importante e come poche righe di codice muovono un vero veicolo.
In questa guida costruiamo insieme una macchinina robot 2WD (a due motori) dall'inizio alla fine: elenco dei materiali e voci di costo, montaggio del telaio, tabelle dei collegamenti, codice per avanti, indietro e sterzate e controllo Bluetooth dallo smartphone. I due problemi su cui i principianti si bloccano più spesso, la macchinina che non va dritta e Arduino che si resetta quando partono i motori, hanno ciascuno una sezione dedicata con soluzioni concrete. Nelle ultime sezioni troverai come guidare la stessa macchinina con un ESP32 o un Raspberry Pi Pico e come trasformarla in un robot che evita gli ostacoli o segue una linea.




Come funziona una macchinina robot con Arduino?
Una macchinina robot si può dividere in quattro parti. Arduino è il cervello: legge il comando che arriva dallo smartphone e decide quale motore gira, in che verso e a che velocità. Il driver L298N è il muscolo: trasforma i deboli segnali a 5 V di Arduino nella corrente elevata che serve ai motori. I motoriduttori fanno girare le ruote e il pacco batterie alimenta tutto. Queste macchinine non hanno sterzo: girano facendo ruotare le due ruote a velocità o in versi diversi. Si chiama trazione differenziale: se la ruota sinistra gira in avanti e la destra all'indietro, la macchinina ruota su se stessa verso destra. Una piccola ruota pivottante davanti o dietro tiene in equilibrio il telaio.

| Caratteristica | Motore TT giallo (1:48) |
|---|---|
| Tensione di lavoro | 3–6 V |
| Rapporto di riduzione | 1:48 (ingranaggi in plastica) |
| Velocità a vuoto | Circa 90–120 giri/min a 3 V, 200–250 giri/min a 6 V |
| Corrente a vuoto | Circa 150–160 mA |
| Corrente di stallo | Circa 1,1–1,5 A |
| Diametro ruota (nei kit) | 65 mm |
| Velocità della macchinina a 6 V | Circa 0,7 m/s (π × 0,065 m × 200 / 60) |
La riga più importante della tabella è la corrente di stallo: quando una ruota spinge contro un ostacolo o la macchinina parte, ogni motore assorbe per un istante più di 1 ampere. Un pin di Arduino invece fornisce al massimo 20–40 mA, per questo i motori si collegano sempre tramite un driver. Nel farlo, l'L298N perde circa 1,5–2,5 V; con un pacco da 7,4 V ai motori restano 5–6 V, proprio l'intervallo ideale per i motori TT. Spieghiamo in dettaglio il funzionamento del driver e del ponte H in Controllo di un motore DC con l'L298N.
Elenco dei materiali
| Componente | Quantità | Nota |
|---|---|---|
| Kit telaio in acrilico 2WD per macchinina robot | 1 | Di solito include 2 motori TT, 2 ruote, ruota pivottante, interruttore, supporti motore e viti |
| Arduino Uno R3 (va bene un clone) + cavo USB | 1 | Va bene anche un Nano; i numeri dei pin sono gli stessi |
| Modulo driver per motori L298N | 1 | 2 A per canale; comanda due motori in modo indipendente |
| Modulo Bluetooth HC-05 o HC-06 | 1 | Per comunicare con uno smartphone Android |
| Batteria al litio 18650 | 2 | Celle di marca in grado di erogare almeno 5 A |
| Portabatterie per 2 celle 18650 (in serie) | 1 | Collega le due celle in serie e fornisce 7,4 V |
| Caricabatterie per 18650 | 1 | Un caricatore che carichi ogni cella separatamente |
| Cavetti jumper (maschio-femmina e femmina-femmina) | 20+ | Tra Arduino, L298N e HC-05 |
| Resistenze da 1 kΩ e 2 kΩ | 1 + 1 | Partitore di tensione per l'ingresso RXD dell'HC-05 |
| Condensatore ceramico da 100 nF | 2–4 | Sui terminali dei motori; attenua i disturbi |
| Condensatore elettrolitico da 470–1000 µF (16 V o più) | 1 | Consigliato; sull'ingresso di alimentazione dell'L298N |
| Fascette, biadesivo, distanziali M3 | Qualche pezzo | Per fissare schede e cavi |
La maggior parte dei kit telaio include anche un portabatterie per 4 stilo AA; come vedrai fra poco, insieme all'L298N risulta troppo debole, ed è per questo che abbiamo aggiunto le 18650 all'elenco. L'HC-06 è il fratello più semplice dell'HC-05, funziona solo come slave ed è più che sufficiente per guidare una macchinina dallo smartphone. I dischi di plastica forati del kit sono dischi encoder per un sensore di velocità che più avanti ti permetterà di andare perfettamente dritto; non buttarli, mettili da parte per ora.
Costi: dove va il budget?
I prezzi cambiano di continuo a seconda del venditore e del cambio, quindi non diamo cifre; ti mostriamo invece quali voci pesano sul budget e dove puoi risparmiare. La regola generale è: i moduli elettronici (L298N, HC-05, resistenze) costano poco, mentre la maggior parte del budget va nella scheda, nel kit telaio e soprattutto nelle batterie e nel caricatore. La batteria è l'ultima cosa su cui risparmiare: buone celle 18650 si ricaricano centinaia di volte e si riutilizzano in tutti i tuoi prossimi progetti di robot.
| Voce | Livello di prezzo | Consiglio per risparmiare |
|---|---|---|
| Kit telaio (motori e ruote inclusi) | Medio | Un kit costa di solito meno che comprare motori, ruote e ruota pivottante separatamente |
| Arduino Uno | Medio (clone) – alto (originale) | Per imparare basta un clone; puoi anche riutilizzare l'Uno o il Nano che hai già |
| Driver L298N | Basso | Un modulo comanda due motori; ne basta uno anche per il 4WD |
| HC-05 / HC-06 | Basso – medio | Se guidi solo dallo smartphone, un HC-06 è sufficiente |
| 2 batterie 18650 + caricatore | La voce più cara | Le celle molto economiche con scritto "9900 mAh" sono di solito false; non risparmiare qui |
| Cavi, resistenze, condensatori, viti | Basso | Quasi tutto si trova già negli starter kit |
2WD o 4WD?
| Caratteristica | 2WD (2 motori + ruota pivottante) | 4WD (4 motori) |
|---|---|---|
| Sterzata | Ruota su se stessa, stretta e senza fatica | Sterza facendo slittare le ruote di lato (skid steer); fatica sul tappeto |
| Assorbimento | Circa 0,3–0,6 A in marcia | Circa il doppio |
| Autonomia | Maggiore | Minore |
| Terreno irregolare | La ruota pivottante può incastrarsi sui bordi | Aderenza migliore |
| Andare dritto | La ruota pivottante può deviare la macchinina quando si riorienta | Più stabile |
| Collegamento all'L298N | Ogni motore sul proprio canale | I due motori di ogni lato in parallelo su un canale |
| Ideale per | Prima macchinina, robot seguilinea | Esterni, carichi più pesanti |
Per la tua prima macchinina consigliamo il 2WD: costa meno, assorbe meno corrente, ruota facilmente su se stessa ed è più adatto a progetti successivi come un robot seguilinea. Se costruisci un 4WD, collega in parallelo i due motori di ogni lato agli stessi morsetti OUT e controlla che girino nello stesso verso. Un canale dell'L298N porta allora la corrente di due motori; nella guida normale non è un problema, ma se le ruote si bloccano si può superare il limite di 2 A per canale e la protezione termica del driver spegne i motori.
Alimentazione: perché due batterie 18650?
La maggior parte dei problemi delle macchinine robot nasce da una batteria sbagliata. La fonte giusta deve soddisfare due condizioni insieme: lasciare ai motori tensione sufficiente dopo la perdita dell'L298N e non crollare quando i motori chiedono diversi ampere in partenza. Due celle al litio 18650 in serie (2S) danno 8,4 V a piena carica e 7,4 V in media, ed erogano senza fatica diversi ampere. Arduino Uno consiglia 7–12 V sull'ingresso VIN, quindi lo stesso pacco può alimentare sia i motori sia Arduino. Con celle da 2500 mAh, una 2WD che assorbe in media 0,8 A in marcia (motori e schede compresi) funziona in teoria circa 3 ore; dato che non scarichi mai del tutto la batteria, 2–2,5 ore è una stima più realistica. Per fare il calcolo con i tuoi valori usa lo strumento Durata della batteria.

| Alimentazione | Tensione | Corrente erogabile | Per una macchinina robot |
|---|---|---|---|
| Batteria da 9 V | 9 V | Molto bassa | Non adatta; la causa più comune dei reset |
| 4 stilo AA alcaline | 6 V (cala in fretta sotto carico) | Media | Debole; dopo l'L298N ai motori arrivano circa 4 V |
| 4 stilo AA NiMH (ricaricabili) | 4,8 V | Buona | Tensione insufficiente con l'L298N |
| 2 batterie 18650 al litio (2S) | 7,4 V (8,4 V cariche) | Alta (diversi ampere) | La scelta migliore |
| 3 batterie 18650 al litio (3S) | 11,1 V (12,6 V cariche) | Alta | Troppo per i motori TT; supera il limite di 12 V del jumper 5V |
| Power bank USB | 5 V | Buona | Solo per alimentare Arduino separatamente |
Invece di indovinare quanta carica resta, puoi misurarla. Collega il positivo della batteria (dopo l'interruttore) ad A0 tramite un partitore di tensione fatto con due resistenze da 10 kΩ: un pacco da 8,4 V appare su A0 come 4,2 V, sotto il limite di lettura di 5 V di Arduino. Il partitore assorbe solo circa 0,4 mA e non incide sull'autonomia.
1// Pil + (anahtardan sonra) → 10 kΩ → A0 → 10 kΩ → GND / battery + (after the switch) → 10 kΩ → A0 → 10 kΩ → GND
2const float DIVIDER = 2.0; // iki eşit direnç gerilimi yarıya böler / two equal resistors halve the voltage
3
4void setup() {
5 Serial.begin(9600);
6}
7
8void loop() {
9 float v = analogRead(A0) * 5.0 / 1023.0 * DIVIDER;
10 Serial.print(F("Pil / Battery: "));
11 Serial.print(v, 2);
12 Serial.println(F(" V"));
13 if (v < 6.6) Serial.println(F("Sarj et / Charge now")); // hücre başına 3,3 V / 3.3 V per cell
14 delay(1000);
15}Montaggio passo passo
- Togli la pellicola protettiva dai pezzi in acrilico. Se i motori arrivano senza fili, salda due fili su ogni motore e rinforza le saldature con colla a caldo; un filo del motore che si stacca per le vibrazioni è il guasto più frequente.
- Fissa i motori sotto il telaio con i supporti in acrilico a T e le viti M3 lunghe del kit. I due alberi devono essere allineati e i terminali dei motori rivolti verso l'interno.
- Se vuoi usare i dischi encoder, montali ora sul lato interno dell'albero del motore; con le ruote già montate è difficile.
- Monta la ruota pivottante al centro dell'altra estremità del telaio con dei distanziali. Scegli un'altezza che tenga il telaio parallelo al pavimento.
- Infila le ruote fino in fondo allineandole all'albero a forma di D; una ruota lenta fa deviare la macchinina di continuo.
- Fissa il portabatterie con biadesivo o velcro in modo che il suo peso sia vicino all'asse delle ruote. Se la maggior parte del peso grava sulla ruota pivottante, le ruote motrici slittano.
- Monta Arduino e l'L298N sul ripiano superiore con distanziali in plastica. Devi poter raggiungere facilmente la porta USB di Arduino e il dissipatore dell'L298N deve restare all'aria; attento che le viti metalliche non tocchino le saldature sotto le schede.
- Collega l'interruttore in serie al filo positivo della batteria; così potrai accendere e spegnere la macchinina senza togliere le celle.
- Attorciglia i due fili di ogni motore fino all'L298N, tieni corti tutti i cavi e raccoglili con le fascette. Prima di inserire le celle, verifica con un multimetro che non ci sia un cortocircuito tra i terminali della batteria.
Schema dei collegamenti
Pensa ai collegamenti in due parti: la parte di potenza (batteria, interruttore, L298N, motori) e la parte di segnale (i fili sottili che vanno da Arduino all'L298N e all'HC-05). Togli i piccoli jumper dai pin ENA ed ENB dell'L298N; collegheremo questi pin alle uscite PWM di Arduino per regolare la velocità da codice. Il jumper 5V dell'L298N invece resta al suo posto: poiché il pacco è sotto i 12 V, il regolatore della scheda alimenta la logica del driver.

| Morsetto dell'L298N | Collegamento |
|---|---|
| OUT1, OUT2 | Motore sinistro (nel 4WD i due motori di sinistra in parallelo) |
| OUT3, OUT4 | Motore destro (nel 4WD i due motori di destra in parallelo) |
| 12V | Positivo della batteria tramite l'interruttore |
| GND | Negativo della batteria e pin GND di Arduino (massa comune) |
| 5V | Libero con Arduino Uno; alimenta la scheda con ESP32 e Pico |
| Jumper 5V | Resta inserito (batteria sotto i 12 V) |
| Jumper di ENA ed ENB | Si tolgono; i pin vanno alle uscite PWM di Arduino |
| Collegamento | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| L298N ENA (velocità motore sinistro) | D5 (PWM) | GPIO 25 | GP15 |
| L298N IN1 | D7 | GPIO 27 | GP14 |
| L298N IN2 | D8 | GPIO 33 | GP13 |
| L298N ENB (velocità motore destro) | D6 (PWM) | GPIO 26 | GP10 |
| L298N IN3 | D9 | GPIO 32 | GP12 |
| L298N IN4 | D4 | GPIO 4 | GP11 |
| HC-05 TXD | D10 (RX di SoftwareSerial) | Non serve (Bluetooth integrato) | GP1 (RX di UART0) |
| HC-05 RXD | D11, tramite partitore 1 kΩ / 2 kΩ | Non serve | GP0 (TX di UART0), diretto |
| HC-05 VCC | 5V | Non serve | Uscita 5V dell'L298N |
| Alimentazione della scheda | VIN ← positivo della batteria dopo l'interruttore | 5V (VIN) ← uscita 5V dell'L298N | VSYS ← uscita 5V dell'L298N |
| GND | In comune con GND dell'L298N e negativo della batteria | In comune | In comune |
Abbiamo scelto D5 e D6 come pin di velocità di proposito. Sull'Uno la libreria Servo disattiva il PWM sui pin 9 e 10 e la funzione tone() quello sui pin 3 e 11. Con ENA ed ENB su 5 e 6, il controllo di velocità continua a funzionare anche quando più avanti aggiungi un servo o un buzzer. D2 e D3 restano riservati agli encoder perché supportano gli interrupt. Puoi vedere la piedinatura della tua scheda nello strumento Pinout.
Primo sketch: avanti, indietro, sinistra e destra
Prima di passare al Bluetooth, proviamo motori e collegamenti da soli. Il cuore del codice è la funzione drive(sinistra, destra): riceve la velocità di ciascun motore separatamente da -255 a 255; un valore positivo significa avanti, uno negativo indietro e zero stop. Come il valore di velocità diventa tensione lo spieghiamo in Che cos'è il PWM?. Prima di caricare lo sketch, appoggia la macchinina su una scatola in modo che le ruote girino a vuoto; l'attesa di 3 secondi in setup() ti dà il tempo per farlo.
1// Sol motor / left motor: ENA=5, IN1=7, IN2=8 — Sağ motor / right motor: ENB=6, IN3=9, IN4=4
2const int ENA = 5, IN1 = 7, IN2 = 8;
3const int ENB = 6, IN3 = 9, IN4 = 4;
4
5const int SPEED = 180; // temel hız 0-255 / base speed 0-255
6const int TRIM = 0; // % düzeltme: + sol, - sağ motoru yavaşlatır / % trim: + slows left, - slows right
7
8void drive(int left, int right) { // her biri -255 … 255 / each -255 … 255
9 if (TRIM > 0) left = left * (100 - TRIM) / 100;
10 if (TRIM < 0) right = right * (100 + TRIM) / 100;
11 digitalWrite(IN1, left > 0); digitalWrite(IN2, left < 0);
12 digitalWrite(IN3, right > 0); digitalWrite(IN4, right < 0);
13 analogWrite(ENA, abs(left));
14 analogWrite(ENB, abs(right));
15}
16
17void forward() { drive(SPEED, SPEED); }
18void backward() { drive(-SPEED, -SPEED); }
19void turnLeft() { drive(-SPEED, SPEED); } // yerinde sola / spin left in place
20void turnRight() { drive(SPEED, -SPEED); } // yerinde sağa / spin right in place
21void stopCar() { drive(0, 0); }
22
23void setup() {
24 int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
25 for (int p : pins) pinMode(p, OUTPUT);
26 stopCar();
27 delay(3000); // tekerlekleri kaldırmak için zaman / time to lift the wheels
28}
29
30void loop() {
31 forward(); delay(1500);
32 stopCar(); delay(500);
33 backward(); delay(1500);
34 stopCar(); delay(500);
35 turnLeft(); delay(600);
36 stopCar(); delay(500);
37 turnRight(); delay(600);
38 stopCar(); delay(2000);
39}| Movimento | Motore sinistro | Motore destro | Codice |
|---|---|---|---|
| Avanti | Avanti | Avanti | drive(180, 180) |
| Indietro | Indietro | Indietro | drive(-180, -180) |
| Rotazione a sinistra sul posto | Indietro | Avanti | drive(-180, 180) |
| Rotazione a destra sul posto | Avanti | Indietro | drive(180, -180) |
| Curva larga a sinistra | Avanti piano | Avanti | drive(90, 180) |
| Stop | Fermo | Fermo | drive(0, 0) |
Con le ruote sollevate, la macchinina deve andare a turno avanti, indietro, a sinistra e a destra. Se una ruota gira al contrario non toccare il codice: scambia i due fili di quel motore sul morsetto OUT dell'L298N. Se girano al contrario entrambe le ruote, scambia i fili di tutti e due i motori. Se i motori ronzano ma non girano, il valore SPEED è troppo basso: la maggior parte dei motori TT ha bisogno di un valore PWM di almeno 80–120 circa per partire, e questa soglia sale man mano che la batteria si scarica.
Controllo Bluetooth dallo smartphone (HC-05)
L'HC-05 funziona come un cavo seriale senza fili tra lo smartphone e Arduino: l'app sul telefono invia una lettera, Arduino la legge ed esegue il movimento corrispondente. La maggior parte delle app di comando che trovi sul Play Store cercando "Bluetooth RC Car" o "Bluetooth RC Controller" invia F per avanti, B per indietro, L per sinistra, R per destra e S per stop quando rilasci il tasto; alcune usano anche G, I, H e J per le diagonali e 0–9 più q per la velocità. Pin, lampeggi del LED e comandi AT del modulo sono spiegati in Modulo Bluetooth HC-05.

- Mentre carichi lo sketch qui sotto, l'interruttore della macchinina può restare spento; Arduino e HC-05 sono alimentati via USB. Se il LED dell'HC-05 lampeggia velocemente, il modulo è in attesa di connessione.
- Cerca l'HC-05 nelle impostazioni Bluetooth del tuo smartphone Android e associalo con il PIN 1234 (o 0000 se non funziona).
- Apri l'app di comando, concedi i permessi Bluetooth e dispositivi nelle vicinanze e scegli l'HC-05 dall'elenco. A connessione avvenuta, il LED del modulo fa due brevi lampeggi ogni due secondi.
- Tieni Arduino collegato via USB, apri il Monitor seriale a 9600 baud e premi i tasti nell'app. Sullo schermo compare la lettera inviata da ogni tasto; se la tua app invia lettere diverse, modifica di conseguenza le righe case del codice.
- Scollega il cavo USB, accendi l'interruttore, appoggia la macchinina a terra e guida.
1#include <SoftwareSerial.h>
2
3SoftwareSerial bt(10, 11); // RX, TX → HC-05 TXD, RXD (RXD bölücüyle / RXD via divider)
4
5const int ENA = 5, IN1 = 7, IN2 = 8; // sol motor / left motor
6const int ENB = 6, IN3 = 9, IN4 = 4; // sağ motor / right motor
7const int TRIM = 0; // % düzeltme / % trim
8const unsigned long TIMEOUT = 600; // ms; 0 = kapalı / 0 = disabled
9
10int speed = 200; // 0-255
11unsigned long lastCmd = 0;
12
13void drive(int left, int right) {
14 if (TRIM > 0) left = left * (100 - TRIM) / 100;
15 if (TRIM < 0) right = right * (100 + TRIM) / 100;
16 digitalWrite(IN1, left > 0); digitalWrite(IN2, left < 0);
17 digitalWrite(IN3, right > 0); digitalWrite(IN4, right < 0);
18 analogWrite(ENA, abs(left));
19 analogWrite(ENB, abs(right));
20}
21
22void setup() {
23 int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
24 for (int p : pins) pinMode(p, OUTPUT);
25 drive(0, 0);
26 Serial.begin(9600); // gelen harfleri görmek için / to see incoming letters
27 bt.begin(9600); // HC-05 veri modu hızı / HC-05 data mode baud rate
28}
29
30void loop() {
31 if (bt.available()) {
32 char c = bt.read();
33 Serial.println(c);
34 lastCmd = millis();
35 int half = speed / 2;
36 switch (c) {
37 case 'F': drive(speed, speed); break; // ileri / forward
38 case 'B': drive(-speed, -speed); break; // geri / backward
39 case 'L': drive(-speed, speed); break; // yerinde sola / spin left
40 case 'R': drive(speed, -speed); break; // yerinde sağa / spin right
41 case 'G': drive(half, speed); break; // ileri-sol / forward-left
42 case 'I': drive(speed, half); break; // ileri-sağ / forward-right
43 case 'H': drive(-half, -speed); break; // geri-sol / back-left
44 case 'J': drive(-speed, -half); break; // geri-sağ / back-right
45 case 'S': drive(0, 0); break; // dur / stop
46 case 'q': speed = 255; break; // tam hız / full speed
47 default:
48 if (c >= '0' && c <= '9') speed = map(c - '0', 0, 9, 100, 240); // hız kademesi / speed level
49 }
50 }
51 if (TIMEOUT > 0 && millis() - lastCmd > TIMEOUT) drive(0, 0); // komut yoksa dur / no command: stop
52}| Lettera | Movimento | Motore sinistro / destro |
|---|---|---|
| F | Avanti | +velocità / +velocità |
| B | Indietro | −velocità / −velocità |
| L | Rotazione a sinistra | −velocità / +velocità |
| R | Rotazione a destra | +velocità / −velocità |
| G, I | Avanti-sinistra, avanti-destra | Un lato a metà velocità |
| H, J | Indietro-sinistra, indietro-destra | Un lato a metà velocità |
| S | Stop | 0 / 0 |
| 0–9, q | Livello di velocità | 0 → 100, 9 → 240, q → 255 |
Il TIMEOUT nel codice è una misura di sicurezza: queste app inviano la stessa lettera in continuazione finché tieni premuto il tasto, quindi se per 600 ms non arriva nessuna lettera il codice presume che la connessione sia caduta e ferma la macchinina. Così la macchinina non continua verso il muro se lo smartphone esce dalla portata o l'app si chiude. Se la tua app invia la lettera una sola volta per ogni pressione, la macchinina si fermerà dopo 600 ms; in quel caso imposta TIMEOUT a 0 per disattivare la funzione. Inoltre non abbiamo usato delay() da nessuna parte in loop(); le attese lunghe ritardano i comandi, e il perché lo trovi in millis() o delay().
La macchinina non va dritta: cause e soluzione
Se la macchinina devia lentamente da un lato anche se dai a entrambi i motori lo stesso valore PWM per "avanti", niente paura: è il problema più comune delle macchinine robot. I motoriduttori economici girano a velocità diverse anche alla stessa tensione; differenze di attrito negli ingranaggi, nelle spazzole e nei magneti rendono ogni motore un po' diverso. Aggiungi una ruota lenta, una ruota pivottante che cambia orientamento o il peso concentrato su un lato, e una deviazione di 20–30 cm su 2 metri è del tutto normale. Elimina prima le cause meccaniche, poi correggi la differenza rimasta via software.
| Sintomo | Causa probabile | Soluzione |
|---|---|---|
| Devia sempre dallo stesso lato | I motori girano a velocità diverse | Correzione software con TRIM, oppure encoder |
| Sbanda in partenza e poi si raddrizza | Un motore parte in ritardo o la ruota pivottante si riorienta | Partenza graduale; ruota a sfera (ball caster) al posto della pivottante |
| La deviazione cambia ogni volta | Ruota lenta, pneumatico che slitta o supporto motore storto | Infila bene la ruota sull'albero, stringi le viti |
| Gira su se stessa invece di andare avanti | I fili di un motore sono invertiti | Scambia i fili di quel motore sul morsetto OUT |
| La deviazione aumenta con la batteria scarica | A bassa tensione la differenza tra i motori cresce | Ricarica la batteria; regola TRIM a batteria carica |
| Tira da un lato quando accelera | Il peso è da un lato | Sposta batteria e schede al centro, vicino all'asse delle ruote |
Risolti i problemi meccanici, fai la regolazione fine via software. La costante TRIM nel codice rallenta in percentuale il motore più veloce: un valore positivo rallenta il motore sinistro, uno negativo il destro. Procedi così:
- Carica completamente le celle; tarare a batteria carica dà risultati coerenti.
- Attacca sul pavimento una striscia di nastro dritta lunga 2 metri e metti la macchinina all'inizio, allineata al nastro.
- Nel loop() del primo sketch lascia solo forward() e un'attesa di 3 secondi, poi lascia andare la macchinina.
- Se la macchinina devia a destra, il motore sinistro è più veloce: aumenta TRIM di 3; se devia a sinistra, diminuisci TRIM di 3.
- Ripeti finché la deviazione su 2 metri scende a pochi centimetri, poi copia lo stesso valore di TRIM nello sketch Bluetooth.
- Tara alla velocità che usi di più; la differenza tra i motori cambia leggermente con la velocità.
Il livello successivo per andare perfettamente dritto e misurare le distanze è l'encoder. Monti sugli alberi dei motori i dischi a 20 fessure del kit e conti ogni fessura con un sensore di velocità a forcella basato sull'LM393. Collega le uscite dei sensori ai pin D2 e D3, che supportano gli interrupt, e confronta il numero di impulsi delle due ruote: se il lato sinistro va più avanti, rallenti un po' il motore sinistro. Questo semplice controllo proporzionale (P) mantiene la macchinina dritta indipendentemente dalla carica della batteria e dal pavimento. Una ruota da 65 mm percorre circa 20,4 cm per giro, quindi ogni impulso corrisponde a circa 1 cm. Spieghiamo come funzionano gli interrupt in Interrupt su Arduino.
Arduino si resetta quando partono i motori
Se Arduino si riavvia o l'HC-05 perde la connessione (il LED torna a lampeggiare velocemente) quando la macchinina parte, cambia direzione o urta un ostacolo, il problema è quasi sempre nell'alimentazione. In partenza due motori insieme possono assorbire 2–3 A; una batteria debole non ce la fa e la sua tensione crolla per un istante. Il processore dell'Uno si resetta per sicurezza quando l'alimentazione scende sotto 2,7 V (brown-out). A questo si aggiungono i disturbi elettrici delle spazzole dei motori e la caduta di tensione nei cavi sottili. Ecco le soluzioni, partendo dalla più efficace:
- Cambia batteria: usa due 18650 cariche al posto di una batteria da 9 V o di stilo AA esauste; qui finisce la maggior parte dei problemi.
- Il percorso di alimentazione giusto: alimenta Arduino dalla batteria tramite VIN; non collegare l'uscita 5V dell'L298N a VIN.
- Condensatori sui motori: salda un condensatore ceramico da 100 nF tra i due terminali di ogni motore; elimina alla fonte i disturbi delle spazzole.
- Condensatore di riserva: collega un elettrolitico da 470–1000 µF ai morsetti 12V e GND dell'L298N (positivo sul 12V). Copre il breve picco di corrente della partenza.
- Partenza graduale: invece di passare subito a 255, aumenta la velocità a gradini come qui sotto; il picco di corrente si riduce.
- Fermati prima di invertire: passare direttamente da avanti a indietro porta la corrente del motore al massimo; fermati per 100–200 ms prima di cambiare verso.
- Cavi di potenza spessi e corti: non usare cavetti jumper né breadboard tra batteria e L298N; usa cavo da almeno 0,5 mm² e morsettiere.
- Alimentazioni separate: se il problema persiste, alimenta Arduino con un power bank e i motori con la batteria, e collega insieme i due GND.
1// Yumuşak kalkış: ilk koddaki drive() ile kullan / soft start: use with drive() from the first sketch
2void rampTo(int target) {
3 for (int s = 60; s < target; s += 20) {
4 drive(s, s);
5 delay(15); // yaklaşık 10 adımda tam hız / full speed in about 10 steps
6 }
7 drive(target, target);
8}
9
10// Kullanım: forward() yerine rampTo(SPEED) / usage: rampTo(SPEED) instead of forward()Macchinina robot con ESP32 e Raspberry Pi Pico
L'ESP32 ha il Bluetooth classico integrato, quindi l'HC-05 non serve: la libreria BluetoothSerial crea la stessa connessione seriale con lo smartphone e le app di comando viste sopra funzionano senza modifiche. Gli ingressi dell'L298N considerano HIGH tutto ciò che supera circa 2,3 V, quindi i segnali a 3,3 V dell'ESP32 bastano. Alimenta la scheda ESP32 dall'uscita 5V dell'L298N sul suo pin 5V (VIN); non collegare la batteria direttamente a quel pin. Questo codice non si compila per ESP32-S3 ed ESP32-C3, perché hanno solo il BLE.
1#include "BluetoothSerial.h"
2
3BluetoothSerial bt;
4
5const int ENA = 25, IN1 = 27, IN2 = 33; // sol motor / left motor
6const int ENB = 26, IN3 = 32, IN4 = 4; // sağ motor / right motor
7
8int speed = 200; // 0-255
9unsigned long lastCmd = 0;
10
11void drive(int left, int right) {
12 digitalWrite(IN1, left > 0); digitalWrite(IN2, left < 0);
13 digitalWrite(IN3, right > 0); digitalWrite(IN4, right < 0);
14 analogWrite(ENA, abs(left));
15 analogWrite(ENB, abs(right));
16}
17
18void setup() {
19 int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
20 for (int p : pins) pinMode(p, OUTPUT);
21 drive(0, 0);
22 bt.begin("BlueGrays-Car"); // telefonda görünecek ad / name shown on the phone
23}
24
25void loop() {
26 if (bt.available()) {
27 char c = bt.read();
28 lastCmd = millis();
29 switch (c) {
30 case 'F': drive(speed, speed); break; // ileri / forward
31 case 'B': drive(-speed, -speed); break; // geri / backward
32 case 'L': drive(-speed, speed); break; // yerinde sola / spin left
33 case 'R': drive(speed, -speed); break; // yerinde sağa / spin right
34 case 'S': drive(0, 0); break; // dur / stop
35 case 'q': speed = 255; break; // tam hız / full speed
36 default:
37 if (c >= '0' && c <= '9') speed = map(c - '0', 0, 9, 100, 240);
38 }
39 }
40 if (millis() - lastCmd > 600) drive(0, 0); // komut yoksa dur / no command: stop
41}Il Raspberry Pi Pico standard non ha il Bluetooth, quindi colleghi l'HC-05 ai pin della UART0. Dato che il Pico lavora a 3,3 V, questa volta il partitore di tensione non serve. Alimenta il Pico dal pin VSYS e l'HC-05 direttamente dall'uscita 5V dell'L298N; funzionando a batteria senza USB, sul pin VBUS non c'è tensione. Nel codice del Pico la velocità si indica in percentuale da -100 a 100:
1from machine import Pin, PWM, UART
2import time
3
4bt = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1)) # GP0 → HC-05 RXD, GP1 ← HC-05 TXD
5
6ena = PWM(Pin(15)); ena.freq(1000) # sol motor hızı / left motor speed
7enb = PWM(Pin(10)); enb.freq(1000) # sağ motor hızı / right motor speed
8in1, in2 = Pin(14, Pin.OUT), Pin(13, Pin.OUT)
9in3, in4 = Pin(12, Pin.OUT), Pin(11, Pin.OUT)
10
11def drive(left, right): # -100 … 100 (%)
12 in1.value(left > 0); in2.value(left < 0)
13 in3.value(right > 0); in4.value(right < 0)
14 ena.duty_u16(int(abs(left) * 655))
15 enb.duty_u16(int(abs(right) * 655))
16
17speed = 80
18last = time.ticks_ms()
19drive(0, 0)
20
21while True:
22 if bt.any():
23 c = bt.read(1)
24 last = time.ticks_ms()
25 if c == b'F': drive(speed, speed) # ileri / forward
26 elif c == b'B': drive(-speed, -speed) # geri / backward
27 elif c == b'L': drive(-speed, speed) # yerinde sola / spin left
28 elif c == b'R': drive(speed, -speed) # yerinde sağa / spin right
29 elif c == b'S': drive(0, 0) # dur / stop
30 elif c == b'q': speed = 100 # tam hız / full speed
31 elif c and 48 <= c[0] <= 57: # '0'…'9' hız kademesi / speed level
32 speed = 40 + (c[0] - 48) * 6
33 if time.ticks_diff(time.ticks_ms(), last) > 600:
34 drive(0, 0) # komut yoksa dur / no command: stopProssimi passi: potenzia la tua macchinina
- Robot che evita gli ostacoli: aggiungi davanti un sensore di distanza HC-SR04 e un servomotore che lo ruoti a destra e a sinistra; i dettagli nella guida Robot che evita gli ostacoli.
- Robot seguilinea: monta 2–3 sensori a infrarossi TCRT5000 sotto la parte anteriore e segui una linea nera sul pavimento; vedi Robot seguilinea.
- Telecomando con joystick: costruisci un vero telecomando, senza smartphone, con un secondo Arduino, un modulo joystick e un nRF24L01.
- Telecomando a infrarossi: guida con i tasti del telecomando della TV; associa i codici di Ricevitore IR e telecomando ai comandi di guida.
- Guida via Wi-Fi: fai servire da un ESP32 una pagina di comando che si apre nel browser dello smartphone; la guida Web server ESP32 e WebSocket spiega le basi.
- Encoder e distanza: con i sensori di velocità fai avanzare la macchinina esattamente di 1 metro e girarla di 90 gradi precisi; è la base dei robot che risolvono labirinti.
- Braccio robotico: monta sulla macchinina un piccolo braccio robotico con servo per trasportare oggetti.



Errori comuni e soluzioni
- Nessun motore gira: i GND non sono in comune, l'interruttore è spento, i jumper di ENA ed ENB sono stati tolti ma i pin non sono collegati, oppure la batteria è scarica.
- Il LED dell'L298N è acceso ma i motori ronzano soltanto: il valore PWM è sotto la soglia di partenza o la tensione della batteria è bassa; aumenta la velocità e ricarica la batteria.
- Lo sketch non si carica: forse hai scelto la porta o la scheda sbagliata; se hai collegato l'HC-05 ai pin 0 e 1, scollegalo durante il caricamento. Altre cause in Lo sketch Arduino non si carica.
- Lo smartphone vede l'HC-05 ma non si connette: il modulo è collegato a un altro telefono, l'app non ha il permesso "dispositivi nelle vicinanze" o il PIN di associazione è sbagliato.
- La macchinina risponde in ritardo: c'è un delay() nel loop() o si stampa troppo sul Monitor seriale; gestisci le attese con millis().
- Il dissipatore dell'L298N scalda molto: le ruote fanno attrito o, nel 4WD, la corrente per canale è eccessiva; controlla l'attrito meccanico.
- La macchinina dà uno scatto all'accensione: all'avvio i pin sono indefiniti per un istante; impostali come uscite e chiama drive(0, 0) nelle primissime righe di setup().
Una macchinina robot con Arduino è un ottimo punto di partenza che insegna controllo dei motori, gestione dell'alimentazione, comunicazione wireless e debug in un solo progetto. Alla fine avrai una base che diventa un po' più intelligente con ogni nuovo sensore. Nell'app BlueGrays trovi passo passo, con schemi e codice, i progetti macchinina controllata via Bluetooth con L298N, robot che evita gli ostacoli e rilevamento del fondo bianco e nero con TCRT5000.
Domande frequenti
Cosa serve per costruire una macchinina con Arduino e quanto costa?
Per una macchinina Bluetooth di base bastano un kit telaio 2WD (2 motori TT, ruote, ruota pivottante), un Arduino Uno, un driver L298N, un modulo Bluetooth HC-05, due batterie 18650 con portabatterie e qualche cavetto jumper. I prezzi dipendono dal venditore; i moduli costano poco e la maggior parte del budget va nella scheda, nel kit telaio e nelle batterie con il caricatore. Se hai già uno starter kit, il costo scende parecchio.
Che batteria usare per una macchinina robot Arduino?
La scelta migliore sono due celle al litio 18650 in serie: forniscono 7,4 V, lasciano 5–6 V ai motori dopo la perdita di circa 2 V dell'L298N ed erogano la corrente elevata necessaria alla partenza. Una batteria da 9 V non fornisce abbastanza corrente e provoca reset, mentre con 4 stilo AA i motori girano lenti dietro un L298N.
Perché la mia macchinina Arduino non va dritta?
I motoriduttori economici girano a velocità diverse anche con lo stesso valore PWM, e ruote lente, ruota pivottante e peso mal distribuito aumentano la deviazione. Sistema prima la meccanica, poi rallenta un po' il motore più veloce con un valore di correzione (trim) nel codice. Per andare perfettamente dritto servono encoder che misurino e uguaglino la velocità delle due ruote.
Perché Arduino si resetta quando partono i motori?
In partenza i motori assorbono diversi ampere e la tensione di una batteria debole crolla per un istante; il processore dell'Uno si resetta quando l'alimentazione scende. Usa 18650 cariche, aggiungi condensatori da 100 nF sui terminali dei motori e uno da 470–1000 µF sull'ingresso dell'L298N, e aumenta la velocità gradualmente. Se il problema resta, alimenta Arduino con una fonte separata e collega insieme i GND.
Una macchinina Bluetooth con HC-05 funziona con l'iPhone?
No. HC-05 e HC-06 usano il profilo porta seriale del Bluetooth classico, e iOS non permette alle normali app di aprire questo tipo di connessione. Per comandarla da iPhone ti serve un modulo BLE come l'HM-10 o un ESP32 con BLE; gli smartphone Android si collegano all'HC-05 senza problemi.
Posso usare uno shield motori L293D al posto dell'L298N?
Sì. Lo shield motori L293D si innesta sopra Arduino Uno e può comandare quattro motori DC, semplificando i collegamenti nelle macchinine 4WD. La sua corrente continua però è di circa 0,6 A per canale, quindi va in difficoltà prima dell'L298N quando i motori si bloccano, e lo shield occupa molti pin. Se cerchi qualcosa di più efficiente, i driver a MOSFET come il TB6612FNG perdono molta meno tensione.
Progetti da realizzare dopo questo articolo
Vedi tutti i progetti
Auto controllata via Bluetooth con L298N
Progetto di auto robot 4WD (quattro motori, quattro ruote motrici) che può essere controllata dal telefono con Arduino e il modulo HC-05 Bluetooth. Un totale di quattro ruote sono azionate simultaneam

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.

Controllare un LED dal telefono tramite Bluetooth
Progetto di controllo wireless che accende e spegne i LED con comandi inviati dal telefono con il modulo Bluetooth HC-06. Insegna lo scambio di dati Bluetooth sulla comunicazione seriale.

TCRT5000 Rilevamento di superfici bianche e nere
Progetto che rileva il colore del terreno con il sensore TCRT5000 e accende il LED rosso sul terreno nero e il LED verde sul terreno bianco. Insegna la logica di rilevamento della soglia di colore che

Misurazione della distanza con TCRT5000
Progetto che misura la quantità di luce riflessa dalla superficie con il sensore a infrarossi TCRT5000 e la visualizza come valore analogico sullo schermo LCD I2C. Insegna le basi del rilevamento otti

HC-SR04 Misura della distanza (display seriale)
Il sensore a ultrasuoni HC-SR04 misura la distanza e visualizza il risultato in cm sul monitor seriale. Insegna il principio del calcolo della distanza con l'onda sonora.

Sensore di parcheggio con HC-SR04
Progetto di sensore di parcheggio con sensore HC-SR04 che aumenta la frequenza del segnale acustico all'avvicinarsi dell'oggetto e lo segnala con un LED. Insegna una logica di feedback proporzionale a

Utilizzo del servomotore
Progetto di base che posiziona il servomotore su angoli di 0°, 90° e 180° in sequenza. Insegna la libreria dei servo e la logica di controllo degli angoli.

