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!
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.