Bonjour à tous,
Je débute dans la programmation d'Arduino. J'ai pour projet un robot suiveur de ligne.
J'utilise un capteur QTR8A (analogique) pour le suivi de ligne afin de recentrer le robot s'il dévie par rapport à une ligne noire. J'ai déjà testé ce capteur seul, mon code fonctionne, chaque cellule retourne une valeur entre 0 et 1000 (plus proche de 1000 si la couleur est noire) et je visualise bien où est la ligne noire par rapport au milieu du capteur en fonction des valeurs retournées par chacune des 8 cellules du capteur QTR8A.
Ensuite, j'ai également testé les deux moteurs pas à pas (28BYJ-48) avec leurs drivers seuls. J'arrive à faire varier leur vitesse, bien que leur couple reste faible. J'ai retenu une vitesse qui me paraissait pas mal pour l'avance du robot et pour effectuer les tests (baseSpeed = 500;).
Dans le code qui combine le capteur QTR8A et les deux moteurs, j'ai donc retenu les mêmes paramètres de vitesse que j'ai retenu dans le code des moteurs seuls.
Cependant, le problème que je rencontre est que les moteurs sont très très lents, et il me semble qu'ils fonctionnent par à-coups. J'ai déjà remplacé les "delay" qui peuvent être une condition "bloquante" au programme, en utilisant plutôt "millis()", mais cela ne change rien. Je me demande si certaines opérations, comme la lecture des capteurs QTR8A ou les calculs de correction pour le suivi de ligne, peuvent ralentir le cycle de la boucle "loop()", réduisant ainsi la fréquence d'exécution de "motorLeft.runSpeed()" et "motorRight.runSpeed()". Les moteurs ne pourraient alors pas tourner en continu et fonctionneraient donc pas à-coups.
J'ai remarqué aussi que lorsqu'on donne comme consigne une vitesse trop élevé aux moteurs pas à pas, ils vibrent. Je ne pense pas que ce soit le cas ici, car la vitesse que j'ai prise, je l'ai testée avec le code des moteurs seuls.
Avez-vous une idée de pourquoi les moteurs tournent très lentement dans le code complet ?
Voyez-vous des conditions "bloquantes" qui font que les moteurs ne pourraient pas tourner de façon continue ?
Merci d'avance pour votre aide !
Voici le code complet en question, qui allie capteur QTR8A et les deux moteurs pas à pas (avec une correction de la vitesse d'un des deux moteurs en fonction de si le robot se trouve trop à gauche ou trop à droite de la ligne pour le recentrer) :
#include <QTRSensors.h>
#include <AccelStepper.h>
// Configuration du capteur QTR-8A
QTRSensors qtr;
const uint8_t SensorCount = 8;
uint16_t sensorValues[SensorCount];
// Configuration des moteurs pas à pas 28BYJ-48
#define STEPS_PER_REV 2048 // Qu'on le mette ou non, j'ai remarqué que ça ne change rien.
//Est-il nécessaire ?
// Pins pour le moteur gauche
#define MOTOR_LEFT_PIN1 2
#define MOTOR_LEFT_PIN2 4
#define MOTOR_LEFT_PIN3 3
#define MOTOR_LEFT_PIN4 5
// Pins pour le moteur droit
#define MOTOR_RIGHT_PIN1 6
#define MOTOR_RIGHT_PIN2 8
#define MOTOR_RIGHT_PIN3 7
#define MOTOR_RIGHT_PIN4 9
// Configuration des moteurs pas à pas 28BYJ-48
AccelStepper motorLeft(AccelStepper::FULL4WIRE, MOTOR_LEFT_PIN1, MOTOR_LEFT_PIN2, MOTOR_LEFT_PIN3, MOTOR_LEFT_PIN4); // Moteur gauche
AccelStepper motorRight(AccelStepper::FULL4WIRE, MOTOR_RIGHT_PIN1, MOTOR_RIGHT_PIN2, MOTOR_RIGHT_PIN3, MOTOR_RIGHT_PIN4); // Moteur droit
// Paramètres de suivi de ligne
int baseSpeed = 500;
int maxCorrection = 8000; // Correction maximale
unsigned long lastPrintTime = 0; // Dernier moment d'affichage
unsigned long printInterval = 100; // Intervalle d'affichage en millisecondes
unsigned long lastMotorUpdateTime = 0; // Dernier moment de mise à jour des moteurs
unsigned long motorUpdateInterval = 5; // Intervalle de mise à jour des moteurs
void setup() {
Serial.begin(9600);
// Configurer les capteurs QTR-8A en mode analogique
qtr.setTypeAnalog();
qtr.setSensorPins((const uint8_t[]){A0, A1, A2, A3, A4, A5, A6, A7}, SensorCount);
// Phase de calibration
for (uint16_t i = 0; i < 400; i++) {
qtr.calibrate();
delay(20);
}
Serial.println("Calibration complète");
// Initialisation des moteurs
motorLeft.setMaxSpeed(3000); // Vitesse maximale augmentée
motorRight.setMaxSpeed(3000);
Serial.print("Vitesse testée : ");
Serial.println(baseSpeed);
motorLeft.setSpeed(baseSpeed); // Vitesse de base
motorRight.setSpeed(baseSpeed);
}
// Déclarer les vitesses des moteurs comme des variables globales
int leftSpeed = 0;
int rightSpeed = 0;
void loop() {
// Lis les valeurs des capteurs
qtr.read(sensorValues);
// Calculer la position de la ligne
long position = qtr.readLineBlack(sensorValues);
int error = position - 3500;
// Afficher la position de la ligne, l'erreur, et les valeurs des capteurs périodiquement
unsigned long currentTime = millis();
if (currentTime - lastPrintTime >= printInterval) {
lastPrintTime = currentTime;
Serial.print("Line position: ");
Serial.println(position); // Affichage de la valeur retournée par qtr.readLineBlack(sensorValues)
Serial.print("Error: ");
Serial.println(error); // Affichage de l'erreur
Serial.print("Sensor values: ");
for (uint8_t i = 0; i < SensorCount; i++) {
Serial.print(sensorValues[i]);
Serial.print('\t');
}
Serial.println();
Serial.print("Left motor speed: ");
Serial.println(leftSpeed); // Affichage de la vitesse du moteur gauche
Serial.print("Right motor speed: ");
Serial.println(rightSpeed); // Affichage de la vitesse du moteur droit
}
// Correction de la trajectoire
int correctionFactor = abs(error) * maxCorrection / 3500; // Facteur de correction plus modéré
correctionFactor = constrain(correctionFactor, 0, baseSpeed * 5); // Limiter la correction pour ne pas trop dévier
if (error < 0) {
// Si trop à gauche, accélérer le moteur droit pour recentrer
leftSpeed = baseSpeed;
rightSpeed = baseSpeed + correctionFactor; // Correction pour le moteur droit
} else if (error > 0) {
// Si trop à droite, accélérer le moteur gauche pour recentrer
leftSpeed = baseSpeed + correctionFactor; // Correction pour le moteur gauche
rightSpeed = baseSpeed;
} else {
leftSpeed = baseSpeed;
rightSpeed = baseSpeed;
}
// Appliquer les vitesses aux moteurs
motorLeft.setSpeed(-leftSpeed); // Inverser la vitesse pour le moteur gauche
motorRight.setSpeed(rightSpeed);
// Avancer les moteurs sans bloquer
if (currentTime - lastMotorUpdateTime >= motorUpdateInterval) {
motorLeft.runSpeed();
motorRight.runSpeed();
lastMotorUpdateTime = currentTime; // Mise à jour du dernier moment d'actualisation des moteurs
}
}
Voici le code qui fait fonctionner uniquement les moteurs à une vitesse :
#include <AccelStepper.h>
// Pins pour le moteur gauche
#define MOTOR_LEFT_PIN1 2
#define MOTOR_LEFT_PIN2 4
#define MOTOR_LEFT_PIN3 3
#define MOTOR_LEFT_PIN4 5
// Pins pour le moteur droit
#define MOTOR_RIGHT_PIN1 6
#define MOTOR_RIGHT_PIN2 8
#define MOTOR_RIGHT_PIN3 7
#define MOTOR_RIGHT_PIN4 9
// Configuration des moteurs pas à pas 28BYJ-48
AccelStepper motorLeft(AccelStepper::FULL4WIRE, MOTOR_LEFT_PIN1, MOTOR_LEFT_PIN2, MOTOR_LEFT_PIN3, MOTOR_LEFT_PIN4); // Moteur gauche
AccelStepper motorRight(AccelStepper::FULL4WIRE, MOTOR_RIGHT_PIN1, MOTOR_RIGHT_PIN2, MOTOR_RIGHT_PIN3, MOTOR_RIGHT_PIN4); // Moteur droit
int speed = 500;
void setup() {
Serial.begin(9600);
// Initialisation des moteurs
motorLeft.setMaxSpeed(2000); // Vitesse maximale (en pas par seconde)
motorRight.setMaxSpeed(2000);
Serial.print("Vitesse testée : ");
Serial.println(speed);
motorLeft.setSpeed(speed); // Définir la vitesse du moteur gauche
motorRight.setSpeed(speed); // Définir la vitesse du moteur droit
// Faire tourner les moteurs pendant 5 secondes à cette vitesse
unsigned long startTime = millis();
while (millis() - startTime < 5000) {
motorLeft.runSpeed();
motorRight.runSpeed();
}
// Arrêter les moteurs après les tests
motorLeft.setSpeed(0);
motorRight.setSpeed(0);
motorLeft.runSpeed();
motorRight.runSpeed();
Serial.println("Test terminé.");
}
void loop() {
}