Bonjour, j'aimerai réaliser un programme permettant l'asservissement en position d'un chariot grace à un moteur à CC disposant d'un codeur incrémental et d'un système poulie-courroie.
// Ce code a pour but d'asservir en position le chariot sur le rail
#include<SimpleTimer.h>
SimpleTimer timer; //Timer pour échantillonage
const int Frequence_Echantillonage = 100; //Fréquence d'exécution de l'asservissement
//Définition des entrées
const int DIR_IN1 = 9; //Commande direction sens rotation 1 moteur
const int DIR_IN2 = 8; //Commande direction sens rotation 2 moteur
const int PWM = 7; //Commande vitesse du moteur
const int PIN_A_ENCODEUR = 2;
const int PIN_B_ENCODEUR = 3;
//---------------------------------------------------------
// Initialisation
//---------------------------------------------------------
//Initialisation compteur
int Encodeur0Pos = 0; //Position de départ
int Encodeur0Pos_Precedente = 0;
boolean A_set = false;
boolean B_set = false;
unsigned int time = 0;
long debut = 0;
//Initialisation moteur
int Rapport_Reduction = 1 / 131;
int Rayon_Poulie = 15.93e-3;
int Resolution = 16; //Nombre de tickks par tour du moteur
//Initialisation paramètres de l'asservissement
float Consigne_en_m = 0.05;
float Angle_Consigne = Consigne_en_m * (1 / (Rapport_Reduction*Rayon_Poulie));
float Angle_Mesure;
float Epsilon = Angle_Consigne;
float Epsilon_ini;
int Rapport_Cyclique;
float Moyenne_Epsilon;
float Delta_Epsilon = 0.1; //Critere d'arret du moteur
//Initialisation parametres boucle while
int Compteur;
float Somme;
//--------------------------------------------------------
// Routine d'utilisation
//--------------------------------------------------------
void setup() {
Serial.begin(9600);
pinMode(PWM, OUTPUT); //Sortie commande moteur
pinMode(DIR_IN1, OUTPUT);
pinMode(DIR_IN2, OUTPUT);
pinMode(PIN_A_ENCODEUR, INPUT); //Sortie encodeur
pinMode(PIN_B_ENCODEUR, INPUT);
digitalWrite(PIN_A_ENCODEUR, HIGH); //Resistance interne arduino ON
digitalWrite(PIN_B_ENCODEUR, HIGH); //Resistance interne arduino ON
attachInterrupt(0, doEncoderA, RISING); //Interruption de l'encodeur A en sortie 0 (pin 2)
attachInterrupt(1, doEncoderB, RISING); //Interruption de l'encodeur B en sortie 1 (pin 3)
}
//----------------------------------------------------------
// Fonction principale
//----------------------------------------------------------
void loop() {
Compteur = 0;
Somme = 0;
Angle_Mesure = Encodeur0Pos * ((2 * PI) / 16);
Epsilon_ini = Angle_Mesure + Angle_Consigne;
Moyenne_Epsilon = Angle_Consigne;
Serial.println(Moyenne_Epsilon);
while (Moyenne_Epsilon >= Delta_Epsilon) {
Angle_Mesure = Encodeur0Pos * ((2 * PI) / 16);
Epsilon = Epsilon_ini - Angle_Mesure;
Rapport_Cyclique = (abs(Epsilon) * 255) / Angle_Consigne;
Somme = Somme + Epsilon;
Compteur = Compteur + 1;
if (Epsilon > 0) {
digitalWrite(DIR_IN1, LOW);
digitalWrite(DIR_IN2, HIGH);
analogWrite(PWM, Rapport_Cyclique);
}
if (Epsilon <= 0) {
digitalWrite(DIR_IN1, HIGH);
digitalWrite(DIR_IN2, LOW);
analogWrite(PWM, -Rapport_Cyclique);
}
if (Compteur == 100) {
Moyenne_Epsilon = Somme / 100;
Compteur = 0;
Somme = 0;
}
Serial.println(String(millis()) + ';' + String((Angle_Mesure * (Rapport_Reduction * Rayon_Poulie))));
}
}
//-----------------------------------------------------------
// Routine incrementation des codeurs A et B
//-----------------------------------------------------------
void doEncoderA() {
B_set = digitalRead(PIN_B_ENCODEUR) == HIGH;
if (B_set) {
Encodeur0Pos = Encodeur0Pos + 1;
}
else {
Encodeur0Pos = Encodeur0Pos - 1;
}
}
void doEncoderB() {
A_set = digitalRead(PIN_A_ENCODEUR) == HIGH;
if (A_set) {
Encodeur0Pos = Encodeur0Pos - 1;
}
else {
Encodeur0Pos = Encodeur0Pos + 1;
}
}
Cependant quand je l'exécute rien ne s'affiche dans le shell, je ne comprends pas d'ou vient le problème... Si vous pouvez m'aider je vous remercie d'avance, bonne soirée à vous
// Ce code a pour but d'asservir en position le chariot sur le rail
#include<SimpleTimer.h>
SimpleTimer timer; //Timer pour échantillonage
const int Frequence_Echantillonage = 100; //Fréquence d'exécution de l'asservissement
//Définition des entrées
const int DIR_IN1 = 9; //Commande direction sens rotation 1 moteur
const int DIR_IN2 = 8; //Commande direction sens rotation 2 moteur
const int PWM = 7; //Commande vitesse du moteur
const int PIN_A_ENCODEUR = 2;
const int PIN_B_ENCODEUR = 3;
//---------------------------------------------------------
// Initialisation
//---------------------------------------------------------
//Initialisation compteur
volatile int Encodeur0Pos = 0; //Position de départ
volatile int Encodeur0Pos_Precedente = 0;
volatile boolean A_set = false;
volatile boolean B_set = false;
unsigned int time = 0;
long debut = 0;
//Initialisation moteur
int Rapport_Reduction = 1 / 131;
int Rayon_Poulie = 15.93e-3;
int Resolution = 16; //Nombre de tickks par tour du moteur
//Initialisation paramètres de l'asservissement
float Consigne_en_m = 0.05;
float Angle_Consigne = Consigne_en_m * (1 / (Rapport_Reduction*Rayon_Poulie));
float Angle_Mesure;
float Epsilon = Angle_Consigne;
float Epsilon_ini;
int Rapport_Cyclique;
float Moyenne_Epsilon;
float Delta_Epsilon = 0.1; //Critere d'arret du moteur
//Initialisation parametres boucle while
int Compteur;
float Somme;
//--------------------------------------------------------
// Routine d'utilisation
//--------------------------------------------------------
void setup() {
Serial.begin(9600);
pinMode(PWM, OUTPUT); //Sortie commande moteur
pinMode(DIR_IN1, OUTPUT);
pinMode(DIR_IN2, OUTPUT);
pinMode(PIN_A_ENCODEUR, INPUT); //Sortie encodeur
pinMode(PIN_B_ENCODEUR, INPUT);
digitalWrite(PIN_A_ENCODEUR, HIGH); //Resistance interne arduino ON
digitalWrite(PIN_B_ENCODEUR, HIGH); //Resistance interne arduino ON
attachInterrupt(0, doEncoderA, RISING); //Interruption de l'encodeur A en sortie 0 (pin 2)
attachInterrupt(1, doEncoderB, RISING); //Interruption de l'encodeur B en sortie 1 (pin 3)
}
//----------------------------------------------------------
// Fonction principale
//----------------------------------------------------------
void loop() {
int Encodeur0PosCopie;
noInterrupts();
Encodeur0PosCopie = Encodeur0Pos;
interrupts();
Compteur = 0;
Somme = 0;
Angle_Mesure = Encodeur0Pos * ((2 * PI) / 16);
Epsilon_ini = Angle_Mesure + Angle_Consigne;
Moyenne_Epsilon = Angle_Consigne;
while (Moyenne_Epsilon >= Delta_Epsilon) {
Angle_Mesure = Encodeur0Pos * ((2 * PI) / 16);
Epsilon = Epsilon_ini - Angle_Mesure;
Rapport_Cyclique = (abs(Epsilon) * 255) / Angle_Consigne;
Somme = Somme + Epsilon;
Compteur = Compteur + 1;
if (Epsilon > 0) {
digitalWrite(DIR_IN1, LOW);
digitalWrite(DIR_IN2, HIGH);
analogWrite(PWM, Rapport_Cyclique);
}
if (Epsilon <= 0) {
digitalWrite(DIR_IN1, HIGH);
digitalWrite(DIR_IN2, LOW);
analogWrite(PWM, -Rapport_Cyclique);
}
if (Compteur == 100) {
Moyenne_Epsilon = Somme / 100;
Compteur = 0;
Somme = 0;
}
Serial.println(String(millis()) + ';' + String((Angle_Mesure * (Rapport_Reduction * Rayon_Poulie))));
}
}
//-----------------------------------------------------------
// Routine incrementation des codeurs A et B
//-----------------------------------------------------------
void doEncoderA() {
B_set = digitalRead(PIN_B_ENCODEUR) == HIGH;
if (B_set) {
Encodeur0Pos = Encodeur0Pos + 1;
}
else {
Encodeur0Pos = Encodeur0Pos - 1;
}
}
void doEncoderB() {
A_set = digitalRead(PIN_A_ENCODEUR) == HIGH;
if (A_set) {
Encodeur0Pos = Encodeur0Pos - 1;
}
else {
Encodeur0Pos = Encodeur0Pos + 1;
}
}
J'ai donc changé la partie du code comme vous l'avez conseillé mais rien ne se passe. Rien ne s'affiche dans le shell même quand je lui demande par exemple de print l'angle consigne
vous avez bien rajouté la copie (Encodeur0PosCopie) mais vous continuez d'utiliser Encodeur0Posdans les calculs de la loop... A quoi sert la copie selon vous ?...
ensuite je n'ai pas lu le code en entier, vous n'avez pas décrit le montage exactement, je ne sais pas où vous regardez l'affichage, etc... Il peut donc y avoir 2000 sources de soucis.
faites un code simple qui affiche simplement dans la loop le compteur (la copie) à chaque fois qu'il change. Vous aurez bien le temps de rajouter tout le reste plus tard
Quand au montage, il est composé d'une carte arduino mega, un hacheur L298N, d'un MCC avec le codeur incremental qui est relié au chariot par un système de poulie, courroie.
Parce que c’est sémantiquement correct de mettre un résultat booléen dans une variable booléenne plutôt que de dépendre d’effet de bords sur le fait que vous savez que HIGH vaut 1 et que le compilateur fera la promotion automatique en true.
Mais il n'y a pas de comparaison, alors ce n'est pas requis . Je comprend que le compilateur vas remplacé HIGH par 1 mais je ne vois pas la nécessité d'ajouter == HIGH?
Il met dans la variable B_set qui est de type Boolean (valeur de vérité) le résultat de la comparaison (test d’égalité qui rend une valeur de vérité) (digitalRead(PIN_B_ENCODEUR) == HIGH)
C’est cohérent et sémantiquement correct et indépendant de la valeur arbitraire de HIGH.
Il me semble que cela fait -1 mais je n'en suis pas sûr. Mais si c'est cela, Moyenne epsilon vaut -1 et le while n'est jamais exécuté; il n'y aura pas d'affichage. Jamais.
Pour moi, il y a plein de variables dont je ne connais pas l'utilité. Le code m'est obscur, et souvent comme c'est ainsi, je passe mon chemin, ou j'attends que les choses éclaircissent. Pour avoir plus de réponses, il vaut mieux expliquer ce que l'on fait. Si moyenne_Epsilon est clair pour vous, je ne sais pas ce que cela représente.