Auswerten eines Encoders

Hallo,

ich habe mir für mein Projekt diesen Encoder gekauft: http://de.rs-online.com/web/p/optische-encoder-mechanische-encoder/7295640/

Mit diesem soll es möglich sein, in einem Menü zu scrollen und Werte zu veränder.

Ich habe jetzt schon alles mögliche im Netz gesucht, aber nichts brauchbares gefunden. Gibt es dafür eine fertige Libary? Oder kann mir jemand sagen wie ich vorgehen muss.

Danke für die Hilfe :wink:

Hihi,
hab jetzt nicht allzu genau in das Datenblatt geschaut, aber in der Regel ist´s rlativ einfach.
Beide Schalter haben einen gemeinsamen Anschluss, beim nach links drehen schließt/öffnet dann zuerst z.B. Schalter 1 und anschließend Schalter 2. Dreht man nach rechts ist´s genau anders rum.
Wie es bei dir genau ist musst mal Datenblatt nachschauen bzw. nachmessen.
Eine Libary wird´s dafür wohl eher nicht geben, das wäre mit Kanonen auf Spatzen schießen.

MfG Jago

Ja genau so ist es.

Aber ich kapiere es nicht wie ich es mit dem Arduino auswerten kann.

Muss man dass mit Interrupt machen?

Hallo schau mal hier rein, dürfte doch genau das Richtige sein:
http://arduino.cc/playground/Main/RotaryEncoders

Gruß
Ardumidi

So hab mal ein paar Beispiele getestet, aber keines läuft so richtig. Zum Beispiel werden ab und zu auch zwei sprünge gezählt. An was kann das liegen?

Hat keiner eine einfache erklärung?

Unregelmäßigekeiten in der Anzahl der Sprünge deuten meist darauf hin, dass die Kontakte prellen. Hast du die "Debounce Circuits" eingebaut?

Nö habe ich nicht, aber ich werde es gleich mal testen. Danke für den Tipp.

Poste doch einfach mal den Aufbau Deiner Schaltung und den Code den Du hast. Das vereinfacht das Troubleshooting deutlich.

#include <Bounce.h>

#define encoder0PinA 2

#define encoder0PinB 3

Bounce bouncerA = Bounce (encoder0PinA, 2);
Bounce bouncerB = Bounce (encoder0PinB, 2);

int valueA;
int valueB;

volatile unsigned int encoder0Pos = 0;

void setup() {

  pinMode(encoder0PinA, INPUT); 
  pinMode(encoder0PinB, INPUT); 

// encoder pin on interrupt 0 (pin 2)

  attachInterrupt(0, doEncoderA, CHANGE);

// encoder pin on interrupt 1 (pin 3)

  attachInterrupt(1, doEncoderB, CHANGE);  

  Serial.begin (9600);

}

void loop()
{ 
 
}
void doEncoderA(){
   
  bouncerA.update();
  bouncerB.update();
  
  valueA = bouncerA.read();
  valueB = bouncerB.read();

  // look for a low-to-high on channel A
  if (digitalRead(valueA) == HIGH) { 

    // check channel B to see which way encoder is turning
    if (digitalRead(valueB) == LOW) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }

  else   // must be a high-to-low edge on channel A                                       
  { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(valueB) == HIGH) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
  Serial.println (encoder0Pos, DEC);          
  // use for debugging - remember to comment out

}

void doEncoderB(){

  // look for a low-to-high on channel B
  if (digitalRead(valueB) == HIGH) {   

   // check channel A to see which way encoder is turning
    if (digitalRead(valueA) == HIGH) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }

  // Look for a high-to-low on channel B

  else { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(valueA) == LOW) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }

}

Ich habe es mal mit der Bounce libary versucht, aber die verstehe ich nicht richtig. Jetzt zählt er nur noch quatsch.

#define encoder0PinA 2

#define encoder0PinB 3

volatile unsigned int encoder0Pos = 0;

void setup() {

  pinMode(encoder0PinA, INPUT); 
  pinMode(encoder0PinB, INPUT); 

// encoder pin on interrupt 0 (pin 2)

  attachInterrupt(0, doEncoderA, CHANGE);

// encoder pin on interrupt 1 (pin 3)

  attachInterrupt(1, doEncoderB, CHANGE);  

  Serial.begin (9600);

}

void loop(){ //Do stuff here }

void doEncoderA(){

  // look for a low-to-high on channel A
  if (digitalRead(encoder0PinA) == HIGH) { 

    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinB) == LOW) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }

  else   // must be a high-to-low edge on channel A                                       
  { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinB) == HIGH) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
  Serial.println (encoder0Pos, DEC);          
  // use for debugging - remember to comment out

}

void doEncoderB(){

  // look for a low-to-high on channel B
  if (digitalRead(encoder0PinB) == HIGH) {   

   // check channel A to see which way encoder is turning
    if (digitalRead(encoder0PinA) == HIGH) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }

  // Look for a high-to-low on channel B

  else { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinA) == LOW) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }

}

Das ist der Orginal Code, der nicht richtig zählt.

Ich kann mir ehrlich gesagt nicht vorstellen, dass eine Interrupt-Lösung vernünftig mit softwareseitigem debouncen funktionieren kann. Der Interrupt ist doch dafür da, dass wirklich alle Impulse registriert werden, es wird dann unmittelbar die Interruproutine aufgerufen. Jedes Kontaktprellen wird also registriert, daher muss dieses schon vorher ausgeschlossen werden, geht also nicht softwareseitig.

Achso okay, dann versuch ichs mal hardwaremäßig

Vielleicht helfen die Informationen hier weiter:
http://www.mikrocontroller.net/articles/Drehgeber

Wolfgang

So ich hab mir jetzt einen anderen Encoder besorgt. Ein optischen und daher denke ich dass der nicht mehr prellt.
Hier das Datenblatt http://docs-europe.electrocomponents.com/webdocs/0dd3/0900766b80dd3ca2.pdf

Folgenden Code habe ich geschrieben:

byte counter=0;
byte aktcounter=10;
int A = 5;
int B = 6;
byte speicherA = 0;
byte speicherB = 0;


void setup()
{
  Serial.begin(9600);
  pinMode(A, INPUT);
  pinMode(B, INPUT);
  digitalWrite(A,LOW);
  digitalWrite(B,LOW);

}

void loop()
{
  if (counter != aktcounter)
  {
    Serial.println(counter);
    aktcounter = counter;
  }
  
  if (digitalRead(A==HIGH) && digitalRead(B==LOW)&& speicherA==0 && speicherB==0)
  {
    counter++;
    speicherA=1;
    speicherB=0;
  }
  else if (digitalRead(A==HIGH) && digitalRead(B==HIGH) && speicherA==1 && speicherB==0)
  {
    counter++;
    speicherA=1;
    speicherB=1;
  }
  else if (digitalRead(A==LOW) && digitalRead(B==HIGH) && speicherA==1 && speicherB==1)
  {
    counter++;
    speicherA=0;
    speicherB=1;
  }
  else if (digitalRead(A==LOW) && digitalRead(B==LOW) && speicherA==0 && speicherB==1)
  {
    counter++;
    speicherA=0;
    speicherB=0;
  }
  
  else if (digitalRead(A==LOW) && digitalRead(B==HIGH) && speicherA==0 && speicherB==0)
  {
    counter--;
    speicherA=0;
    speicherB=1;
  }
  else if (digitalRead(A==HIGH) && digitalRead(B==HIGH) && speicherA==0 && speicherB==1)
  {
    counter--;
    speicherA=1;
    speicherB=1;
  }
  else if (digitalRead(A==HIGH) && digitalRead(B==LOW) && speicherA==1 && speicherB==1)
  {
    counter--;
    speicherA=1;
    speicherB=0;
  }
  else if (digitalRead(A==LOW) && digitalRead(B==LOW) && speicherA==1 && speicherB==0)
  {
    counter--;
    speicherA=0;
    speicherB=0;
  }
  
}

Wenn ich nun starte zählt das programm die ganze zeit hoch. Von 9 - 255.

Wo liegt der Fehler? Vielleicht kann mir jemand helfen.

Ich habe pin 6 an 5 V, pin 1 an Masse, pin 5 (A) an pin 5 (Arduino) und pin 6 (B) an pin 6 (Arduino).

Gerne würde ich auch wissen wie ich z.B. nur bis 3 zähle und dann wieder bei 0 beginne. 0,1,2,3,0,1,2.....

Kurze Frage zur Beschaltung: Hast du externe Pullups verwendet? Die internen schaltest du nämlich mit deiner digitalWrite()-Anweisung aus.

Da steckt der Fehler:

(digitalRead(A==HIGH) && digitalRead(B==LOW)

Das sollte wohl heissen:

(digitalRead(A)==HIGH && digitalRead(B)==LOW)

Also das "==HIGH", bzw. "==LOW" muss aus der Klammer des digitalRead() raus, da sonst immer erst der innere Teil "A==HIGH" ausgewertet wird und das Ergebnis davon dann als Wert für digitalRead() verwendet wird. Intern werden "true" und "false" als "0" und "1" dargestellt. Damit machst du dann immer ein digitalRead(0) oder digitalRead(1), je nachdem welchen Wert A und B gerade haben. Du wirst aber NIE von Pin5 und Pin 6 lesen, sondern immer nur von Pin0 und Pin1.
Mario.

@sth77: Nein ich nehme keine externe pullups. Wäre das besser?

@mkl0815: Danke damit ist das Problem mit dem Dauerzählen behoben. Hab ich voll verrafft. XD

Aber die Funktion ist noch nicht da.

Ich dachte, du schließt den Spaß nach dem Datenblatt an, da sind die Pullups doch auch dargestellt. Hab auch nur auf das Datenblatt Bezug nehmen wollen. :wink:

So jetzt funktioniert es. Ich habe die Pullups vom ardunio eingeschaltet und habe gemerkt dass ich ein Verdrahtungsfehler hatte.

Kann mir jetzt noch jemand sagen wie ich immer von z.B. 0-3 zähle?

Schau Dir mal die Modulo-Operation an:

int value;
...
value ++;
value  = value % 4; // zählt damit immer nur von 0 bis 3

okay danke