(→INT0/1 oder Polling ?) |
K (→Drehgeber-Auswertung: Link angepasst) |
||
(6 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
=Drehgeber-Auswertung= | =Drehgeber-Auswertung= | ||
Es gibt in RN-Wissen schon einige (sehr gute) Artikel über Drehgeber und Auswertungsvarianten. Denen will ich hier keine Konkurrenz machen.<br/> | Es gibt in RN-Wissen schon einige (sehr gute) Artikel über Drehgeber und Auswertungsvarianten. Denen will ich hier keine Konkurrenz machen.<br/> | ||
− | [[Sensorarten# | + | [[Sensorarten#Drehgeber Sharp GP1A30 und GP1A38|Technisches]] findet man hier, [[Beispiel_Drehzahlmessung_mit_Drehgeber#Richtung.2C_Geschwindigkeit_und_Position_mit_Doppellichtschranke_ermitteln|Grundsätzliches]] über das Quadratur-Signal da, und [[Drehencoder|Programm-Beispiele]] für Drehencoder gibt es auch<br/> |
Ich möchte dem einige grundsätzliche Überlegungen zur Drehgeber-Auswertung hinzufügen, damit es einem Einsteiger leichter fällt, eine Auswahl für seine konkreten Anforderungen zu treffen. | Ich möchte dem einige grundsätzliche Überlegungen zur Drehgeber-Auswertung hinzufügen, damit es einem Einsteiger leichter fällt, eine Auswahl für seine konkreten Anforderungen zu treffen. | ||
Zeile 8: | Zeile 8: | ||
[[Bild:quad_0.png|center]] | [[Bild:quad_0.png|center]] | ||
===Auswertung der Flanken=== | ===Auswertung der Flanken=== | ||
− | Gerade bei den AVR's bietet es sich an, das A-Signal an einen "Externen Interrupt" | + | Gerade bei den AVR's bietet es sich an, das A-Signal an einen "Externen Interrupt" anzuschließen. |
− | Da man meist auch zwei Drehgeber hat (für links u. rechts), kommt man da wunderbar mit INT0 u. INT1 aus. | + | Da man meist auch zwei Drehgeber hat (für links u. rechts), kommt man da wunderbar mit INT0 u. INT1 aus. Allerdings zeigt sich, dass dieser Weg nicht ideal ist. |
====Vorwärts==== | ====Vorwärts==== | ||
Bei einer Konfiguration "steigende Flanke" wird bei den dicken Pfeilen der Interrupt ausgelöst. Liest man in der ISR den B-Kanal, kann man daraus direkt die Richtung entnehmen (im Beispiel ist das ebenfalls "1") und auf den Schrittzähler 1 addieren. | Bei einer Konfiguration "steigende Flanke" wird bei den dicken Pfeilen der Interrupt ausgelöst. Liest man in der ISR den B-Kanal, kann man daraus direkt die Richtung entnehmen (im Beispiel ist das ebenfalls "1") und auf den Schrittzähler 1 addieren. | ||
Zeile 24: | Zeile 24: | ||
=== Auswertung der Übergänge=== | === Auswertung der Übergänge=== | ||
(Genaugenommen der Zustände unmittelbar danach)<br/> | (Genaugenommen der Zustände unmittelbar danach)<br/> | ||
− | Die | + | Die korrekte Auswertung ist möglich, wenn man alle Übergänge steigend/fallend von beiden Kanälen (A u. B) bewertet. Das kann man ebenfalls mit ISR's machen, wenn man den µC so konfigurieren kann, dass er bei beiden Flankenarten auslöst. Da die Auswertung nicht nach der Art des Interrupts unterscheidet, kann dies auch eine gemeinsame ISR sein, etwa der Pin-Change Interrupt beim AVR. |
− | + | Um auch auf sehr kurze Pulse, wie sie etwa durch Störungen oder eine schnelle hin und her Bewegung entstehen können, darf man sich nicht auf die Auslösung des Interrupts stützen (da kann ggf. eine verloren gehen), sondern muss den Zustand (A und B) jeweils einmal auslesen und mit den alten (aus dem letzten Interrupt) vergleichen. | |
− | Im Grunde ist das dann dasselbe, als wenn man ohne ISR periodisch die Eingänge abtastet, was natürlich oft genug geschehen muss, damit nichts verlorengeht. Die Flanken selbst erkennt man an dem | + | Im Grunde ist das dann dasselbe, als wenn man ohne ISR periodisch die Eingänge abtastet, was natürlich oft genug geschehen muss, damit nichts verlorengeht. Die Flanken selbst erkennt man an dem Unterschied AB / AB-alt.<br/> |
− | In beiden Fällen erfolgt dann die Auswertung an den | + | In beiden Fällen erfolgt dann die Auswertung an den strichlinierten senkrechten Linien. |
− | [[Bild:quad_states.png|center]] | + | [[Bild:quad_states.png|center]] |
====Vorwärts==== | ====Vorwärts==== | ||
Von dem Mitte nach rechts gelesen bekommt also an den bezeichneten Stellen die Werte | Von dem Mitte nach rechts gelesen bekommt also an den bezeichneten Stellen die Werte | ||
Zeile 43: | Zeile 43: | ||
* 10 vorher: 11 | * 10 vorher: 11 | ||
* usw | * usw | ||
+ | ====Störpulse==== | ||
+ | Bei Störpulsen kommt es in kurzer Zeit zu einem Schritt vor und zurück (oder andersherum). Wenn die beiden Schritte zu schnell kommen, wird ggf. nur einmal die Auswertung aufgerufen. Dabei ist dann der alte und neue Wert gleich - so dass kein Schritt erfolgt. | ||
+ | |||
===Programmtechnische Umsetzung=== | ===Programmtechnische Umsetzung=== | ||
− | ==== | + | ====Externer Interrupt oder Polling ?==== |
− | + | Bei der Auswertung hat man die Wahl zwischen einem externen Interrupt, der auf jede Änderung reagiert (z.B. der Pin-Change Interrupt beim neueren AVR wie Mega88) oder dem regelmäßigen Polling des Zustandes, etwa in einer Timer ISR, oder weniger gut ggf. auch in der Schleife im Hauptprogramm. Der eigentliche Code zur Auswertung ist der gleiche - die Frage ist also nur noch wann er aufgerufen wird. | |
− | + | ||
− | + | Beim Polling wird eine häufige Abfrage benötigt, um keine Schritte zu verlieren. Auch wenn sich in den meisten Fällen nichts getan hat, wird dafür Rechenzeit benötigt. Die Belastung für den µC ist damit praktisch unabhängig vom Signal, abhängig von der maximalen erlaubten Geschwindigkeit. | |
− | + | Bei der Interrupt-Lösung, erfolgt die Auswertung nur wenn wirklich ein Schritt erfolgt oder halt gerade eine Störung kommt. Hat man nur selten Störungen ist dies ein echter Vorteil, weil das Hauptprogramm nur selten unterbrochen wird. Bei dem seltenen Extremfall von starken Störungen, kann es aber passieren das die ISR sehr häufig aufgerufen wird und kaum noch Rechenzeit für da Hauptprogramm übrig bleibt. Wenn solche extremen Störungen möglich sind (etwa optische Geber ohne Hysterese), sind externe Interrupts generell nicht zu empfehlen. Bei schneller Bewegung und entsprechend vielen ISR-Aufrufen kann die Geschwindigkeit des Hauptprogramms geringer werden. Wartezeiten durch Warteschleifen sind dann nicht mehr zuverlässig. Oft wird aber nur ein sehr kleiner Anteil der Rechenleistung benötigt. | |
− | + | ||
− | + | Sofern man kleine Fehler tolerieren kann, etwa für eine Menüsteuerung oder Geschwindigkeitsmessung ohne Richtungswechsel, kann man natürlich auch die Auswertung über einen externen Interrupt wählen, der nur eine Flanke auswertet. Damit reduziert sich ggf. die Rechenzeit auf Kosten geringerer Auflösung und möglicher Schrittfehler. | |
====Auswertung der Signale==== | ====Auswertung der Signale==== | ||
− | + | Auch wenn bei der Benutzung von Interrupts schon eine Information da ist, welcher Kanal sich geändert hat (und ggf. auch in welche Richtung), sollte die Auswertung trotzdem wie beim Polling erfolgen: Die beiden Kanäle einmal Auslesen, und dann zusammen mit dem vorherigen Wert bestimmen ob es einen Schritt gab und in welche Richtung. So kann verhindert werden, dass durch zu schnelle Interrupts, z.B. durch kurzzeitige Störungen Schritte verloren gehen und Fehler entstehen. | |
+ | Sofern von Hand nötig, muss das Interruptflag vor dem Auslesen des Ports zurückgesetzt werden, so dass alle Änderungen nach dem Auslesen erfasst werden. | ||
− | * mit beiden Flanken | + | * Bei der Auswertung nur einer Flanke (also z.B. steigende Flanke von Kanal A) ist die Sache einfach: Es erfolgt ein Schritt, die Richtung zeigt der andere Kanal. Allerdings lässt sich mit nur einer Flanke der oben beschrieben Fehler beim Pendeln um den Übergang nicht vermeiden, weil ein Schritt vor bzw. zurück nicht an der gleichen Stelle erkannt werden. |
+ | * mit beiden Flanken eines Kanals ist die Sache auch nicht viel komplizierter und man kann Schrittfehler vermeiden: | ||
** A = B --> vorwärts | ** A = B --> vorwärts | ||
** A <> B --> rückwärts | ** A <> B --> rückwärts | ||
− | + | * Bei den Übergängen des anderen Kanals dreht sich die Richtung um und die Auflösung wird verdoppelt. | |
− | + | Die Auswertung der Übergänge kann man natürlich auf viele Arten machen. Je nach Sprache bietet sich | |
− | + | * "Select/Case" (Bascom) oder "switch/case" (GCC) an. Als Beispiel das [[Bascom_Inside-Code#.28Quadratur-.29_ENCODER|Assembler-listing]] für die Bascom-ENCODER()-Funktion<br/> | |
− | Als Beispiel das [[Bascom_Inside-Code#.28Quadratur-.29_ENCODER|Assembler-listing]] für die Bascom-ENCODER()-Funktion<br/> | + | * IF THEN ELSE oder in C auch die bedingte Berechnung mit dem ? Operator an. |
− | ** Eine andere Möglichkeit ist es, die neuen und die vorhergegangenen AB Werte zusammenzufassen und als Index für | + | * Eine andere Möglichkeit ist es, die neuen und die vorhergegangenen AB Werte zusammenzufassen und als Index für eine Werte- oder Sprungtabelle mit 16 Werten zu verwenden. In einer solche Tabelle muss man allerdings auch die ungültigen AB Kombinationen belegen, damit das funktioniert. |
==Autoren== | ==Autoren== |
Aktuelle Version vom 21. September 2014, 18:03 Uhr
Inhaltsverzeichnis
Drehgeber-Auswertung
Es gibt in RN-Wissen schon einige (sehr gute) Artikel über Drehgeber und Auswertungsvarianten. Denen will ich hier keine Konkurrenz machen.
Technisches findet man hier, Grundsätzliches über das Quadratur-Signal da, und Programm-Beispiele für Drehencoder gibt es auch
Ich möchte dem einige grundsätzliche Überlegungen zur Drehgeber-Auswertung hinzufügen, damit es einem Einsteiger leichter fällt, eine Auswahl für seine konkreten Anforderungen zu treffen.
Signalfolge
Zur Erinnerung:
Auswertung der Flanken
Gerade bei den AVR's bietet es sich an, das A-Signal an einen "Externen Interrupt" anzuschließen. Da man meist auch zwei Drehgeber hat (für links u. rechts), kommt man da wunderbar mit INT0 u. INT1 aus. Allerdings zeigt sich, dass dieser Weg nicht ideal ist.
Vorwärts
Bei einer Konfiguration "steigende Flanke" wird bei den dicken Pfeilen der Interrupt ausgelöst. Liest man in der ISR den B-Kanal, kann man daraus direkt die Richtung entnehmen (im Beispiel ist das ebenfalls "1") und auf den Schrittzähler 1 addieren.
Richtungsumkehr
Wird nun die Drehrichtung geändert, wird die bis dahin fallende Flanke von A zur steigenden Flanke, und B ist zu diesem Zeitpunkt dann "0". Die Sache ist eindeutig, man kann nun von Schrittzähler eins abziehen.
Dabei tritt aber natürlich eine Verschiebung auf. Wenn die Impulsfolge im Verhältnis zum zurückgelegten Weg gross ist, kann man das ignorieren, es geht ja letztlich meistens nur um ein paar Millimeter, und wo genau sich ein Drehgeber zwischen zwei Impulsen befindet, kann man ohnehin nie sagen.
Möglicher Fehler
Es gibt aber auch Situationen, wo es zu Fehlern kommt. Hier wird der zweite Interrupt noch ausgelöst und (richtig) als Schritt vorwärts gezählt. Dann bewegt sich der Geber etwas zurück, kommt aber nicht bis zu nächsten steigenden Flanke, sondern bewegt sich wieder nach vorne.
Unsere Logik zählt nun einen Impuls zweimal, obwohl der drehgeber sich immer noch am selben Platz befindet.
Auswertung der Übergänge
(Genaugenommen der Zustände unmittelbar danach)
Die korrekte Auswertung ist möglich, wenn man alle Übergänge steigend/fallend von beiden Kanälen (A u. B) bewertet. Das kann man ebenfalls mit ISR's machen, wenn man den µC so konfigurieren kann, dass er bei beiden Flankenarten auslöst. Da die Auswertung nicht nach der Art des Interrupts unterscheidet, kann dies auch eine gemeinsame ISR sein, etwa der Pin-Change Interrupt beim AVR.
Um auch auf sehr kurze Pulse, wie sie etwa durch Störungen oder eine schnelle hin und her Bewegung entstehen können, darf man sich nicht auf die Auslösung des Interrupts stützen (da kann ggf. eine verloren gehen), sondern muss den Zustand (A und B) jeweils einmal auslesen und mit den alten (aus dem letzten Interrupt) vergleichen.
Im Grunde ist das dann dasselbe, als wenn man ohne ISR periodisch die Eingänge abtastet, was natürlich oft genug geschehen muss, damit nichts verlorengeht. Die Flanken selbst erkennt man an dem Unterschied AB / AB-alt.
In beiden Fällen erfolgt dann die Auswertung an den strichlinierten senkrechten Linien.
Vorwärts
Von dem Mitte nach rechts gelesen bekommt also an den bezeichneten Stellen die Werte
- 00 vorher: 01
- 10 vorher: 00
- 11 vorher: 10
- 01 vorher: 11
- usw
Rückwärts
Von dem Mitte nach links gelesen bekommt dann an den bezeichneten Stellen die Werte
- 00 vorher: 10
- 01 vorher: 00
- 11 vorher: 01
- 10 vorher: 11
- usw
Störpulse
Bei Störpulsen kommt es in kurzer Zeit zu einem Schritt vor und zurück (oder andersherum). Wenn die beiden Schritte zu schnell kommen, wird ggf. nur einmal die Auswertung aufgerufen. Dabei ist dann der alte und neue Wert gleich - so dass kein Schritt erfolgt.
Programmtechnische Umsetzung
Externer Interrupt oder Polling ?
Bei der Auswertung hat man die Wahl zwischen einem externen Interrupt, der auf jede Änderung reagiert (z.B. der Pin-Change Interrupt beim neueren AVR wie Mega88) oder dem regelmäßigen Polling des Zustandes, etwa in einer Timer ISR, oder weniger gut ggf. auch in der Schleife im Hauptprogramm. Der eigentliche Code zur Auswertung ist der gleiche - die Frage ist also nur noch wann er aufgerufen wird.
Beim Polling wird eine häufige Abfrage benötigt, um keine Schritte zu verlieren. Auch wenn sich in den meisten Fällen nichts getan hat, wird dafür Rechenzeit benötigt. Die Belastung für den µC ist damit praktisch unabhängig vom Signal, abhängig von der maximalen erlaubten Geschwindigkeit.
Bei der Interrupt-Lösung, erfolgt die Auswertung nur wenn wirklich ein Schritt erfolgt oder halt gerade eine Störung kommt. Hat man nur selten Störungen ist dies ein echter Vorteil, weil das Hauptprogramm nur selten unterbrochen wird. Bei dem seltenen Extremfall von starken Störungen, kann es aber passieren das die ISR sehr häufig aufgerufen wird und kaum noch Rechenzeit für da Hauptprogramm übrig bleibt. Wenn solche extremen Störungen möglich sind (etwa optische Geber ohne Hysterese), sind externe Interrupts generell nicht zu empfehlen. Bei schneller Bewegung und entsprechend vielen ISR-Aufrufen kann die Geschwindigkeit des Hauptprogramms geringer werden. Wartezeiten durch Warteschleifen sind dann nicht mehr zuverlässig. Oft wird aber nur ein sehr kleiner Anteil der Rechenleistung benötigt.
Sofern man kleine Fehler tolerieren kann, etwa für eine Menüsteuerung oder Geschwindigkeitsmessung ohne Richtungswechsel, kann man natürlich auch die Auswertung über einen externen Interrupt wählen, der nur eine Flanke auswertet. Damit reduziert sich ggf. die Rechenzeit auf Kosten geringerer Auflösung und möglicher Schrittfehler.
Auswertung der Signale
Auch wenn bei der Benutzung von Interrupts schon eine Information da ist, welcher Kanal sich geändert hat (und ggf. auch in welche Richtung), sollte die Auswertung trotzdem wie beim Polling erfolgen: Die beiden Kanäle einmal Auslesen, und dann zusammen mit dem vorherigen Wert bestimmen ob es einen Schritt gab und in welche Richtung. So kann verhindert werden, dass durch zu schnelle Interrupts, z.B. durch kurzzeitige Störungen Schritte verloren gehen und Fehler entstehen. Sofern von Hand nötig, muss das Interruptflag vor dem Auslesen des Ports zurückgesetzt werden, so dass alle Änderungen nach dem Auslesen erfasst werden.
- Bei der Auswertung nur einer Flanke (also z.B. steigende Flanke von Kanal A) ist die Sache einfach: Es erfolgt ein Schritt, die Richtung zeigt der andere Kanal. Allerdings lässt sich mit nur einer Flanke der oben beschrieben Fehler beim Pendeln um den Übergang nicht vermeiden, weil ein Schritt vor bzw. zurück nicht an der gleichen Stelle erkannt werden.
- mit beiden Flanken eines Kanals ist die Sache auch nicht viel komplizierter und man kann Schrittfehler vermeiden:
- A = B --> vorwärts
- A <> B --> rückwärts
- Bei den Übergängen des anderen Kanals dreht sich die Richtung um und die Auflösung wird verdoppelt.
Die Auswertung der Übergänge kann man natürlich auf viele Arten machen. Je nach Sprache bietet sich
- "Select/Case" (Bascom) oder "switch/case" (GCC) an. Als Beispiel das Assembler-listing für die Bascom-ENCODER()-Funktion
- IF THEN ELSE oder in C auch die bedingte Berechnung mit dem ? Operator an.
- Eine andere Möglichkeit ist es, die neuen und die vorhergegangenen AB Werte zusammenzufassen und als Index für eine Werte- oder Sprungtabelle mit 16 Werten zu verwenden. In einer solche Tabelle muss man allerdings auch die ungültigen AB Kombinationen belegen, damit das funktioniert.