Hi,
ich habe einen Drehimpulsgeber ALPS EC11 mit 30 Rastungen und 15
Impulsen - also zwischen 2 Rastungen wechselt jede Spur genau 1x.
Jetzt habe ich mir den Code von PeDa genommen und ein wenig angepasst.
Dabei bin ich auf das Problem gestoßen, dass der Drehgeber (bzw die
Auswertung) Fehler macht, wenn ich die Auswertung zu schnell laufen
lasse. Ich hänge mal meinen Code in den Anhang. Wie ihr sehen könnt, ist
das mehr oder weniger PeDa's Code zur Drehgeberauswertung, nur ohne
Interrupt. Ich habe zu Testzwecken mal auf den Interrupt verzichtet.
Am Ende steht ein _delay_ms(1); Damit läuft der Code gut und tut das,
was er soll - an PB0 und PB1 hängt jeweils eine LED. Die eine wechselt
ihren Zustand bei Drehung nach rechts, die andere bei Drehung nach
links. Durch den Delay am Ende der Schleife wird die Auswertung auf 1kHz
gedrosselt und wie gesagt, das läuft auch gut.
Wenn ich jetzt allerdings den Delay raus nehme, flackern beide LEDs,
wenn ich drehe. Zwar ist klar zu erkennen, welche LED zu welcher Drehung
gehört, weil die bei jeder Rastung einmal flackert, aber hin und wieder
ändert auch die falsche LED ihren Zustand. Diese Fehler passieren aber
nur bei schneller Auswertung. Kann mir jemand verraten, warum?
Viele Grüße
Nun,
die richtige Funktion von Peda gehört in eine Timerinterruptroutine und
diese kann bei einige Encoder auch mit 3kHz laufen müssen !
Bei deiner Betrachtung fehlen vollkommen die drei Auswertefunktionen für
den Anwender !
Der original Code von Peda funktioniert !
Man muss nur mit der passenden Auswertefunktion die Abfrage im
Hauptprogramm machen.
Was ist den eine .ino Datei ?
C Code sollte man als .c auch speichern.
Da mein Drehencoder 2 Wechsel pro Rastung hat, hab ich die Funktion
encode_read2() direkt in die Schleife mit rein gepackt. Die anderen
beiden Funktionen brauche ich ja nicht. Die Datei ist aus der Arduino
IDE.
drehgeber schrieb:> Kann mir jemand verraten, warum?
Weil du das System aushebelst. Der Timer ist ja gerade der Kniff, der
den Drehgeber auch bequem im Hintergrund bearbeitet, ohne dabei viel
Rechenzeit zu kosten. Mit deinem _delay() legst du den MC ja erstmal
lahm, und nach deiner Methode würde es zwar dann gehen. Der Timer aber
macht genau diesen 1ms Ticker von alleine, und enthebt dich der
Notwendigkeit, das Rad nochmal zu erfinden.
@mschoeldgen: Schon klar, dass der Timer auch diese 1ms warten kann
statt dem delay. Meine Frage war, warum es nicht mehr funktioniert, wenn
ich zu häufig abfrage...
Beispiel: Timer nicht mit 1ms sondern 10us. Die Auswertung macht Fehler.
Warum?
drehgeber schrieb:> Beispiel: Timer nicht mit 1ms sondern 10us. Die Auswertung macht Fehler.> Warum?
Hast du dir denn den Timerinterrupt mal genau angesehen? Der Code fragt
den Drehgeber nämlich zweimal ab, bevors einen Schritt weitergeht. Wenn
du das zu schnell machst, funktioniert das nicht mehr und der Code
vermutet z.B., das der Drehgeber immer hin und her gedreht wird.
Und ein normaler mechanischer Drehgeber prellt auch. Die Fehlimpulse
sind bei 10µs Zyklus schon im Messbereich der ISR und werden dann auch
so ausgewertet - als Fehlimpulse.
Matthias S. schrieb:> Hast du dir denn den Timerinterrupt mal genau angesehen? Der Code fragt> den Drehgeber nämlich zweimal ab, bevors einen Schritt weitergeht.
Ja, ich weiß. Daher ja auch der Teil
1
val = enc_delta;
2
enc_delta = val & 1;
3
val = (val >> 1);
Erst, wenn sich enc_delta 2x geändert hat, wird val +/- 1 gesetzt.
drehgeber schrieb:> Kann mir jemand verraten, warum?
Der Code zählt dann jeden Preller mit, d.h. man hat scheinbar mehrere
Richtungswechsel.
Das macht in der Praxis nichts, da ja nach einem Preller wieder sofort
zurück gezählt wird.
Man hat dann z.B. folgendes Verhalten beim Drehen um einen Schritt:
0-1-2(Preller)-1
Du hebelst das aber elegant aus, indem Du ständig den Wert wieder auf 0
zurück setzt.
Marius schrieb:> Siehe Entprellen
Drehencoder müssen normalerweise nicht entprellt werden, da die
richtige Auswertung nicht über Flankenwechsel, sondern über
Zustände gemacht wird(gemacht werden sollte). Man muss natürlich
dafür sorgen, das Preller nicht das Auswerteprogramm irritieren
oder im Extremfall sogar lähmen.
Harald W. schrieb:> Drehencoder müssen normalerweise nicht entprellt werden, da die> richtige Auswertung nicht über Flankenwechsel, sondern über> Zustände gemacht wird(gemacht werden sollte).
Das ist vom Grundsatz her falsch.
Drehencoder können prellen oder bei optischen kann die Flanke zu flach
sein, sodaß es zu Fehlimpulsen und somit zu Fehlzuständen kommt.
Deshalb müssen ALLE Drehencoder geeignet entprellt werden. Entweder
analog oder eben digital. Ist im Prinzip wurscht, aber die rein analoge
passive per 2 Kondensatoren ist bei weitem die effektivste: extrem
billig und ausreichend wirksam und kostet keinerlei Programmieraufwand.
Du solltest das mal vom ganz prinzipiellen Blick her verstehen: Ein
Programm in einem µC kann einen Port oder eine davon abgeleitete
Variable abfragen und das ist ein Samplingvorgang. Also schlägt das
Abtast-Theorem zu und es muß bereits VOR der Abtastung dafür gesorgt
sein, daß selbiges eingehalten wird, sonst gibt es Alias, was in diesem
Falle eben Fehlinterpretation des Drehvorganges bedeutet.
W.S.
W.S. schrieb:> Das ist vom Grundsatz her falsch.> Du solltest das mal vom ganz prinzipiellen Blick her verstehen
Harald hat völlig recht und du irrst.
Sicher ist es eine Auffassungssache, ob eine Auswertung, die keine
Probleme und Fehlzählungen durch Kontaktprellen mechanischer Encoder
hat, sowieso "entprellt".
Aber so lange man keine Flanken sondern Zustände auswertet, wie
Harald es richtig erwähnt, interessiert einen überhaupt nicht, ob
Kontakte mehrmals zwischen Zuständen hin und her wechseln.
Du findest also im richtigen Code keine Befehle zur Entprellung.