Encoderul rotativ

In acest articol vom testa functionalitate unui encoder rotativ.

Modulul are 5 terminale:

GND

+5V

SW - pentru apasare

DT 

CLK

Ultimele 2 sunt pentru citirea sensului de rotatie a encoderului.

Conexiunile intre Arduino si modul sunt facute in felul urmator:

Arduino      Encoder

D6 ---------  SW

D5 ---------  DT

D4 ---------  CLK 

Eu voi testa un modul gata facut dar voi puteti folosi orice fel de encoder, chiar si unul recuperat de la vechile dvd-playere numai ca va trebui sa adaugati rezistoare PULL-UP de 10KiloOhmi intre +5V si cele 3 iesiri (SW, DT si CLK).

Fotografia modulului este mai jos:

Montajul realizat pe breadboard arata asa:

 Pentru inceput vom folosi un sketch in care vom citi si afisa in terminalul serial o valoare pozitiva in cazul rotirii in sensul acelor de ceasornic sau o valoare negativa in cazul rotirii in directia opusa. Acesta este urmatorul:

#define intrareA 4  // CLK - inrare D4
#define intrareB 5  // DT - intrare D5

int numara = 0; 
int stareCurentaA;
int stareAnterioaraA; 
String afisare ="";
 
void setup() {
  pinMode (intrareA,INPUT);
  pinMode (intrareB,INPUT);
  Serial.begin (9600);
  Serial.println("Monitorizare encoder rotativ");
  stareAnterioaraA = digitalRead(intrareA);
}

void loop() {
 stareCurentaA = digitalRead(intrareA);
 encoder(stareCurentaA, stareAnterioaraA);
 stareAnterioaraA = stareCurentaA;
}

void encoder(int stareCurentaA, int stareAnterioaraA) {  
  if (stareCurentaA != stareAnterioaraA){ 
     if (digitalRead(intrareB) != stareCurentaA) {
      if (digitalRead(intrareB) == 1) { 
       numara --;
       afisare ="Sens antiorar";
       Serial.print("Directie rotire: ");
       Serial.print(afisare);
       Serial.print(" -- Valoare: ");
       Serial.println(numara);
      }   
     } else {
      if (digitalRead(intrareB) == 1) {
       numara ++;
       afisare ="Sens orar"; 
       Serial.print("Directie rotire: ");
       Serial.print(afisare);
       Serial.print(" -- Valoare: ");
       Serial.println(numara);
      }         
     } 
   }  
}

Urmatorul pas este sa vedem cum functioneaza apasarea butonului si sa afisam acest lucru in terminalul serial. Am folosit urmatoul sketch:

#define intrareC 6  // SW - intrare D6 - butonul encoderului

int stareButon = 1;  
int ultimaStareButon = 1;
unsigned long ultimulDebounceTime = 0;
unsigned long intarziereDebounce = 100;
int citireButon;

 
void setup() {
  pinMode (intrareC,INPUT);
  Serial.begin (9600);
  Serial.println("Apasarea butonului unui encoder rotativ");
}

void loop() {
  int citireButon = digitalRead(intrareC);

   if (citireButon != ultimaStareButon) {
    ultimulDebounceTime = millis();
  }

  if ((millis() - ultimulDebounceTime) > intarziereDebounce) {
    if (citireButon != stareButon) {
      stareButon = citireButon;
      if (stareButon == 0) {
        Serial.println("Buton apasat...");
      } 
    }
  }
 ultimaStareButon = citireButon; 
}

Urmatorul pas logic este sa unim cele doua sketch-uri intr-unul singur. Iar pentru a face ceva deosebit vom stabili ca la apasarea butonului vom reseta valoarea afisata de catre rotirea encoderului.

Sketch-ul final este urmatorul:

#define intrareA 4  // CLK - inrare D4
#define intrareB 5  // DT - intrare D5
#define intrareC 6  // SW - intrare D6 - butonul encoderului

int stareButon = 1;  
int ultimaStareButon = 1;
unsigned long ultimulDebounceTime = 0;
unsigned long intarziereDebounce = 100;
int citireButon;

int numara = 0; 
int stareCurentaA;
int stareAnterioaraA; 
String afisare ="";

int resetare = 0;
 
void setup() {
  pinMode (intrareA,INPUT);
  pinMode (intrareB,INPUT);
  pinMode (intrareC,INPUT);
  Serial.begin (9600);
  Serial.println("Monitorizare encoder rotativ");
  stareAnterioaraA = digitalRead(intrareA);
}

void loop() {
 apasareButon(); 
 stareCurentaA = digitalRead(intrareA);
 encoder(stareCurentaA, stareAnterioaraA, resetare);
 stareAnterioaraA = stareCurentaA;
}

int apasareButon() {
  int citireButon = digitalRead(intrareC);

   if (citireButon != ultimaStareButon) {
    ultimulDebounceTime = millis();
  }

  if ((millis() - ultimulDebounceTime) > intarziereDebounce) {
    if (citireButon != stareButon) {
      stareButon = citireButon;
      if (stareButon == 0) {
        Serial.println("Numaratoarea este resetata la 0.");
        numara = 0;
      }
    }
  }
 ultimaStareButon = citireButon; 
 return numara;
}


void encoder(int stareCurentaA, int stareAnterioaraA, int resetare) {  
  if (stareCurentaA != stareAnterioaraA){ 
     if (digitalRead(intrareB) != stareCurentaA) {
      if (digitalRead(intrareB) == 1) { 
       numara --;
       afisare ="Sens antiorar";
       Serial.print("Directie rotire: ");
       Serial.print(afisare);
       Serial.print(" -- Valoare: ");
       Serial.println(numara);
      }   
     } else {
      if (digitalRead(intrareB) == 1) {
       numara ++;
       afisare ="Sens orar"; 
       Serial.print("Directie rotire: ");
       Serial.print(afisare);
       Serial.print(" -- Valoare: ");
       Serial.println(numara);
      }         
     } 
   }
}

Un filmulet cu functionarea montajului este mai jos:

Daca dorim sa mergem mai departe cu acest proiect atunci vom afisa toate valorile acestui encoder pe un display LCD. Pentru acest lucru voi folosi display-ul prezentat in acest articol. Tin sa precizez ca in acest sketch am folosit Arduino Mega.

Sketch-ul rezultat este urmatorul:

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#define intrareA 22  // CLK - inrare D22 Arduino Mega
#define intrareB 24  // DT - intrare D24 Arduino Mega
#define intrareC 26  // SW - intrare D26 - butonul encoderului Arduino Mega

int stareButon = 1;  
int ultimaStareButon = 1;
unsigned long ultimulDebounceTime = 0;
unsigned long intarziereDebounce = 100;
int citireButon;

int numara = 0; 
int stareCurentaA;
int stareAnterioaraA; 
String afisare ="";

int resetare = 0;

void setup()
{   
  pinMode (intrareA,INPUT);
  pinMode (intrareB,INPUT);
  pinMode (intrareC,INPUT);
  stareAnterioaraA = digitalRead(intrareA);
  lcd.begin(16,4); 
  lcd.setCursor ( 0, 0 ); 
  lcd.print (" www.");  
  lcd.setCursor (0, 1 ); 
  lcd.print ("electronicstore");
  lcd.setCursor (0, 2 );
  lcd.print ("            .ro");
  lcd.setCursor (0, 3 );
  lcd.print ("****************");
  delay (2000); 
   lcd.clear(); 
   lcd.setCursor ( 0, 0 ); 
   lcd.print ("Rotire: Initial");  
   lcd.setCursor (0, 1 );
   lcd.print("Valoare: 0"); 
}

void loop()
{
 apasareButon();
 stareCurentaA = digitalRead(intrareA);
 encoder(stareCurentaA, stareAnterioaraA);
 stareAnterioaraA = stareCurentaA;
}

void encoder(int stareCurentaA, int stareAnterioaraA) {  
  if (stareCurentaA != stareAnterioaraA){ 
     if (digitalRead(intrareB) != stareCurentaA) {
      if (digitalRead(intrareB) == 1) { 
       numara --;
       lcd.clear();
       afisare ="Antiorar";
       lcd.setCursor ( 0, 0 ); 
       lcd.print ("Rotire: ");  
       lcd.print(afisare);
       lcd.setCursor (0, 1 );
       lcd.print("Valoare: ");
       lcd.print(numara);
      }   
     } else {
      if (digitalRead(intrareB) == 1) {
       numara ++;
       lcd.clear();
       afisare ="Orar    "; 
       lcd.setCursor ( 0, 0 ); 
       lcd.print ("Rotire: ");   
       lcd.print(afisare);
       lcd.setCursor (0, 1 );
       lcd.print("Valoare: ");
       lcd.print(numara);
      }         
     } 
   }
}

int apasareButon() {
  int citireButon = digitalRead(intrareC);

   if (citireButon != ultimaStareButon) {
    ultimulDebounceTime = millis();
  }

  if ((millis() - ultimulDebounceTime) > intarziereDebounce) {
    if (citireButon != stareButon) {
      stareButon = citireButon;
      if (stareButon == 0) {
        lcd.setCursor (0, 1 );
        lcd.print("Valoare: 0      "); 
        lcd.setCursor (0, 2 );
        lcd.print("Resetat!");
        numara = 0;
      }
    }
  }
 ultimaStareButon = citireButon; 
 return numara;
}

 Filmuletul cu montajul in functiune este mai jos:

 

Autentificare