Moteur CC

Introduction

  • Un moteur CC (Courant Continu) ou DC (Direct Currant) doit être alimenté avec une alimentation continue (Batterie)
  • Le sens de rotation dépend de la polarité de la batterie. Si on inverse la polarité, le moteur tourne dans l'autre sens

Commande Marche/Arrêt

Si on contrôle le moteur à l'aide d'un commutateur électronique comme un transistor bipolaire ou un transistor MOS, il faut garder à l'esprit que le moteur est une charge inductive. A chaque coupure du courant il génère une surtension qui peut atteindre des centaines de Volts et détruire le transistor. Pour protéger le transistor il faut absolument ajouter une diode de récupération


Contrôle de vitesse

La commande de vitesse d'un moteur à courant continu (DC) se fait principalement par la modulation de la largeur d'impulsion (PWM, pour Pulse Width Modulation). Au lieu d'alimenter le moteur d'une manière permanente, on l'alimente a travers un commutateur commandé par un signal PWM.


Le signal PWM est caractérisé par une période fixe T. En faisant varier la largeur de l'impulsion active H au sein de cette période, on modifie le rapport cyclique, c'est-à-dire le ratio H/T. Ce rapport cyclique détermine la proportion de temps durant laquelle la tension est appliquée au moteur, influençant ainsi la puissance moyenne fournie et, par conséquent, la vitesse du moteur. Lorsque H est augmenté, le rapport cyclique augmente, ce qui accroît la vitesse du moteur. À l'inverse, en réduisant H, on diminue la vitesse


Contrôler le sens de rotation

Pour contrôler le sens de rotation du moteur, on le commande à l'aide d'un pont en H.

Un pont en H est tout simplement un ensemble de 4 interrupteurs. Si on ferme A et D, le moteur est alimenté dans un sens. Si on ferme B et C, le moteur est alimenté dans l'autre sens






Le pont en H L298

Le circuit:

Le circuit L298 fabriqué par STMicroelectronics contient deux ponts en H ce qui permet de contrôler deux moteurs à courant continu ou un moteur pas à pas bipolaire.



Table de vérité:


Contrôle de vitesse:

Conformément à la table de vérité, si on applique un '1' (5V permanent) sur l'entré ENA (ou ENB), le moteur tourne à sa vitesse nominale

Pour controler la vitesse, on applique un signal PWM sur l'entrée ENA (ou ENB), La vitesse de rotation sera proportionnelle au rapport cyclique du signal PWM. La fréquence du signal PWM ne devrait pas être trop élevée, une valeur entre 60Hz et 500Hz me parait optimale. Voir Ce paragraphe pour savoir comment modifier la fréquence

Branchement:

Le branchement du L298 avec un seul Moteur est indiqué ci-dessous :


On y trouve :

  • Une alimentation 5V qui alimente les circuits logiques du L298
  • Une alimentation allant de 4,5V à 46V pour alimenter le moteur. Il faut toujours prévoir 2Volts de plus que la tension nominale du moteur à cause de la chute de tension dans les transistors. Par exemple, si on a un moteur 12V, il faut prendre une alimentation de 14Volts
  • Quatres diiodes de récupération
  • Des condensateurs de filtrage

Le Module:

Le module L298 disponible dans le commerce a l'avantage d'être tout équipé et prêt à l'emploi. Il intègre :

  • Un circuit L298 monté sur radiateur,
  • Des bornier à vis pour faciliter le branchement des moteurs et des alimentations,
  • 8 diodes de protection, 4 pour chaque pont,
  • Un jumper qui permet d'alimenter un régulateur qui fabrique l'alimentation 5V à partir de l'alimentation du moteur,
  • Les entrée de contrôle (IN1, In2, ENA) du pont A et (IN3, In4, ENB) du pont B
  • Deux Jumpers qui permettent si on le désire de relier les broches ENA et ENB à 5V
  • Des condensateurs et une LED

Exemple 1: Vitesse fixe

Dans cet exemple, on a un seul moteur branché sur le pont A

  • On contrôle le sens de rotation à l'aides des broches IN1 et IN2
  • La broche ENA est validée en permanence à l'aide de son jumper (ou reliée à 5V), le moteur tournera à sa vitesse max
  • La source d'alimentation du moteur doit tenir compte de la chute de tension voisine de 2Volts perdue dans le pont
  • Le jumper 5V est en place, l'alim 5V est produite localement à partie de l'alimentation du moteur
  • On envoie des commandes à partir du moniteur série:
    • F ou f ==> Rotation avant (Forward)
    • B ou b ==> Rotation Arrière (Backward)
    • S ou s ==> Arrêt (Stop)


Exemple 2: Vitesse Variable

Dans cet exemple, on a un seul moteur branché sur le pont A

  • On contrôle le sens de rotation à l'aides des broches IN1 et IN2
  • On contrôle la vitesse en appliquant un signal PWM sur la broche ENA. (enlever le jumper)
  • La source d'alimentation du moteur doit tenir compte de la chute de tension voisine de 2Volts perdue dans le pont
  • Le jumper 5V est en place, l'alim 5V est produite localement à partie de l'alimentation du moteur
  • On envoie des commandes à partir du moniteur série. La commande est constituée d'un caractère majuscule ou minuscule (F, B, ou S) suivi d'un nombre N. Le caractère définit le sens de rotation, le nombre N (de 0 à 255) représente le paramètre de la fonction analogWrite() qui défini le rapport cyclique N/255 du signal PWM. Par exemple :
    • f 255 ==> Rotation avant, vitesse max
    • F 50 ==> Rotation avant, vitesse faible
    • B 127 ==> Rotation Arrière, vitesse médiane
    • F 0 ou B 0 ==> Roue Libre
    • S ou s ==> Arrêt (Stop)
  • On va utiliser la fonction Serial.parseInt() pour lire le paramètre N. Cette fonction laisse le retour à ligne de la commande '\r' '\n' dans le buffer de réception, d'où la nécessité de vider le buffer à chaque fois


Moteur CC, Avant/Arrière, vitesse Variable
                        
#define ENA 10
#define IN1 9
#define IN2 8

void setup() {
  TCCR1B = TCCR1B & B11111000 | B00000100;    // f = 122.55 Hz,  T = 8.16ms (D9, D10)
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  analogWrite(ENA,0);
  Serial.begin(9600);
  Serial.setTimeout(5000);
  Serial.println(F("F N -->  Forward (Avant), vitesse ~ N/255"));
  Serial.println(F("B N -->  Backward (Arrière), vitesse ~ N/255"));
  Serial.println(F("S  -->  Stop (Arrêt)"));
  Serial.println("Le moniteur Série doit envoyer un Fin de Ligne");
}

void loop() {
  if (Serial.available()) {
    char c = toupper(Serial.read());
    if(c == 'S'){
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, LOW);
      return;
    }
    uint8_t N = Serial.parseInt();
    clearInputBuffer();
    Serial.println(String(c)+" --> "+String(N));
    if (c == 'F') {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW); // gauche
      analogWrite(ENA,N);
    } else if (c == 'B') {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      analogWrite(ENA,N);
    } else {
      Serial.println(String(c)+" ---> Bad Command ");
    }
  }
}

void clearInputBuffer() {
  do {
    delay(2);
    Serial.read();
  } while (Serial.available());
}
                        

Exemple 3: Commande par un Joystick

Dans cet exemple, on va controller un moteur CC à l'aide d'un Joystick

  • Le joystick est constitué de deux potentiomètres Px et Py,
  • Quand on bouge le joystick dans l'axe X, il fait tourner le potentiomètre Px
  • Quand on bouge le joystick dans l'axe Y, il fait tourner le potentiomètre Py
  • Si on branche le potentiomètre entre la masse et 5Volts, les deux tensions de sorties VRX et VRY (points milieux) vont varier entre 0 Volts et 5 Volts
  • Si on applique une sortie (VRX ou VRY) à une entrée analogique du Arduino et on lit sa valeur avec la fonction analogRead() on obtient une valeurs comprise entre 0 et 1023
  • Les premiers tests montrent que le joystick n'est pas parfait:
    • Il n'est pas centré, à la position médiane, il ne délivre pas 2.5V,
    • Les limites 0v d'un coté et 5V de l'autre sont atteintes bien avant que la position du joystick ne soit arrivée au maximum,
    • Il semble que la tension obtenue sur la sortie du joystick (VRX ou VRY) ne varie pas linéairement avec les déplacements du potentiomètre: Un déplacement ΔP du joystick ne produit pas toujours la même variation de tension ΔV,
    • Il faudra donc adapter les programmes à ces considérations.
  • Pour notre exemple, on va faire simple. On va partager l'excursion (de chaque coté en trois plages):
    • Quand le joystick est au repos (position médiane), la valeur lue sur Arduino est voisine de 500. On va réserver une plage autour de cette valeur et l'affecter à l'action: Arrêt
    • Quand on pousse un peu le Joystick, on va arriver dans une nouvelle plage que nous allons affecter à une rotation Vitesse Faible
    • Quand on pousse le Joystick, on va arriver dans une nouvelle plage que nous allons affecter à une rotation Vitesse Forte
    • On peut par exemple essayer les plages suivantes et les adapter ensuite après utilisation
    • [900→1023] ==>  Rotation avant, Vitesse Forte
      [600→900]  ==>  Rotation avant, Vitesse Faible
      [400→600]  ==>  Arrêt
      [100→400]  ==>  Rotation arrière, Vitesse Faible
      [0 → 100]  ==>  Rotation arrière, Vitesse Forte
                                  



Commande Moteur CC par Joystick
    
/*
  0            100                400             600                900          1023
  |Ariere fort|---arrière faible---|-----Arrêt-----|---Avant faible---|-Avant fort-|

  Moteur branché sur pont A du L298
  Joystick sur A0
*/
#define ENA 10
#define IN1 9
#define IN2 8

#define PWML 100 // vitesse faible 
#define PWMH 255 // vitesse forte
#define N1  100  // modifier les paliers si nécessaire
#define N2  400
#define N3  600
#define N4  900


void setup() {
  TCCR1B = TCCR1B & B11111000 | B00000100;    // f = 122.55 Hz,  T = 8.16ms (D9, D10)
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
}

void loop() {
  delay(10);
  int N = analogRead(A0);
  if (N < N1) {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
    analogWrite(ENA, PWMH); // arrière Fort
  } else if (N < N2) {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
    analogWrite(ENA, PWML); // arrière Faible
  } else if (N < N3)analogWrite(ENA, 0); // Roue libre
  else if (N < N4) {
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
    analogWrite(ENA, PWML);  // Avant faible
  }
  else {
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
    analogWrite(ENA, PWMH); // Avant fort
  }
}
    


Le pont en H BTS7960

Le BTS7960 est un pont en H conçu pour contrôler des moteurs à courant continu (DC) de forte puissance. Il contient deux 1/2 ponts à base de transistors de puissance MOS

Ces caractéristiques principales sont :

  • Alimentation du moteur : 6V à 27V (B+ , B-)
  • Alimentation du circuit de contrôle : 5V (Vcc, GND)
  • Courant maximal : Jusqu'à 43A

La nomenclature des broches de contrôle porte à confusion. Il n'y a pas forcément une seule façon de controller le module. Nous proposons la méthode suivante :

  • Les broches L_EN et R_EN seront reliées ensemble et serviront à valider et contrôler la vitesse
  • Les Broches RPWM et LPWM servent à contrôler le sens de rotation
  • Le tableau suivant liste toutes les possibilité

Voici un exemple de branchement avec Arduino UNO et Arduino Mega

Pour le signal PWM, La fonction analogWrite() permet de régler le rapport cyclique mais pas la fréquence.

Pour contrôler un moteur CC, il me semble que la fréquence optimale devrait être dans la plage [60Hz, 500Hz]

En fonction de la sortie PWM choisie, on peut fixer la fréquence en ajoutant une ligne qui modifie un registre de configuration du timer qui gère la sortie.


Fréquences PWM pour Arduino UNO
// For Arduino Uno, Nano, Micro Magician, Mini Driver, Lilly Pad and any other board using ATmega 8, 168 or 328
//-------------- fréquences PWM sur les broches D5 & D6 -------------------------------
TCCR0B = TCCR0B & B11111000 | B00000001;    // f = 62500.00 Hz, 	T = 0.016ms
TCCR0B = TCCR0B & B11111000 | B00000010;    // f = 7812.50 Hz, 	T = 0.128ms
TCCR0B = TCCR0B & B11111000 | B00000011;    // f = 976.56 Hz,  	T = 1.024ms (The DEFAULT)
TCCR0B = TCCR0B & B11111000 | B00000100;    // f = 244.14 Hz, 	T = 4.096ms
TCCR0B = TCCR0B & B11111000 | B00000101;    // f = 61.04 Hz, 	T = 16.383ms

//---------------------------------------------- Set PWM frequency for D9 & D10 ------------------------------
TCCR1B = TCCR1B & B11111000 | B00000001;    // f = 31372.55 Hz,	T = 0.032ms
TCCR1B = TCCR1B & B11111000 | B00000010;    // f = 3921.16 Hz, 	T = 0.255ms
TCCR1B = TCCR1B & B11111000 | B00000011;    // f = 490.20 Hz,	T = 2.04ms (The DEFAULT)
TCCR1B = TCCR1B & B11111000 | B00000100;    // f = 122.55 Hz,	T = 8.16ms
TCCR1B = TCCR1B & B11111000 | B00000101;    // f = 30.64 Hz,	T = 32.637ms

//---------------------------------------------- Set PWM frequency for D3 & D11 ------------------------------
TCCR2B = TCCR2B & B11111000 | B00000001;    // f = 31372.55 Hz,	T = 0.032ms
TCCR2B = TCCR2B & B11111000 | B00000010;    // f = 3921.16 Hz, 	T = 0.255ms
TCCR2B = TCCR2B & B11111000 | B00000011;    // f = 980.39 Hz, 	T = 1.020ms
TCCR2B = TCCR2B & B11111000 | B00000100;    // f = 490.20 Hz,	T = 2.04ms (The DEFAULT)
TCCR2B = TCCR2B & B11111000 | B00000101;    // f = 245.10 Hz,	T = 4.080ms
TCCR2B = TCCR2B & B11111000 | B00000110;    // f = 122.55 Hz,	T = 8.16ms
TCCR2B = TCCR2B & B11111000 | B00000111;    // f = 30.64 Hz,		T = 32.637ms


Fréquences PWM pour Arduino MEGA
//For Arduino Mega1280, Mega2560, MegaADK, Spider or any other board using ATmega1280 or ATmega2560

//------------------------------ Set PWM frequency for D4 & D13 ------------------------------
TCCR0B = TCCR0B & B11111000 | B00000001;    // f = 62500.00 Hz, 	T = 0.016ms
TCCR0B = TCCR0B & B11111000 | B00000010;    // f = 7812.50 Hz, 	T = 0.128ms
TCCR0B = TCCR0B & B11111000 | B00000011;    // f = 976.56 Hz,  	T = 1.024ms (The DEFAULT)
TCCR0B = TCCR0B & B11111000 | B00000100;    // f = 244.14 Hz, 	T = 4.096ms
TCCR0B = TCCR0B & B11111000 | B00000101;    // f = 61.04 Hz, 	T = 16.383ms

//------------------------------ Set PWM frequency for D11 & D12 -----------------------------
TCCR1B = TCCR1B & B11111000 | B00000001;    // f = 31372.55 Hz,	T = 0.032ms
TCCR1B = TCCR1B & B11111000 | B00000010;    // f = 3921.16 Hz, 	T = 0.255ms
TCCR1B = TCCR1B & B11111000 | B00000011;    // f = 490.20 Hz,	T = 2.04ms (The DEFAULT)
TCCR1B = TCCR1B & B11111000 | B00000100;    // f = 122.55 Hz,	T = 8.16ms
TCCR1B = TCCR1B & B11111000 | B00000101;    // f = 30.64 Hz,		T = 32.637ms

//-------------------=---------- Set PWM frequency for D9 & D10 ------------------------------
TCCR2B = TCCR2B & B11111000 | B00000001;    // f = 31372.55 Hz,	T = 0.032ms
TCCR2B = TCCR2B & B11111000 | B00000010;    // f = 3921.16 Hz, 	T = 0.255ms
TCCR2B = TCCR2B & B11111000 | B00000011;    // f = 980.39 Hz, 	T = 1.020ms
TCCR2B = TCCR2B & B11111000 | B00000100;    // f = 490.20 Hz,	T = 2.04ms (The DEFAULT)
TCCR2B = TCCR2B & B11111000 | B00000101;    // f = 245.10 Hz,	T = 4.080ms
TCCR2B = TCCR2B & B11111000 | B00000110;    // f = 122.55 Hz,	T = 8.16ms
TCCR2B = TCCR2B & B11111000 | B00000111;    // f = 30.64 Hz,		T = 32.637ms

//------------------------------ Set PWM frequency for D2, D3 & D5 ---------------------------
TCCR3B = TCCR3B & B11111000 | B00000001;    // f = 31372.55 Hz		T = 0.032ms
TCCR3B = TCCR3B & B11111000 | B00000010;    // f = 3921.16 Hz		T = 0.255ms
TCCR3B = TCCR3B & B11111000 | B00000011;    // f = 490.20 Hz		T = 2.04ms (DEFAULT)
TCCR3B = TCCR3B & B11111000 | B00000100;    // f = 122.55 Hz		T = 8.16ms
TCCR3B = TCCR3B & B11111000 | B00000101;    // f = 30.64 Hz			T = 32.637ms

//------------------------------ Set PWM frequency for D6, D7 & D8 ---------------------------
TCCR4B = TCCR4B & B11111000 | B00000001;    // f = 31372.55 Hz		T = 0.032ms
TCCR4B = TCCR4B & B11111000 | B00000010;    // f = 3921.16 Hz		T = 0.255ms
TCCR4B = TCCR4B & B11111000 | B00000011;    // f = 490.20 Hz		T = 2.04ms (DEFAULT)
TCCR4B = TCCR4B & B11111000 | B00000100;    // f = 122.55 Hz		T = 8.16ms
TCCR4B = TCCR4B & B11111000 | B00000101;    // f = 30.64 Hz		T = 32.637ms

//------------------------------ Set PWM frequency for D44, D45 & D46 ------------------------
TCCR5B = TCCR5B & B11111000 | B00000001;    // f = 31372.55 Hz		T = 0.032ms
TCCR5B = TCCR5B & B11111000 | B00000010;    // f = 3921.16 Hz		T = 0.255ms
TCCR5B = TCCR5B & B11111000 | B00000011;    // f = 490.20 Hz		T = 2.04ms (DEFAULT)
TCCR5B = TCCR5B & B11111000 | B00000100;    // f = 122.55 Hz		T = 8.16ms
TCCR5B = TCCR5B & B11111000 | B00000101;    // f = 30.64 Hz		T = 32.637ms


Exemple pour Arduino UNO
/*
 * Exemple de code pour tester le Module BTS7960
 */
#define PSTEP 10
#define EN_PWM 9
#define DR 2
#define DL 4

void setup() {
  pinMode(EN_PWM, OUTPUT);
  pinMode(DR, OUTPUT);
  pinMode(DL, OUTPUT);
  digitalWrite(EN_PWM,LOW); // roue libre au déppart
  Serial.begin(9600);  
  Serial.println("Taper une commande");
  Serial.println("L --->   Roue Libre");
  Serial.println("D --->   Droite");
  Serial.println("G --->   Gauche");
  Serial.println("S --->   Stop (frein HIGH)");
  Serial.println("s --->   Stop (frein LOW)");
  Serial.println("+ --->   Accélerer");
  Serial.println("- --->   Ralentir");
  TCCR1B = TCCR1B & B11111000 | B00000101;    // set timer 1 divisor to  1024 for PWM frequency of    30.64 Hz

}
int pwm = 127;
void loop() {
  if (Serial.available() > 0){
    char c = Serial.read();
    switch (c) {
    case 'L':
      digitalWrite(EN_PWM,LOW); // roue libre
      Serial.println("Libre");
      break;
    case 'G':
      digitalWrite(DR,LOW);
      digitalWrite(DL,HIGH); // gauche
      analogWrite(EN_PWM,pwm);   // vitesse
      Serial.println("G --->  " + String(pwm));
      break;
    case 'D':
      digitalWrite(DR,HIGH);
      digitalWrite(DL,LOW);
      analogWrite(EN_PWM,pwm);
      Serial.println("D --->  " + String(pwm));
      break;
    case 'S':
      digitalWrite(DR,HIGH);  // frein
      digitalWrite(DL,HIGH);
      digitalWrite(EN_PWM,HIGH);
      Serial.println("Frein H");
      break;
    case 's':
      digitalWrite(DR,LOW);  // frein
      digitalWrite(DL,LOW);
      digitalWrite(EN_PWM,HIGH);
      Serial.println("Frein L");
      break;
    case '+':
      pwm += PSTEP;
      if (pwm > 255) pwm = 255;
      analogWrite(EN_PWM, pwm);
      Serial.println(pwm);
      break;
    case '-':
      pwm -= PSTEP;
      if (pwm < 0) pwm = 0;
      analogWrite(EN_PWM, pwm);
      Serial.println(pwm);
      break;
    }
  }
}