Forum: Mikrocontroller und Digitale Elektronik Drehgeber (Rotary Encoder) hochauflösend und prellfrei decodieren


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Uwe K. (ukhl)


Angehängte Dateien:

Lesenswert?

Und täglich grüßt das Murmeltier. Nein, die Routine ist wirklich anders. 
Ich habe mir den Beitrag über Drehgeber genau durchgelesen. Und auch 
andere Beiträge wie:

http://www.technoblogy.com/show?1YHJ
oder
http://www.dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29

sind interessant.

Hier ist meine Idee. Primär ist es für Handdrehgeber gemacht, da das 
Prellen hier sehr störend ist. Der entscheidende Unterschied ist das 
Speichern der letzten beiden Positionen anstatt nur der Letzten. Damit 
ist auch ein Richtungswechsel erkennbar. Und genau das passiert beim 
Prellen bzw. Flattern am Schaltpunkt. Die Routine filtert den 
Richtungswechsel, und damit auch das Prellen, heraus. Das Ganze 
funktioniert auch mit der hohen 1:4 Abtastung. Das Programm ist sehr 
einfach an eine 1:1, 1:2 oder 1:4 Abtastung anzupassen, indem man die 
Lookup Tabelle ändert.

Als Eingabeparameter gibt es A und B. Eine 0 ist ein Low-Pegel und alles 
was größer als 0 ist, ist ein High-Pegel. Damit kann man den 
entsprechenden Pin eines Ports übergeben, ohne das Bit verschieben zu 
müssen.

Zurück kommt entweder 0 (nichts passiert), 1 (ein Schritt nach vorne) 
und -1 (ein Schritt zurück). Damit kann man das Ergebnis direkt auf 
einen Zähler addieren. Natürlich kann man es auch individuell auswerten.

Das Beispiel ist auf einem ATtiny13A im Einsatz. Es kann aber, durch 
seinen sehr einfachen Aufbau, leicht an andere Controller oder sogar 
Sprachen angepasst werden.

Ob man diese Routine mit Polling oder Interrupt aufruft, soll hier nicht 
das Thema sein. Der Routine ist das egal.

FAQ:

Ist es eine Sparvariante?

Nein, beide Signale werden ausgewertet.

Muss ich die Signale entprellen?

Nein. Die Routine entprellt automatisch.

Was mache ich bei wackeligen Rastpunkten?

Nix. Wird gefiltert.

Kann ich bei "wackeligen" Drehgebern Spur A und B beliebig vertauschen?

Ja. Ist egal.

Gibt es ein böses Prellen bei der Abtastung?

Nein, was auch immer das ist.

Ist die Routine Positions-Stabil?

Ja, die Position der Drehgeber stimmt immer mit der gesendeten Position 
überein. Ein Hoch- oder Runterzählen bei kurzen Hin- und Her- Bewegungen 
findet nicht statt. Das ist bei der Routine von technoblogy.com nicht 
der Fall.

Gibt es sonst was zu beachten?

Bei der 1:4 Abtastung fehlt beim rückwärts drehen ein Signal. Beim 
vorwärts drehen passt es aber wieder. Wenn man will, kann man das bei 
der Ausgabe des Zählers kompensieren. Es darf aber nicht auf den 
eigentlichen Zahler addiert werden, sondern nur bei der Ausgabe. 
Normalerweise sollte das Verhalten nicht stören. Bei der 1:1 oder 1:2 
Abtastung gibt es das Problem nicht.

Sollte bei der 1:1 Abtastung die Signale A und B auf Low liegen, sind 
die beiden IF abfragen zu invertieren. Bei der 1:2 oder 1:4 Abtastung 
ist das nicht notwendig.
1
  if (dgA != 0) dgVal |= 0b01;
2
  if (dgB != 0) dgVal |= 0b10;

Was haltet ihr von der Idee? Eine alternative zur PeDa Lösung?

: Bearbeitet durch User
von m.n. (Gast)


Lesenswert?

Uwe K. schrieb:
> Ob man diese Routine mit Polling oder Interrupt aufruft, soll hier nicht
> das Thema sein. Der Routine ist das egal.

Stimmt. Die Zählfehler werden woanders gemacht ;-)

von Stefan F. (Gast)


Lesenswert?

Uwe K. schrieb:
> FAQ:

Wer hat diese Fragen häufig gestellt?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Uwe K. schrieb:
> Das ist bei der Routine von technoblogy.com nicht
> der Fall.

Schlechte Drehgeber Routinen gibt es immer mal wieder. Muss man also 
nicht unbedingt vergleichen.

> Eine alternative zur PeDa Lösung?

Die Frage ist, ob man eine braucht. Ich jedenfalls bin damit recht 
glücklich, zumal der gleiche Timer Interrupt auch gleich Buttons 
bedienen kann und damit die Benutzerschnittstelle komplett abdeckt. Wer 
möchte, benutzt die gleiche ISR auch noch für den Ticker.

von Einer (Gast)


Lesenswert?

Uwe K. schrieb:
> Was haltet ihr von der Idee?

Dein Code funktioniert nicht.

Du shiftest den Zustand bei jedem Aufruf weiter. D.h. die Signale vom 
Drehgeber müssten sich synchron zur Abtastung ändern, so wie Du Dir das 
in Deiner Gedankenwelt gerade wünscht.

von Teo D. (teoderix)


Lesenswert?

Einer schrieb:
> Dein Code funktioniert nicht.

KA
Aber folgendes ist Quatsch mit Soße³!
> Du shiftest den Zustand bei jedem Aufruf weiter.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Einer schrieb:
> Du shiftest den Zustand bei jedem Aufruf weiter.

Nein, nur wenn sich mindestens einer der beiden Signalpegel geändert
hat:
1
  if ( ( dgHist & 0b11 ) == dgVal) return 0; // no change, return

Das ist schon richtig so.

von Einer (Gast)


Lesenswert?

Ah ja. Übersehen.

von mIstA (Gast)


Lesenswert?

Uwe K. schrieb:
> Sollte bei der 1:1 Abtastung die Signale A und B auf Low
> liegen, sind die beiden IF abfragen zu invertieren. Bei der
> 1:2 oder 1:4 Abtastung ist das nicht notwendig.
>   if (dgA != 0) dgVal |= 0b01;
>   if (dgB != 0) dgVal |= 0b10;


Also möglicherweise steh ich jetzt komplett auf der Leitung, aber das 
ergibt für mich keinen Sinn, weil dann Deine Routine ausschließlich 0 
als Rückgabewert liefern kann. (Wenn man für den Fall, daß sowohl dgA 
als auch dgB gleich 0 sind, die beiden IFs invertiert, dann kann dgVal 
in Folge nie 0b00 sein, aber die einzigen Bitmuster, die bei 1-fach 
Abtastung etwas anderes als 0 zurückliefern würden, enthalten beide eine 
eine Folge von zwei 0-Bits in der Mitte.)

von Uwe K. (ukhl)


Lesenswert?

mIstA schrieb:
> ... weil dann Deine Routine ausschließlich 0
> als Rückgabewert liefern kann. (Wenn man für den Fall, daß sowohl dgA
> als auch dgB gleich 0 sind, die beiden IFs invertiert, dann kann dgVal
> in Folge nie 0b00 sein ...

Schaut man sich etwas mehr vom Coding an, sollte es funktionieren.
1
  dgVal = 0;
2
  if (dgA != 0) dgVal |= 0b01;
3
  if (dgB != 0) dgVal |= 0b10;
wird zu
1
  dgVal = 0;
2
  if (dgA == 0) dgVal |= 0b01;
3
  if (dgB == 0) dgVal |= 0b10;

Der Ruhezustand des Drehgebers sollte für dgVal 0b11 ergeben.

Wenn dgA = 1 und dgB = 1 ist, wird aus dgVal = 0b00, weil sich nichts 
ändert.

von Uwe K. (ukhl)


Lesenswert?

Stefan ⛄ F. schrieb:
>> FAQ:
> Wer hat diese Fragen häufig gestellt?

Natürlich niemand. Es sind eher PAQ (possible ask questions).

Es sind hauptsächlich Problematiken die im Drehgeber Artikel 
thematisiert werden. Es soll auch Zeigen, das die Idee es ein paar Tests 
hinter sich hat.

von Stefan F. (Gast)


Lesenswert?

Uwe K. schrieb:
>>> FAQ:
>> Wer hat diese Fragen häufig gestellt?
> Natürlich niemand. Es sind eher PAQ (possible ask questions).

Dachte ich mir. Nenne sie beim nächsten mal "Q & A"

von Uwe (Gast)


Lesenswert?

Abtastintervall schneller machen und nen bisl Niquist 🥳👍

von Holger D. (hodoe)


Lesenswert?

Um eine Routine zu prüfen würde ich von Pollin eine Tüte Encoder 
empfehlen. Da sind gute und recht schrottige dabei. Aber mit einer guten 
Routine bekommt
man alle zum laufen.

von Uwe K. (ukhl)


Lesenswert?

Guter Plan. Wenn die alle Laufen, dann taugt es was.

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.