Aiuto: lettura encoder "quadruplicata"

buon primo maggio a tutti!
in questi giorni ho un problema di questo tipo, ho comprato un encoder da robotstoe (questo: http://www.robotstore.it/product/501/Encoder-Rotativo-Illuminato-con-LED-RGB.html ) e usando qualsiasi sketch di esempio e librerie varie trovate in rete non riesco ad avere il risultato desiderato ovvero ad ogni scatto aumentare il valore dell encoder di uno step (ora come ora me ne dà 4 ogni scatto).
Molto probabilmente il motivo è che seppur avendo letto qualsiasi cosa sul codice gray non ho neancora capito come funziona .
in realtà un modo lo avevo trovato ovvero far stampare sulla seriale il valore dell encoder diviso 4 ; se qualcuno con un buon cuore mi spiega come modificare il codice per far leggere ad ogni scatto poi vi spiegherò i problemi successivi :~
in allegato lo sketch che funziona meglio di tutti:

#include <Encoder.h>

//From bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/

//these pins can not be changed 2/3 are special pins
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);
  pinMode(encoderPin2, INPUT);

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

  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3)
  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);

}

void loop(){
  //Do stuff here

  Serial.println(encoderValue/4);
  delay(100); //just here to slow down the output, and show it will work  even during a delay
}


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
}

grazie matteo

in particolare non capisco il pezzo di codice seguente , soppratutto le 2 righe di incremento o decremento nonostante abbia provato a modificarle

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 codice Gray é un codice binario usato per encoder assoluti che ha la particolaritá che a ogni passo cambia solo 1 bit. Questo ha il vantaggio che se il lettore del codice non é allineato perfettamente non crea problemi. Questo succederebbe se usi un codice binari normale dove per esempio nel passaggio da 7 a 8 cambiano tutti i 4 bit. Un codice assoluto é un codice che legge la posizione in ogni momento e non i passi da un punto di riferimento.

Quel Encoder non usa il codice Gray ma é incrementivo.
Hai 2 segnali rettamgolari che sono sfasati di 90 gradi (considerando un periodo intero del segnale 360 gradi; nell immagine 4 righe rosse.).

http://www.microcontroller.it/Tutorials/Corso_asm/Es_18/es11/esercitaz18_11.htm

Se adesso controlli ogni cambio di stato puoi ottenere un segnale 4 volte maggiore dei passi che ha l'encoder.

percui quel encoder con 24 impulsi per rotazione con la tecnica di quadratura ottieni 96 impulsi per rotazione.
http://www.ilb2b.it/node/24694

Per modificare il segnale di uscita del Encoder devi modificare la libreria, usare un altra libreria o leggere l' ancoder col Tuo sketch.

Prova con questa libreria:
http://code.google.com/p/arduino-rotary-encoder-with-velocity/

Ciao Uwe

leggendo questo topic incominciavo a credere che il problema fosse il rimbalzo.. (http://arduino.cc/forum/index.php?topic=129872.0)
la libreria rotaryencoder l ho già provata ora rifaccio una prova, ma nel mio sketch per risolvere basterebbe che cambiassi il pezzo di codice che incrementa e decrementa?(quello dove cè il sum=)
comunque ora incomincio ad avere le idde un po chiare wikipedia non era abbastanza =(

uwefed:
Quel Encoder non usa il codice Gray ma é incrementivo.

In realtà anche gli encoder incrementali usano la codifica Grey, è a due bit :slight_smile:

ok, il caso di 2 segnali sfasati di 90 gradi corrisponde come forma d'onda a un codice Gray a 2 bit.

00, 01, 11, 10.

Ciao Uwe

1 Like

quindi per leggere un solo incremento ogni scatto dovrei rifare le due righe xor così giusto?

 if(sum == 0b00 || sum == 0b01) encoderValue ++;
  if(sum == 0b11 || sum == 0b10) encoderValue --;

aggiornamento:
ho provato ma la situazione peggiora... con tutte le combinazioni.
@uwe ho provato con la libreria suggerita ma non funge neancora , mi da valori +1 o -1 a seconda del verso di rotazione e ogni scatto mi scrive 4 volte il +1 o -1 ma non sempre correttamente ogni qualche scatto mi scrive:

1
1
1
1
-1
-1
-1
-1
-1
1
-1
1
-1
1
-1
-1
-1
-1

Se può esserti d'aiuto questo è lo sketch che ho fatto tempo fà per provare degli encoder Bourns da 256 impulsi/giro.
Praticamente ho collegato il canale A all'interrupt 0, che chiama la funzione encoder che legge lo stato del canale B per discriminare la direzione.
Nel loop aggiorno il display.

#include <LiquidCrystal.h>

LiquidCrystal lcd(14,15,16,17,18,19);
int a = 0;

void setup(){
  lcd.begin(16,2);
  lcd.print("  *Encoder* ");
  lcd.setCursor(0,1);
  lcd.print("Var. A=");
  pinMode(2,INPUT);
  pinMode(4,INPUT);
  pinMode(7,INPUT);
  attachInterrupt(0,encoder,RISING);
}

void loop(){
  lcd.setCursor(7,1);
  lcd.print(a);
  lcd.print("    ");
  if (digitalRead(7) == HIGH){
    a=0;
  }
}

void encoder(){
  if (digitalRead(4) ==LOW){
    a++;
  }
  else{
    a--;
  }
}

Mandi

Barbezuan

sicuramente c'è un modo più serio ma io ho risolto così:

  if (newPosition != oldPosition) {
    Partenza =false;
     if (newPosition == oldPosition + 4){
     rifTemp=rif+1;
     oldPosition = newPosition;}
     if (newPosition == oldPosition - 4){
     rifTemp=rif-1;
     oldPosition = newPosition;} 
  }

}

purtroppo ho l arduino bloccato... io devo usare l edncoder per navigare in un menu di case e avendole provate tutte ho bisogno che ogni scatto sia un incremento e non riesco a capire il perchè me ne legga 4...

niente credo mi arrenderò le ho provate tutte... a quanto pare ogni scatto ci sono le 4 combinazioni sia di incremento che di decremento in codice gray(dentro l encoder) =(

mah.. secondo me hai fatto dei casini col serial.print e semplicemente una stampa di 4 volte la stessa cosa
e gli dai il significato di 4 impulsi

Scusa la polemica, ma hai letto il post di uwefed?

Se vuoi leggere uno step a impulso, a cosa ti serve la libreria?

Mandi

Barbezuan

@ gingardu non non è un problema di serial print perchè con altri codici mi stampa tutti i valori (1,2,3,4,5,6,7,8,9,10,11,12) e quando l encoder scatta si ferma al 4 8 12 etc....

@barzezuan si ho letto tutti i post ma credo che il modo di leggere un solo impulso a scatto non esista dal momento che ogni scsatto internamente ha 4 intervalli

barbezuan:
Mandi

Barbezuan

OT: Sei friulano?
Ciao
C

aspi:
@barzezuan si ho letto tutti i post ma credo che il modo di leggere un solo impulso a scatto non esista dal momento che ogni scsatto internamente ha 4 intervalli

Secondo il datasheet non è come dici tu, ma come ti ha scritto uwefed. Allora, SENZA NESSUNA LIBRERIA (che legge i fronti di salita e discesa di entrambi i canali) prova a leggere un canale per volta e vedi cosa ti esce.

cece99:
OT: Sei friulano?
Ciao
C

Si si, sono di udine.

Mandi

Barbezuan

Si capisce dal Mandi :smiley: