Project

General

Profile

h1. Asservissement

/*
Travail du Club Robot de l'école Centrale Marseille


Programme d'asservissement de moteurs
Version du 07/12/2015

Définition des constantes:

Constantes Physiques*/
float const d=10;//distance entre les roues en cm
float const Vmax=12.5;//vitesse max en cm/s
float const conversion=0.0486; //permet de transformer le nombre de ticks en vitesse par seconde

/* Définition des constantes pour la correction /
float const decalage=1;//le compteur G délivre moins de ticks que le droit pour une même vitesse
float const correctionRegulationMAv=251.0/200.0;//compense l'erreur de régulation en marche avant - Moteur Gauche trop rapide
float const correctionRegulationMAr=233.0/200.0;//compense l'erreur de régulation en marche arrière - Moteur gauche trop rapide
float const KiG=2.0;// correcteur intégrale du moteur gauche
float const KpG=18.0;// correcteur proportionnel du moteur gauche
float const KiD=2.0;
float const KpD=18.0;
/

Méthode de calcul de la conversion
tick en 200ms -> tick/s -> tour/s -> cm/s
5 1/1938 6*Pi
*/

/Définition des variables globales du moteur Gauche/
int PWMG = 3; //pin du pwm du moteur gauche
int sensG=12;//pin du sens de rotation du moteur. Si sensG à LOW => marche avance. Si sensG à HIGH => marche arrière.
int entreeG = A5;// pin du capteur à effet haul du moteur
boolean etatG;
float consigneG=0;//en cm/s
float integraleG;

/Définition des variables globales du moteur Droit/
int PWMD=11;
int sensD=13;//Si sensD à LOW => marche avant. Si sensD à HIGH => marche arrière.
int entreeD=A3;// pin du capteur à effet haul du moteur
boolean etatD;
float consigneD=0;//en cm/s
float integraleD;

#include

void setup() {
Wire.begin(); //join i2c bus (address optional for master)
pinMode(PWMG, OUTPUT);
pinMode(sensG, OUTPUT);
pinMode(PWMD, OUTPUT);
pinMode(sensD, OUTPUT);
pinMode(entreeG, INPUT);
pinMode(entreeD, INPUT);
Serial.begin(9600);
integraleG=0;
integraleD=0;
AdaptationConsigneRobot(7.0, 0);
}

void loop() {
int ticks[3];
int commandeSortie[3];
float vitesse[3];

AcquisitionTicks(ticks);

TraitementTicks(ticks,commandeSortie,vitesse);

/* Adaptation à l'alimentation par générateur*/
if(consigneG !=0 && consigneD != 0 && ticks[0]==0 && ticks[1]==0) {
analogWrite(PWMG,0);
analogWrite(PWMD, 255);//envoie de la commande au moteur droit
delay(100);
analogWrite(PWMG, 255);
} else{
//Envoi des commandes aux moteurs
analogWrite(PWMD, commandeSortie[1]);//envoie de la commande au moteur droit
analogWrite(PWMG, commandeSortie[0]);//envoie de la commande au moteur gauche
}
//Envoi de données pour correction du code
Serial.print(commandeSortie[0]);//Gauche
Serial.print(" ");
Serial.print(commandeSortie[1]);//Droit
Serial.print(" ");
Serial.print(consigneG);
Serial.print(" ");
Serial.print(consigneD);
Serial.print(" ");
Serial.print(vitesse[0]);//gauche
Serial.print(" ");
Serial.println(vitesse[1]);//droit

//Gestion de la communication i2c
communication(vitesse);
}
// Permet le comptage des ticks effectués lors de la rotation du moteur
void AcquisitionTicks(int ticks[3]) {
unsigned long timeInit=millis();
boolean UpG;
boolean UpD;
int tickG=0;
int tickD=0;
/*
Acquisition des ticks des deux moteurs
/
while(millis()-timeInit < 100) {
//Détection des ticks pour le moteur de Gauche par détection de fronts descendants
if(analogRead(entreeG)*5.0/1024.0>2.0) {
UpG=true;
}
if(analogRead(entreeG)*5.0/1024.02.0) {
UpD=true;
}
if(analogRead(entreeD)*5.0/1024.0<2.0 && UpD==true) {
UpD=false;
tickD++;
}
}
ticks[0]=tickG;
ticks[1]=tickD;
/

Fin de la détection


*/
}
//permet de faire une rectification de la commande du moteur à partir du nombre de ticks
void TraitementTicks(int ticks[3], int commandeSortie[3], float vitesse[3]) {
int tickG=ticks[0];
int tickD=ticks[1];
int commandeSortieD;
int commandeSortieG;
float erreurG;
float erreurD;
float proportionnelleD;
float proportionnelleG;
float vitesseG;
float vitesseD;
tickG=tickG*decalage;
if(consigneG != 0 && tickG == 0) {//permet de vite faire démarrer le moteur en cas de faible vitesse
integraleG=200;
commandeSortieG=255;
} else {//cas normal
vitesseG=tickG*conversion;
erreurG = (consigneG - vitesseG);//application du correcteur;
integraleG =integraleG+ KiG*erreurG;
proportionnelleG = KpG*erreurG;
commandeSortieG = int(integraleG + proportionnelleG);
commandeSortieG = constrain(commandeSortieG, 0, 255);
}

/*
La fonction commande s'occupe de la commande a envoyé au moteur droit pour atteindre la consigne
*/
if(consigneD != 0 && tickD == 0) {//permet de vite faire démarrer le moteur en cas de faible vitesse
integraleD=200;
commandeSortieD=255;
} else {//cas normal
vitesseD=tickD*conversion;
erreurD = (consigneD - vitesseD);//application du correcteur;
integraleD =integraleD+ KiD*erreurD;
proportionnelleD = KpD*erreurD;
commandeSortieD = int(integraleD + proportionnelleD);
commandeSortieD = constrain(commandeSortieD, 0, 255);
}
//mise à jour des tableaux
ticks[0]=tickG;
ticks[1]=tickD;
commandeSortie[0]=commandeSortieG;
commandeSortie[1]=commandeSortieD;
vitesse[0]=vitesseG;
vitesse[1]=vitesseD;
//Fin du traitement du nombre de ticks pour déduire la commande des moteurs.
}

void AdaptationConsigneMoteur(boolean AvG, float consignePourMG, boolean AvD, float consignePourMD) {

//Mise à jour des consignes de vitesse des moteurs
consigneG=consignePourMG;
consigneD=consignePourMD;
int commandeSortieG;
int commandeSortieD;
//Redéfinition des sens de rotation du moteur gauche
if(AvG==false&&etatG != LOW) {
etatG=LOW;
integraleG=50;
commandeSortieG=255;
} else if(AvG==true&&etatG != HIGH) {
etatG=HIGH;
integraleG=50;
commandeSortieG=255;
}

//Redéfinition des sens de rotation du moteur droit
if(AvD==false&&etatD != LOW) {
etatD=LOW;
integraleD=50;
commandeSortieD=255;
} else if(AvD==true&&etatD != HIGH) {
etatD=HIGH;
integraleD=50;
commandeSortieD=255;
}

//Correction de la consigne pour l'adapter à la réalité - f(consigne)=rotation différent pour les deux moteurs-
if(etatD==false){
consigneD=consigneD*correctionRegulationMAv;
} else {
consigneD=consigneD*correctionRegulationMAr;
}
// Correction des consignes pour ne pas saturer les moteurs et obtenir n'importe quoi
if(consigneG>Vmax && consigneG>consigneD) {
consigneD=consigneD*Vmax/consigneG;
consigneG=Vmax;
} else if(consigneD>Vmax) {
consigneG=consigneG*Vmax/consigneD;
consigneD=Vmax;
}

/*
Transmission des consignes aux moteurs
* En cas de changement de sens, on transmet le dirac afin de faire changer le sens des moteurs.
* En cas de maintient du sens des moteurs, la valeur envoyé aux moteurs ne change pas et l'asservissement va se charger d'atteindre la consigne de vitesse
*/
digitalWrite(sensG, etatG);//envoie de la commande au moteur
digitalWrite(sensD, etatD);//envoie de la commande au moteur

analogWrite(PWMG, commandeSortieG);//envoie de la commande au moteur
analogWrite(PWMD, commandeSortieD);//envoie de la commande au moteur

}

void AdaptationConsigneRobot(float vitesseTranslation, float vitesseRotation) {
//vitesse en cm/s et vitesseRotation en rad/s
float vg=vitesseTranslation-vitesseRotation*d/2;
float vd=vitesseTranslation+vitesseRotation*d/2;
boolean etmg=false;
boolean etmd=false;
//mise en forme pour utilisation d'AdaptationConsigneMoteur(boolean AvG, float consignePourMG, boolean AvD, float consignePourMD);
if(vg<0) {
etmg=true;
vg=-vg;
}
if(vd<0) {
etmd=true;
vd=-vd;
}
AdaptationConsigneMoteur(etmg,vg,etmd,vd);
}

//Intégration de la variation de position
void VariationPosition(float vitesseG, float vitesseD, float tab[3]) {
tab[0]=0.2*vitesseG;
tab[1]=0.2*vitesseD;
}

void communication(float vitesse[3]) {
float tabPosition[3];
int tabPositionInt[3];
float vitesseG;
float vitesseD;
vitesseG=vitesse[0];
vitesseD=vitesse[1];
float vitesseTranslation;
float vitesseRotation;
VariationPosition(vitesseG, vitesseD, tabPosition);
tabPositionInt[0]=(int)(tabPosition[0]*10.0);
tabPositionInt[1]=(int)(tabPosition[1]*10.0); // !!!!!!!vérifier l'ajustement pour avoir une bonne précision, si besoin, changer de méthode
Wire.beginTransmission(8); // transmit to device #8
Wire.write(tabPositionInt[0]); // sends speed of left motor
Wire.write(tabPositionInt[1]); // sends speed of right motor
Wire.endTransmission(); // stop transmitting

Wire.requestFrom(8, 1); //request vitesseTranslation
while (Wire.available()) { // slave may send less than requested
int c = Wire.read(); // receive a byte as int
//Serial.print(c);
//Serial.print(" ");
vitesseTranslation=((float) c)/10.0;
}
Wire.requestFrom(8, 1); //request vitesseRotation
while (Wire.available()) { // slave may send less than requested
int c = Wire.read(); // receive a byte as int
//Serial.print(c);
//Serial.print(" ");
vitesseRotation=((float) c)/100.0;
}
//Serial.println("Et on repart");
AdaptationConsigneRobot( vitesseTranslation, vitesseRotation);
}