Asservissement moteur DC

Salut a tous

j 'utilise deux moteurs que j 'aimerais asservir en vitesse

Comme Dispositif ou matériel utilise:

  • une voiture robot avec deux moteurs Dc
  • deux capteurs rotatifs incrémentaux (Link & Recht) de types optocoupleur
  • un Motorschield (L298N) pour l asservissement de mes moteurs

j 'utilise ces deux capteurs incrémentaux pour le calcul de la vitesse que je voulais asservir

  • A partir de ces deux capteurs et de mes fonctions interrupts ( dans le code) je peux calculer la vitesse en tours/s en sachant que le disque codeur a 20 tics par tour et je peux de ce fait le convertir en cm/s puisque je connais le rayon de ma roue

  • J 'ai donc créer la fonction asservissement dans mon programme code ou je calcule la vitesse chaque 250 ms et je l'asservis .

C est pourquoi je voudrais savoir si j 'ai bien calculer les vitesses de mes moteurs 'right' et 'link' en cm/s , et également si j ai bien implémenter mon asservissement ?

Merci

#include <SimpleTimer.h>

SimpleTimer timer;

// définition des pins de l'Arduino qui contrôlent le  moteur droit (jaune)
#define pinIN1 8
#define pinIN2 12
#define pinENA 6 // doit être une pin PWM     

// définition des pins de l'Arduino qui contrôlent le  moteur gauche(Bleue)
#define pinIN3 13
#define pinIN4 4
#define pinENB 5 // doit être une pin PWM   
volatile int  comptageImpulsion_link=0; // variable accessible dans la routine interruption externe 0
volatile int comptageImpulsion_right=0; // variable accessible dans la routine interruption externe 1

volatile int i;
volatile int j ;
         
volatile int vitMoteur = 0.;     

volatile  double speed_right ;
volatile  double speed_link ;
volatile  double vit ;
volatile  double erreur;

const int pas= 20 ;// nombre de ticks sur le disque codeur

double consigne_moteur= 0.0; // cm/s

// init calculs asservissement PID
double erreur_precedente= consigne_moteur;  // (en cm/s)
double somme_erreur = 0;

//Definition des constantes du correcteur PID
double kp = 0.4;           // Coefficient proportionnel   
double ki = 2;              // Coefficient intégrateur
double kd = 1;           // Coefficient dérivateur



// duree d asservissement
double time_asservissement = 250; // millisseconde

int timerId;

// duree d 'asservissement en seconde
double dt = time_asservissement /1000 ;

unsigned long duree ;
void setup() {

  Serial.begin(9600);


  // Moteur Gauche
  pinMode(pinIN1, OUTPUT);
  pinMode(pinIN2, OUTPUT);
  pinMode(pinENA, OUTPUT);
  analogWrite(pinENA, 0);  // Initialisation sortie moteur à 0
  delay(300);                // Pause de 0,3 sec pour laisser le temps au moteur de s'arréter si celui-ci est en marche
// Moteur droit
  pinMode(pinIN3, OUTPUT);
  pinMode(pinIN4, OUTPUT);
  pinMode(pinENB, OUTPUT);
  analogWrite(pinENB, 0);  // Initialisation sortie moteur à 0
  delay(300);                // Pause de 0,3 sec pour laisser le temps au moteur de s'arréter si celui-ci est en marche


attachInterrupt(1, speedright, RISING );
attachInterrupt(0, speedlink, RISING);

timerId= timer.setInterval(time_asservissement, asservissement);


}

void loop() {

//duree= millis();
//asservissement();
//duree =millis()-duree;
//Serial.print("duree");
//Serial.print(duree); 
//Serial.println();
//// 

timer.run();
delay(10);


//timer.disable(timerId);
}

void asservissement(){
   
   int link = comptageImpulsion_link;
   int recht =comptageImpulsion_right;

// reinitialisation de mon tick de la codeuse
 comptageImpulsion_link= 0; //  reset counter to zero
 comptageImpulsion_right= 0;
 
  double rotation_link = ( link/ pas)/dt ;// vitesse du moteur gauche en tour/s
  double speed_link = ( 2*3.14*radius)*rotation_link; // cm /s
  double rotation_right = (recht / pas)/dt ;// vitesse du moteur droit en  1 tour/s
  double speed_right = (2*3.14*radius)*rotation_right;  // cm/s
 

//Serial.print("speed_link");
//Serial.print(speed_link); 
//Serial.println();
 
  double vit = (speed_right);
 //double vit = (speed_right+speed_link)/2;


Serial.print("peedright:");
Serial.print(speed_right);
Serial.print("speedlink:");
Serial.print(speed_link); 
Serial.println();

//Serial.print("Istzustand:");
//  Serial.print(vit,8); 
//  Serial.println();

/******* Régulation PID ********/
 double erreur = consigne_moteur-vit;
somme_erreur=somme_erreur+ erreur ;

double delta = erreur -erreur_precedente;

 erreur_precedente = erreur;

  vitMoteur = (kp*erreur +ki*somme_erreur+ kd*delta) ;

 /******* Régulation PID ********/
if (vitMoteur > 255) {
   vitMoteur = 255;  // sachant que l'on est branché sur un pont en H L298
 }
 else if (vitMoteur <0) {
  vitMoteur = 0;
 }


avancer(vitMoteur);

  Serial.print("Erreur:");
  Serial.print(erreur,4);
  Serial.println();

  Serial.print("Commande:");
  Serial.print(vitMoteur);
Serial.println();
    Serial.println();


  }


 void avancer(int Powerrate){

  analogWrite( pinENA, Powerrate );
  digitalWrite( pinIN1, false );
  digitalWrite( pinIN2, true );
 
  // Moteur droit
   analogWrite( pinENB, Powerrate );
  digitalWrite( pinIN3, LOW );
  digitalWrite( pinIN4, HIGH );
  }

void speedlink() {// la fonction appelée par l'interruption externe n°0

comptageImpulsion_link=comptageImpulsion_link+1; // Incrémente la variable de comptage

}

void speedright() {// la fonction appelée par l'interruption externe n°1

comptageImpulsion_right=comptageImpulsion_right+1; // Incrémente la variable de comptage

}

Que constatez vous ? est-ce que ça fonctionne ?

dans votre fonction asservissement(), lorsque vous accédez et remettez à 0 les comptageImpulsion_link et comptageImpulsion_right il serait bon de mettre cela en zone critique (bloquer les interruptions pendant ce temps là) pour ne pas que les octets soient modifiés en même temps que vous faites des opérations dessus).

(et décidez soit pour l'allemands links et recht ou l'anglais left et right... ou le français... mais ne mélangez pas tout).

Merci du Conseil;
Lorsque je réduis le temps d'asservissement, l'asservissement ne fonctionne plus vraiment.

Ma valeur de la consigne et les valeurs de mes codeurs ont vraiment un gros écart, je pense le problème vient de mes facteurs d'asservissement. Comment je peux les avoir de façon experimentale ?

Comment mettre (comptageimpulsion_link et comptageimpulsion_right) en zone critique