Hallo, ich habe einen EC11 Drehencoder und das Signal prellt beim Zählen. In meinen bisherigen Projekten war so etwas nie ein Problem, jetzt habe ich jedoch einen "Beep" als Feedback und möchte das Prellen deshalb ausschließen. Finde leider kein gutes Codebeispiel. Wollte das Rad nicht neu erfinden. Hat jemand einen Tipp ? Samsing
Samsing schrieb: > Da wird aber nichts entprellt. Wenn die Auswertung "richtig" gemacht wird (Pegel- und nicht Flanken- gesteuert) brauchst Du auch nicht zu entprellen. Gruss Harald
Vielleicht solltest du angeben, wie du bisher die Encoder-Werte verarbeitest? An welchem uC wird der Drehencoder betrieben? Verwendest du eine Hardware-Unterstützung (Zähler in Hardware) oder ist alles in Software realisiert?
>Da wird aber nichts entprellt.
Kann jemand der einen fertigen Code sucht, aus welchem Grund auch immer,
kann so jemadn auch fertigen COde beurteilen? Hat er sich überhaupt die
Mühe gemacht?
Oder muß im Kommentar des Codes nur drinstehen: "hier wird entprellt" ?
Harald Wilhelms schrieb: >Wenn die Auswertung "richtig" gemacht wird (Pegel- und nicht Flanken- >gesteuert) brauchst Du auch nicht zu entprellen. Ja. Die Auswertung habe ich richtig gemacht. @Seppl Ich lese die Encoderwerte in einer 1ms Task ein, nehme die beiden Zustände aus der letzten Task hinzu, gehe damit in eine State-Tabelle und habe als Ergebnis eben ein "HOCH" oder "RUNTER"-Zählen. Der Drehencoder wird an einem PIC16F1713 betrieben. Interne Weak-Pull Ups. Auswertung in Software (1ms Task) >aus welchem Grund auch immer Weil ich gerne bewährtes benutze. Man muss es ja nicht 1:1 übernehmen. Aber verstehen und für sein Projekt anpassen.
Samsing schrieb: > Auswertung in Software (1ms Task) Dann hast du in der Software vermutlich vergessen, eine Hysterese zu implementieren oder du hast ein Problem mit der Lage der Rastpunkte.
Hallo Mike, die Rastepunkte sollten eigentlich richtig liegen, denn ich zähle genau am "Berg". Das passt auch. Wenn ich den nur leicht berühre habe ich keine Probleme. >Dann hast du in der Software vermutlich vergessen, eine Hysterese zu >implementieren Ich verstehe den Begriff Hysterese hier nicht genau. Aber möglicherweise meinst Du damit das, was ich mit "Prellen" meine.
Da sich wohl nichts findet, bin ich gerade an einer Entprellung dran. Vielleicht überarbeite ich den Artikel dann in dieser Richtung, wenn es funktioniert.
Wie äußert sich denn dieses Prellen? Samsing schrieb: > Ich lese die Encoderwerte in einer 1ms Task ein, nehme die beiden > Zustände aus der letzten Task hinzu, gehe damit in eine State-Tabelle > und habe als Ergebnis eben ein "HOCH" oder "RUNTER"-Zählen. Das ist prinzipiell in Ordnung so. Allerdings kann es erforderlich sein, die Zustandstabelle an die spezifischen Eigenschaften¹ des verwendeten Drehgebers anzupassen. Liegt bspw. eine Signalflanke auf oder sehr dicht an einem Einrastpunkt, sollte an dieser Stelle kein für den Benutzer sichtbarer Zustandswechsel stattfinden. Bei vielen Drehgebern ist es möglich, die Inkrementpunkte gegenüber den Dekrementpunkten um eine Flanke zu versetzen. Damit erhält man eine Art Hysterese, die verhindert, dass der Wert beim langsamen Drehen zwischen zwei Zählerständen zwischen diesen hin und her zappelt. Mit einem schnellen Copy/Paste von Code aus dem Netz kommst du oft nicht zum Ziel. Wenn du aber dir aber Gedanken um die genaue Funktionsweise deines Drehgebers und des Auswerteverfahrens machst, ist die Anpassung hinterher ganz leicht. Du musst jedenfalls keinen zusätzlichen Entprellcode schreiben. An Anpassen der Zustandstabelle ist völlig ausreichend. ———————————— ¹) Insbesondere die Lage der Signalflanken relativ zu den Einrastpunkten undAnzahl der Signalflanken zwischen zwei Einrastpunkten, beides kann durch Messungen ermittelt werden.
Samsing schrieb: > Ich verstehe den Begriff Hysterese hier nicht genau. Wenn dein Geber an der Flanke einer der Phasen zwischen zwei Zuständen hin und her springt, stört das einen richtig aufgebauten Zustandsautomaten nicht. Trotzdem kann das für den Nutzer natürlich unerwünscht sein. Das kannst aber nur du über Zusatzfilterung für den ausgegebenen Zustand verhindern, weil der Drehgeber nicht unterscheiden kann, ob du hin und her drehst, oder ob da eine Flanke zappelt. Beispielsweise könnte man eine Hysterese für den Drehweg implementieren, die am Ausgang Zustandswechsel unterbindet, wenn nur einen Schritt in der Drehrichtung erfolgte und danach schon wieder ein Drehrichtungswechsel. Ob das sinnvoll ist, hängt von der Anwendung ab.
@Yalu Ich habe eine Tabelle mit 16 Einträgen. Davon gäbe es 4 für "RECHTS". Ich hatte bisher nur eine der 4 Flanken benutzt. Diese, die am besten zum mechanischen Raster passte. Hab jetzt auch mal die anderen 3 versucht. Ändert sich aber nichts. Abtastfrequenz ist allerdings 10kHz und nicht wie zuerst geschrieben 1kHz. @Mike Ja genau. Und ich hab halt so eine Anwendung. Ich drehe von 0 bis 100 und jedemal gibt es eine Feedback durch einen leisen Beep. Bei 100 ist man dann am rechten Rand und es soll nichts mehr zu hören sein. Signal des Drehencoders sieht jedoch so aus, wenn ich nach rechts weiter drehe: + + + -++ + + Das "+" wird begrenzt (kein Beep), das -++ wird jedoch als "kurz LINKS" erkannt und mit Beep quittiert.
Samsing schrieb: > Ich hatte bisher nur eine der 4 Flanken benutzt. Das ist vermutlich das Problem. Wenn du den Drehgeber über diese Flanke hinwegdrehst und der Kontakt etwas prellt, zappelt der ermittelte Zählwert, da das Inkrementieren und Dekrementieren exakt an derselben Stelle erfolgt. Schließ mal zwei LEDs an die Kanäle des Drehgebers an, dreh ihn ganz langsam durch zeichne dabei die Winkelpositionen der Signalflanken von A und B sowie der Rastpunkte relativ zueinander auf. Das muss nicht aufs Grad genau sein, aber wenigstens so genau, dass man erkennen kann, ob ein Rastpunkt etwa in der Mitte zwischen zwei Signalflanken oder ganz nah bei einer der Flanken liegt. So ein Digramm könnte (muss aber nicht) folgendermaßen aussehen:
1 | _______ ____ |
2 | A ____| : |_______| : |
3 | : : : |
4 | _______ _______ |
5 | B | : |_______| : | |
6 | : : : |
7 | Rastp. ^ ^ ^ |
8 | ———————————————————————————> Drehwinkel |
9 | |
10 | : : : : : : |
11 | ——> <—— ——> <—— ——> <—— |
12 | + - + - + - |
Wenn du in diesem Beispiel bei jedem Zustandswechsel von B den Zähler inkrementierst bzw. dekrementierst, macht sich genau an diesen Punkten das Kontaktprellen (oder deine zittrige Hand ;-)) negativ bemerkbar. Edit: Bitte den Beitrag ab hier ignorieren, es folgt nur noch Mist:
1 | | Wenn du hingegen bei positivem Drehsinn den Zähler beim Zustandswechsel |
2 | | von A inkrementierst und ihn bei negativem Drehsinn beim Zustandswechsel |
3 | | von B dekrementierst, passiert das nicht. |
4 | | |
5 | | Um während einer positiven Drehung den Wert fälschlicherweise um 1 |
6 | | zurückspringen zu lassen, müsstest du nämlich den Knopf um etwa eine |
7 | | Viertelsignalperiode bzw. eine halbe Rastweite zurückdrehen. So arg |
8 | | zitterst du aber nicht. Auch das Kontaktprellen stört nicht mehr, denn |
9 | | während A prellt ist B stabil und umgekehrt. Es kann also ein Inkrement |
10 | | und Dekrement an derselben Winkelposition stattfinden. |
11 | | |
12 | | Die kleinen Pfeile mit den Plus- und Minuszeichen verdeutlichen dies. So |
13 | | sagt bspw. der erste dieser Pfeile folgendes aus: Wenn der Drehknopf in |
14 | | positiver Richtung (im Diagramm also von links nach rechts) über die |
15 | | steigende Flanke von A bewegt wird, während B high ist, wird der Zähler |
16 | | inkrementiert. |
17 | | |
18 | | Der Winkelabstand zwischen den Inkrement- und Dekrementpunkten ist die |
19 | | Hysterese. Je größer sie ist, umso zuverlässiger wird die Auswertung. |
20 | | So, wie du die Auswertung bisher realisiert hast, ist die Hysterese aber |
21 | | null, d.h. Kontaktprellen und Zittern machen sich maximal bemerkbar. |
22 | | |
23 | | Das Hystereseverhalten kannst du durch eine geeignetee Anpassung der |
24 | | Zustandstabelle realisieren. Am Programmcode selber musst du vermutlich |
25 | | nichts ändern. Solltest du Schwierigkeiten dabei haben, kannst du ja das |
26 | | Signaldiagramm für deinen Drehgeber zusammen mit deinem Auswertecode |
27 | | posten. Dann wird dir sicher jemand helfen. |
Hallo Yalu, das Diagramm hab ich nicht gezeichnet. Ich hab's aber mal programmtechnisch so umgesetzt wie Du gesagt hast. Es bringt aber keine Verbesserung. Ich hab ja 4 Zustände 0 bis 3 und entsprechend 4 Übergänge. Mechanisch raster der Drehgeber bei Zustand 0 ich hatte bisher bei 2->3 ein "RECHTS" und bei 3->2 ein "LINKS" erkannt. Das habe ich geändert auf 2->3: RECHTS 1->0: LINKS Jetzt drehe ich also und habe bei 2->3 die obere (rechte) Softwaregrenze erreicht. Es soll in Zukunft nicht mehr weiter nach oben (rechts) gezählt werden. Er letzter "Beep". Ich drehe gedanklich weiter. 3->0->1->2->3 (diesmal kein Beep). Alles o.k. Ich drehe gedanklich weiter. 3->0->1->0[PRELL]->1-> ....das Prellen wird trotzdem fälschlicherweise als "LINKS" erkannt. Es ist jetzt sogar so, dass das System noch schlechter geworden ist. Denn jetzt würde ein Zittern um 0 und 1 zu einem mehrfachen Linkszählen führen. Zählfehler also.
Samsing schrieb: > Da wird aber nichts entprellt. Erzähl mal noch einen vom Pferd. Natürlich wird hier entprellt: http://www.mikrocontroller.net/articles/Drehgeber#Solide_L.C3.B6sung:_Beispielcode_in_C Der Trick ist, daß nicht nur an den Rastungen gezählt wird, sondern an jedem Wechsel. Somit wird ein Preller bei der nächsten Abtastung sofort wieder zurück gezählt. Bei Encodern, die genau an einer Flanke rasten, muß man den Startwert so wählen, daß dort kein Zählerwechsel erfolgt, sondern nur das unterste Bit zappelt.
Samsing schrieb: > Es ist jetzt sogar so, dass das System noch schlechter geworden ist. Was hindert Dich daran, einfach mal das Beispiel auszuprobieren, so wie es ist?
>Was hindert Dich daran, einfach mal das Beispiel auszuprobieren, so wie >es ist? Ich hab meinen Programmcode. Der ist wie das Beispiel "Drehgeber mit wackeligem Rastpunkt dekodieren". Nur etwas anders geschrieben. Aber gleiche Funktion. >Erzähl mal noch einen vom Pferd. >Natürlich wird hier entprellt: >http://www.mikrocontroller.net/articles/Drehgeber#... Nein. Wird nicht. Diese Beispiele sind geschrieben auf: "Prellen ist weiterhin möglich, ein Prellen führt aber zu keinem Zählfehler" >Somit wird ein Preller bei der nächsten Abtastung sofort wieder zurück >gezählt. Genau. Und eben diese Preller brauche ich bei meiner Anwendung nicht. Deswegen such ich eine Programmschnipsel, dass entprellt. ... bzw. ich such nicht mehr. Ich hab's jetzt hinbekommen.
teilweise Pseudocode, um es universeller zu halten. Wobei "cnt" hier nicht wirklich die Zählvariable ist, sondern nur ein "Hilfszähler" der von -2 bis +2 zählt.
1 | ....
|
2 | // Decode rotary encoder
|
3 | switch (EN_StepTab[encoderState]) { |
4 | case ENC_NO_STEP: |
5 | break; |
6 | case ENC_LEFT_STEP: |
7 | cnt --; |
8 | cnt_timeout = 0; |
9 | break; |
10 | case ENC_RIGHT_STEP: |
11 | cnt ++; |
12 | cnt_timeout = 0; |
13 | break; |
14 | case ENC_ERROR_STEP: |
15 | break; |
16 | }
|
17 | |
18 | |
19 | // If there were 2 steps, do not wait.
|
20 | // Count them immediatly
|
21 | if (cnt == 2) { |
22 | cnt = 0; |
23 | cnt_timeout = 0; |
24 | DoMyThings(INC); |
25 | DoMyThings(INC); |
26 | }
|
27 | |
28 | // If there were 2 steps, do not wait.
|
29 | // Count them immediatly
|
30 | if (cnt == -2) { |
31 | cnt = 0; |
32 | cnt_timeout = 0; |
33 | DoMyThings(DEC); |
34 | DoMyThings(DEC); |
35 | }
|
36 | |
37 | // Wait x ms for "no change in signal A and B"
|
38 | if (cnt_timeout < x_ms) { |
39 | cnt_timeout ++; |
40 | }
|
41 | else { |
42 | |
43 | // For at least x ms "no change"
|
44 | // now you can count them.
|
45 | if (cnt == 1 ) |
46 | DoMyThings(INC); |
47 | if (cnt == -1) |
48 | DoMyThings(DEC); |
49 | |
50 | cnt = 0; |
51 | }
|
>Der Winkelabstand zwischen den Inkrement- und Dekrementpunkten ist die >Hysterese. Je größer sie ist, umso zuverlässiger wird die Auswertung. Oh ! Man MUSS IMMER an einer Flanke hoch und runter zählen. Es ist zwar nicht notwendig, jede Flanke zu zählen. Aber wenn man es tut, dann immer die steigende und die fallenden. Nur eine zu zählen ist der Schlimmste Fehler, den man machen kann. Schlimmer als HTML Layout mit Tabellen. Schlimmer als IC ohne Abblockkondensatoren.
rostblau schrieb: > Man MUSS IMMER an einer Flanke hoch und runter zählen. Danke für den Hinweis! Ja, das war vollkommener Mist, den ich da geschrieben habe. Mir ist das gestern Abend sogar noch aufgefallen, hatte aber nicht mehr die Muße, das sofort zu korrigieren, zumal der TE ja inzwischen eine eigene Lösung gefunden hat. Ich schäme mich deswegen und nehme hiermit das, was ich oben geschrieben habe, zurück. Drehgeber kenne ich sonst nur von der Antriebs- und Steuerungstechnik, da ist es üblich, dass immer alle Flanken und in beide Richtungen ausgewertet werden, um die maximale Auflösung zu erhalten. Dort stellt sich dieses Problem deswegen überhaupt nicht. Eine Hysterese bei Drehgebern in Bedienfeldern zur Entprellung ist aber trotzdem möglich, allerdings sollte man sie nicht direkt auf die Abtastung der Gebersignale, sondern auf die Zählerwerte anwenden.
Ehrt Dich! Vor Leuten, die sich selbst mal korrigieren, habe ich mehr Respekt als vor denen, die alles wissen.
rostblau schrieb: >>Der Winkelabstand zwischen den Inkrement- und Dekrementpunkten ist die >>Hysterese. Je größer sie ist, umso zuverlässiger wird die Auswertung. > Oh ! > Man MUSS IMMER an einer Flanke hoch und runter zählen. Es ist zwar nicht > notwendig, jede Flanke zu zählen. Aber wenn man es tut, dann immer die > steigende und die fallenden. > > Nur eine zu zählen ist der Schlimmste Fehler, den man machen kann. Du hast es nicht begriffen. Der Zustandsautomat macht schon richtig einen Zustandsübergang für jeden Codewechsel. Aber es ist eine Halbschrittauswertung - es liegen zwei Codewechsel zwischen benachbarten Rastpunkten. Die für den Anwender sichtbare Zählvariable wird also nur an einem der beiden Codewechsel hoch- bzw. runtergezählt. Und welcher Codewechsel das sein soll, das kann man sich aussuchen. Durchaus auch unterschiedlich je nach Drehrichtung. XL
>Nein. Wird nicht. Diese Beispiele sind geschrieben auf: "Prellen ist >weiterhin möglich, ein Prellen führt aber zu keinem Zählfehler" Was ist für Dich denn die Definition von "Entprellen"? Ich würd behaupten wollen, daß der Encoder entprellt ist, wenn das Prellen eines Encoderes (ist eine Eigenschaft des Bauteils) keine Auswirkung auf den Zählerstand hat. Leistet das Deine Routine wirklich? Teile davon hast Du nicht veröffentlicht. Sieht aber auf den ersten Blick aus, als wenn Du keine 4-fach-Auswertung machst, sondern teilst. Und damit das erkannte Prellen (betrifft ja nur das letzte Bit des Zählers) verschwinden läßt.
Axel Schwenke schrieb: > Du hast es nicht begriffen. Doch, doch, "rostblau" hat es schon begriffen. Der, der es nicht begriffen hat, bin (bzw. war) ich ;-) Sein Hinweis bezog sich auf meinen Beitrag, und ich bin dort tatsächlich einem Trugschluss verfallen.
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.