Encodeur rotatif KY-040

Encodeur rotatif KY-040
Encodeur rotatif KY-040

Le module KY-040 est un codeur incrémental avec deux sorties légèrement décalées que nous permettent de savoir dans quelle direction nous tournons l’axe.

Broches de l'encodeur rotatif KY-040.

Un encodeur rotatif a un nombre fixe de positions par tour. Le modèle KY-040 a trente positions et elles sont marquées par progressifs déclics à la fois que nous tournons l’engrenage. En plus, il contient un bouton-poussoir interne.

Dans les encodeurs incrémentaux (ou de quadrature) comme ce dispositif, pour savoir dans quelle position il se trouve, il faut faire appel au software.

Son fonctionnement est plus facile qu’il n’y paraît: le module produit de signaux digitaux sur les pins A et B. Ces signaux seront à un niveau High et, au fur et à mesure que nous tournions l’axe, et en fonction du sens de rotation; l’ un de ces signaux changera d’état (Low) avant l’autre. Arduino est capable de détecter ces signaux.

Schéma du mouvement des positions dans l'encodeur rotatif KY-040

Nous pouvons observer que partant d’un signal High, si on continue à faire tourner l’axe (à droite) la sortie A change à Low, et la sortie B reste toujours High; pendant t2, les deux sorties sont en état Low. Pendant t3, la sortie A change à High et B reste Low…ce décalage entre les sorties nous aide à déterminer le sens de rotation de l’axe, la position et la vitesse.

Dans l’image ci dessous, il est representé le virement à droite. A et B sont les pins de sortie, tandis que C (GND) est connecté à un plat denté. Premièrement, A et B son en état High mais quand le encodeur avance une position, le pin A fait contact avec C et passe à l’état Low pendant que B reste High:

Encodeur rotatif, explication de changement de position à droite

Caractéristiques:

  • Encodeur rotatif incrémental
  • Tension alimentation: 5V
  • Courant: 10mA
  • Cycles par révolution: 30
  • Impulsions par révolution: 20
  • Dimensions: 20 x 30 x 30 mm
  • Poids: 10g

Connexion avec Arduino.

Schéma:

Connexion de l'encodeur rotatif et Arduino
Connexion de l’encodeur rotatif et Arduino

On va réaliser une code d’exemple et on vera comment virant l’encodeur vers la droite la valeur augmentera jusqu’à 50 et tournant à gauche, la valeur diminuera jusqu’à -50. Tout cela partant de 0.

Nous commençons par créer les variables nécessaires:

int A = 2;
int B = 3;
int ANTERIEUR = 0;
volatile int POSITION = 0;

On établit deux variables entières A et B en leur assignant les pins 2 et 3 respectivement. A correspond au signal A (CLK) et B avec le signal B (DT).

La variable ANTERIEUR nous servira à enregistrer la position antérieur et la variable POSITION, de type global on la déclare comme volatile pour pouvoir l’utiliser dans la fonction ISR.

Dans le bloc setup() on configure les pins A et B comme entrées, on initialise la communication série et, finalement, on ajoute l’interruption avec la fonction attachInterrupt(), qu’on produira sur le pin A; la fonction associée encodeur; y le mode Low.

void setup() {
  pinMode(A, INPUT);
  pinMode(B, INPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(A), encodeur, LOW);
}

La fonction encodeur() se vérifiera chaque fois que A soit en état Low. Dans ce cas, on teste: si B est High, cela signifie qu’on tourne a droite, alors on additionne une position; si B est Low, on tourne à gauche pourtant on soustrait une position.

void encodeur(){
    if (digitalRead(B) == HIGH){
      POSITION++;
    }else{
      POSITION--;
    }
}

Dans la fonction loop() on demande de imprimer sur l’écran du moniteur série la position, mais uniquement si elle est différente à celle d’avant.

void loop() {
  if (POSITION != ANTERIEUR) {
    Serial.println(POSITION);
    ANTERIEUR = POSITION;
  }
}

Si on essaye ce code on vera que les valeurs qu’on reçoit sont erratiques parce que le signal n’est pas net dû à des contacts mécaniques. Il y a des rebondissements produits par la friction des éléments mécaniques et les connexions. Pour éviter cela, on appliquera un système anti-rebonds configurant une période de temps majeur à 5 millisecondes entre les interruptions:

void encodeur()  {
  static unsigned long derniereInterruption = 0;
  unsigned long tempsInterruption = millis();
  if (tempsInterruption - derniereInterruption > 5) {
    if (digitalRead(B) == HIGH){
      POSITION++;
    }else{
      POSITION--;
    }
    POSITION = min(50, max(-50, POSITION));
    derniereInterruption = tempsInterruption;
  }
}

Code complet:

int A = 2;
int B = 3;

int ANTERIEUR = 0;

volatile int POSITION = 0;

void setup() {
  pinMode(A, INPUT);
  pinMode(B, INPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(A), encodeur, LOW);
}


void loop() {
  if (POSITION != ANTERIEUR) {
    Serial.println(POSITION);
    ANTERIEUR = POSITION;
  }
}

void encodeur()  {
  static unsigned long derniereInterruption = 0;
  unsigned long tempsInterruption = millis();

  if (tempsInterruption - derniereInterruption > 5) {
    if (digitalRead(B) == HIGH){
      POSITION++;
    }else{
      POSITION--;
    }

    POSITION = min(50, max(-50, POSITION));
    derniereInterruption = tempsInterruption;
  }
}
Articles similaires
Laisser un commentaire