</> Intelligence & Code
Vue d'Ensemble du Programme
Le code ci-dessous est le cerveau de notre robot. Écrit en C++ pour un microcontrôleur de type ESP32, il gère le déplacement précis grâce à des moteurs pas-à-pas et utilise un Lidar pour la détection d'obstacles. Le robot peut être contrôlé par des commandes envoyées via le port série.
Les deux bibliothèques principales utilisées sont :
- AccelStepper.h : Pour un contrôle avancé des moteurs pas-à-pas, gérant l'accélération et la décélération.
- RPLidar.h : Pour communiquer avec le Lidar et interpréter les données de distance.
Le Code Complet
Voici le code source principal qui est téléversé sur le microcontrôleur XIAO ESP32-S3.
#include <AccelStepper.h>
#include <RPLidar.h>
const int LEFT_STEP_PIN = D1;
const int LEFT_DIR_PIN = D0;
const int RIGHT_STEP_PIN = D3;
const int RIGHT_DIR_PIN = D2;
const int DRIVER_ENABLE_PIN = D8;
const int LIDAR_MOTOR_PIN = D9;
const float STEPS_PER_REV = 200;
const float MICROSTEP_FACTOR = 8;
const float TOTAL_STEPS_PER_REV = STEPS_PER_REV * MICROSTEP_FACTOR;
const float WHEEL_DIAMETER_MM = 80;
const float WHEEL_CIRCUMFERENCE_MM = WHEEL_DIAMETER_MM * PI;
const float STEPS_PER_MM = TOTAL_STEPS_PER_REV / WHEEL_CIRCUMFERENCE_MM;
const float ROBOT_WIDTH_MM = 150.0;
const float MAX_SPEED_MM_PER_SEC = 300;
const float ACCELERATION_MM_PER_SEC2 = 2000;
AccelStepper leftMotor(AccelStepper::DRIVER, LEFT_STEP_PIN, LEFT_DIR_PIN);
AccelStepper rightMotor(AccelStepper::DRIVER, RIGHT_STEP_PIN, RIGHT_DIR_PIN);
RPLidar lidar;
float mmPerSecToStepsPerSec(float mm_per_sec) {
return mm_per_sec * STEPS_PER_MM;
}
float mmPerSec2ToStepsPerSec2(float mm_per_sec2) {
return mm_per_sec2 * STEPS_PER_MM;
}
void setup() {
Serial.begin(115200);
lidar.begin(Serial1);
pinMode(DRIVER_ENABLE_PIN, OUTPUT);
digitalWrite(DRIVER_ENABLE_PIN, LOW);
pinMode(LIDAR_MOTOR_PIN, OUTPUT);
analogWrite(LIDAR_MOTOR_PIN, 200);
leftMotor.setMaxSpeed(mmPerSecToStepsPerSec(MAX_SPEED_MM_PER_SEC));
leftMotor.setAcceleration(mmPerSec2ToStepsPerSec2(ACCELERATION_MM_PER_SEC2));
rightMotor.setMaxSpeed(mmPerSecToStepsPerSec(MAX_SPEED_MM_PER_SEC));
rightMotor.setAcceleration(mmPerSec2ToStepsPerSec2(ACCELERATION_MM_PER_SEC2));
delay(1000);
rplidar_response_device_health_t health;
if (!IS_OK(lidar.getHealth(health)) || health.status != RPLIDAR_STATUS_OK) {
analogWrite(LIDAR_MOTOR_PIN, 0);
while(1);
}
lidar.startScan();
}
void moveForward(int distance_mm) {
long steps = round(distance_mm * STEPS_PER_MM);
leftMotor.move(steps);
rightMotor.move(steps);
}
void turnRobot(int angle_deg) {
float wheel_arc_mm = (angle_deg * (PI / 180.0)) * (ROBOT_WIDTH_MM / 2.0);
long steps = round(wheel_arc_mm * STEPS_PER_MM);
leftMotor.move(steps);
rightMotor.move(-steps);
}
void stopMotors() {
leftMotor.stop();
rightMotor.stop();
}
void processLidar() {
if (IS_OK(lidar.waitPoint())) {
float distance = lidar.point.distance;
float angle = lidar.point.angle;
byte quality = lidar.point.quality;
if (quality > 10 && distance > 0 && distance < 200) {
stopMotors();
}
}
}
void processSerialCommands() {
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
command.trim();
char cmdChar = command.charAt(0);
int value = command.substring(1).toInt();
if (cmdChar == 'f') {
moveForward(value);
} else if (cmdChar == 't') {
turnRobot(value);
} else if (cmdChar == 's') {
stopMotors();
}
}
}
void loop() {
processSerialCommands();
if (leftMotor.isRunning() || rightMotor.isRunning()) {
leftMotor.run();
rightMotor.run();
} else {
processLidar();
}
}
Décomposition du Code
Constantes et Configuration
Le début du code définit toutes les constantes importantes :
- Pins de connexion : Les variables `..._PIN` lient le code aux broches physiques du microcontrôleur pour les moteurs et le Lidar.
- Paramètres mécaniques : Des constantes comme `WHEEL_DIAMETER_MM` (diamètre de roue) et `ROBOT_WIDTH_MM` (largeur du robot) permettent de convertir des distances et angles en nombre de pas pour les moteurs.
- Paramètres de performance : `MAX_SPEED_MM_PER_SEC` et `ACCELERATION_MM_PER_SEC2` définissent le comportement dynamique du robot.
Initialisation (fonction `setup`)
Cette fonction est exécutée une seule fois au démarrage. Elle configure le robot :
- Démarre les communications série pour le débogage et le Lidar.
- Active les drivers des moteurs (`digitalWrite(DRIVER_ENABLE_PIN, LOW)`).
- Lance la rotation du moteur du Lidar.
- Configure la vitesse et l'accélération maximales pour chaque moteur.
- Vérifie l'état de santé du Lidar. Si un problème est détecté, le programme s'arrête.
- Démarre le scan du Lidar pour commencer à recevoir des données.
Fonctions de Mouvement
Trois fonctions gèrent les déplacements de base :
moveForward(distance)
: Fait avancer le robot en ligne droite sur une distance donnée en millimètres.turnRobot(angle)
: Fait pivoter le robot sur lui-même d'un certain angle en degrés. Un angle positif tourne dans un sens, un angle négatif dans l'autre.stopMotors()
: Arrête immédiatement les moteurs.
Gestion des Capteurs et Commandes
processLidar()
: Cette fonction lit un point de donnée du Lidar. Si un obstacle de bonne qualité est détecté à moins de 200 mm, elle appelle `stopMotors()` pour un arrêt d'urgence simple.processSerialCommands()
: Lit les commandes arrivant sur le port série. Elle permet de piloter le robot manuellement.
Boucle Principale (fonction `loop`)
Le `loop` est le cœur du programme qui s'exécute en continu. Sa logique est la suivante :
- Il vérifie d'abord si une commande série a été reçue.
- Si un mouvement est en cours : il se consacre à l'exécution de ce mouvement en appelant `leftMotor.run()` et `rightMotor.run()`. Ces fonctions doivent être appelées le plus souvent possible.
- Si le robot est à l'arrêt : il utilise ce temps libre pour analyser les données du Lidar (`processLidar()`).
Comment Utiliser
Pour contrôler le robot, connectez-vous au microcontrôleur via le moniteur série de l'IDE Arduino (ou un autre terminal série).
- Assurez-vous que la vitesse de communication (baudrate) est réglée sur 115200.
- Envoyez des commandes suivies de la touche "Entrée".
Format des commandes : `[lettre][valeur]`
f100
: Fait avancer le robot de 100 mm.t90
: Fait tourner le robot de 90 degrés.t-45
: Fait tourner le robot de -45 degrés.s
: Arrête les moteurs.