hallo,
nachdem mich gestern die encoder doch ziemlich genervt haben, hab ich mal n bisschen ursachenforschung betrieben. Leider hab ich in Augsburg weder Werkzeug, noch Messgerät oder ähnliches. Ging aber auch ohne, und ich hab sogar ne Flick-Lösung in C gefunden ![]()
Also nochmal das Problem im Detail: Bei den Pollin-Encodern gibt es einige (2-3) (Rast-)Stellungen, in denen der Rastpunkt ziemlich genau mit der Flanke des 2ten Encoder-Pins zusammenfällt. Liegt vermutlich am ungewöhnlichen (?) Aufbau des Encoders. Das führt nun dazu, dass der Pin bei der leichtesten Erschütterung umschaltet.
Ich hab ursprünglich MIOS_ENC_MODE_DETENTED mit “Speed-Mode Fast (2)” verwendet. Laut der Übersicht http://www.ucapps.de/mios/mios_encoder_modes.gif ist das genau der erste INC-Übergang. Genau das beobachte ich auch in der Software: in DIN_ENC_NotifyToggle kommen zufällig “incrementer >0” an und mein zähler springt munter nach oben. da der DEC-Übergang auf einer anderen Flanke liegt, gehts auch nicht wieder nach unten.
probeweise hab ich mal MIOS_ENC_MODE_UNDETENTED mit “Speed-Mode Normal” verwendet. Da hier jede Flanke ausgewertet wird, habe ich erwartet, dass nun abwechselnd +/-1 als incrementer ankommt. mein zähler würde also nicht mehr nach oben zählen sondern zufällig zwischen zwei benachbarten Werten wechseln. Interessanterweise kamen aber immernoch aufeinanderfolgende incrementer == +1.
Also hab ich mal n bisschen nach Theorie zur Encoder-Auswertung gesucht und bin auch schnell fündig geworden http://www.hilpers.com/604594-prelldauer-bei-encoder-drehimulsgeber (kein schöner thread, aber die info, die ich gesucht hab, war drin) . Kurz zusammengefasst gibts im Wesentlichen folgende gängige Implementierungen:
Abfrage: regelmäßiges Polling <-> Interrupt
-da die Encoder am SR hängen, geh ich bei MIOS mal von ersterem aus
Auswertung: Finite-State-Maschine <-> Ein Pin wird als Takt, zweiter als Richtung ausgewertet
-die zweite Möglichkeit hab ich nicht hundertprozentig verstanden, aber laut dem Thread würde sie genau das beobachtete Verhalten erklären. Dafür braucht sie weniger Rechenleistung.
Eine “saubere” Encoder-Implementierung verwendet also grundsätzlich eine Finite-State-Maschine zur auswertung, die Art der Abfrage spielt dann keine Rolle. Also hab ich mal meinen einen Encoder aus ENC_TABLE gelöscht und in DIN_NotifyToggle eine eigene Encoder-Auswertung geschrieben. Der Encoder funktioniert jetzt einwandfrei, allerdings komm ich bei allzu schnellem Drehen an die Performance-Grenzen. Liegt mit Sicherheit an C bzw. meinem noch optimierbaren Code.
Die Zustände der Finite-State-Machine entsprechen der PinA/B-Kombination. Theoretisch möglich sind 16 Übergänge zwischen diesen Zuständen. Da nur benachbarte Zustände interessieren, sind nur 8 Übergänge relevant. Ich hab das ganze mal in ne Grafik gepackt:
Mein Code is eigentlich ganz simpel. Er merkt sich bei nem neuen DIN_NotifyToggle-Aufruf den letzten Zustand und packt den mit dem neuen Zustand in ein variable, so dass darin letztendlich ein Übergang entsprechend der Tabelle oben enthalten ist. Hat diese den Wert 2 oder D, wird ENC_NotifyChange mit positivem incrementer aufgerufen, bei Wert 8 oder 7 mit negativem. Die wackligen Übergänge 1 und 4 spielen also gar keine Rolle mehr.
Schöner wärs natürlich, wenn MIOS schon einen entsprechenden ENC_MODE hätte *zwinker*
u.U. könnten die rastungen natürlich auch in die andere Richtung verschoben sein. Deshalb wären zwei neue Modi ne feine Sache:
MIOS_ENC_MODE_DETENTED4
positiver incrementer für Übergang 2 und D, negativer für Übergang 8 und 7
MIOS_ENC_MODE_DETENTED5
positiver incrementer für Übergang B und 4, negativer für Übergang E und 1
BTW, mit is grad MIOS_ENC_MODE_DETENTED3 in mios_enc_table.inc aufgefallen. was macht denn der?
Grüße,
Alex
