Construire un robot à roues Mecanum Arduino : Mobilité 360° Guide DIY
Dans ce tutoriel, nous allons apprendre à construire un robot à roues Mecanum piloté par Arduino, capable de se déplacer dans n'importe quelle direction. Cette mobilité unique est obtenue grâce à des roues spéciales : les roues Mecanum. Vous pouvez regarder la vidéo suivante ou lire le tutoriel écrit ci-dessous. J'ai conçu et imprimé en 3D ces roues car elles sont assez chères à l'achat. Elles fonctionnent très bien et piloter cette plateforme robot est vraiment amusant. Contrôle sans fil via modules radio NRF24L01, ou dans mon cas, via mon émetteur RC DIY (vidéo précédente). Contrôle aussi possible via smartphone en Bluetooth. J'ai créé une application Android personnalisée pour contrôler le robot dans toutes les directions, avec curseur de vitesse. Le cerveau est une carte Arduino Mega contrôlant chaque roue individuellement. Chaque roue est montée sur un moteur pas-à-pas NEMA 17. Grâce au contrôle précis des pas-à-pas, j'ai ajouté une fonction de programmation automatique dans l'app : bouton « Save » pour enregistrer chaque position/étape, puis lecture automatique en boucle. Même bouton pour pause, réinitialisation/suppression des étapes. Conception du robot via logiciel 3D. La base est un simple coffre en panneaux MDF 8mm. Quatre moteurs pas-à-pas fixés sur cette base, roues Mecanum sur les arbres moteurs. Modèle 3D disponible en téléchargement et exploration navigateur sur Thangs. Télécharger le modèle d'assemblage 3D sur Thangs. Fichiers STL pour impression 3D : Une roue Mecanum a des rouleaux sur sa circonférence, positionnés en diagonale (45°) par rapport à l'axe de rotation. Cela fait exercer une force diagonale quand la roue tourne avant/arrière. En faisant tourner les roues selon certains schémas, on utilise ces forces diagonales pour mouvoir le robot dans n'importe quelle direction. Il faut deux types de roues Mecanum : « gauchères » et « droitières ». La différence est l'orientation des rouleaux, elles doivent être installées à des positions précises. L'axe de rotation du rouleau supérieur de chaque roue doit pointer vers le centre du robot. Démonstration rapide des mouvements selon rotations : Base de la plateforme en panneaux MDF 8mm. Découpe à la scie sur table selon dimensions du modèle 3D. Perçage mèche 3mm et forêt 25mm sur panneaux latéraux pour fixation moteurs pas-à-pas. Assemblage colle à bois + vis. Point crucial : ouvertures moteurs précises pour contact uniforme des roues au sol. On pourrait aussi imprimer la base en 3D (fichier 3D inclus dans l'article). Peinture blanche en bombe sur base et couvercle. Roues Mecanum : deux parties (extérieur/intérieur) fixées par boulons/écrous M4. 10 rouleaux chacune, coupleur d'arbre pour moteur NEMA 17. Impression 3D pièces roues sur Creality CR-10. Fabrication axes des rouleaux : fil acier 3mm, longueur ~40mm, coupé à la meuleuse rotative. Assemblage roue : fixation deux côtés + coupleur par 4 boulons/écrous M4 (longueur 45mm). Installation rouleaux : insertion légère axe dans trous face intérieure, petite rondelle M3, rouleau, enfoncement axe dans encoche face extérieure. Une seule rondelle par manque de place pour la seconde. Répétition pour 10 rouleaux. Facile et ludique. Important : rouleaux doivent tourner librement. Quelques gouttes de colle cyanoacrylate dans chaque trou interne pour éviter desserrage. Roues prêtes → assemblage robot complet. Fixation moteurs pas-à-pas sur base : vis M3 12mm. Fixation roues sur arbres moteurs. Coupleur imprimé a logement pour écrou M3, boulon M3 traverse et fixe roue à l'arbre. Fixation couvercle supérieur : tiges filetées sur deux coins de la base, trous correspondants sur couvercle, insertion et serrage facile. Arrière de la base : trou 20mm pour interrupteur d'alimentation, 5mm pour LED. Électronique : schéma complet du projet. Contrôle 4 moteurs pas-à-pas NEMA 17 via 4 drivers DRV8825 (ou A4988). Alimentation 12V (batterie Li-Po 3S ~12V). Radio NRF24L01, Bluetooth HC-05. Diviseur de tension pour surveillance batterie, LED indicateur batterie < 11V. Régulateur 5V dédié (~3A) inclus (optionnel) : prévu pour futur combo avec mon projet bras robotique (servos 5V). Composants nécessaires : Pour organiser l'électronique et éviter le câblage en désordre, PCB custom via EasyEDA. Ce PCB agit comme shield Arduino MEGA (connexion directe par-dessus). Utilisation faces supérieures/inférieures pour routage. Broches Arduino inutilisées : connecteurs disponibles pour futures extensions. Inclus connecteurs 12V, 5V, GND, et sélection résolution pas (microstepping). Lien fichiers projet PCB. Génération fichiers Gerber pour fabrication. Commande chez JLCPCB (sponsor vidéo). Glisser-déposer Gerber, vérification visualiseur, sélection propriétés (couleur bleue pour assortir Arduino), commande prix raisonnable. Première commande : jusqu'à 10 PCB pour 2$. Réception quelques jours plus tard : qualité excellente, conforme au design. Soudure composants petits d'abord : résistances, condensateurs. Insertion/soudure connecteurs mâles pour connexion à l'Arduino. Connecteurs femelles en place et soudés. Pour connexions moteurs pas-à-pas et sélection microstepping : connecteurs mâles (connexion directe moteurs, jumpers pour microstepping). Soudure borniers, potentiomètre, régulateur. PCB prêt. Insertion drivers et connexion moteurs. Jumpers microstepping : 1/16 via connexion MS3 à 5V. Drivers DRV8825 par-dessus, modules NRF24L01 et HC-05. Fixation PCB sur Arduino. Connexion batterie au bornier, placement dans base. Interrupteur d'alimentation en place, connexion à l'autre bornier. LED indicateur batterie au-dessus de l'interrupteur. Connexion moteurs au PCB. Important : moteurs opposés → connecteurs inversés. Ainsi commande « avant » fait tourner les deux dans le même sens bien qu'inversés physiquement (un horaire, l'autre anti-horaire). Insertion couvercle supérieur → robot Mecanum terminé. Deux codes séparés : contrôle via NRF24L01 et contrôle via smartphone. Code pour contrôle radio NRF24L01 : Description : Bibliothèques RF24 (radio) et AccelStepper (pas-à-pas). Définition broches, variables, setup : vitesse max pas-à-pas, init radio. Loop : lecture données émetteur RC (voir tutoriel dédié). Selon données reçues (ex: joystick gauche avant >160 → moveForward()). Fonctions de mouvement : vitesse positive = avant, négative = arrière, combinaisons appropriées pour autres directions. Exécution via runSpeed() dans loop. Surveillance batterie via diviseur tension sur entrée analogique, LED si < 11V. Code pour contrôle smartphone : Description : Code similaire, module Bluetooth au lieu radio. Initialisation Bluetooth dans setup(). Lecture données smartphone/app Android : envoi nombres 0-15 via Bluetooth selon boutons pressés. App faite avec MIT App Inventor (détails dans tutoriel dédié). Téléchargement app et fichier projet modifiable : Pour programmation mouvement automatique : bouton « SAVE » → stockage positions actuelles pas-à-pas dans tableaux. Bouton « RUN » → fonction runSteps() exécute toutes étapes stockées via boucles for/while. J'espère que ce tutoriel vous a plu et appris quelque chose. Questions en commentaires, et découvrez ma collection de projets Arduino.Vue d'ensemble


Modèle 3D robot roues Mecanum


Fonctionnement des roues Mecanum


Fabrication du robot à roues Mecanum















Schéma de circuit

Conception PCB




Assemblage PCB








Code Arduino robot roues Mecanum
/* === Robot Arduino Roues Mecanum === Contrôle radio NRF24L01 par Dejan, www.HowToMechatronics.com Bibliothèques: RF24, https://github.com/tmrh20/RF24/ AccelStepper by Mike McCauley: https://www.airspayce.com/mikem/arduino/AccelStepper/index.html */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <AccelStepper.h>
RF24 radio(48, 49); // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
AccelStepper LeftBackWheel(1, 42, 43);
AccelStepper LeftFrontWheel(1, 40, 41);
AccelStepper RightBackWheel(1, 44, 45);
AccelStepper RightFrontWheel(1, 46, 47);
int wheelSpeed = 1500;
struct Data_Package {
byte j1PotX; byte j1PotY; byte j1Button;
byte j2PotX; byte j2PotY; byte j2Button;
byte pot1; byte pot2;
byte tSwitch1; byte tSwitch2;
byte button1; byte button2; byte button3; byte button4;
};
Data_Package data;
void setup() {
LeftFrontWheel.setMaxSpeed(3000);
LeftBackWheel.setMaxSpeed(3000);
RightFrontWheel.setMaxSpeed(3000);
RightBackWheel.setMaxSpeed(3000);
radio.begin();
radio.openReadingPipe(0, address);
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
radio.startListening();
Serial.begin(115200);
}
void loop() {
currentTime = millis();
if ( currentTime - lastReceiveTime > 1000 ) { resetData(); }
if (radio.available()) {
radio.read(&data, sizeof(Data_Package));
lastReceiveTime = millis();
}
wheelSpeed = map(data.pot1, 0, 255, 100, 3000);
if (data.j1PotX > 150) { moveSidewaysLeft(); }
else if (data.j1PotX < 100) { moveSidewaysRight(); }
else if (data.j1PotY > 160) { moveForward(); }
else if (data.j1PotY < 100) { moveBackward(); }
else if (data.j2PotX < 100 & data.j2PotY > 160) { moveRightForward(); }
else if (data.j2PotX > 160 & data.j2PotY > 160) { moveLeftForward(); }
else if (data.j2PotX < 100 & data.j2PotY < 100) { moveRightBackward(); }
else if (data.j2PotX > 160 & data.j2PotY < 100) { moveLeftBackward(); }
else if (data.j2PotX < 100) { rotateRight(); }
else if (data.j2PotX > 150) { rotateLeft(); }
else { stopMoving(); }
LeftFrontWheel.runSpeed(); LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed(); RightBackWheel.runSpeed();
int sensorValue = analogRead(A0);
float voltage = sensorValue * (5.0 / 1023.00) * 3;
if (voltage < 11) { digitalWrite(led, HIGH); } else { digitalWrite(led, LOW); }
}
void moveForward() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); }
void moveBackward() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); }
void moveSidewaysRight() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); }
void moveSidewaysLeft() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); }
void rotateLeft() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); }
void rotateRight() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); }
void moveRightForward() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(wheelSpeed); }
void moveRightBackward() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(0); }
void moveLeftForward() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(0); }
void moveLeftBackward() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(-wheelSpeed); }
void stopMoving() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(0); }
void resetData() {
data.j1PotX = 127; data.j1PotY = 127; data.j2PotX = 127; data.j2PotY = 127;
data.j1Button = 1; data.j2Button = 1; data.pot1 = 1; data.pot2 = 1;
data.tSwitch1 = 1; data.tSwitch2 = 1; data.button1 = 1; data.button2 = 1; data.button3 = 1; data.button4 = 1;
}/* === Robot Arduino Roues Mecanum === Contrôle Smartphone via Bluetooth par Dejan, www.HowToMechatronics.com Bibliothèques: RF24, AccelStepper */
#include <SoftwareSerial.h>
#include <AccelStepper.h>
SoftwareSerial Bluetooth(A8, 38); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX)
AccelStepper LeftBackWheel(1, 42, 43);
AccelStepper LeftFrontWheel(1, 40, 41);
AccelStepper RightBackWheel(1, 44, 45);
AccelStepper RightFrontWheel(1, 46, 47);
#define led 14
int wheelSpeed = 1500;
int dataIn, m;
int lbw[50], lfw[50], rbw[50], rfw[50];
int index = 0;
void setup() {
LeftFrontWheel.setMaxSpeed(3000);
LeftBackWheel.setMaxSpeed(3000);
RightFrontWheel.setMaxSpeed(3000);
RightBackWheel.setMaxSpeed(3000);
Serial.begin(38400);
Bluetooth.begin(38400);
Bluetooth.setTimeout(1);
delay(20);
pinMode(led, OUTPUT);
}
void loop() {
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.read();
if (dataIn == 0) { m = 0; }
if (dataIn == 1) { m = 1; }
if (dataIn == 2) { m = 2; }
if (dataIn == 3) { m = 3; }
if (dataIn == 4) { m = 4; }
if (dataIn == 5) { m = 5; }
if (dataIn == 6) { m = 6; }
if (dataIn == 7) { m = 7; }
if (dataIn == 8) { m = 8; }
if (dataIn == 9) { m = 9; }
if (dataIn == 10) { m = 10; }
if (dataIn == 11) { m = 11; }
if (dataIn == 12) { m = 12; }
if (dataIn == 14) { m = 14; }
if (dataIn >= 16) { wheelSpeed = dataIn * 10; Serial.println(wheelSpeed); }
}
if (m == 4) { moveSidewaysLeft(); }
if (m == 5) { moveSidewaysRight(); }
if (m == 2) { moveForward(); }
if (m == 7) { moveBackward(); }
if (m == 3) { moveRightForward(); }
if (m == 1) { moveLeftForward(); }
if (m == 8) { moveRightBackward(); }
if (m == 6) { moveLeftBackward(); }
if (m == 9) { rotateLeft(); }
if (m == 10) { rotateRight(); }
if (m == 0) { stopMoving(); }
if (m == 12) {
if (index == 0) {
LeftBackWheel.setCurrentPosition(0);
LeftFrontWheel.setCurrentPosition(0);
RightBackWheel.setCurrentPosition(0);
RightFrontWheel.setCurrentPosition(0);
}
lbw[index] = LeftBackWheel.currentPosition();
lfw[index] = LeftFrontWheel.currentPosition();
rbw[index] = RightBackWheel.currentPosition();
rfw[index] = RightFrontWheel.currentPosition();
index++; m = 0;
}
if (m == 14) {
runSteps();
if (dataIn != 14) {
stopMoving();
memset(lbw, 0, sizeof(lbw));
memset(lfw, 0, sizeof(lfw));
memset(rbw, 0, sizeof(rbw));
memset(rfw, 0, sizeof(rfw));
index = 0;
}
}
LeftFrontWheel.runSpeed(); LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed(); RightBackWheel.runSpeed();
int sensorValue = analogRead(A0);
float voltage = sensorValue * (5.0 / 1023.00) * 3;
if (voltage < 11) { digitalWrite(led, HIGH); } else { digitalWrite(led, LOW); }
}
void runSteps() {
for (int i = index - 1; i >= 0; i--) {
LeftFrontWheel.moveTo(lfw[i]); LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.moveTo(lbw[i]); LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.moveTo(rfw[i]); RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.moveTo(rbw[i]); RightBackWheel.setSpeed(wheelSpeed);
while (LeftBackWheel.currentPosition() != lbw[i] & LeftFrontWheel.currentPosition() != lfw[i] & RightFrontWheel.currentPosition() != rfw[i] & RightBackWheel.currentPosition() != rbw[i]) {
LeftFrontWheel.runSpeedToPosition(); LeftBackWheel.runSpeedToPosition();
RightFrontWheel.runSpeedToPosition(); RightBackWheel.runSpeedToPosition();
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.read();
if (dataIn == 15) {
while (dataIn != 14) {
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.read();
if (dataIn == 13) { stopMoving(); break; }
}
}
}
if (dataIn >= 16) { wheelSpeed = dataIn * 10; dataIn = 14; }
if (dataIn == 13) { break; }
}
}
}
for (int i = 1; i <= index - 1; i++) {
LeftFrontWheel.moveTo(lfw[i]); LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.moveTo(lbw[i]); LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.moveTo(rfw[i]); RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.moveTo(rbw[i]); RightBackWheel.setSpeed(wheelSpeed);
while (LeftBackWheel.currentPosition() != lbw[i] & LeftFrontWheel.currentPosition() != lfw[i] & RightFrontWheel.currentPosition() != rfw[i] & RightBackWheel.currentPosition() != rbw[i]) {
LeftFrontWheel.runSpeedToPosition(); LeftBackWheel.runSpeedToPosition();
RightFrontWheel.runSpeedToPosition(); RightBackWheel.runSpeedToPosition();
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.read();
if (dataIn == 15) {
while (dataIn != 14) {
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.read();
if (dataIn == 13) { stopMoving(); break; }
}
}
}
if (dataIn >= 16) { wheelSpeed = dataIn * 10; dataIn = 14; }
if (dataIn == 13) { break; }
}
}
}
}
void moveForward() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); }
void moveBackward() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); }
void moveSidewaysRight() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); }
void moveSidewaysLeft() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); }
void rotateLeft() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); }
void rotateRight() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); }
void moveRightForward() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(wheelSpeed); }
void moveRightBackward() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(0); }
void moveLeftForward() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(0); }
void moveLeftBackward() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(-wheelSpeed); }
void stopMoving() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(0); }

Processus de fabrication
- Construire un robot Raspberry Pi piloté par Bluetooth avec retour audio
- Robot Évitement d'Obstacles Piloté par Servomoteur : Construction avec Arduino et HC-SR04
- Créez un robot suiveur de ligne autonome avec Arduino UNO
- Robot commandé par la voix avec Arduino Nano et Bluetooth
- PiBot : Robot pianiste Arduino pour performance musicale de précision
- LittleArm 2C : Bras Robot 3D Imprimé Arduino pour Éducation STEM
- Robot Assistant Domestique Autonome : Liste Complète et Guide de Configuration
- Contrôlez votre bras robot Arduino via une application Android dédiée
- Kit de robot de navigation intérieure intelligente pour projets Arduino