Projet DIY

Robot 2 roues autonome avec Raspberry Pi : le tutoriel complet

Le projet parfait pour démarrer en robotique DIY : construire un petit robot mobile qui évite les obstacles, avec un Raspberry Pi, un module L298N, deux moteurs et un capteur ultrason. Matériel, câblage, code Python commenté.

Au club scout de Saint-Herblain où j’anime des ateliers robotique un samedi sur deux, le projet « robot qui roule et évite un mur » est devenu le rite de passage. Deux heures, quarante euros de composants, une poignée de jeunes entre 12 et 16 ans, et à la fin de l’après-midi chaque groupe repart avec un robot qui avance sur le bitume de la cour jusqu’à détecter un mur à vingt centimètres, faire marche arrière, pivoter, repartir. C’est ce projet exact qu’on te propose de reproduire ici, détaillé assez pour que tu le fasses seul, chez toi, à ton rythme.

Ce que tu vas construire

Un robot à deux roues motrices, contrôlé par un Raspberry Pi, avec un capteur ultrason HC-SR04 fixé à l’avant. Le code Python pilote les moteurs via un driver L298N et lit la distance au mur en continu. Dès que la distance passe sous le seuil de vingt centimètres, le robot recule pendant une demi-seconde, tourne sur lui-même pendant un quart de seconde, puis repart droit devant. Quarante lignes de code, six fils à brancher (en plus de l’alimentation), et un résultat visible en deux heures.

Ce n’est pas un robot intelligent. C’est un robot qui réagit. La nuance est importante : il ne cartographie pas la pièce, il ne mémorise pas les obstacles, il ne planifie pas de trajectoire. Il se contente de répondre « je vois un mur, je tourne ». C’est précisément pour ça qu’il fonctionne comme premier projet : le code est lisible, le comportement est prévisible, et les erreurs se diagnostiquent en dix secondes.

Liste complète du matériel

Voici ce que j’achète pour chaque groupe de trois scouts. Tout est disponible chez Gotronic ou sur AliExpress avec un délai de deux à trois semaines. Les prix indiqués sont ceux de début 2026.

ComposantRéférence typePrix indicatifRemarque
Châssis 2 roues avec moteurs DCKit « Smart Car 2WD »8-12 €Inclut 2 moteurs DC 3-6V, roues, roulette arrière, visserie
Module driver moteur L298NL298N dual H-bridge3-5 €Pilote les 2 moteurs simultanément
Capteur ultrason HC-SR04HC-SR041,50-3 €Mesure distance 2 cm à 400 cm
Raspberry Pi 4 ou 5 (4 Go)RPi 4B / RPi 545-60 €Pi 4 occasion 35 € est très bien
Carte microSD 32 GoSanDisk Extreme A18-12 €Flashée avec Raspberry Pi OS Lite
Batterie porteursSupport 4xAA (recommandé) ou LiPo 7,4V3-8 €4xAA = 6V, idéal pour moteurs 3-6V. La LiPo 7,4V en entrée du L298N donne 3,5 à 5V aux bornes du moteur après la chute de 2 à 4V dans le pont en H (Vce_sat des deux Darlington en série). Pour des moteurs 3-6V de kit, c’est suffisant mais sans marge. Les 4xAA à 6V en entrée donnent ~4V aux moteurs, résultat comparable. Préfère les piles AA si tu n’as pas d’expérience LiPo, tu évites le risque batterie.
Powerbank USB (alim Pi)5V 2A minimum, 5000mAh10-15 €Alimente le Pi séparément des moteurs
Breadboard mini + fils dupontMB-102 demi + 20 jumpers M-F3-5 €Ou prototypage soudé si tu préfères le définitif
Résistances 330 Ω et 470 Ω (×1 chaque)1/4W métal0,10 €Pour le pont diviseur du HC-SR04

Total : 80 à 120 euros avec Pi neuf, 35 à 60 euros si tu as déjà un Pi qui traîne. Le poste le plus cher est le Pi lui-même (45-60€ neuf). Les autres composants (kit châssis, L298N, HC-SR04, alimentation, breadboard, résistances) font ensemble entre 30 et 50€ selon fournisseur et qualité.

Ce qu’on n’achète pas (et pourquoi)

Pas de HAT moteur tout-en-un type Adafruit Motor HAT ou PiMotor. Ces cartes sont pratiques mais elles cachent le fonctionnement du pont en H, ce qui va à l’encontre du but pédagogique du projet. Le L298N à 4 euros fait le même travail, et tu comprends chaque fil que tu branches. C’est mon biais, je l’assume : mieux vaut trois fils de plus et savoir pourquoi le moteur tourne.

Principe du câblage

Le câblage se décompose en deux circuits indépendants qui partagent une seule chose : la masse (GND). Les confondre est la source de 80 % des problèmes en atelier.

Circuit 1 : alimentation + moteurs

La batterie (4xAA = 6V, ou LiPo 7,4V) alimente le L298N par ses bornes VIN et GND. Le L298N distribue ensuite le courant aux deux moteurs via ses sorties OUT1/OUT2 (moteur gauche) et OUT3/OUT4 (moteur droit). Ce circuit ne passe jamais par le Pi. Les moteurs DC tirent entre 200 mA et 1 A au démarrage, ce qui grillerait les GPIO du Pi (max 16 mA par broche) en quelques secondes.

Circuit 2 : contrôle (Pi → L298N + capteur)

Le Raspberry Pi envoie des signaux logiques (3,3V, quelques milliampères) au L298N pour lui dire quoi faire : avancer, reculer, tourner, accélérer. Le Pi lit aussi le capteur ultrason HC-SR04 pour mesurer la distance au mur. L’alimentation du Pi vient d’une source séparée (powerbank USB ou alim secteur), pas de la batterie des moteurs.

Tableau de câblage GPIO

ComposantBroche composantGPIO PiRemarque
L298NIN1GPIO 17Direction moteur gauche
L298NIN2GPIO 27Direction moteur gauche
L298NIN3GPIO 22Direction moteur droit
L298NIN4GPIO 23Direction moteur droit
L298NENAGPIO 12 (PWM hardware)Vitesse moteur gauche. GPIO 12 est une broche PWM matérielle (canal PWM0), plus stable que le PWM logiciel pour le contrôle moteur.
L298NENBGPIO 13 (PWM hardware)Vitesse moteur droit. GPIO 13 = canal PWM1.
HC-SR04TRIGGPIO 24Déclencheur ultrason (3,3V OK)
HC-SR04ECHOGPIO 25 via pontSignal retour divisé de 5V → 3,3V
HC-SR04VCCPin 2 (5V Pi)Alim capteur
TousGNDPin 6 (GND Pi)Masse commune obligatoire

Le pont diviseur sur ECHO (obligatoire)

Le HC-SR04 fonctionne en 5V. Sa broche ECHO renvoie un signal à 5V. Le GPIO du Pi supporte au maximum 3,3V en entrée. Brancher ECHO directement sur le GPIO, c’est risquer d’endommager le SoC du Pi. La solution tient en deux résistances : un pont diviseur avec R1 = 330 Ω en série et R2 = 470 Ω vers la masse. Le calcul : 5V × 470 / (330 + 470) = 2,94V, valeur safe pour le GPIO.

Si tu utilises la bibliothèque gpiozero (ce qu’on fait dans ce tuto), elle gère le timing du signal ECHO automatiquement. Mais le pont diviseur matériel reste indispensable.

Installer le système

Flashe Raspberry Pi OS Lite (64-bit, sans bureau graphique) sur la carte microSD avec Raspberry Pi Imager. Active SSH et configure le Wi-Fi dans les paramètres avancés d’Imager, parce qu’on ne branchera jamais d’écran sur ce Pi. Le tutoriel d’installation détaillé de Claire couvre ça étape par étape si c’est la première fois.

Une fois le Pi démarré et connecté en SSH, installe les dépendances :

sudo apt update && sudo apt upgrade -y
sudo apt install python3-gpiozero python3-lgpio -y

gpiozero est la bibliothèque de contrôle GPIO qu’on va utiliser. Elle est préinstallée sur Raspberry Pi OS Desktop, mais pas sur Lite. lgpio est le backend matériel pour Pi 5 (et fonctionne aussi sur Pi 4).

Le code Python complet

Voilà le script en entier. Je l’explique section par section juste après.

#!/usr/bin/env python3
"""
robot_evite.py — Robot 2 roues évite-obstacles
Auteur : Rémi Favreau (rasrobot.com)
Matériel : Raspberry Pi + L298N + HC-SR04

# TODO: refacto cette fonction tourner_droite, elle est moche
#       (version rapide pour atelier du 12 mars, jamais nettoyée)
"""

from gpiozero import Motor, DistanceSensor
from time import sleep
from signal import pause
import sys

# --- Configuration des GPIO ---
moteur_gauche = Motor(forward=17, backward=27, enable=12)
moteur_droit  = Motor(forward=22, backward=23, enable=13)
capteur       = DistanceSensor(echo=25, trigger=24, max_distance=2)

# --- Paramètres réglables ---
SEUIL_CM      = 20      # distance déclenchement en cm
VITESSE       = 0.7     # 0.0 à 1.0 (70 % par défaut)
DUREE_RECUL   = 0.5     # secondes de marche arrière
DUREE_ROTATION = 0.4    # secondes de rotation sur place

def avancer():
    moteur_gauche.forward(VITESSE)
    moteur_droit.forward(VITESSE)

def reculer():
    moteur_gauche.backward(VITESSE)
    moteur_droit.backward(VITESSE)

def tourner_droite():
    moteur_gauche.forward(VITESSE)
    moteur_droit.backward(VITESSE)

def stop():
    moteur_gauche.stop()
    moteur_droit.stop()

# --- Boucle principale ---
print("Robot démarré. Ctrl+C pour arrêter.")

try:
    while True:
        distance_m = capteur.distance    # en mètres
        distance_cm = distance_m * 100

        if distance_cm < SEUIL_CM:
            print(f"  Obstacle à {distance_cm:.0f} cm — recul + rotation")
            stop()
            sleep(0.1)
            reculer()
            sleep(DUREE_RECUL)
            stop()
            sleep(0.1)
            tourner_droite()
            sleep(DUREE_ROTATION)
            stop()
            sleep(0.1)
        else:
            avancer()

        sleep(0.05)   # 20 mesures par seconde

except KeyboardInterrupt:
    print()  # saut de ligne
    print("Arrêt propre.")
    stop()
    sys.exit(0)

Ce que fait chaque partie

Les imports : gpiozero fait le travail dur (gestion des signaux GPIO, calcul de distance ultrason, PWM des moteurs). On n'utilise rien d'autre que la bibliothèque standard Python et gpiozero.

La configuration GPIO : Motor(forward=17, backward=27, enable=12) crée un objet moteur qui sait avancer (IN1 haut, IN2 bas) et reculer (l'inverse). Le paramètre enable active le contrôle de vitesse par PWM sur ENA/ENB du L298N. Si tu ne veux pas de contrôle de vitesse (moteurs toujours à fond), retire enable et laisse le jumper du L298N en place.

Le capteur : DistanceSensor(echo=25, trigger=24, max_distance=2) mesure la distance en mètres via le HC-SR04. Le max_distance=2 fixe la portée max à 2 mètres, ce qui est largement suffisant en intérieur et réduit le risque d'échos parasites.

La boucle : vingt fois par seconde (toutes les 50 ms), le script lit la distance. Si elle passe sous 20 cm, il stoppe, recule un demi-seconde, tourne un quart de seconde, puis repart. Le petit sleep(0.1) entre chaque changement de direction protège le L298N d'un changement de sens trop brutal (les bobines des moteurs n'aiment pas les inversions instantanées).

Le cleanup Ctrl+C : sans le bloc try/except KeyboardInterrupt, le script crasherait sans appeler stop() et les moteurs resteraient sous tension. Mauvais pour les batteries et potentiellement dangereux si le robot est sur une table.

Lancer le robot

Pose le robot sur le sol (pas sur une table, au cas où il fonce en avant au premier test), et depuis ta session SSH :

python3 robot_evite.py

Si tout est bien câblé, le robot démarre immédiatement. Tu devrais voir dans le terminal les messages de distance chaque fois qu'il détecte un obstacle.

Les trois pannes classiques du premier essai

Le robot ne bouge pas du tout. Vérifie d'abord que la batterie moteurs est chargée et connectée au L298N (LED rouge du L298N allumée). Puis vérifie que le jumper 5V du L298N est en place (ou qu'une alim logique est connectée). Enfin, vérifie que les fils IN1-IN4 vont bien aux bons GPIO.

Un moteur tourne à l'envers. C'est la panne la plus fréquente et la plus facile à corriger. Inverse physiquement les deux fils du moteur concerné sur les bornes OUT du L298N, ou permute forward et backward dans le code pour ce moteur.

Le capteur donne toujours la même distance (0 ou max). Trois causes dans l'ordre de fréquence : le pont diviseur est mal câblé, TRIG et ECHO sont inversés (je me souviens d'un gamin au club qui a passé deux heures sur ce bug avant qu'on comprenne), ou le capteur est défectueux (ça arrive sur les lots à 1 euro AliExpress). Teste le capteur seul avec un script minimal :

from gpiozero import DistanceSensor
from time import sleep

capteur = DistanceSensor(echo=25, trigger=24)

while True:
    print(f"Distance : {capteur.distance * 100:.1f} cm")
    sleep(0.5)

Passe la main devant le capteur : la distance affichée doit varier en temps réel. Si elle reste fixe, le problème est matériel. Si elle varie, le problème est dans le câblage moteur ou le reste du code principal.

Ajustements après le premier test

Les réglages qui changent le comportement du robot :

  • SEUIL_CM = 20 : trop bas et le robot frôle les murs avant de réagir. Trop haut et il tourne trop souvent. En intérieur, 15 à 25 cm marchent bien.
  • VITESSE = 0.7 : 70 % est un bon compromis. À 100 % le robot est vif mais les virages sont brusques. À 40 % il est mou mais plus précis dans les espaces étroits.
  • DUREE_RECUL = 0.5 : raccourcir si le robot recule trop loin. Allonger si la roulette arrière accroche et empêche le pivotement.
  • DUREE_ROTATION = 0.4 : raccourcir pour des virages serrés (45°), allonger pour des demi-tours complets (180° prend environ 0.8 à 1 seconde selon la surface et le poids).
  • sleep(0.05) en fin de boucle : si le robot réagit trop lentement aux murs, descends à 0.03. Si le CPU chauffe, monte à 0.1.

Sécurité et bonnes pratiques

Quelques trucs que j'ai appris à la dure en atelier.

  • Ne jamais laisser le robot sur une table sans surveillance. Il suffit d'un capteur mal orienté pour qu'il fonce dans le vide. Tester au sol, toujours.
  • Batteries LiPo : ne pas décharger sous 3,3 V par cellule (7,4V LiPo = ne pas descendre sous 6,6V total). En dessous, la cellule se dégrade irréversiblement. Si tu débutes, les piles AA sont plus pardonnantes.
  • Couper l'alimentation moteurs en premier quand tu veux modifier le câblage. Le Pi peut rester allumé, mais les moteurs sous tension + des fils qui bougent = court-circuit possible sur le L298N.
  • Pas vraiment une règle mais un réflexe : j'ai toujours un multimètre branché en parallèle sur la batterie moteurs pendant les tests. Quand la tension passe sous 6V sur un pack 4xAA (ou sous 6,6V sur une LiPo 2S), je coupe. Les batteries en bas de décharge ont un comportement bizarre qu'on prend parfois pour un bug logiciel.

Questions fréquentes

Peut-on faire ce robot avec un Arduino à la place du Raspberry Pi ?

Oui, et c'est même souvent plus simple pour ce projet précis. L'Arduino est temps réel, consomme 10 fois moins, et n'a pas besoin d'OS à booter. Les seuls gains du Raspberry Pi ici sont l'option future d'ajouter une caméra ou du Wi-Fi. Pour un robot évite-obstacles basique sans extensions, un Arduino Nano fait l'affaire pour 10 € au lieu de 60 €.

Quelle autonomie de batterie peut-on attendre ?

Avec 4xAA NiMH de 2 500 mAh en alimentation moteurs et un powerbank 5 000 mAh pour le Pi : compter 2 à 3 heures en roulage continu pour le Pi 4, 1h30 à 2h pour le Pi 5 (qui consomme plus). Les AA s'épuisent généralement avant le powerbank. Avec une LiPo 7,4V 2 200 mAh côté moteurs, l'autonomie double mais la complexité aussi.

Le Raspberry Pi Zero 2W fonctionne-t-il pour ce projet ?

Oui, avec des réserves. Le Zero 2W est moins puissant mais suffit largement pour le code Python du tuto (consommation CPU négligeable). Deux limitations : il faut souder des pin-headers GPIO (le Zero 2W est livré sans), et il a moins de ports USB pour brancher une manette ou une caméra. Pour un robot minimaliste embarqué où le Pi doit être discret, le Zero 2W est un excellent choix.

Quelle différence entre L298N et TB6612FNG ou DRV8833 ?

Le L298N est le driver historique (années 1990, transistors bipolaires). Sa chute de tension de 2 à 4V gaspille de l'énergie en chaleur et réduit la tension disponible pour les moteurs. Le TB6612FNG (Toshiba) et le DRV8833 (Texas Instruments) sont basés sur MOSFET : chute ~0,3V, rendement 90 % contre 70 % pour le L298N. Ils coûtent 2 à 3 € (comparables) mais il faut les souder soi-même (pas de bornier à vis). Pour apprendre : L298N. Pour la version finale d'un projet qui doit durer : DRV8833 ou TB6612FNG.

Comment ajouter un deuxième capteur ultrason latéral ?

Quatre broches GPIO libres suffisent : un TRIG et un ECHO (via pont diviseur 330/470 Ω) par capteur. Côté code, on ajoute un deuxième objet DistanceSensor(echo=X, trigger=Y) et on lit les deux dans la boucle principale. Logique simple : si l'obstacle de face est proche, on tourne vers le côté le plus dégagé. Ça corrige le défaut du tuto actuel (le robot tourne toujours à droite).

Puis-je alimenter les moteurs depuis le même powerbank que le Pi ?

Techniquement oui via la sortie 5V du L298N, mais je le déconseille. Les pics de courant au démarrage des moteurs font chuter la tension du powerbank, ce qui peut faire rebooter le Pi. Mieux : powerbank dédié au Pi, pack de piles AA ou LiPo dédié aux moteurs. C'est le coût de 3-5 € de support AA pour éviter la moitié des problèmes de fiabilité que je vois en atelier.

Aller plus loin

Le robot qui évite un mur, c'est la version zéro. Une fois que ça roule, voilà quatre directions dans lesquelles j'ai vu les jeunes du club continuer naturellement.

  • Deux capteurs latéraux : ajouter un HC-SR04 à gauche et un à droite pour que le robot choisisse le meilleur côté au lieu de toujours tourner à droite. Coût : 3 euros, 4 lignes de code en plus.
  • Pilotage Wi-Fi : un serveur Flask sur le Pi expose des routes /avancer, /reculer, /gauche, /droite, /stop. On pilote depuis le navigateur du téléphone. L'atelier « télécommande Wi-Fi » prend environ trois heures.
  • Suivi de ligne : remplacer le capteur ultrason par trois capteurs IR TCRT5000 en barre sous le châssis, et faire suivre une ligne noire au sol. C'est le projet suivant que les jeunes du club préfèrent.
  • Caméra et vision : coller une Pi Camera v3 et utiliser OpenCV pour détecter un objet coloré précis (une balle rouge, par exemple). Nettement plus complexe, mais le résultat impressionne les parents lors des démonstrations.

Le guide complet « construire son premier robot DIY » détaille ces extensions et les concepts théoriques qui vont avec (PID, odométrie, cinématique). Si tu veux d'abord comprendre les bases des capteurs avant de modifier le projet, l'article sur les 5 capteurs indispensables en robotique est un bon point de départ.

Si ton robot roule et que tu veux partager le résultat ou poser une question de câblage, passe par la page contact. Les photos de robots qui marchent, même (surtout) imparfaits, sont exactement ce qu'on aime voir ici.

Autres projets DIY