Forum: Projekte & Code Drehencoder bullet proof und einfach


von Peter M. (Gast)


Angehängte Dateien:

Lesenswert?

Nachdem ich mich hier mit fast allen Beiträgen und Codebeispielen 
auseinandergesetzt habe und nichts wirklich "bullet proof" war bzw. in 
meiner Anwendung instabil gelaufen ist. Habe ich im Netz nach weitern 
Ideen gesucht.
Und wurde bei
http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
fündig.

Den Code von Ben habe ich dann AVR tauglich in Standard C angepasst.

Da ich von dem Ergebnis begeistert bin, wollte ich euch diesen Code 
nicht vorenthalten.

Alle Codes hier aus dem Forum und den von Ben auch, hatte ich mit einem 
PANASONIC ENCODER Typ EVEQDBRL416B_V2 (von Pollin) mit eine ATmega32 / 
16 MHz getestet.
Die Codes hatte ich jeweils in einen 2 ms Timerinterrupt gelegt.
Keiner der Codes aus diesem Forum lief stabil mit diesem Encoder.
Die negativsten Ergebnisse hatte ich mit dem Code von Peter Dannegger.
Hier wurde offenbar, dass kein sauberes Entprellen stattfindet. Denn in 
jeder Raststellung konnte durch sanften, seitlichen Druck auf die Achse 
des Encoders ein Prellen und damit verbunden ein ständiger 
Zustandswechsel erzeugt werden.

Der Code von Ben ist genial einfach, gut und sehr stabil.
Auch kein Springen der Werte bei Raststellung durch seitliches drücken 
auf die Achse.

Wenn man mit HALFSTEP übersetzt, wird bei jeder Rastung ein Wert 
geliefert. So wie man es eigentlich möchte/erwartet.

Bei FULLSTEP wird nur bei jeder 2. Raststellung ein Zustandsänderung 
gemeldet.


Ich kann nur sagen: Genial!

von Reiner W. (reiner_w)


Angehängte Dateien:

Lesenswert?

Peter M. schrieb:
> Die negativsten Ergebnisse hatte ich mit dem Code von Peter Dannegger.
Scheint mir nicht unbedingt an Peters Code zu liegen. Generell ist es 
eigentlich egal, ob man eine SM per Tabelle oder nach Peters Variante 
realisiert.
Ich setzte o.g. Encoder erfolgreich mit Peters Code auf ARM ein. 
Allerdings habe ich ein Detail modifiziert.
Generell ist es ja so, dass ein typischer Drehencoder durch 2 
Eigenschaften definiert werden.
1
#define NUMBER_OF_DETENT  20     // 32 for Pansonic EVEQ, 20 for my Alps
2
#define NUMBER_OF_PULSE   20     // 16 for Pansonic EVEQ, 20 for my Alps

Daraus kann man leicht errechnen, wieviel Stati pro Raste gezählt werden
1
#define ENCODER_MODE ((4 * NUMBER_OF_PULSE / NUMBER_OF_DETENT))  //Number of counts of detent

Ich zähle nun nicht jeden Status, sondern jede Raste.
Der große Vorteil ist, dass sich problemlos Encoder unterschiedlicher 
Detent/Pulse einsetzen lassen, ohne den eigentlichen Code anpassen zu 
müssen. Der Counter zählt immer gleich, nur die Rasten.
1
... Peters Code
2
void read_encoder(void){
3
    uint8 encA = ENCA_Read();
4
    uint8 encB = ENCB_Read();
5
    uint8 s = encB;          //stati      
6
    
7
    if (encA) {s ^= 3;}  //S = ENCB ^3 
8
    
9
    s -=  myEncoder.sLast;
10
    if (s & 1) {                                    //if bit0 set (diff is 1 or 3) 
11
        myEncoder.sLast += s;                       //s is now s-sLast -> sLast + s – sLast = s
12
        if (0 == myEncoder.sLast % (1 << myEncoder.encoderMode) ) {  //only the right state (1<<encoderMode) => 0,1,2->1,2,4
13
            uint32 lastCounterValue = myEncoder.counterValue;
14
            myEncoder.counterValue += (s & 2) - 1;   //clear bit -> (0 vw; 2 bw)-1 
15
            myEncoder.direction = (lastCounterValue < myEncoder.counterValue) ? '+':'-'; //encoder direction
16
        }
17
    }
18
}

Für mich Top-Erebnisse gibt eigentlich die Kombination von Peters Code, 
wenn das Polling durch einen IRQ an den Encoderausgängen angestoßen 
wird. Das gibt dann eine perfekte Kombination von IR-Verfahren und 
Polling;-)

Wie man auf dem Bild sieht wird das Polling mit dem ersten Impuls 
angestossen, was recht einfach zu realisieren ist, da es nicht darauf 
ankommt, welcher Eingang/Flanke den IR auslöst. Und wenn nach X 
Pooling-Impulsen keine weiteren Eingangsimpulse mehr kommen wird das 
Polling wider abgeschaltet.

Soll nur evl. ne Anregung sein. Um Gottes Willen nicht wieder ne 
Endlos-Encoder-Diskussion vom Zaun brechen;.)

Reiner

von Harald W. (wilhelms)


Lesenswert?

Peter M. schrieb:

> Nachdem ich mich hier mit fast allen Beiträgen und Codebeispielen
> auseinandergesetzt habe und nichts wirklich "bullet proof" war bzw. in
> meiner Anwendung instabil gelaufen ist.

Die einzig sichere Auswertung von inkrementellen Drehencodern ist
die Auswertung der vier möglichen Zustände an den zwei Ausgängen.
Alles andere ist mehr oder weniger instabil. Siehe auch DSE-FAQ.

: Bearbeitet durch User
von Axel S. (a-za-z0-9)


Lesenswert?

Peter M. schrieb:
> Nachdem ich mich hier mit fast allen Beiträgen und Codebeispielen
> auseinandergesetzt habe und nichts wirklich "bullet proof" war bzw. in
> meiner Anwendung instabil gelaufen ist.

> wurde bei
> http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
> fündig.

> Da ich von dem Ergebnis begeistert bin, wollte ich euch diesen Code
> nicht vorenthalten.

Das erscheint mir viel Code für so ein bißchen Funktionalität. Für mich 
funktioniert der Code aus dem Artikel Drehgeber, genauer gesagt 
Drehgeber: Dekoder für Drehgeber mit wackeligen Rastpunkten ganz 
hervorragend. Das Prinzip scheint ganz ähnlich.

Für den Beitrag "Kurzzeittimer (z.B. für Platinenbelichter)" habe ich diesen 
Code noch um Dynamik erweitert. Und die Entprell-Routine für den 
Push-Button kann noch zwischen kurzem und langem Tastendruck 
unterscheiden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.