Hi,
habe nach langem Stöbern in diversen Foren, selber eine Routine zum
auswerten eines Drehgebers geschrieben. Die wollte ich hier kurz
vorstellen:
Der Drehgeber ist an PD2 (INT0) und PD3 (INT1) angeschlossen. Dies auch
nur aus Platzgründen. Benutzt wird nur INT0.
Die Routine entspricht weitgehend dem Flussdiagramm aus dem Datenblatt
des Drehgebers von dem großen "C".
Hier erst der code:
Initialisierung:
Funktion:
Der INT0 ist auf "any Change" eingestellt. Also wird eine
Interruptroutine ausgelößt, wenn sich der zustand an PD2 von 0-1 oder
1-0 ändert.
Wenn das passiert, wird eine kurze Pause aufgerufen (ca. 25 Zyclen).
Dann wird der komplette Port D eingelesen.
Einmal in temp(r16) und in r17. r17 wird 1 Bit nach rechts verschoben.
Das gewünschte Bit wird ausmaskiert. Dann wird verglichen.
Wenn beide Bits 1 sind (beide Pins vom Drehgeber), wurde rechts rum
gedreht, wenn sie ungleich sind, links rum.
Der Hintergrundgedanke: Wenn rechtsrum gedreht wird, ändert sich erst
z.B. A, dann B. Wenn der INT0 an B ausgelößt wird, sind immer beide Pins
gleich.
Wenn linksrum gedreht wird, ändert sich erst B, dann A. Wenn INT0 an B
ausgelößt wird, sind immer beide Pins ungleich.
Die Routine läuft super. Sogar wenn das Register, in dem Gezählt wird,
Dezimal auf einem LC Display angezeigt wird.
Dafür müssen natürlich, während das Display Daten erhält, die Interrupt
ausgestellt werden.
Hardwareseitig ist fast nichts entprellt. Nur jweweils ein kleiner
Kondensator zwischen A & GND und B & GND (20nF oder so :-) ist
eingebaut.
Mfg
S. Engel
Drehgeber
Warum Sparvarianten nicht gut sind
Oft sieht man im Netz "clevere" Sparvarianten, welche angeblich
ebensogut zur Auswertung von Drehgebern gegeignet sind. Ein genaueres
Hinschauen sowie Tests unter realen Bedingungen zeigen jedoch schnell
die Schwächen dieser Ansätze.
[bearbeiten]
Flankenerkennung von A und Pegelauswertung von B
Viele Sparvarianten verwenden einen externen Interrupt, welcher auf die
steigende oder fallende Flanke von Spur A auslöst und dann den Pegel von
B auswertet. Ist B=0, dann dreht der Encoder nach rechts, anderenfalls
nach links. Diese Auswertung hat zwei Schwachstellen.
* Die Auflösung wird auf ein Viertel reduziert, weil nur jede
steigende Flanke von A ausgewertet wird.
* Pendelt der Encoder zwischen zwei Codes, bei denen A seinen Pegel
wechselt,
o kommt es zu (sehr) vielen Interrupts, die den
Mikrocontroller vollkommen auslasten können.
o interpretiert die Auswertung jede steigende Flanke als neuen
Schritt, der Encoder scheint sich für die Auswertung immer weiter zu
drehen, obwohl er nur pendelt.
Das Pendeln kann zwei Ursachen haben.
* Der Encoder pendelt wirklich; das kann z.B. bei hochauflösenden
Encodern ohne Rastung geschehen, welche an jeder beliebigen Stelle
stehen bleiben können und durch geringe mechanische Erschütterungen dann
zwischen zwei Codes pendeln; das kann z.B. bei hochauflösenden Encodern
in CNC-Maschinen der Fall sein.
* Die Signale prellen; das kommt vor allem bei billigen
elektromechanischen Drehknöpfen vor, welche einfache Schleifkontakte zur
Kodierung nutzen.
Wie man sieht ist diese Methode nicht geeignet, einen Drehgeber solide
zu dekodieren.
Das mag bei Drehgebern zur Positionsbestimung zutreffen.
Aber bei Anwendugen, wo der Drehgeber als "Eingabegerät" arbeitet reicht
es aus.
Auf nem Steckboard hat das super Funktioniert. Pro schritt wurd
entwerder +1 oder -1 bei dem Testprogramm gerechnet. Dies Funktioniert
auch, wenn man "Blind" z.B. 35 Schritte linksrum dreht, werden auch nur
35 abgezogen.
Und bei dem oben beschriebenem Programm ist der Interrupt als "Any
Change" eingestellt. Es wird also immer ein Interrupt ausgelößt, wenn
sich das Signal von High auf Low, oder umgekehrt ändert.
Die Routine entspricht übrigens 100%tig einem Flussdiagramm, welches ich
in einem Datenblatt von einem Drehgeber gefunden hatte.
Und das ganze funktioniert sogar in verbindung mit einem LC-Display.
Hier wird aber die Eingabegeschwindigkeit begrenzt, da das Display mit
großzügigen Zeiten angesteuert wird.
Und während der Displayausgabe sind Interrupts ausgeschaltet.
Wir hatten auch den 'C'-Drehgeber in einem Prototyp drin, wurde auch
aufwändig entprellt (Software), nur halten die Teile nicht lange durch,
der hat nach kürzester Zeit schon so geprellt, dass eine vernünftige
Auswertung kaum noch möglich war.
In einem NEC OMICRON - Achtkanalschreiber ist ein APLS-Drehencoder drin,
dort tritt nach einiger Zeit das gleiche Problem auf. In den 10 Jahren,
in dem wir das Teil haben, Nicht mal allzuoft eingesetzt, haben wir den
Encoder schon 3x wechseln müssen.
Ich würde lieber etwas mehr Geld in die Hand nehmen und den optischen
Enc. von Reichelt nehmen.
@ Sebastian Engel (Gast)
>Aber bei Anwendugen, wo der Drehgeber als "Eingabegerät" arbeitet reicht>es aus.
Lies den Artikel nochmal in Ruhe und denk drüber nach.
>Auf nem Steckboard hat das super Funktioniert.
Das haben Laborprototypen so an sich.
>Pro schritt wurd>entwerder +1 oder -1 bei dem Testprogramm gerechnet. Dies Funktioniert>auch, wenn man "Blind" z.B. 35 Schritte linksrum dreht, werden auch nur>35 abgezogen.
Einmal gestestet, hat einmal funktioniert, wird also immer
funktionieren?
>Und bei dem oben beschriebenem Programm ist der Interrupt als "Any>Change" eingestellt. Es wird also immer ein Interrupt ausgelößt, wenn>sich das Signal von High auf Low, oder umgekehrt ändert.
Eben das ist das Problem.
>Die Routine entspricht übrigens 100%tig einem Flussdiagramm, welches ich>in einem Datenblatt von einem Drehgeber gefunden hatte.
Was nicht allzuviel heissen muss. Link?
>Und das ganze funktioniert sogar in verbindung mit einem LC-Display.
WOW! DAS Killerkriterium.
>Hier wird aber die Eingabegeschwindigkeit begrenzt, da das Display mit>großzügigen Zeiten angesteuert wird.>Und während der Displayausgabe sind Interrupts ausgeschaltet.
Wozu? Traust du deiner Progrmmierkunst doch nicht so?
MFG
Falk
Falk Brunner wrote:
>>Hier wird aber die Eingabegeschwindigkeit begrenzt, da das Display mit>>großzügigen Zeiten angesteuert wird.>>Und während der Displayausgabe sind Interrupts ausgeschaltet.>> Wozu? Traust du deiner Progrmmierkunst doch nicht so?
Ich auch nicht.
Das hier ist ja wohl der Killer:
> Interruptroutine:
1
encoder:rcallwarte;ca.25Prozessorzyclenwarten
Auch wenn es nur 25 Zyklen sind, ist es fast immer eine schlechte Idee
in einem Interrupt warten zu lassen. Zudem ist es fast immer vermeidbar.
@ Simon K. (simon)
>encoder: rcall warte ;ca. 25 Prozessorzyclen warten
Uups, hab ich gar nicht soo gesehen ;-)
>Auch wenn es nur 25 Zyklen sind, ist es fast immer eine schlechte Idee>in einem Interrupt warten zu lassen. Zudem ist es fast immer vermeidbar.
Eben. Vor allem, wozu soll das gut sein? Zur Entprellung ? 25 Takte
bei 1 MHz sind gerade mal 25 us. Taster und billige Encoder prellen
hundert bis tausendmal solange.
MFG
Falk
Ich hab mir den Artikel nochmal angeschaut. Und diesen Thread auch.
> >Aber bei Anwendugen, wo der Drehgeber als "Eingabegerät" arbeitet reicht> >es aus.> Lies den Artikel nochmal in Ruhe und denk drüber nach.
Zitat des Artikels: "... dass mit Hilfe von sog. Pin Change Interrupts
Rechenzeit gespart werden kann ... Diese Methode ist besser, aber nicht
gut genug ... Sie vermeidet Fehler ... aber nicht 2.1, da auch sie durch
einen pendelnden/prellenden Encoder die CPU stark belastet."
Dies , so stehts im Artikel, passiert wenn (sehr) viele interrupts
auftreten.
Bei einer menüführung dreht man nicht sehr schnell.
> >Auf nem Steckboard hat das super Funktioniert.> Das haben Laborprototypen so an sich.
Ich wollte darauf hinaus, das ein entgültiges Gerät Störungssicherer
ist.
> >Pro schritt wurd> >entwerder +1 oder -1 bei dem Testprogramm gerechnet. Dies Funktioniert> >auch, wenn man "Blind" z.B. 35 Schritte linksrum dreht, werden auch nur> >35 abgezogen.> Einmal gestestet, hat einmal funktioniert, wird also immer> funktionieren?
Bisher öfters getestet. Verscheidene Anwendungen, verscheidene
Drehgeber, verschiedene Controller. Hat immer super Funktioniert.
> >Und bei dem oben beschriebenem Programm ist der Interrupt als "Any> >Change" eingestellt. Es wird also immer ein Interrupt ausgelößt, wenn> >sich das Signal von High auf Low, oder umgekehrt ändert.> Eben das ist das Problem.
Deshalb die paar µS Pause. Kann ja auch erweitert werden.
Zu der Pause im Interrupt: Why not? Bei meinen anwendungen führt das zu
keinen Problemen.
> >Die Routine entspricht übrigens 100%tig einem Flussdiagramm, welches ich> >in einem Datenblatt von einem Drehgeber gefunden hatte.> Was nicht allzuviel heissen muss. Link?http://www.vlsi.informatik.tu-darmstadt.de/student_area/sep/427z1.pdf
Es ist ein Beispiel, welches super Funktioniert.
> >Und das ganze funktioniert sogar in verbindung mit einem LC-Display.> WOW! DAS Killerkriterium.
Es Funktioniert auch, wenn der Controller anderen Zeitaufwendigen Code
erledigen muss.
> >Hier wird aber die Eingabegeschwindigkeit begrenzt, da das Display mit> >großzügigen Zeiten angesteuert wird.> >Und während der Displayausgabe sind Interrupts ausgeschaltet.> Wozu? Traust du deiner Progrmmierkunst doch nicht so?
Ohne die Deaktivierung kam es zu Problemen bei der Datanübertragung zum
LCD. Es hätte villeicht auch ein paar push und pops geholfen. Hab ich
aber bisher nicht ausprobiert.
> @ Simon K. (simon)> >encoder: rcall warte ;ca. 25 Prozessorzyclen warten> Uups, hab ich gar nicht soo gesehen ;-)
S.o.: Why Not? In meinen bisherigen Anwendungen kommt es darauf nicht
an.
---------------
Jetzt nochmal Allgemein: Das ist EINE Möglichkeit. Es gibt sehr viele
varianten. Diese ist schlank und Funktioniert für einfache Anwendungen.
Warum soll ich ein Riesiges Codemonster einsetzten, was ich überall
einsetzten kann, wenn ich z.B. hohe Umdrehungsfrequenzen nicht erfassen
muss?
Und könnt ihr, Falk und Simon, mal KONSTRUKTIVE Kritik posten???
Das was ihr da geschrieben habt, ist überflüssig. NICHT Hilfreich!!!
Das klingt so, als habt ihr euch auf den "Artikel" und paar aussagen zum
Controller festgebissen. Und alles was abweicht wäre schlecht und
funktioniert generell nicht.
Hat einer von euch das mal ausprobiert?
Soviel noch dazu...
- S. Engel
>Und könnt ihr, Falk und Simon, mal KONSTRUKTIVE Kritik posten???>Das klingt so, als habt ihr euch auf den "Artikel" und paar>aussagen zum Controller festgebissen.
Sie haben aber Recht. Und wozu sollen sie noch etwas konstruieren, wo
doch alles gesagt ist?
Der Code von Peter ist einfach gut durchdacht und hat nicht diese
Nachteile wie Deiner. Wozu sollte man also Deinen einsetzen?
Nimm doch die Kritik an und sieh ein, daß es sich für andere nicht
lohnt, sich mit Deinem Code auseinanderzusetzen, wo sie mit Peters Code
viel besser bedient sind.
Ist doch nicht schlimm, Du hast halt wenig Erfahrung und für Dich reicht
Dein Code aus. Prima. Andere nutzen halt die pfiffigere Lösung von
Peter.
@ Sebastian Engel (Gast)
>gut genug ... Sie vermeidet Fehler ... aber nicht 2.1, da auch sie durch>einen pendelnden/prellenden Encoder die CPU stark belastet.">Bei einer menüführung dreht man nicht sehr schnell.
Bis du blind? Es geht nicht um schnelles Drehen sondern um Prellen !
Und das machen voer allem die billigen mechanischen Encoder.
>Bisher öfters getestet. Verscheidene Anwendungen, verscheidene>Drehgeber, verschiedene Controller. Hat immer super Funktioniert.
Du musst noch einges zum Thema Fehleranlayse und Logik lernen. Mussten
wir alle. Du wählst den scmerzhaften Weg. Machen auch viele ;-)
>Deshalb die paar µS Pause. Kann ja auch erweitert werden.
Die reichen hinten und vorne nicht. Das Prellen dauert
Grössenordnungen länger.
>Zu der Pause im Interrupt: Why not? Bei meinen anwendungen führt das zu>keinen Problemen.
Die berühmten Labormuster in geringer Stückzahl. Und JA, bei Encodern
für Menüs ist es im allgemeinen unkritisch, wenn die mal einen Schritt
weiter springen. Ist nur ggf. nervig.
>http://www.vlsi.informatik.tu-darmstadt.de/student...>Es ist ein Beispiel, welches super Funktioniert.
Die Schalter werden sich bedanken, wenn sie permanent einen geladenen
33nF Kondensator kurzschliessen müssen. Die Pulsströme liegen im
Ampere-Bereich. Auch ne Möglichkeit die Lebensdauer zu verkürzen und für
Umsatz zu sorgen.
> >encoder: rcall warte ;ca. 25 Prozessorzyclen warten> Uups, hab ich gar nicht soo gesehen ;-)>S.o.: Why Not? In meinen bisherigen Anwendungen kommt es darauf nicht>an.
Ach auf einmal? Zitat von vor 3 Minuten
"Es Funktioniert auch, wenn der Controller anderen Zeitaufwendigen Code
erledigen muss."
Ausserdem ist die Zeit wie bereits gesagt viel zu kurz.
>Und könnt ihr, Falk und Simon, mal KONSTRUKTIVE Kritik posten???
Das tun wir permanent. Aber Du bist nicht kritikfähig und
lernresistent.
>Das was ihr da geschrieben habt, ist überflüssig. NICHT Hilfreich!!!
Der Herr belieben zu scherzen.
>Das klingt so, als habt ihr euch auf den "Artikel" und paar aussagen zum>Controller festgebissen. Und alles was abweicht wäre schlecht und>funktioniert generell nicht.
Irrtum. Alles andere funktioniert nur zu 99%. Das kann für ein
Hobbyprojekt ausreichen. Für ein wasserdichtes, proessionelles Design
aber nicht.
>Hat einer von euch das mal ausprobiert?
Sicher. Es gibt leider sogar professionelle Produkte, die keine solide
Auswertung der Drehgeber machen. hab ich mal bei einem Oszi von TEK
gesehen.
MFG
Falk
Es wird schon besser.
Nun kann ich endlich ein wenig Informationen aus deinem Posting
entnehmen.
Kritik vertrage ich sehrwohl. Ich hab ja darum gebeten.
Aber ein "Eben das ist das Problem." hilft mir nicht sonderlich weiter
;-)
Sowas verstehe ich unter Konstruktiv:
> "Die Schalter werden sich bedanken, wenn sie permanent einen geladenen> 33nF Kondensator kurzschliessen müssen. Die Pulsströme liegen im> Ampere-Bereich. Auch ne Möglichkeit die Lebensdauer zu verkürzen und für> Umsatz zu sorgen."
(auch wenn das jetzt nicht die "Fehler" der Routine betrifft, ist es
dennoch hilfreich)
Was mich aber immer noch interessiert: Warum keine Wartezeiten in
Interruptroutinen? Ich seh das so, das es dem Controller doch egal ist,
ob er 25x "nichts" macht, oder ob er "nützlicher" code bearbeitet.
> Das tun wir permanent. Aber Du bist nicht kritikfähig und> lernresistent.
Wozu schreib ich sonst hier ins Forum?
Dieser Thread ist dafür da, um zu Kritisieren.
Im Forum "µC & Elektronik" stell ich öfters Fragen.
Ich bin mir da ziemlich sicher, das das deine Aussage wiederlegt!
>Was mich aber immer noch interessiert: Warum keine Wartezeiten in>Interruptroutinen?
Weil dann das Hauptprogramm länger als nötig unterbrochen wird.
>Ich seh das so, das es dem Controller doch egal ist,>ob er 25x "nichts" macht, oder ob er "nützlicher" code bearbeitet.
Dem Controller ist es egal, und mir ist es auch egal wenn du das machst
;)
Trotzdem ist es bei den meisten Anwendungen ein Pferdefuss (Interrupts
können übersehen werden), nachträgliche Änderungen führen dann zu
unerwarteten Fehlern...
>Kritik vertrage ich sehrwohl. Ich hab ja darum gebeten.
In deinem ersten Post lese ich davon nichts, nur:
>Die Routine läuft super.
Klingt nicht nach einer Anregung für konstruktive Kritik, oder? Im
übrigen ist es wegen dieser 'Geschichte' nicht wahr:
>Dafür müssen natürlich, während das Display Daten erhält, die Interrupt>ausgestellt werden.
Die Routine läuft gar nicht, sie muss während der Anwendung sogar
deaktiviert werden...
> Die Routine läuft gar nicht, sie muss während der Anwendung sogar> deaktiviert werden...
Weil der Status, r16 und r17 nicht gerettet werden.
push r16
push r17
in r16,sr
push r16
...
pop r16
out sr,r16
pop r17
pop r16
reti
oder so ähnlich
das Programm sollte auch ohne call warte laufen.
Der Drehgeber aus der Maus ist optisch, nicht mechanisch. Sollte nicht
prellen.
@ Sebastian Engel (Gast)
>Was mich aber immer noch interessiert: Warum keine Wartezeiten in>Interruptroutinen?
Weil diese das normale Programm unterbrechen und andere, wichtige
Interrupts solange blockieren. Ist einfach schlechter Stil, und man
fällte damit nur allzuoft auf die Nase.
> Ich seh das so, das es dem Controller doch egal ist,>ob er 25x "nichts" macht, oder ob er "nützlicher" code bearbeitet.
Die 25 NOPs sind viel zu kurz, um als wirksame Entprellung zu dienen.
MfG
Falk
Hi,
hatte auch schon mal einen billigen mech. Hand-Drehimpulsgeber per
Interrupt on change ausgewertet. Wenn das Prellen NICHT länger dauert
als die Zeit bis zur zweiten Flanke eines Drehschrittes (d.h. die Flanke
an Leitung B, wenn vorher Flanke an A und umgekehrt), sollte man
saubererweise den Interrupt für die Zeit des Prellens deaktivieren. da
ich das Datenblatt dieses Pulsgebers jetzt nicht parat habe, kann ich
nicht sagen, wie kurz diese Zeitdifferenz mindestens (dh bei sehr
schnellem Drehen) ist.
Am besten: Mit 2-Kanal-Oszi analysieren und erst mal überlegen.
Warten im Int. finde ich auch schlecht (Falk hat recht) - absolut
indiskutabel in professionellen bzw kommerziellen Projekten.
Im Grunde genommen verhält sich diese "Prellerei" ganz ähnlich wie bei
Tasten, siehe Forum "Entprellen und trotzdem schnell reagieren", da
gibts einige Anregungen dazu.