Rotary Encoder: come utilizzare un encoder con Arduino

In questi giorni ho ricevuto da un appassionato lettore del Blog: “Cosimo” un encoder rotativo ( Rotary encoder ) da testare e inserire in un progetto più articolato.

rotary encoder con Arduino

Prima di cimentarmi con il progetto vero e proprio ho preferito fare dei test con l’encoder e qualche sketch per Arduino. Degli encoder hai già letto nell’articolo Rover 5: usare l’encoder, in cui hai analizzato il tipo di encoder presente nel Rover5, usato in altri progetti, e la teoria dei 90° di differenza tra le onde quadre presenti sui 2 pin dell’encoder stesso.

Ho eseguito due, entrambi si basano sull’uso degli interrupt di Arduino e prendono spunto da questo esempio di codice ben fatto: Rotary Encoder + Arduino puoi tuttavia trovare validissimi esempi anche nel Playgroung ufficiale Arduino.

Il primo sketch del Rotary Encoder

fa uso del Rotary Encoder e di un solo led ( collegato al pin 5 PWM ). I pin dell’encoder sono connessi rispettivamente ai pin 2, Gnd  e 3 di Arduino, questo permette all’encoder di funzionare correttamente sfruttando gli interrupt 0 ed 1 dell’Arduino Uno. Il pin centrale va connesso a massa.

int encoderPin1 = 2;
int encoderPin2 = 3;
int ledPin1     = 5; // PWM

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);
  pinMode(encoderPin2, INPUT);
  pinMode(ledPin1, OUTPUT);

  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
  analogWrite (ledPin1,LOW);

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

}

void loop(){
  Serial.println(encoderValue);
  if ( encoderValue > 255 ) { encoderValue = 255; }
  if ( encoderValue < 0 )   { encoderValue = 0; }

  analogWrite(ledPin1,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 --;

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

il punto principale dello sketch è senza dubbio la funzione updateEncoder() che si occupa di leggere i valori dell’encoder e incrementare o decrementare la variabile encoderValue in funzione del verso di rotazione del Rotary Encoder.

I pin 2 e 3 di arduino puoi utilizzarli anche come interrupt, ossia assegnare loro una funzione ogni colta che lo stato cambia, questo avviene alle linee 24-25 in cui puoi leggere il comando attachInterrupt( interrupt, funzione, metodo) dove interrupt è 0 per il pin 2 e 1 per il pin 3 di Arduino, la funzione è quella che vuoi sia invocata e il metodo indica in quale caso debba essere chiamata la funzione, nell’esempio usi CHANGE ossia quando il pin 2 o il pin 3 passa da HIGH a LOW e viceversa.

il controllo del led avviene nella funzione loop() in cui alle linee 31-32: definisci i limiti letti dall’encoder rispetto ai valori che puoi inviare al pin PWM 5 mediante il comando analogWrite() e alla linea 34: imposti il valore sul pin corrispondente.

Il secondo Sketch del Rotary Encoder

Il secondo esempio è un po’ più complesso in quanto oltre a rilevare i valori dell’encoder fa uso di quattro led che si illuminano in sequenza al crescere del valore letto dall’encoder.

In questo caso il Rotary Encoder è utilizzato quasi come un potenziomentro in cui i valori vanno da 0 a 1023, quindi potresti utilizzare un comune potenziometro per ottenere lo stesso risultato con lo svantaggio che non puoi ottenere range differenti, mantre con un Rotary Encoder puoi arrivare a valori infiniti è solo legato ai limiti che imposti nello sketch.

I led sono collegati rispettivamente ai pin 5,6,9 e 10 di Arduino:

rotary encoder led

Ecco l’esempio:

int encoderPin1 = 2;
int encoderPin2 = 3;
int ledPin1     = 5; // PWM
int ledPin2     = 6; // PWM
int ledPin3     = 9; // PWM
int ledPin4     = 10; // PWM

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

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

int ledPin = ledPin1;
int value  = 0;

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

  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);

  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
  analogWrite (ledPin1,LOW);
  analogWrite (ledPin2,LOW);
  analogWrite (ledPin3,LOW);
  analogWrite (ledPin4,LOW);

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

}

void loop(){
  Serial.print(ledPin);
  Serial.print( " - " );
  Serial.println(encoderValue);

  if ( encoderValue > 1024 ) { encoderValue = 1024; }
  if ( encoderValue < 0 )    { encoderValue = 0;   }

  if ( encoderValue > 0 && encoderValue < 255)    { ledPin =ledPin1; value = encoderValue; }
  if ( encoderValue > 256 && encoderValue < 512)  { ledPin =ledPin2; value = map( encoderValue,255,512,0,255); }
  if ( encoderValue > 513 && encoderValue < 767)  { ledPin =ledPin3; value = map( encoderValue,512,767,0,255); }
  if ( encoderValue > 768                        ) { ledPin =ledPin4; value = map( encoderValue,767,1024,0,255); }

  if ( value > 250 ) { value = 255; }
  if ( value < 5 )   { value = 0;   }

  analogWrite(ledPin,value);
}

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 --;

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

Ti sei accorto che sono state aggiunte delle linee:

linee 03-06: definisci i pin a cui sono collegati i 4 led;

linee 24-27: imposti i pin dei led come pin di tipo OUTPUT con il comando pinMode(pin,Mode);

linee 31-34: invia il valore LOW o 0 a ciascun pin a cui è connesso un led in modo da tenerli spenti all’avvio;

A questo punto la lettura dei valori dell’encoder rotativo ( Rotary Encoder ) la lasciamo immutata alla funzione updateEncoder() invocata dagli interrupt di Arduino, e ci concentriamo sulla funzione loop():

linee 46-47: definisci i limiti dei valori letti dall’encoder per i quali decidi di accentere il led, essendo 4 led ho deciso di usare solo i primi 1023 valori ma potresti decidere di utilizzare 4000 valori per ottenere un passaggio più lento della luminosità;

linee 49-52: sono il cuore dell’effetto ottenuto sui led, eseguendo l’operazione 1024 ( 0-1023) diviso 4 ottieni 1024/4 = 255 per cui i range saranno di 255 in 255: 0-255, 256-512, 513-767, 768-1023. Vai quindi a scrivere le 4 condizioni:

se il valore dell’encoer è compreso tra 0 e 255, accendi il led connesso al pin 5 inviando un valore pari a quello dell’encoder stesso;

se il valore dell’encoer è compreso tra 256 e 512, accendi il led connesso al pin 6 inviando un valore mappato su 0-255, ricorda che il PWM può inviare solo valori da 0 a 255;

se il valore dell’encoer è compreso tra 513 e 767, accendi il led connesso al pin 9;

se il valore dell’encoer è compreso tra 768 e 1023, accendi il led connesso al pin 10;

Nell’ultima condizione ti sarai accorto che manca il limite superiore ( 1024 ) in realtà questo limite è impostato alla linea 46;

linee 54-55: definisci i limiti da passare al pin PWM, serve come precauzione in caso di essrori presenti nei calcoli o nelle linee precedenti il valore passato al led è sempre compreso nel suo range. In particolare noti che la prima condizione non dice value > 255 ma value > 250 e la seconda non si rapporta a 0 ma a 5 serve ad introdurre una tolleranza tra i valori calcolati nelle linee 49-52 ed il valore realmente passato al’analogWrite() in corrispondenza degli esteremi 0 e 255;

linea 57: invii finalmente il valore PWM al pin corrispondente.

Per comprendere meglio quello che hai realizzato ho prodotto un breve filmato che ti aiuta a capire come funzionano i due sketch:

Buon divertimento !!!

  • Questo sito ed i suoi contenuti è fornito "così com'è" e Mauro Alfieri non rilascia alcuna dichiarazione o garanzia di alcun tipo, esplicita o implicita, riguardo alla completezza, accuratezza, affidabilità, idoneità o disponibilità del sito o delle informazioni, prodotti, servizi o grafiche correlate contenute sul sito per qualsiasi scopo.
  • Ti chiedo di leggere e rispettare il regolamento del sito prima di utilizzarlo
  • Ti chiedo di leggere i Termini e Condizioni d'uso del sito prima di utilizzarlo
  • In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei qualora siano presenti link al suddetto sito.

Permalink link a questo articolo: https://www.mauroalfieri.it/elettronica/arduino-rotary-encoder.html

47 commenti

3 ping

Vai al modulo dei commenti

    • angelo il 4 Febbraio 2013 alle 13:32
    • Rispondi

    salve e complimenti.
    sono un elettronico e da poco sto nel mondo di arduino.
    vorrei chiederti , ho bisogno di leggere gli impulsi di un encoder su displey lcd, puoi indicarmi qualcosa o dirmi qualche indirizzo

    1. Ciao Angelo,
      trovi nel blog sia i tutorial su come leggere un segnale da un encoder sia quelli per scrivere su un LCD.

      Mauro

    • Fabio il 1 Maggio 2013 alle 13:02
    • Rispondi

    Salve,
    prima di tutto un ringraziamento per i preziosi tutorial e passo al sodo:
    ho utilizzato il tuo codice con un encoder realizzato con il motore di un hard disk, ho utilizzato un LM393 per questo, funziona abbastanza bene, ma è veramente troppo sensibile, vorrei utilizzarlo per scorrere righe in un display LCD e 16 valori per me sarebbero più che sufficienti… certo avrei potuto utilizzare un potenziometro oppure un “vero” encoder rotativo… ma vuoi mettere il fascino di utilizzare pezzi da buttar via?
    Come posso rendere meno sensibile la lettura e spostarmi da un valore all’altro solo con un abbondante rotazione del motore?
    Grazie!
    Fabio.

    1. Grande Fabio,
      mi piacerebbe pubblicare il tuo progetto, oltre che provarlo.
      Manderesti alla casella info del blog qualche foto e lo schema.

      Sono della tua stessa idea: la soddisfazione del riciclare è unica.

      Per la tua richiesta, hai pensato ad un divisore, non so se sia la soluzione o sia possibile ma potresti provare a dividere i valori letti per un valore costante, es.: se leggi 1600 valori a giro e dividi tale valore per 100 dovresti ottenere i 16 valori di cui hai bisogno.

      So che non sarà così semplice ma magari è un suggerimento che ti porterà ad altre idee.
      Aspetto fiducioso le evoluzioni del tuo progetto 🙂

      Mauro

    • Fabio il 3 Maggio 2013 alle 10:51
    • Rispondi

    Ciao Mauro,
    grazie per l’apprezzamento ed il consiglio, nel fine settimana ci metto mano, è probabile anche che la sensibilità e instabilità è dovuta ad una scelta sbagliata del comparatore o più semplicemente del valore delle resistenze… appena posso ti mando lo schema e delle foto, così magari ne ricaviamo un articolo, mi farebbe molto piacere.

    A presto.

    1. Ciao Fabio,
      ottimo, attendo incuriosito.

      Mauro

    • alessandro il 2 Dicembre 2013 alle 14:28
    • Rispondi

    ciao ho letto questo articolo e mi sto chiedendo se puoi aiutarmi, sto realizzando un progetto che dovrebbe portarmi ad avere un rower semi automatizzato, ho utilizzato sia arduino che raspberry. Sono arrivato al punto che riesco a controllarlo bene da remoto tramite interfaccia web ma mi sono accorto che va “storto” chiaramente i due motori essendo indipendenti non saranno mai allineati come numeri di giri.
    Ho pensato di usare due encoder ottici per rilevare la velocita angolare e modulare le due uscite pwm per uniformare la velocità ma ottengo letture sbagliate sul pin3(uso arduino nano)
    secondo te ho sbagliato qualcosa lato software?

    1. Ciao Alessandro,
      ti chiedo la cortesia di non incollare codice nei commenti, leggi il messaggio in fondo ai miei articoli.
      Non sono così bravo da leggere e interpretare il codice che mi incollate, anche se si leggesse bene.
      Non ho il tempo e gli strumenti per riprodurre tutti i progetti che mi inviate ogni giorno.

      Quindi chiedo di evitare di incollare codice nei comenti.

      In merito alla tua richiesta, l’arduino nano ha la possibilità di leggere sul pin 3 un interrupt così come sul pin 2 è necessario dichiarare entrambi come interrupt perchè questa modalità di controllo funzioni.

      Mauro

    • Emiliano il 17 Febbraio 2014 alle 15:33
    • Rispondi

    Buon giorno Mauro,
    grazie innanzitutto per i lavori svolti che aiutano tante persone agli inizi come me.
    Ho eseguito il tuo sketch e ovviamente funziona benissimo, poi riprovando varie configurazioni mi sono accorto di una cosa, se utilizzo i pin 2 e 3 come hai fatto tu, tutto ok. Se ad esempio uso i pin 2 e 4 il comportamento non è lineare, ovvero ad ogni spostamento dell’encoder non corrisponde un cabio di valore, ma magari si devono eseguire più giri prima di vedere aggiornare il valore a monitor.
    Mi potresti spiegare il perché di questo comportamento?

    Grazie

    Emiliano

    1. Ciao. Emiliano, come avrai letto nell’articolo solo i pin 2 e 3 sono di tipo interrupt per cui con il pin 4 non puoi leggere l’encoder.

      Mauro

    • Emiliano il 19 Febbraio 2014 alle 21:03
    • Rispondi

    Sì ti chiedo scusa, effettivamente dopo averti fatto la domanda mi sono accorto che la risposta era già nell’articolo, non era mia intenzione farti perdere tempo con domande banali. Quindi volevo chiarire una cosa, avendo arduino solo due pin legati alla funzione interrupt non è possibile gestire due encoder nello stesso circuito? Ovviamente controllando i due encoder in ogni direzione.

    1. Ciao Emiliano, nessun problema.
      Usando gli interrupt no, ho letto che qualcuno ha realizzato dei progetti usando altri pin con dei trucchi nel loop() che francamente non mi convincono troppo come tutte le volte che via Sw cerchi si sopperire ad una mancanza Hw.

    • Davide il 20 Giugno 2014 alle 15:57
    • Rispondi

    Salve Mauro, ho cercato molto in rete ma non riesco a capire se con arduino, tramite shield o altro, è possibile controllare due encoder. Eventualmente, ci sono delle limitazioni per il tipo di encoder? Perdonami se le domande sono stupide ma sono in fase di studio.
    Grazie

    1. Ciao Davide,
      per leggere gli encoder hai bisogno dei pin di interrupt, come descritto in questo articolo.
      Arduino Uno ne possiede solo 2 per cui se usi un encoder rotativo a 2 segnali ne potrai leggere solo uno.

    • Domenico il 2 Luglio 2014 alle 22:18
    • Rispondi

    Ciao Mauro, voglio farti una domanda anch’io. Dovrei controllare la rotazione di un brandeggio e pensavo di usare questo encorer monogiro assoluto in quanto avrei bisogno, se spengo tutto, di avere la posizione esatta di dove si trova alla riaccensione.

    EMS22A della Bourns Electronic Solutions

    http://www.alldatasheet.com/view.jsp?Searchword=Ems22a

    Come vedi ha 1024 di risoluzione (10 bit). Ci hai mai avuto a che fare?
    Dovrei usarlo con Arduino UNO o NANO e mi farebbe comodo, prima di comperarlo, dato che costa più di 50 €, trovare qualche sketch per capire come tirare fuori i dati da rimappare a 0/359.
    Grazie e complimenti per tutto quello che fai.
    Domenico

    1. Ciao Domenico,
      non ho mai provato questo encoder.
      Come sketch penso tu possa utilizzare questo per verificarne il funzionamento, controlla solo che i segnali siano 0-5v e non superiori.

    • Domenico il 3 Luglio 2014 alle 15:55
    • Rispondi

    Grazie Mauro, appene avrò 50€ da buttare proverò.
    Tempo fa ti avevo interpellato in merito alla motorizzazione di una antenna satellitare, voglio solo dirti che avevo poi risolto i problemi e pubblicato l’articolo, se ti interessa dare uno sguardo, lo trovi qui:

    http://www.camperlife.it/fai-da-te/parabola-motorizzata-selfsat-hh-90-48268.html

    ciao e grazie ancora, Domenico.

    1. Wow che bello, domani leggero il tuo articolo 🙂

  1. Salve, da qualche giorno sto studiando su questo sito per poter realizzare un progetto a cui sto lavorando.
    Questo prevede l’utilizzo di un motoriduttore e di un encoder. Applicando la motor shield e collegando l’encoder su questa lo sketch dell’encoder può essere integrato con quello per il controllo del motore, arduino riesce a gestire tutto?
    Grazie mille

    1. Ciao Alessio, non conosco i componenti che stai utilizzando ma ho realizzato anche io un progetto con motore ed encoder e sono riuscito ad ottenere il mio scopo. Non posso pubblicare o diffondere quel codice perché di un progetto su commissione.

    • Fabio il 5 Settembre 2014 alle 11:24
    • Rispondi

    Ciao, complimenti per l’ottimo lavoro.
    Vorrei sapere a cosa serve la seguente linea di codice:
    long lastencoderValue = 0;
    Grazie

    1. Ciao Fabio,
      si tratta di un refuso da un esperimento di partenza, in questo caso puoi ometterla.

        • Fabio il 5 Settembre 2014 alle 19:01
        • Rispondi

        Grazie mille

    • Vincenzo il 3 Novembre 2014 alle 21:26
    • Rispondi

    Ciao Mauro,
    vorrei utilizzare il tuo sketch per controllare un driver per motore DC in applicazioni CNC (i classici segnali step&dir).
    Quello di cui avrei di bisogno è:
    – un’uscita digitale che mi dia valore alto se l’encoder gira in senso orario, o basso (0V) se l’encoder gira in senso antiorario;
    – un’uscita che mandi un impulso alto per ogni lettura dell’encoder.

    Mi potresti suggerire come integrare il tuo sketch.

    Ciao e complimenti

    1. Ciao Vincenzo,
      partendo dal mio sketch, leggendo linea per linea la spiegazione, non dovresti aver problemi ad ottenere quello che ti occorre.
      Se non ricordo male, c’è già una variabile che ti indica la direzione che puoi usare per controllare il pin di direzione ed un valore HIGH/LOW per ogni impulso dell’encoder.
      Quello di cui non sono certo è che il tuo ragionamento logico funzioni, in quanto ogni impulso al motore DC non corrisponde ad un effettivo movimento, in quanto il motore ha solitamente un ritardo tra quando riceve il segnale e quando inizia a muoversi.
      I motori DC sono controllati in tempo e non in impulso per questo nelle CNC si usano i motori passo-passo che garantiscono spostamenti precisi e controllabili.

    • antonio il 17 Gennaio 2015 alle 19:35
    • Rispondi

    Gentile Mauro

    avrei bisogno di un programmatore per un progetto con arduino

    zona crema/cremona

    sai dove posso andare a parare

    grazie
    Antonio

    1. Ciao Antonio,
      io realizzo progetti su commissione.
      Ne ho realizzati già molti in tutta italia.

      Scrivimi alla casella info del blog che ti racconto come opero.

    • Alessandro il 1 Febbraio 2015 alle 12:42
    • Rispondi

    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 –;

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

    Ciao Mauro! saresti così gentile da spiegarmi meglio queste righe del programma?

    1. Ciao Alessandro,
      si tratta di operazioni su bit eseguite con gli operatori bit a bit.
      Puoi trovare la descrizione di ciascun operatore sul reference di arduino ( http://arduino.cc/en/pmwiki.php?n=Reference/HomePage )

    • Alessandro il 16 Febbraio 2016 alle 19:18
    • Rispondi

    Dovrei gestire un braccio meccanico dotato di otto motori con relativi encoder. Hai qualche idea come gestire gli encoder con arduino il quale limite è di solo due interrupt? Grazie Alessandro.

    1. Ciao Alessandro,
      l’articolo che hai letto ed il tuo commento si rispondono da soli.
      Il limite di Arduino Uno con gli encoder rotativi è dato dai due interrupt, in qualche progetto ho letto dei timidi tentativi di simulare vis sw un terzo interrupt ma penso cambi poco ai fini della tua esigenza.

    • Andrea il 30 Giugno 2016 alle 22:21
    • Rispondi

    Ciao Mauro,
    come sempre GRAZIE per il tuo lavoro.
    Sto utilizzando un encoder con una scheda Arduino MEGA. I pin che uso sono rispettivamente 20 ( int.3 ) e 21 ( int.2 ) .
    ho utilizzato esattamente il codice che hai proposto.
    Apparentemente funziona, tranne che dopo alcune letture la scheda va in blocco, ovvero non legge più i valori e talvolta il display si ripulisce senza dare più cenni di vita.
    Ho provato codici diversi trovati sui numerosi siti, ma si verifica sempre lo stesso errore.
    Sapresti suggerirmi una possibile causa?
    Ti ringrazio moltissimo.
    Andrea

    1. Ciao Andrea,
      nel mio articolo non ho connesso un display ma dei led.
      Puoi verificare che non sia un conflitto generato dai timer della libreria LCD con quelli dell’encoder.

    • davide il 17 Agosto 2016 alle 14:48
    • Rispondi

    avrei bisogno di leggere ed eventualmente riutilizzare i dati letti da un encoder rotativo trasmessi da un arduino ad un secondo arduino via wifi,pensa sia una cosa fattibile?

    1. Ciao Davide,
      a mio avviso il wifi è troppo lento per il trasferimento di dati provenienti dall’encoder, opterei per altri sistemi di trasmissione come l’I2C che ho descritto in numerosi articoli sul blog.

    • claudio il 23 Gennaio 2017 alle 18:44
    • Rispondi

    Per prima cosa ti faccio i complimenti e ti ringrazio per servizio che fai a tutti noi, se sono riuscito a fare qualcosa con arduino è grazie ai tuoi tutorial.
    vengo alla domanda, sto facendo delle prove con un encoder rotativo a tre piedini più il pulsante, non o utilizzato alcun circuito de debounce, il tutto funziona, ma non riesco a capire come mai ad ogni step la numerazione avanza e diminuisce con incrementi di 4 es: 0-4-8-12 ecc. anzichè di un in uno , non riesco a capirne il motivo. ho utilizzato il tuo skech di base.

    grazie

    1. Ciao Claudio,
      è un effetto che ho anche io, dipende dal codice di lettura del dato.
      Darti una spiegazione in merito non è semplice, si tratta di matematica binaria, tuttavia puoi fidarti del valore, la ripetizione è costante e puoi dividerlo per 4 certo del risultato.

    • D'angelo il 7 Marzo 2017 alle 23:06
    • Rispondi

    Ciao Mauro mi daresti un aiuto a programmare un firmiware con encoder rotativi 5 assi x cnc stepp e direzione.

    1. Ciao Giuseppe,
      per i progetti su commissione puoi scrivermi alla casella info del blog.
      Se ti occorrono consigli o chiarimenti sui miei articoli puoi chiederli attraverso i commenti.

    • Andrea il 15 Ottobre 2017 alle 19:46
    • Rispondi

    Salve Mauro, ho realizzato il suo sketch per far funzionare il mio encoder. Purtroppo non funziona nel senso che sembra proprio che gli interrupt non entrino in gioco. Il mio encoder è del tipo a 5 pin, GND, VCC, SW, D1, CLK.. io ho collegato CLK sul 2 e D1 sul 3….non capisco cosa non vada, cosa mi suggerisce di controllare?
    Grazie
    Andrea

    1. Ciao Andrea,
      trovo strani i pin D1 e CLK che non sembrano essere degli interrupt ma già dotati di segnale di clock ( CLK ) e dati ( D1 ) verifica sul sito del produttore che tipo di codifica utilizza e se esiste una libreria o uno sketch di esempio con cui utilizzarlo.
      Il mio codice funziona solo con encoder rotativi senza interfaccia, con i semplici segnali ENC_A, ENC_B in quadratura.

    • Mario Priolisi il 1 Settembre 2018 alle 11:59
    • Rispondi

    Salve Mauro e complimenti per il lavoro svolto a favore di chi come me, di programmazione ne capisce ben poco. Sono un musicista con la passione per l’elettronica e oramai dall’età di sette anni che risalgono ahimè ai primi anni ’70, all’utilizzo dei famosi baracchini è questo mi ha portato qualche tempo fa, a preparami per i fatidici esami e conseguire la patente radioamatoriale così ho avuto modo di imparare molte cose riguardo l’elettronica e affini, da veri OM trovati in etere! Solo da qualche mese mi sono appassionato ad Arduino e sto cercando di capirci qualcosa!
    Allora, spiego cosa dovrei realizzare!
    Ho due motori alimentati con un circuito da me modificato e realizzato che sfrutta l’onda quadra di un NE555 che posso variare in ampiezza e frequenza utile a comandare due motorini indipendenti dedicati il primo, ad una bobina Roller che regola l’induttanza e il secondo motorino per comandare un condensatore per variare la capacità di un accordatore di antenna….naturalmente autocostruito e tutto questo perchè le bande dedicate ai radioamatori vanno dai 160 ai 10 metri e quindi, con un accordatore con queste caratteristiche, montato sotto il sistema radiante, nel mio caso 30 metri di filo da 2,5mm, questi viene opportunamente accordato in base la banda utilizzata.

    Ho trovato uno sketch che però non svolgeva il compito da me richiesto e dall’alto della mia ignoranza, si dice che la fortuna aiuti gli audaci, i bambini, gli ubriachi e gli scimuniti ma il fatto è che audace mica tanto, bambino dall’alto dei miei 54 anni mi sembra una forzatura, ubriaco…sono astemio dopo anni di lavoro nei night di mezza italia, non rimane che la quarta ipotesi….SIGH…che però ha funzionato!!!! ho iniziato a cambiare numeri a casaccio e ho raggiunto il mio scopo che è quello di leggere sul display la variazione di ogni singolo step dell’encoder. Il problema è che dovrei fare leggere i due encoder montati sui due componenti, sullo stesso display!
    Un motore roller sul rigo superiore e l’altro su quello inferiore.
    Ci sto impazzendo da qualche settimana, ho cercato sul web ma nulla, ho letto in questi mesi, dei PDF che ho trovato sul web e che parlano di linguaggio C/C++ ho capito qualcosa ma naturalmente alcune problematiche mi vengono di difficile comprensione e soluzione! Non mi interessa questo sketch in particolare, a me interesserebbe riuscire nell’impresa…HIHIHI!!! ma mi piacerebbe capire perchè non ci sono riuscito e cosa avrei dovuto fare ed è per questo che leggo spesso gli sketch che presenti! Sei l’unico che spiega stringa dopo stringa cosa accade e il loro significato oltre la funzione!

    Risolto questo che è il problema principale, mi rimangono altri due problemi, anzi uno e mezzo:
    Il primo lo potrei risolvere a prescindere da arduino. Quando si spegne e si riaccende, se i motori si trovano in una determinata posizione, il display si azzera ma i motori rimangono fermi e quindi magari mi trovo sulla decima spira del roller e sul display leggo 200, ma dopo spento, riaccendendo leggo 0 visto che il tutto si è resettato ma il motore rimane sulla decima spira. Potrei risolvere o provando una batteria tampone che dovrebbe alimentare solo l’integrato di Arduino se possibile, o con un circuito elettronico che dovrò studiare, in maniera che dopo spento in realtà rimane
    sotto alimentazione per tot secondi riportando a zero i due motorini anche se questo comporterebbe il dovere riaccordare ogni volta che si accende il sistema radioricetrasmittente!
    L’ideale sarebbe avere la possibilità di memorizzare le varie posizioni richiamabili tramite commutatore rotativo e quindi dopo un primo accordo dell’antenna e relativa memorizzazione, richiamare queste tramite commutatore ma non credo di essere in questo momento in grado di fare un passo simile in quanto immagino l’utilizzo della EEPROM e i concetti potrebbero essere troppo complessi per la mia attuale preparazione!!!

    L’altro problema, è che sarebbe utile potere dare l’informazione che passa sul display, anche in audio. Ho visto delle schede che potrebbero essere utili e dei video su you tube ma non ho idea di come funzionino!!! Questo per me sarebbe utile in quando potrei utilizzarlo anche per altro. Penso per esempio ad un amperometro, si trovano dei tester “parlanti” ma non misurano la corrente, oppure per avere info audio per leggere una distanza o una temperatura etc…
    Insomma….i quesiti sono troppi e io sono troppo scarso…HIHIHI!!!
    Scusa del disturbo e grazie per l’attenzione.
    cordialmente
    Mario Priolisi

    1. Ciao Mario,
      ho letto la tua storia e la trovo interessante e ben descritta.
      In merito ai risultati raggiunti ti porgo i miei complimenti per esserci riuscito anche se di base consiglio, a chiunque voglia raggiungere un risultato, di rileggere gli sketch e comprendere fino in fondo cosa hai scritto e perché funziona in modo da poter eseguire tutte le modifiche che desideri.
      In merito alla prima domanda: hai ragione sull’uso della EEPROM ti serve sia per memorizzare le posizioni da raggiungere sia per memorizzare la posizione raggiunta prima di spegnere.
      Passando alla seconda domanda: ti consiglio di leggere e comprendere come funziona il DFRobot Mini Mp3 che puoi usare per i messaggi audio in modo semplice e rapido.

        • Mario Priolisi il 1 Settembre 2018 alle 20:03
        • Rispondi

        Grazie per la risposta e per la velocità! Pienamente d’accordo sul ragionare su ciò che si modifica per capire cosa realmente accade, ma il problema è che mi mancano totalmente le basi della programmazione ed è quindi un mondo tutto nuovo. Cerco di appoggiarmi su ciò che trovo sul web e a chiedere a chi ne sa più di me così come ho fatto con l’elettronica! Sapessi quanti diodi e transistor ho visto incenerirsi e condensatori esplodere…AHAHAHAH!!!! Oggi mi succede un po meno, per mia fortuna e tranquillità della mia famiglia!
        Mi piacerebbe farti avere lo sketch che ho trovato e la modifica fatta da me e se possibile come potere utilizzare un’altro encoder come scritto, per leggere sul secondo rigo del display i giri del condensatore oltre che del roller, solo che siccome è stato trovato in rete, non lo voglio postare senza autorizzazione dell’autore!

        1. Ciao Mario,
          come hai giustamente letto nelle regole del blog non è consentito allegare o inserire sketch nei commenti.
          Non riesco a correggere gli sketch che scrivete perché non ho tutto il progetto ed i componenti e non potrei testare le modifiche, non sono in grado di scrivere alla cieca.
          Se la tua necessità è scrivere sulla seconda linea del display ti basta usare il comando setCursor() e posizionare il cursore dove desideri scrivere.

          Trovi molti articoli in cui utilizzo e spiego il comando.

    • Lorenzo Baldini il 29 Ottobre 2020 alle 17:48
    • Rispondi

    Salve Mauro, avrei bisogno di un piccolo aiuto. Sto lavorando con un encoder in quadratura da 50 ppr. Con Arduino vorrei dividere la frequenza per ottenere in uscita 1/5 della risoluzione, cioè come avere un encoder da 10 ppr. Sono riuscito ad ottenere una divisione perfetta di entrambi i canali ma perdo la quadratura dei segnali A e B, cioè la sfasatura di 90°.
    Non potendo postare il codice ti chiedo un suggerimento. Grazie

    1. Ciao Lorenzo,
      la divisione potrebbe essere corretto eseguirla dopo la lettura, in modo da non perdere la quadratura.
      Hai già provato così ?

  1. […] « Rotary Encoder: come utilizzare un encoder con Arduino […]

  2. […] trattato in passato l’argomento encoder rotativi ( puoi leggerlo qui ) per spiegare la teoria con la quale è possibile leggere il valore di rotazione ed il […]

  3. […] utilizzare l’encoder, parte della descrizione dello sketch la trovi in un mio precedente articolo dedicato agli encoder che ti invito a […]

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.