Voiture robot Arduino : construction et pilotage en Bluetooth
Voiture robot Arduino pas à pas : matériel et coût, câblage L298N et HC-05, accus 18650, code moteur, contrôle au smartphone, dérive et redémarrages réglés.
Fabriquer une voiture Arduino est l'une des façons les plus amusantes d'apprendre l'électronique et la programmation dans un seul projet. Avec deux motoréducteurs, un driver de moteurs L298N, deux accus 18650, un module Bluetooth HC-05 et un Arduino Uno, tu peux construire en un week-end une voiture robot que tu pilotes depuis ton smartphone. Tu verras par toi-même pourquoi les moteurs ne se branchent pas directement sur l'Arduino, pourquoi le choix de la batterie compte autant et comment quelques lignes de code font bouger un vrai véhicule.
Dans ce guide, nous construisons ensemble une voiture robot 2WD (deux moteurs) de A à Z : liste du matériel et postes de coût, montage du châssis, tableaux de câblage, code pour avancer, reculer et tourner, et pilotage en Bluetooth depuis le smartphone. Les deux problèmes qui bloquent le plus souvent les débutants, la voiture qui ne roule pas droit et l'Arduino qui redémarre quand les moteurs démarrent, ont chacun leur section avec des solutions concrètes. Dans les dernières sections, tu verras comment piloter la même voiture avec un ESP32 ou un Raspberry Pi Pico, et comment la transformer en robot éviteur d'obstacles ou suiveur de ligne.




Comment fonctionne une voiture robot Arduino ?
On peut diviser une voiture robot en quatre parties. L'Arduino est le cerveau : il lit la commande envoyée par le smartphone et décide quel moteur tourne, dans quel sens et à quelle vitesse. Le driver L298N est le muscle : il transforme les faibles signaux de 5 V de l'Arduino en courant élevé dont les moteurs ont besoin. Les motoréducteurs font tourner les roues et le pack d'accus alimente l'ensemble. Ces voitures n'ont pas de direction : elles tournent en faisant tourner les deux roues à des vitesses ou dans des sens différents. C'est la conduite différentielle : si la roue gauche avance et la roue droite recule, la voiture pivote sur place vers la droite. Une petite roue folle à l'avant ou à l'arrière assure l'équilibre du châssis.

| Caractéristique | Moteur TT jaune (1:48) |
|---|---|
| Tension de fonctionnement | 3–6 V |
| Rapport de réduction | 1:48 (engrenages en plastique) |
| Vitesse à vide | Environ 90–120 tr/min à 3 V, 200–250 tr/min à 6 V |
| Courant à vide | Environ 150–160 mA |
| Courant de blocage | Environ 1,1–1,5 A |
| Diamètre de roue (dans les kits) | 65 mm |
| Vitesse de la voiture à 6 V | Environ 0,7 m/s (π × 0,065 m × 200 / 60) |
La ligne la plus importante du tableau est le courant de blocage : quand une roue bute contre un obstacle ou que la voiture démarre, chaque moteur consomme brièvement plus de 1 ampère. Une broche d'Arduino ne fournit que 20–40 mA au maximum, c'est pourquoi les moteurs passent toujours par un driver. En faisant ce travail, le L298N perd environ 1,5–2,5 V ; avec un pack de 7,4 V, il reste 5–6 V aux moteurs, soit exactement la plage idéale des moteurs TT. Nous détaillons le fonctionnement du driver et le pont en H dans Commander un moteur CC avec le L298N.
Liste du matériel
| Pièce | Quantité | Remarque |
|---|---|---|
| Kit châssis acrylique 2WD pour voiture robot | 1 | Contient en général 2 moteurs TT, 2 roues, une roue folle, un interrupteur, des supports moteur et des vis |
| Arduino Uno R3 (un clone suffit) + câble USB | 1 | Un Nano convient aussi ; les numéros de broches sont identiques |
| Module driver de moteurs L298N | 1 | 2 A par canal ; pilote deux moteurs indépendamment |
| Module Bluetooth HC-05 ou HC-06 | 1 | Pour communiquer avec un smartphone Android |
| Accu lithium-ion 18650 | 2 | Cellules de marque capables de fournir au moins 5 A |
| Support pour 2 accus 18650 (en série) | 1 | Met les deux cellules en série pour 7,4 V |
| Chargeur 18650 | 1 | Un chargeur qui charge chaque cellule séparément |
| Câbles Dupont (mâle-femelle et femelle-femelle) | 20+ | Entre l'Arduino, le L298N et le HC-05 |
| Résistances de 1 kΩ et 2 kΩ | 1 + 1 | Pont diviseur pour l'entrée RXD du HC-05 |
| Condensateur céramique 100 nF | 2–4 | Sur les bornes des moteurs ; atténue les parasites |
| Condensateur électrolytique 470–1000 µF (16 V ou plus) | 1 | Recommandé ; sur l'entrée d'alimentation du L298N |
| Colliers de serrage, adhésif double face, entretoises M3 | Quelques-uns | Pour fixer les cartes et les câbles |
La plupart des kits châssis contiennent aussi un support pour 4 piles AA ; comme tu vas le voir, ce support est trop faible avec le L298N, c'est pourquoi nous avons ajouté des accus 18650 à la liste. Le HC-06 est le petit frère plus simple du HC-05, qui fonctionne uniquement en esclave, et il suffit largement pour piloter une voiture depuis un smartphone. Les disques en plastique ajourés du kit sont des disques d'encodeur pour un capteur de vitesse qui te permettra plus tard de rouler parfaitement droit ; ne les jette pas, mets-les de côté pour l'instant.
Coût : où part le budget ?
Les prix changent sans cesse selon le vendeur et le taux de change, nous ne donnons donc pas de chiffres ; nous te montrons plutôt quels postes pèsent sur le budget et où tu peux économiser. La règle générale : les modules électroniques (L298N, HC-05, résistances) sont bon marché, l'essentiel du budget part dans la carte, le kit châssis et surtout les accus et le chargeur. L'accu est le dernier poste sur lequel économiser : de bonnes cellules 18650 se rechargent des centaines de fois et serviront à tous tes futurs projets de robots.
| Poste | Niveau de prix | Astuce pour économiser |
|---|---|---|
| Kit châssis (moteurs et roues inclus) | Moyen | Un kit revient en général moins cher que moteurs, roues et roue folle achetés séparément |
| Arduino Uno | Moyen (clone) – élevé (original) | Un clone suffit pour apprendre ; tu peux aussi réutiliser ton Uno ou ton Nano |
| Driver L298N | Faible | Un module pilote deux moteurs ; un seul suffit aussi pour un 4WD |
| HC-05 / HC-06 | Faible – moyen | Si tu pilotes uniquement au smartphone, un HC-06 suffit |
| 2 accus 18650 + chargeur | Le poste le plus cher | Les cellules très bon marché marquées "9900 mAh" sont souvent des contrefaçons ; n'économise pas ici |
| Câbles, résistances, condensateurs, vis | Faible | La plupart se trouvent déjà dans les kits de démarrage |
2WD ou 4WD ?
| Caractéristique | 2WD (2 moteurs + roue folle) | 4WD (4 moteurs) |
|---|---|---|
| Virage | Pivote sur place, facilement et serré | Tourne en faisant glisser les roues latéralement (skid steer) ; peine sur la moquette |
| Consommation | Environ 0,3–0,6 A en roulant | Environ le double |
| Autonomie | Plus longue | Plus courte |
| Sol irrégulier | La roue folle peut accrocher les bords | Meilleure adhérence |
| Rouler droit | La roue folle peut dévier la voiture en pivotant | Plus stable |
| Branchement au L298N | Chaque moteur sur son propre canal | Les deux moteurs d'un même côté en parallèle sur un canal |
| Idéal pour | Une première voiture, un suiveur de ligne | L'extérieur, des charges plus lourdes |
Pour ta première voiture, nous conseillons le 2WD : il est moins cher, consomme moins, pivote facilement sur place et convient mieux aux projets suivants comme un robot suiveur de ligne. Si tu construis un 4WD, branche en parallèle les deux moteurs de chaque côté sur les mêmes bornes OUT et vérifie qu'ils tournent dans le même sens. Un canal du L298N transporte alors le courant de deux moteurs ; en roulage normal, pas de souci, mais si les roues se bloquent, la limite de 2 A par canal peut être dépassée et la protection thermique du driver coupe les moteurs.
Alimentation : pourquoi deux accus 18650 ?
La plupart des problèmes de voitures robots viennent d'une mauvaise batterie. La bonne source doit remplir deux conditions à la fois : laisser assez de tension aux moteurs après la perte du L298N, et ne pas s'effondrer quand les moteurs réclament plusieurs ampères au démarrage. Deux cellules lithium-ion 18650 en série (2S) donnent 8,4 V pleines et 7,4 V en moyenne, et fournissent sans peine plusieurs ampères. L'Arduino Uno recommande 7–12 V sur son entrée VIN : le même pack peut donc alimenter à la fois les moteurs et l'Arduino. Avec des cellules de 2500 mAh, une voiture 2WD qui consomme en moyenne 0,8 A en roulant (moteurs et cartes compris) tient en théorie environ 3 heures ; comme on ne vide jamais complètement l'accu, 2–2,5 heures est un chiffre plus réaliste. Pour calculer avec tes propres valeurs, utilise l'outil Autonomie de batterie.

| Source d'alimentation | Tension | Courant disponible | Pour une voiture robot |
|---|---|---|---|
| Pile 9 V | 9 V | Très faible | Inadaptée ; la cause de redémarrage la plus fréquente |
| 4 piles AA alcalines | 6 V (chute vite en charge) | Moyen | Faible ; après le L298N, il ne reste qu'environ 4 V aux moteurs |
| 4 accus AA NiMH | 4,8 V | Bon | Tension insuffisante avec le L298N |
| 2 accus 18650 Li-ion (2S) | 7,4 V (8,4 V pleins) | Élevé (plusieurs ampères) | Le meilleur choix |
| 3 accus 18650 Li-ion (3S) | 11,1 V (12,6 V pleins) | Élevé | Trop pour des moteurs TT ; dépasse la limite de 12 V du cavalier 5V |
| Batterie externe USB | 5 V | Bon | Uniquement pour alimenter l'Arduino séparément |
Plutôt que de deviner l'autonomie restante, tu peux la mesurer. Relie le plus de l'accu (après l'interrupteur) à A0 via un pont diviseur de tension formé de deux résistances de 10 kΩ : un pack de 8,4 V apparaît comme 4,2 V sur A0, sous la limite de lecture de 5 V de l'Arduino. Le pont ne consomme qu'environ 0,4 mA et n'affecte donc pas l'autonomie.
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}Montage pas à pas
- Retire le film protecteur des pièces en acrylique. Si les moteurs sont livrés sans fils, soude deux fils sur chaque moteur et renforce les soudures à la colle chaude ; un fil de moteur arraché par les vibrations est la panne la plus fréquente.
- Fixe les moteurs sous le châssis avec les supports acryliques en forme de T et les longues vis M3 du kit. Les deux axes doivent être alignés et les cosses des moteurs tournées vers l'intérieur.
- Si tu comptes utiliser les disques d'encodeur, monte-les maintenant côté intérieur de l'axe du moteur ; une fois les roues en place, c'est difficile.
- Monte la roue folle au centre de l'autre extrémité du châssis avec des entretoises. Choisis une hauteur qui garde le châssis parallèle au sol.
- Enfonce les roues à fond en les alignant sur l'axe en forme de D ; une roue qui a du jeu fait dévier la voiture en permanence.
- Place le support d'accus avec de l'adhésif double face ou du scratch de façon que son poids soit proche de l'axe des roues. Si la majeure partie du poids repose sur la roue folle, les roues motrices patinent.
- Monte l'Arduino et le L298N sur le plateau supérieur avec des entretoises en plastique. Le port USB de l'Arduino doit rester facile d'accès et le dissipateur du L298N à l'air libre ; veille à ce que les vis métalliques ne touchent pas les soudures sous les cartes.
- Branche l'interrupteur en série sur le fil positif de l'accu ; tu pourras ainsi allumer et éteindre la voiture sans retirer les accus.
- Torsade les deux fils de chaque moteur jusqu'au L298N, garde tous les câbles courts et regroupe-les avec des colliers. Avant de mettre les accus, vérifie au multimètre qu'il n'y a pas de court-circuit entre les bornes de l'accu.
Schéma de câblage
Pense le câblage en deux parties : la partie puissance (accu, interrupteur, L298N, moteurs) et la partie signal (les fils fins qui vont de l'Arduino au L298N et au HC-05). Retire les petits cavaliers des broches ENA et ENB du L298N ; nous relierons ces broches aux sorties PWM de l'Arduino pour régler la vitesse par le code. Le cavalier 5V du L298N, lui, reste en place : le pack étant sous 12 V, le régulateur de la carte alimente la logique du driver.

| Borne du L298N | Branchement |
|---|---|
| OUT1, OUT2 | Moteur gauche (en 4WD, les deux moteurs gauches en parallèle) |
| OUT3, OUT4 | Moteur droit (en 4WD, les deux moteurs droits en parallèle) |
| 12V | Plus de l'accu via l'interrupteur |
| GND | Moins de l'accu et broche GND de l'Arduino (masse commune) |
| 5V | Non branchée avec l'Arduino Uno ; alimente la carte avec l'ESP32 et le Pico |
| Cavalier 5V | Reste en place (accu sous 12 V) |
| Cavaliers ENA et ENB | Retirés ; les broches vont aux sorties PWM de l'Arduino |
| Branchement | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| L298N ENA (vitesse moteur gauche) | D5 (PWM) | GPIO 25 | GP15 |
| L298N IN1 | D7 | GPIO 27 | GP14 |
| L298N IN2 | D8 | GPIO 33 | GP13 |
| L298N ENB (vitesse moteur droit) | D6 (PWM) | GPIO 26 | GP10 |
| L298N IN3 | D9 | GPIO 32 | GP12 |
| L298N IN4 | D4 | GPIO 4 | GP11 |
| HC-05 TXD | D10 (RX SoftwareSerial) | Inutile (Bluetooth intégré) | GP1 (RX UART0) |
| HC-05 RXD | D11, via un pont 1 kΩ / 2 kΩ | Inutile | GP0 (TX UART0), en direct |
| HC-05 VCC | 5V | Inutile | Sortie 5V du L298N |
| Alimentation de la carte | VIN ← plus de l'accu après l'interrupteur | 5V (VIN) ← sortie 5V du L298N | VSYS ← sortie 5V du L298N |
| GND | Commun avec le GND du L298N et le moins de l'accu | Commun | Commun |
Nous avons choisi D5 et D6 comme broches de vitesse exprès. Sur le Uno, la bibliothèque Servo désactive la PWM des broches 9 et 10, et la fonction tone() celle des broches 3 et 11. Avec ENA et ENB sur 5 et 6, ton réglage de vitesse continue de fonctionner quand tu ajoutes plus tard un servo ou un buzzer. D2 et D3 sont réservées aux encodeurs car elles gèrent les interruptions. Tu peux voir le brochage de ta carte dans l'outil Pinout.
Premier programme : avancer, reculer, tourner à gauche et à droite
Avant de passer au Bluetooth, testons les moteurs et le câblage seuls. Le cœur du code est la fonction drive(gauche, droite) : elle reçoit la vitesse de chaque moteur séparément, de -255 à 255 ; une valeur positive veut dire marche avant, une valeur négative marche arrière et zéro l'arrêt. Nous expliquons comment la valeur de vitesse devient une tension dans Qu'est-ce que la PWM ?. Avant de téléverser, pose la voiture sur une boîte pour que les roues tournent dans le vide ; l'attente de 3 secondes dans setup() te laisse le temps de le faire.
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}| Mouvement | Moteur gauche | Moteur droit | Code |
|---|---|---|---|
| Avancer | Avant | Avant | drive(180, 180) |
| Reculer | Arrière | Arrière | drive(-180, -180) |
| Pivoter à gauche sur place | Arrière | Avant | drive(-180, 180) |
| Pivoter à droite sur place | Avant | Arrière | drive(180, -180) |
| Large virage à gauche | Avant lent | Avant | drive(90, 180) |
| Arrêt | Arrêté | Arrêté | drive(0, 0) |
Roues dans le vide, la voiture doit successivement avancer, reculer, tourner à gauche puis à droite. Si une roue tourne à l'envers, ne touche pas au code : inverse les deux fils de ce moteur sur la borne OUT du L298N. Si les deux roues tournent à l'envers, inverse les fils des deux moteurs. Si les moteurs bourdonnent sans tourner, la valeur SPEED est trop basse : la plupart des moteurs TT ont besoin d'une valeur PWM d'au moins 80–120 environ pour démarrer, et ce seuil augmente à mesure que l'accu se vide.
Pilotage Bluetooth depuis le smartphone (HC-05)
Le HC-05 fonctionne comme un câble série sans fil entre le smartphone et l'Arduino : l'application envoie une lettre, l'Arduino la lit et exécute le mouvement correspondant. La plupart des applications de télécommande que tu trouves sur le Play Store en cherchant "Bluetooth RC Car" ou "Bluetooth RC Controller" envoient F pour avancer, B pour reculer, L pour la gauche, R pour la droite et S pour l'arrêt quand tu relâches un bouton ; certaines utilisent aussi G, I, H et J pour les diagonales, ainsi que 0–9 et q pour la vitesse. Les broches, les clignotements de la LED et les commandes AT du module sont détaillés dans Module Bluetooth HC-05.

- Pendant le téléversement du code ci-dessous, l'interrupteur de la voiture peut rester éteint ; l'Arduino et le HC-05 sont alimentés par l'USB. Si la LED du HC-05 clignote vite, le module attend une connexion.
- Cherche le HC-05 dans les réglages Bluetooth de ton smartphone Android et appaire-le avec le code 1234 (ou 0000 en cas d'échec).
- Ouvre l'application de télécommande, accorde les autorisations Bluetooth et appareils à proximité, puis choisis le HC-05 dans la liste. Une fois connecté, la LED du module fait deux brefs clignotements toutes les deux secondes.
- Laisse l'Arduino branché en USB, ouvre le moniteur série à 9600 bauds et appuie sur les boutons de l'application. La lettre envoyée par chaque bouton s'affiche ; si ton application envoie d'autres lettres, adapte les lignes case du code.
- Débranche le câble USB, allume l'interrupteur, pose la voiture au sol et pilote.
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}| Lettre | Mouvement | Moteur gauche / droit |
|---|---|---|
| F | Avancer | +vitesse / +vitesse |
| B | Reculer | −vitesse / −vitesse |
| L | Pivoter à gauche | −vitesse / +vitesse |
| R | Pivoter à droite | +vitesse / −vitesse |
| G, I | Avant-gauche, avant-droite | Un côté à mi-vitesse |
| H, J | Arrière-gauche, arrière-droite | Un côté à mi-vitesse |
| S | Arrêt | 0 / 0 |
| 0–9, q | Niveau de vitesse | 0 → 100, 9 → 240, q → 255 |
Le TIMEOUT du code est une sécurité : ces applications renvoient la même lettre en boucle tant que tu maintiens un bouton, donc si aucune lettre n'arrive pendant 600 ms, le code considère que la liaison est coupée et arrête la voiture. Ainsi, la voiture ne continue pas vers le mur si le smartphone sort de portée ou si l'application se ferme. Si ton application n'envoie la lettre qu'une fois par appui, la voiture s'arrêtera au bout de 600 ms ; dans ce cas, mets TIMEOUT à 0 pour désactiver cette fonction. Nous n'avons d'ailleurs utilisé delay() nulle part dans loop() ; les longues attentes retardent les commandes, et tu trouveras pourquoi dans millis() ou delay().
La voiture ne roule pas droit : causes et solution
Si la voiture dérive lentement d'un côté alors que tu donnes la même valeur PWM aux deux moteurs pour "avancer", pas d'inquiétude : c'est le problème le plus courant des voitures robots. Les motoréducteurs bon marché tournent à des vitesses différentes même à tension égale ; les différences de frottement des engrenages, de balais et d'aimants rendent chaque moteur un peu différent. Ajoute une roue qui a du jeu, une roue folle qui change d'orientation ou un poids mal réparti, et une dérive de 20–30 cm sur 2 mètres est tout à fait normale. Élimine d'abord les causes mécaniques, puis corrige la différence restante par logiciel.
| Symptôme | Cause probable | Solution |
|---|---|---|
| Dérive toujours du même côté | Les moteurs ne tournent pas à la même vitesse | Correction logicielle avec TRIM, ou encodeurs |
| Fait un écart au démarrage puis se redresse | Un moteur démarre plus tard ou la roue folle pivote | Démarrage progressif ; roue à bille (ball caster) au lieu de la roue folle |
| La dérive change à chaque essai | Roue avec du jeu, pneu qui glisse ou support moteur tordu | Enfonce bien la roue sur l'axe, resserre les vis |
| Pivote sur place au lieu d'avancer | Les fils d'un moteur sont inversés | Inverse les fils de ce moteur sur la borne OUT |
| La dérive augmente quand l'accu se vide | À basse tension, l'écart entre les moteurs grandit | Recharge l'accu ; règle TRIM avec un accu plein |
| Tire d'un côté en accélérant | Le poids est d'un seul côté | Place l'accu et les cartes au centre, près de l'axe des roues |
Une fois les problèmes mécaniques réglés, fais le réglage fin par logiciel. La constante TRIM du code ralentit en pourcentage le moteur le plus rapide : une valeur positive ralentit le moteur gauche, une valeur négative le droit. Procède ainsi :
- Charge complètement les accus ; un réglage avec un accu plein donne des résultats cohérents.
- Colle au sol une bande adhésive droite de 2 mètres et place la voiture à son début, dans l'axe de la bande.
- Dans loop() du premier programme, ne garde que forward() et une attente de 3 secondes, puis laisse la voiture avancer.
- Si la voiture dérive à droite, le moteur gauche est plus rapide : augmente TRIM de 3 ; si elle dérive à gauche, diminue TRIM de 3.
- Recommence jusqu'à ce que la dérive sur 2 mètres ne soit plus que de quelques centimètres, puis reporte la même valeur de TRIM dans le code Bluetooth.
- Fais le réglage à la vitesse que tu utilises le plus ; l'écart entre les moteurs varie un peu avec la vitesse.
Le niveau suivant pour rouler parfaitement droit et mesurer les distances, c'est l'encodeur. Tu montes les disques à 20 fentes du kit sur les axes des moteurs et tu comptes chaque fente avec un capteur de vitesse à fourche basé sur le LM393. Relie les sorties des capteurs aux broches D2 et D3, qui gèrent les interruptions, et compare le nombre d'impulsions des deux roues : si le côté gauche prend de l'avance, ralentis un peu le moteur gauche. Cette simple régulation proportionnelle (P) garde la voiture droite quels que soient la charge de l'accu et le sol. Une roue de 65 mm parcourt environ 20,4 cm par tour, chaque impulsion correspond donc à environ 1 cm. Nous expliquons le fonctionnement des interruptions dans Les interruptions sur Arduino.
L'Arduino redémarre quand les moteurs démarrent
Si l'Arduino redémarre ou si le HC-05 perd la connexion (la LED se remet à clignoter vite) quand la voiture démarre, change de sens ou heurte un obstacle, le problème vient presque toujours de l'alimentation. Au démarrage, deux moteurs peuvent appeler ensemble 2–3 A ; un accu faible ne peut pas les fournir et sa tension s'effondre un instant. Le processeur du Uno se réinitialise par sécurité quand son alimentation passe sous 2,7 V (brown-out). S'y ajoutent les parasites électriques des balais des moteurs et la chute de tension dans des fils trop fins. Voici les solutions, de la plus efficace à la moins efficace :
- Change d'accu : utilise deux accus 18650 chargés au lieu d'une pile 9 V ou de piles AA fatiguées ; la plupart des problèmes s'arrêtent là.
- Le bon chemin d'alimentation : alimente l'Arduino depuis l'accu par VIN ; ne relie pas la sortie 5V du L298N à VIN.
- Condensateurs sur les moteurs : soude un condensateur céramique de 100 nF entre les deux bornes de chaque moteur ; il étouffe les parasites des balais à la source.
- Condensateur réservoir : branche un électrolytique de 470–1000 µF sur les bornes 12V et GND du L298N (plus sur 12V). Il couvre le bref appel de courant au démarrage.
- Démarrage progressif : au lieu de passer d'un coup à 255, augmente la vitesse par paliers comme ci-dessous ; le pic de courant diminue.
- S'arrêter avant d'inverser : passer directement de la marche avant à la marche arrière porte le courant du moteur au maximum ; arrête-toi 100–200 ms avant de changer de sens.
- Câbles d'alimentation épais et courts : pas de câbles Dupont ni de breadboard entre l'accu et le L298N ; utilise du fil d'au moins 0,5 mm² et des borniers.
- Alimentations séparées : si le problème persiste, alimente l'Arduino avec une batterie externe et les moteurs avec l'accu, et relie les deux 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()Voiture robot avec un ESP32 et un Raspberry Pi Pico
L'ESP32 intègre le Bluetooth classique, tu n'as donc pas besoin de HC-05 : la bibliothèque BluetoothSerial crée la même liaison série avec le smartphone et les applications de télécommande ci-dessus fonctionnent sans changement. Les entrées du L298N considèrent comme HIGH tout ce qui dépasse environ 2,3 V, donc les signaux 3,3 V de l'ESP32 suffisent. Alimente la carte ESP32 depuis la sortie 5V du L298N sur sa broche 5V (VIN) ; ne branche pas l'accu directement sur cette broche. Ce code ne compile pas pour l'ESP32-S3 et l'ESP32-C3, qui n'ont que le 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}Le Raspberry Pi Pico standard n'a pas de Bluetooth : tu branches donc le HC-05 sur les broches de l'UART0. Comme le Pico fonctionne en 3,3 V, aucun pont diviseur n'est nécessaire cette fois. Alimente le Pico par la broche VSYS et le HC-05 directement depuis la sortie 5V du L298N ; sur accu, sans USB, la broche VBUS n'a pas de tension. Dans le code du Pico, la vitesse est donnée en pourcentage de -100 à 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: stopÉtapes suivantes : améliore ta voiture
- Robot éviteur d'obstacles : ajoute à l'avant un capteur de distance HC-SR04 et un servomoteur qui le fait pivoter à gauche et à droite ; tous les détails dans le guide Robot éviteur d'obstacles.
- Robot suiveur de ligne : place 2–3 capteurs infrarouges TCRT5000 sous l'avant et suis une ligne noire au sol ; voir Robot suiveur de ligne.
- Télécommande à joystick : fabrique une vraie télécommande, sans smartphone, avec un second Arduino, un module joystick et un nRF24L01.
- Télécommande infrarouge : pilote avec les touches de la télécommande de ta télé ; associe les codes de Récepteur IR et télécommande aux commandes de déplacement.
- Pilotage en Wi-Fi : fais servir par un ESP32 une page de commande qui s'ouvre dans le navigateur du smartphone ; le guide Serveur web ESP32 et WebSocket en pose les bases.
- Encodeurs et distance : avec des capteurs de vitesse, fais avancer la voiture d'exactement 1 mètre et tourner de 90 degrés pile ; c'est la base des robots qui résolvent des labyrinthes.
- Bras robotique : installe sur la voiture un petit bras robotique à servos pour transporter des objets.



Erreurs fréquentes et solutions
- Aucun moteur ne tourne : les GND ne sont pas communs, l'interrupteur est éteint, les cavaliers ENA et ENB ont été retirés sans brancher les broches, ou l'accu est vide.
- La LED du L298N est allumée mais les moteurs bourdonnent seulement : la valeur PWM est sous le seuil de démarrage ou la tension de l'accu est basse ; augmente la vitesse et recharge l'accu.
- Le programme ne se téléverse pas : le port ou la carte sont peut-être mal sélectionnés ; si tu as branché le HC-05 sur les broches 0 et 1, débranche-le pendant le téléversement. Autres causes dans Impossible de téléverser sur Arduino.
- Le smartphone voit le HC-05 mais ne se connecte pas : le module est connecté à un autre téléphone, l'application n'a pas l'autorisation "appareils à proximité" ou le code d'appairage est faux.
- La voiture réagit en retard : il y a un delay() dans loop() ou trop d'affichages dans le moniteur série ; gère les attentes avec millis().
- Le dissipateur du L298N chauffe beaucoup : les roues forcent ou, en 4WD, le courant par canal est trop élevé ; vérifie les frottements mécaniques.
- La voiture tressaute à la mise sous tension : au démarrage, les broches sont indéfinies un court instant ; configure-les en sortie et appelle drive(0, 0) dès les premières lignes de setup().
Une voiture robot Arduino est un excellent point de départ qui enseigne la commande de moteurs, la gestion de l'alimentation, la communication sans fil et le débogage en un seul projet. Une fois terminée, tu disposes d'une base qui devient un peu plus intelligente à chaque nouveau capteur. Dans l'application BlueGrays, tu trouveras pas à pas, avec schémas et code, les projets voiture pilotée en Bluetooth avec L298N, robot éviteur d'obstacles et détection de sol noir et blanc avec TCRT5000.
Questions fréquentes
De quoi a-t-on besoin pour fabriquer une voiture Arduino et combien ça coûte ?
Pour une voiture Bluetooth simple, il suffit d'un kit châssis 2WD (2 moteurs TT, roues, roue folle), d'un Arduino Uno, d'un driver L298N, d'un module Bluetooth HC-05, de deux accus 18650 avec leur support et de quelques câbles Dupont. Les prix varient selon le vendeur ; les modules sont bon marché et l'essentiel du budget part dans la carte, le kit châssis et les accus avec leur chargeur. Si tu as déjà un kit de démarrage, le coût baisse nettement.
Quelle batterie utiliser pour une voiture robot Arduino ?
Le meilleur choix est deux accus lithium-ion 18650 en série : ils donnent 7,4 V, laissent 5–6 V aux moteurs après la perte d'environ 2 V du L298N et fournissent le fort courant nécessaire au démarrage. Une pile 9 V ne fournit pas assez de courant et provoque des redémarrages, et avec 4 piles AA les moteurs tournent lentement derrière un L298N.
Pourquoi ma voiture Arduino ne roule-t-elle pas droit ?
Les motoréducteurs bon marché tournent à des vitesses différentes même avec la même valeur PWM, et les roues qui ont du jeu, la roue folle et un poids mal réparti accentuent la dérive. Règle d'abord la mécanique, puis ralentis un peu le moteur le plus rapide avec une valeur de correction (trim) dans le code. Pour rouler parfaitement droit, il faut des encodeurs qui mesurent et égalisent la vitesse des deux roues.
Pourquoi mon Arduino redémarre-t-il quand les moteurs démarrent ?
Les moteurs appellent plusieurs ampères au démarrage et la tension d'un accu faible s'effondre un instant ; le processeur du Uno se réinitialise quand son alimentation chute. Utilise des accus 18650 chargés, ajoute des condensateurs de 100 nF sur les bornes des moteurs et un de 470–1000 µF sur l'entrée du L298N, et augmente la vitesse progressivement. Si le problème persiste, alimente l'Arduino par une source séparée et relie les GND.
Une voiture Bluetooth avec HC-05 fonctionne-t-elle avec un iPhone ?
Non. Le HC-05 et le HC-06 utilisent le profil port série du Bluetooth classique, et iOS n'autorise pas les applications ordinaires à ouvrir ce type de liaison. Pour piloter depuis un iPhone, il te faut un module BLE comme le HM-10 ou un ESP32 avec BLE ; les smartphones Android se connectent sans problème au HC-05.
Peut-on utiliser un shield moteur L293D à la place du L298N ?
Oui. Le shield moteur L293D s'enfiche sur l'Arduino Uno et peut piloter quatre moteurs CC, ce qui simplifie le câblage d'une voiture 4WD. Mais son courant permanent n'est que d'environ 0,6 A par canal : il atteint ses limites plus vite que le L298N quand les moteurs se bloquent, et le shield occupe beaucoup de broches. Pour plus d'efficacité, les drivers à MOSFET comme le TB6612FNG perdent beaucoup moins de tension.
Projets à réaliser après cet article
Voir tous les projets
Voiture contrôlée par Bluetooth avec L298N
Projet de voiture robot 4WD (quatre moteurs, quatre roues motrices) qui peut être contrôlée depuis le téléphone avec Arduino et le module Bluetooth HC-05. Un total de quatre roues est entraîné simulta

Robot évitant les obstacles
Que diriez-vous de construire un véhicule intelligent qui trouve son propre chemin ? Le Robot Évitant les Obstacles scrute en permanence son environnement grâce au capteur ultrasonique situé devant lu

Contrôler une LED depuis un téléphone via Bluetooth
Projet de contrôle sans fil qui permet d'allumer et d'éteindre des LED à l'aide de commandes envoyées depuis un téléphone équipé d'un module Bluetooth HC-06. Enseigne l'échange de données Bluetooth pa

TCRT5000 Détection de surface noire et blanche
Projet qui détecte la couleur du sol avec le capteur TCRT5000 et allume une LED rouge sur un sol noir et une LED verte sur un sol blanc. Il enseigne la logique de détection du seuil de couleur qui con

Mesure de distance avec TCRT5000
Projet qui mesure la quantité de lumière réfléchie par la surface avec le capteur infrarouge TCRT5000 et l'affiche sous forme de valeur analogique sur l'écran LCD I2C. Enseigne les bases de la détecti

HC-SR04 Mesure de la distance (affichage en série)
Le capteur ultrasonique HC-SR04 permet de mesurer la distance et d'afficher le résultat en cm sur le moniteur série. Il enseigne le principe du calcul de la distance à l'aide d'une onde sonore.

Capteur de stationnement avec HC-SR04
Projet de capteur de stationnement avec un capteur HC-SR04 qui augmente la fréquence du buzzer à l'approche de l'objet et l'avertit par une LED. Enseigne la logique de retour d'information proportionn

Utilisation du servomoteur
Projet d'utilisation de base qui positionne le servomoteur à des angles de 0°, 90° et 180° dans l'ordre. Enseigne la bibliothèque des servos et la logique de contrôle des angles.

