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: