Les servo que tu as commandé ne te donnent aucune information en retour.
Le capteur que tu as est un peu trop précis pour ce genre d'application, mais peut être tout à fait utilisable quand même.
L'idéal est de prendre des moteurs avec codeur attenant:
Il y en a même avec une roue.
La résolution de l'encodeur par tour de roue, est la réduction * 11 (11 étant le nombre d'impulsions à l'axe du moteur)
Pour "lire" ces encodeurs, il y a la bibliothèque Encoder.h.
Pour commander tes moteur, via des signaux PWM, il te faut des ponts en H comme ceci:
Qui est un pont qui peut commander 2 moteurs. Ce pont est bien entendu, pour le type de moteur ci-dessus
PS: Au vu de la photo du post#6, ma proposition est bien sûre que pour essayer la "mécanique" en plus petit.
Je me permets une petite intrusion dans ce fil en espérant qu'elle sera courte.
Je connaissais les petits servo-moteurs à débattement limité.
Apparemment, le servo-moteur employé ici est à rotation continue. Pour autant, pour le commander, il faut lui envoyer un créneau dont la largeur va définir sa position.
Donc, je suppose que si on veut une rotation continue, lorsque l'on a atteint la position "360°" avec un créneau de largeur maxi, il faut tout de suite envoyer un créneau de largeur mini pour le faire basculer à la position "0°" ... en espérant qui aille à la position "0°" en continuant sa rotation et non pas en revenant en marche arrière. Oui, non ?
Dans le cas des servo 360°, le créneau décide de la vitesse de rotation, pas de l'angle, ce moteur est à l'arrêt, manche au milieu.
C'est un abus de langage que d'appeler ça un servo, c'est plus un moteur asservi en vitesse.
Il s'agit de lire les encodeurs et de transposer ça en signaux de commande des moteur, en général du PWM.
Tu peux essayer de poser la question du comment à ChatGPT, c'est bonne expérience
'servo 360' = rotation continue en fait = moteurs dont la vitesse de rotation dépend de la largeur de l'impulsion reçue( signal analogue à celui envoyé aux vrais servos
Asservissement me parait excessif pour ces 'ex-servos (asservissement de position) mis en boucle ouverte'
on a une variation de vitesse, pas d'asservissement
Pour faire simple, je veux retirer la radiocommande et piloter les moteurs avec ma carte arduino mega qui elle meme est piloté par mon programme python. J'ai déja fais le programme qui gère le gps RTK pour le positionnement par satelite...
#include <VarSpeedServo.h>
// Définition des pins pour les servomoteurs
#define MOTOR_LEFT_PIN 9
#define MOTOR_RIGHT_PIN 10
// Définition des pins pour les capteurs de quadrature (A et B)
#define ENCODER_LEFT_A_PIN 2
#define ENCODER_LEFT_B_PIN 3
#define ENCODER_RIGHT_A_PIN 4
#define ENCODER_RIGHT_B_PIN 5
// Variables pour le comptage des impulsions
volatile long encoderLeftCount = 0;
volatile long encoderRightCount = 0;
// Variables pour les moteurs
VarSpeedServo motorLeft;
VarSpeedServo motorRight;
// Paramètre de calibration (nombre d'impulsions par mètre)
long pulsesPerMeter = 10000; // Nombre d'impulsions pour parcourir 1 mètre
// Variables pour la gestion des commandes
char command[32];
int distanceCommand = 0;
int rotationCommand = 0;
// Fonction d'interruption pour capteur de quadrature
void encoderLeftInterruptA() {
if (digitalRead(ENCODER_LEFT_B_PIN) == HIGH) {
encoderLeftCount++;
} else {
encoderLeftCount--;
}
}
void encoderRightInterruptA() {
if (digitalRead(ENCODER_RIGHT_B_PIN) == HIGH) {
encoderRightCount++;
} else {
encoderRightCount--;
}
}
// Fonction d'initialisation
void setup() {
// Initialisation des servomoteurs
motorLeft.attach(MOTOR_LEFT_PIN);
motorRight.attach(MOTOR_RIGHT_PIN);
// Initialisation des capteurs de quadrature
pinMode(ENCODER_LEFT_A_PIN, INPUT);
pinMode(ENCODER_LEFT_B_PIN, INPUT);
pinMode(ENCODER_RIGHT_A_PIN, INPUT);
pinMode(ENCODER_RIGHT_B_PIN, INPUT);
// Attachement des interruptions
attachInterrupt(digitalPinToInterrupt(ENCODER_LEFT_A_PIN), encoderLeftInterruptA, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENCODER_RIGHT_A_PIN), encoderRightInterruptA, CHANGE);
// Initialisation du port série pour recevoir les commandes
Serial.begin(9600);
Serial.println("Prêt à recevoir des commandes.");
}
// Fonction pour avancer
void moveForward(int distanceInCm) {
long targetPulses = distanceInCm * (pulsesPerMeter / 100); // Conversion en impulsions
encoderLeftCount = 0;
encoderRightCount = 0;
motorLeft.write(90); // Moteur gauche à pleine vitesse dans le sens horaire
motorRight.write(90); // Moteur droit à pleine vitesse dans le sens horaire
while (encoderLeftCount < targetPulses && encoderRightCount < targetPulses) {
// Attente jusqu'à ce que la distance soit parcourue
}
motorLeft.write(0); // Arrêt du moteur gauche
motorRight.write(0); // Arrêt du moteur droit
}
// Fonction pour reculer
void moveBackward(int distanceInCm) {
long targetPulses = distanceInCm * (pulsesPerMeter / 100); // Conversion en impulsions
encoderLeftCount = 0;
encoderRightCount = 0;
motorLeft.write(10); // Moteur gauche à pleine vitesse dans le sens antihoraire (recul)
motorRight.write(10); // Moteur droit à pleine vitesse dans le sens antihoraire (recul)
while (encoderLeftCount < targetPulses && encoderRightCount < targetPulses) {
// Attente jusqu'à ce que la distance soit parcourue
}
motorLeft.write(0); // Arrêt du moteur gauche
motorRight.write(0); // Arrêt du moteur droit
}
// Fonction pour tourner à droite
void rotateRight(int angle) {
long targetPulses = angle * (pulsesPerMeter / 360); // Conversion de l'angle en impulsions
encoderLeftCount = 0;
encoderRightCount = 0;
motorLeft.write(90); // Moteur gauche en marche avant
motorRight.write(0); // Moteur droit en marche arrière
while (encoderLeftCount < targetPulses) {
// Attente jusqu'à ce que l'angle soit parcouru
}
motorLeft.write(0); // Arrêt du moteur gauche
motorRight.write(0); // Arrêt du moteur droit
}
// Fonction pour tourner à gauche
void rotateLeft(int angle) {
long targetPulses = angle * (pulsesPerMeter / 360); // Conversion de l'angle en impulsions
encoderLeftCount = 0;
encoderRightCount = 0;
motorLeft.write(0); // Moteur gauche en marche arrière
motorRight.write(90); // Moteur droit en marche avant
while (encoderRightCount < targetPulses) {
// Attente jusqu'à ce que l'angle soit parcouru
}
motorLeft.write(0); // Arrêt du moteur gauche
motorRight.write(0); // Arrêt du moteur droit
}
void loop() {
// Vérification des données reçues par le port série
if (Serial.available() > 0) {
// Lecture de la commande série
int index = 0;
while (Serial.available() > 0 && index < sizeof(command) - 1) {
command[index] = Serial.read();
if (command[index] == '\n' || command[index] == '\r') break; // Fin de commande
index++;
}
command[index] = '\0'; // Fin de chaîne
// Analyse et exécution de la commande
if (strncmp(command, "avance-", 7) == 0) {
distanceCommand = atoi(&command[7]);
moveForward(distanceCommand);
}
else if (strncmp(command, "reculer-", 8) == 0) {
distanceCommand = atoi(&command[8]);
moveBackward(distanceCommand);
}
else if (strncmp(command, "rotation_droite-", 16) == 0) {
rotationCommand = atoi(&command[16]);
rotateRight(rotationCommand);
}
else if (strncmp(command, "rotation_gauche-", 17) == 0) {
rotationCommand = atoi(&command[17]);
rotateLeft(rotationCommand);
}
else {
Serial.println("Commande non reconnue.");
}
}
}
Si j’ai bien compris, Il a expliqué que ce modèle fonctionne avec une télécommande et qu’il veut enlever la télécommande pour mettre un arduino à la place du récepteur radio et que l’arduino pilote le robot de façon autonome grâce à son autre projet de GPS différentiel.
Oui çà j'ai bien compris, mais ce que vous décrivez, c'est "l’intelligence" de la machine, les "muscles" (l'électronique de puissance, les moteurs...) sont probablement parfaitement adapté, il est donc fort probable qu'il n'y ais pas besoin d'un nouveau "pont en H" ou autres...