Moteur avec encodeur

Il existe des moteurs avec encodeur incorporé. J’ai trouvé celui-ci chez Lextronic, le modèle est un DCM2. Il y a 6 fils connectés au moteur. Le rouge et le noir sont les alimentations habituelles d’un moteur. Les 4 autres fils s’occupent de capteurs intégrés au moteur. Ce ne sont pas des capteurs optiques comme dans les montages précédents mais des capteurs magnétiques à effet Hall.

Les capteurs sont à alimenter en 5 v :

– le fil marron est l’alimentation des capteurs
– le fil vert est la masse pour les capteurs

– le fil bleu est la sortie du capteur A
– le fil violet est la sortie du capteur B

On peut utiliser un seul capteur et travailler dans le même esprit que précédemment. On peut aussi utiliser les deux capteurs ce qui est intéressant car cela nous permet de connaître le sens de rotation du moteur. (Les capteurs envoient des signaux carrés, en quadrature et cela permet de retrouver le sens de rotation du moteur).

On peut écrire un programme analogue à ceux utilisés jusqu’ici :


/*
   Moteur encodeur V0
   
   on utilise ici uniquement 
   
   le capteur A
    
       
 */
 
int ENC_A = 2; // encodeur A à la pin 2 
 
int E1 = 5; //M1 Controle de vitesse PWM
 
int M1 = 4; //M1 Controle du sens de rotation

// on va stocker les chgts de l'encodeur 

volatile long chgt_encodeur = 0;


// la fonction de traitement de l'interruption

void compte_chgt()
{

chgt_encodeur ++ ;

}

 
void marche_avant(char a) //Marche avant
{
  analogWrite (E1,a); // PWM (reglage vitesse)
  digitalWrite(M1,HIGH); // sens de rotation
} 
 
void marche_arriere (char a) //Marche arrière
{
  analogWrite (E1,a); // PWM (reglage vitesse)
  digitalWrite(M1,LOW); // sens de rotation
}

void stop_moteur () 
{
  analogWrite (E1,0); // PWM (reglage vitesse)
  delay(100);
}
 
 
/////////////////////////////////////////////////////////////////////
void marche_nb_pas( int vitesse, int nb_pas, char sens)
/////////////////////////////////////////////////////////////////////

{


chgt_encodeur = 0;


// lancer le moteur

 if (sens == 'A') {
      marche_avant (vitesse);
     }
     
 if (sens == 'R') {
      marche_arriere (vitesse);
     }
     

while ( chgt_encodeur < nb_pas  ) {        
  
  // on ne fait rien
  // chgt_encodeur est incrémentée
  // par la fonction de
  // traitement de l'interruption
     
  }      

stop_moteur();
}
 
 
 
// Executee une seule fois
 
void setup() {
   
   // initialiser la communication serie
    
   Serial.begin(9600);
    
   pinMode(E1, OUTPUT); // E1 est utilisee en sortie
    
   pinMode(M1, OUTPUT); // M1 est utilisee en sortie
   
   pinMode(ENC_A,INPUT); 
   
   // pour que le capteur à effet Hall fonctionne
   // il faut activer la resistance pull-up
   // de l'Arduino
   
   digitalWrite(ENC_A,HIGH);
   
   // l'interruption 0 (pin 2) déclenche la fonction compte_chgt
   
   attachInterrupt(0, compte_chgt, CHANGE);        
  
}
 
// executee en boucle
 
void loop() {
  
    
   Serial.println("On avance de 300 pas");
     
   marche_nb_pas(200,300,'A');
   
   delay(3000);
    
   
  Serial.println("On recule de 300  pas");
   
   marche_nb_pas(200,300,'R');
   
   delay(3000);
   
  
}


On peut aussi recourir à des bibliothèques optimisées et qui simplifient l’écriture , ce que l’on a fait dans le programme ci-dessous :


/*
   Moteur encodeur V1   
    
       
 */
 
 #include <Encoder.h>
 
 int A = 2; // pin encodeur A
 int B = 3; // pin encodeur B
 
Encoder position_moteur1(A,B);
 
 
int E1 = 5; //M1 Controle de vitesse PWM
 
int M1 = 4; //M1 Controle du sens de rotation



 
void marche_avant(char a) //Marche avant
{
  analogWrite (E1,a); // PWM (reglage vitesse)
  digitalWrite(M1,HIGH); // sens de rotation
} 
 
void marche_arriere (char a) //Marche arrière
{
  analogWrite (E1,a); // PWM (reglage vitesse)
  digitalWrite(M1,LOW); // sens de rotation
}

void stop_moteur () 
{
  analogWrite (E1,0); // PWM (reglage vitesse)
  delay(100);
}
 
 
/////////////////////////////////////////////////////////////////////
void marche_nb_pas( int vitesse, int nb_pas, char sens)
/////////////////////////////////////////////////////////////////////

{

position_moteur1.write(0);

long pos_M1  = 0;

// lancer le moteur

 if (sens == 'A') {
      marche_avant (vitesse);      
      
     }
     
 if (sens == 'R') {
      marche_arriere (vitesse);      
         
     }
     

 while (  abs(position_moteur1.read()) < nb_pas  ) {        
  
  }      

stop_moteur();

} 
 
 
// Executee une seule fois
 
void setup() {
   
   // initialiser la communication serie
    
   Serial.begin(9600);
    
   pinMode(E1, OUTPUT); // E1 est utilisee en sortie
    
   pinMode(M1, OUTPUT); // M1 est utilisee en sortie
   
   pinMode(A,INPUT); 
   pinMode(B,INPUT); 
   
   // pour que le capteur à effet Hall fonctionne
   // il faut activer la resistance pull-up
   // de l'Arduino
   
   digitalWrite(A,HIGH);
   digitalWrite(B,HIGH);
          
  
}
 
// executee en boucle
 
void loop() {
  
    
   Serial.println("On avance de 720 pas");
     
   marche_nb_pas(200,720,'A');
   
   delay(3000);
    
   
   Serial.println("On recule de 720  pas");
   
   marche_nb_pas(200,720,'R');
   
   delay(3000);
   
  
}

On peut enfin décider de raisonner non pas en nombre de pas à faire dans un sens ou dans l’autre mais en position à atteindre.


/*
   Moteur encodeur V2   
    
       
 */
 
 #include <Encoder.h>
 
 int A = 2; // pin encodeur A
 int B = 3; // pin encodeur B
 
Encoder position_moteur1(A,B);

 
int E1 = 5; //M1 Controle de vitesse PWM
 
int M1 = 4; //M1 Controle du sens de rotation

 
void marche_avant(char a) //Marche avant
{
  analogWrite (E1,a); // PWM (reglage vitesse)
  digitalWrite(M1,HIGH); // sens de rotation
} 
 
void marche_arriere (char a) //Marche arrière
{
  analogWrite (E1,a); // PWM (reglage vitesse)
  digitalWrite(M1,LOW); // sens de rotation
}

void stop_moteur () 
{
  analogWrite (E1,0); // PWM (reglage vitesse)
  delay(100);
}
 
 
/////////////////////////////////////////////////////////////////////
void marche_vers_position( int vitesse, int position_cible_M1)
/////////////////////////////////////////////////////////////////////

{
   
       while (position_moteur1.read() < position_cible_M1) {
              marche_avant(vitesse);           
       }
      
       while (position_moteur1.read() > position_cible_M1) {
              marche_arriere(vitesse);
        }           
        

stop_moteur();

}

 
// Executee une seule fois
 
void setup() {
   
   // initialiser la communication serie
    
   Serial.begin(9600);
    
   pinMode(E1, OUTPUT); // E1 est utilisee en sortie
    
   pinMode(M1, OUTPUT); // M1 est utilisee en sortie
   
   pinMode(A,INPUT); 
   pinMode(B,INPUT); 
   
   // pour que le capteur à effet Hall fonctionne
   // il faut activer la rsistance pull-up
   // de l'Arduino
   
   digitalWrite(A,HIGH);
   digitalWrite(B,HIGH);
   
          
  
}
 
// executee en boucle
 
void loop() {
  
   position_moteur1.write(0);     
      
   Serial.println("On avance position 300");
     
   marche_vers_position(200,300);
   
   Serial.println(position_moteur1.read());
   
   delay(3000);    
   
  Serial.println("On retourne position 0");
   
   marche_vers_position(200,0);
   
   Serial.println(position_moteur1.read());
   
   delay(3000);
   
   Serial.println("******************");
   
  
}

Ce dernier programme met en lumière un souci : on demande la position 300 mais on l’atteint pas forcément… En effet si l’alimentation moteur est bien coupée à la position 300, le moteur continue à tourner par inertie et va jusqu’à la position 305 (alim moteur 4,5v) ou 370 (alim moteur 12v).

Nous verrons comment améliorer la situation dans un prochain article.