Rotary Encoder Arduino

In questo tutorial ti mostrerò come utilizzare un Rotary Encoder in quadratura con Arduino.

Cos’è un Rotary Encoder?

Molti di voi hanno un’autoradio in macchina, alcune autoradio (soprattutto modelli di marche famose e di fascia medio/alta) hanno, per la regolazione del volume e dei toni, una manopola che ruota. I più attenti già sanno che quella manopola non è assolutamente il classico potenziometro (altrimenti come mai gira di continuo, senza blocchi? Ok qualcuno potrebbe pure obiettare che esistono i potenziometri a rotazione continua ma dal momento che costano tanto non si tratta assolutamente di questo caso). Quella manopola è un congegno davvero semplice ma geniale per alcuni aspetti: si tratta di un encoder rotativo (Rotary Encoder). Una “manopola” del genere la troviamo comunque un po’ dappertutto: ce l’hanno anche alcuni forni a microonde, anche se il suo utilizzo più “in voga” è attualmente quello della regolazione del volume audio negli impianti hi-fi.
Sappiamo bene che un encoder, in senso generale, è un dispositivo che serve per codificare un tipo di segnale in un’altra “forma”. Un encoder rotativo è appunto un dispositivo che permette di codificare la rotazione di un albero in un segnale elettrico.
Gli encoder rotativi vengono utilizzati, soprattutto in ambito industriale, per il computo delle velocità degli alberi di rotazione. Erano usati nei vecchi mouse con la “pallina” per far muovere il puntatore, sono utilizzatissimi anche in robotica per determinare le velocità delle ruote dei robottini e quindi correggerne la traiettoria, e come abbiamo appena detto vi è anche questo utilizzo più “ludico” per il controllo del volume su un impianto audio o per impostare la temperatura del forno a microonde.
Un encoder rotativo altro non è che una serie di “contatti” (azionati in vari modi: meccanicamente, tramite infrarossi o sfruttando l’effetto hall) che chiudono ciclicamente un contatto quando l’albero ad essi collegato effettua una rotazione. A seconda del numero di contatti e del modo in cui questi vengono chiusi, abbiamo vari tipi di encoder. In questo articolo ci occuperemo unicamente dei cosiddetti encoder in quadratura.

Tratto da settorezero.com

Ora vediamo come utilizzare un Rotary Encoder con Arduino. Innanzitutto bisogna procurarsi un Encoder simile a questo, acquistabile facilmente su amazon.

Come puoi notare dall’immagine precedente, il modulo con Encoder è composta da cinque pin denominati (CLK, DT, SW, VCC, GND), collegate questi pin su Arduino come illustrato nella tabella successiva:

EncoderArduino
CLK2
DT3
SW 
VCC+5V
GNDGND

I pin CLK e DT corrispondono ai due contatti che forniscono due segnali sfalsati di 90°. Il pin SW corrisponde al pulsante interno (utilizzabile premendo sulla manopola). Mentre VCC e GND sono i due pin di alimentazione.

Se invece non hai a disposizione un modulo con Encoder ma solo l’Encoder (immagine precedente) si dovranno fare i seguenti collegamenti:

Per utilizzare al meglio l’Encoder in quadratura è possibile utilizzare i pin interrupts 0 e 1 di Arduino UNO corrispondenti ai pin digitali 2 e 3. Ci sono versioni di Arduino con più pin interrupt, come per esempio Arduino Zero che monta come microcontroller un Atmel ATSAMD21G18A.

Dopo aver completato i collegamenti passiamo allo sketch da caricare sulla board Arduino.

Sketch con Monitor Seriale

int encoderPin1 = 2;
int encoderPin2 = 3;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

void setup() {
  Serial.begin (9600);

  pinMode(encoderPin1, INPUT_PULLUP);
  pinMode(encoderPin2, INPUT_PULLUP);

  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);

}

void loop() {
  Serial.println(encoderValue);
}

void updateEncoder() {
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 1) | LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  //if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  //if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
  if (sum == 0b1000) encoderValue ++;
  if (sum == 0b0010) encoderValue --;

  lastEncoded = encoded; //store this value for next time
}

Sketch con Display LCD

In questo esempio utilizzeremo un Display LCD invece del monitor seriale per visualizzare il valore della variabile encoderValue. Se non sai come collegare un display LCD ad Arduino ti invito a leggere il mio tutorial QUI.

#include <LiquidCrystal.h>

LiquidCrystal lcd(4, 5, 6, 7, 8, 9);

int encoderPin1 = 2;
int encoderPin2 = 3;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

void setup() {

  lcd.begin(16, 2);

  pinMode(encoderPin1, INPUT_PULLUP);
  pinMode(encoderPin2, INPUT_PULLUP);

  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);

  lcd.setCursor(0, 0);
  lcd.print("Lettura Valore  ");
  lcd.setCursor(0, 1);
  lcd.print("Rotary Encoder  ");
  delay(2000);
  lcd.clear();
}

void loop() {

  lcd.setCursor(0, 0);
  lcd.print("Valore: ");
  lcd.print(encoderValue);
  lcd.print("        ");

}

void updateEncoder() {
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 1) | LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  //if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  //if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
  if (sum == 0b1000) encoderValue ++;
  if (sum == 0b0010) encoderValue --;

  lastEncoded = encoded; //store this value for next time
}

Video

Ecco a te un video che illustra il funzionamento degli sketch.