So, jetzt muss ich doch mal einen Beitrag verfassen. Ich habe mich
wirklich mehrere Stunden bemüht das Problem selbst zu lösen, leider
vergebens.
Es geht um folgendes: Ich habe einen Drehimpulsgeber von diesem Typ:
http://www.pollin.de/shop/downloads/D240313D.PDF
an einen PIC Mikrocontroller (Hilfe Hilfe PIC...) angeschlossen.
Ich möchte die Drehung des Gebers in einem Timer Interrupt (wie z.B.
hier von Peter Danegger beschrieben:
Beitrag "Drehgeber auslesen") auswerten. Ich verwende genau
den dort geposteten Code (main.c im Anhang...).
Das Ergebnis enc_delta gebe ich dann auf einem Anzeigeelement aus.
Leider kommt immer entweder eine EINS (=0b01) oder eine ZWEI (0b10)
heraus. Und das immer abwechselnd.
sagen wir enc_delta war eine EINS. Wenn ich nun den Geber um eine Raste
in beliebiger Richtung weiter drehe ist enc_delta ZWEI. Drehe ich
wiederum weiter kommt wieder eine EINS raus usw.... Wird gar nicht
gedreht ändert sich der Wert (erwartungsgemäß) nicht.
Ich taste etwa 1x pro Millisekunde ab.
Wenn jemand sich der Sache annähme und eine Idee hätte woran dies liegt
würde ich mich sehr freuen!
Schöne Grüße,
Alex
Das kann daran liegen, daß die Codierung dieses Encoders anders ist, als
das Programm dies erwartet. Es gibt Encoder, die einen 'Vollschritt'
kodieren und nach einer Rastung wieder 0 auf beiden Terminals ausgeben.
Dieser Encoder jedoch gibt nach einer Rastung jeweils einen Wechsel an
je einem Terminal, also einen 'Halbschritt'.
Mit
>Dieser Encoder jedoch gibt nach einer Rastung jeweils einen Wechsel an>je einem Terminal, also einen 'Halbschritt'.
meinst du, dass es so, wie beschrieben funktionieren sollte, oder wie
war das gemeint?
Ich meine nur, daß es verschiedene Codierungen gibt und die Routine im
Programm dies berücksichtigen muß. Aber um vielleicht Abhilfe zu
schaffen: vertausche mal A und B Terminal an Deinem Controller und
gucke, ob es dann geht. Der Drehencoder von Panasonic ist leicht
asymmetrisch in seinem elektrischen Verhalten.
Das ist ja eigenartig. Wenn ich es (softwaremäßig) vertausche wechselt
das enc_delta immer zwischen NULL (0b00) und EINS (0b01) anstatt wie
vorher zwischen EINS und ZWEI (0b10).
Wie kann man sich das denn erklären?
Ich benutze auf dem AVR die folgende Routine für die Pollin-Drehgeber.
Es stimmt, dass die asymmetrisch sind, ich musste beim Portieren auf ein
anderes Projekt auch schonmal die Anschlüsse vertauschen. Die Routine
wird von der Mainloop alle 1 ms aufgerufen.
Hallo Hannes,
ich muss gestehen, dass ich mich in Assembler gar nicht auskenne.
Ich verstehe vor allem
> mov wl,drg ;Bitmuster merken (neu, alt, aelter, uralt)
und
> sbrc drg,1 ;fallende Flanke? - ja...
nicht. Aber ich verstehe auch den Rest leider gar nicht... Ich vermute
mal du hast davon kein Prozess-Flow-Chart?? :-)
Alex Bürgel wrote:
> ich muss gestehen, dass ich mich in Assembler gar nicht auskenne.
Schade eigentlich, der Mikrocontroller kann nur Maschinencode, der 1 zu
1 nur in Assembler notierbar ist...
>> Ich verstehe vor allem>> mov wl,drg ;Bitmuster merken (neu, alt, aelter, uralt)
MOV steht für Bewege, meint aber Kopiere...
Es wird also der Inhalt des Registers, das "drg" heißt in das Register
namens "wl" kopiert. In den Registern repräsentieren jeweils zwei
zusammenliegende Bits den Zustand der beiden Drehgeber-Schalter zu einer
bestimmten Zeit. Der neueste Zustand steht links (Bit 7:6), der vom
letzten mal (letzte Runde, letzter Prozeduraufruf) daneben, dann der
vorletzte Zustand und ganz rechts der davorige Zustand (uralt). Das
Register fasst also die Drehgeberzustände von 4 verschiedenen
Zeitpunkten zusammen.
>> lsr drg ;Bitmuster nach unten schieben>> lsr drg ;(leer, neu, alt, aelter)
Mit diesen beiden Rechts-Schiebebefehlen rücken alle Bitmuster
(Drehgeberzustände) einen Schritt (zwei Bits) in Richtung alt. Dabei
werden die uralten entsorgt, alle anderen rücken nach, in die obere
(neueste) Position werden Nullen eingeschoben.
>> eor wl,drg ;Aenderungen erfassen
Durch EXOR-Verknüpfung (wobei drg unverändert bleibt) werden die
"gealterten" Zustände mit den in wl geretteten Zuständen verglichen,
Änderungen (Ungleichheiten) werden 1 (Bitwerte), wo keine Änderung ist,
ist das Ergebnis 0.
>> andi wl,dgprell ;nur Aenderungsbits stehen lassen
AND-Verknüpfung mit der Konstante (siehe Deklaration) mit dem Ziel, nur
die Änderungen stehen zu lassen, die für die weitere Betrachtung
relevant sind. Es wird die Kopie bearbeitet, das Original (drg) bleibt
erhalten.
>> cpi wl,2 ;nur aeltestes Aenderungsbit gesetzt?>> brne drehgeber3 ;nein...
Verzweigt nach drehgeber3 (beendet die Überprüfung), wenn der Wert des
Bytes nicht 2 ist. Der Wert ist 2, wenn nur das Bit 1 gesetzt ist und
alle anderen Bits gelöscht sind. Das ist der Fall, wenn Schalter A des
Drehgebers zweimal hintereinander denselben Zustand hatte, davor aber
eine Änderung stattfand. Dies dient der Entprellung, Änderungen werden
also nur übernommen, wenn dere Zustand danach stabil ist (zweimal
gleich).
>> und>> sbrc drg,1 ;fallende Flanke? - ja...
Skip (if) Bit Register (is) Clear ...
Überspringt den nächsten Befehl, wenn das Bit 1 im Register drg 0
(clear) ist. Das ist der Fall, wenn am Drehgebereingang eine fallende
Flanke war. Ein recht starker ASM-Befehl, der ohne Veränderung des SREG
arbeitet...
>> nicht. Aber ich verstehe auch den Rest leider gar nicht...
Schade eigentlich...
> Ich vermute> mal du hast davon kein Prozess-Flow-Chart?? :-)
Nein, die Informationen, die Andere in ein Struktogramm oder PAP
schreiben, stehen bei mir in den Kommentaren. Da werden ein paar
Konventionen eingehalten, z.B. bedeutet bei mir "..." am Ende der Zeile,
dass "gesprungen" wird. Ein Fragezeichen kennzeichnet die Frage, die
beim PAP im Verzweigungs-Rhombus steht, die Antworten darauf (meist nur
ja oder nein) stehen auch in den Kommentaren. Man kann also anhand
meiner Kommentare den Algorithmus rekonstruieren.
...
Wenn der Zählerstand immer nur zwischen zwei aufeinanderfolgenden
Werten wechselt, wird vermutlich einer der beiden Kanäle nicht richtig
gelesen.
Ursache kann ein Verdrahtungsfehler, ein Hardwaredefekt oder ein
falsch konfigurierter Port sein.
Fangen wir mal mit dem letzten an:
1
TRISA=0b001100;//I/O direction for PORTA
Ich habe keine Ahnung von PICs, aber sollten in TRISA die Bits 3 und 4
nicht gleich sein, da beides Eingänge sind? Oder ist der Drehgeber gar
nicht an 3 und 4, sondern an 2 und 3 angeschlossen? Dann ist's im
Interrupthandler falsch.
> Ursache kann ein Verdrahtungsfehler, ein Hardwaredefekt oder ein> falsch konfigurierter Port sein.
Ich hatte den Eindruck, dass diese Drehgeber nicht (nur) "asymmetrisch"
sind, sondern dass einer ihrer Schalter (immer derselbe) recht unsauber
(stark prellend, Aussetzer) arbeitet. Wenn ich den Schalter zur
Flankenerkennung nutze, dann macht meine Routine auch Müll. Wenn ich den
ordentlichen Schalter zur Flankenerkennung nutze, dann gibt es keine
Probleme, der andere Schalter wird dann ja nur auf Zustand abgefragt.
Wenn ich mich nicht irre, wertet Peters Routine beide Flanken aus. Ich
halte es für möglich, dass diese Drehgeber dafür ungeeignet sind.
Ich selbst kann über diese Drehgeber aber nicht klagen, mit meiner
Routine und bei richtiger Polung funktionieren sie sehr präziese.
...
Guten Morgen!
Ich muss gestehen, dass es in der Tat daran lag, dass ich am PORTA die
Pins 2 & 3 als input eingestellt habe, obwohl der Drehgeber an 3 & 4
angeschlossen ist.
Es funktioniert jetzt so ungefähr... Er überspringt oft ein oder zwei
Schritte, aber das sollte in den Griff zu bekommen sein...
Danke vor allem an Yalu und Hannes für die Mühe.
Ich werde auch mal versuchen deinen Code, Hannes, in C zu transferieren.
Schönes Wochenende noch!
Alex
Ich benutze auf einem Tiny15 folgende Routine im Timerinterupt um den
Drehgeber abzufragen (der Timer wurde bei mir für nichts anderes
gebraucht)
Prescaler hab ich mein ich bei 64 gesezt also wird das ganze bei 1,6Mhz
etwa ale 10ms abgetastet, das funktioniert recht zuverlässig. mit
Prellen hatte ich dann auch keine Probleme.
1
INT_OV0:
2
in int_sreg_save, SREG ; SREG sichern
3
sbis PINB, A ; Ist Terminal A High oder LOW?
4
rjmp int_low ; ---> Sprung zu Low
5
int_high: ; Sonst war Pegel High
6
sbrc FLAGS, F_LASTPEGEL ; war lezter Pegel Low --> wechsel
7
rjmp int_ende ; sonst ende --> es hat sich nix verändert
sbis PINB, B ; Ist Terminal B High? --> Wir drehen vorwärts
20
sbr FLAGS, (1<<F_UP) ; --> Flag für Hauptprogram setzen
21
sbic PINB, B ; Ist Terminal B Low? --> Wir drehen rückwärts
22
sbr FLAGS, (1<<F_DOWN) ; --> Flag für Hauptprogram setzen
23
int_ende:
24
out SREG, int_sreg_save ; SREG zurückschreiben
25
reti
Algemein kann man zu dem Drehgeber sagen, Terminal A wechselt pro
Rasterung immer 1/0/1/0 während B je nach Rasterstellung/Drehrichtung 1
oder 0 ist (sollte auch im Quellcode ersichtlich sein). Man hat den
Vorteil das man den Drehgeber an die (meist) ungenuzten ISP Pins hängen
kann und trozdem Problemlso programmieren kann, falls es nicht geht,
einfach eine Rasterstellung weiter... Ach ja Pullups nicht vergessen ;)
> Algemein kann man zu dem Drehgeber sagen, Terminal A wechselt pro> Rasterung immer 1/0/1/0 während B je nach Rasterstellung/Drehrichtung 1> oder 0 ist
Sollte ich mich da sooooo vermessen haben?
Ich habe in Erinnerung, dass die Pollin-Drehgeber pro Rastung einen
halben Zyklus machen, also in eingerasteter Stellung beide Kontakte
offen sind oder beide Kontakte geschlossen. Beim Überwinden einer
Raststellung entsteht dann an jedem Kontakt ein Pegelwechsel (keine 4),
die Pegelwechsel sind natürlich zeitlich versetzt.
Mit 10 ms funktioniert das auch, da darf man aber nicht allzu schnell
drehen. Ich habe daher 1 ms gewählt (das bot sich auch aufgrund anderer
Synchronisationen im Programm an). Es wird natürlich auch vom
Timer-Interrupt (über Flag) synchronisiert, läuft aber in der Mainloop,
um die Interrupts (da gibt es noch mehrere) kurz zu halten. Bit-Zugriffe
auf die Portpins habe ich bewusst vermieden, um die Prellsicherheit zu
erhöhen. Ich wollte mit einer "Kopie" des Port-(Eingangs-)Zustandes
arbeiten, um beide Zustände zeitnah zu erfassen. Die Bitschaufelei
(Swap) am Anfang meiner Routine rührt daher, dass mir nur noch diese
Portpins für den Drehgeber zur Verfügung standen. Meine Routine ist auch
deshalb etwas aufgebläht, weil sie nicht nur Flags setzt, sondern gleich
den Zähler manipuliert, und das auch noch (abhängig vom Drucktaster des
Drehgebers, der mittels PeDa-Entprellung zusammen mit den Tastern
entprellt wird) in zwei verschiedenen Schrittweiten. Unter dem Aspekt,
dass zur Entprellung des Drehgebers nur ein (stastisches) Register
blockiert wird, halte ich den Code schon für halbwegs effizient.
Bit- & Bytebruch,
Hannes
Also Hannes das kann natürlich auch sein, ich hab leider kein Oziloskop,
kann daher nur sagen das es so bei mir funktioniert.
Ich benutz das nur für das einstellen eines Countdowns, da ist es nicht
schlimm wenn mal eine Rasterung verloren geht :) Da gibts sicher noch
Optimierungsbedarf.
Ich greife diesen Thread mal auf, denn ich habe genau das gleiche
Problem:
Bisher hatte ich die Pollin Drehgeber immer per Interrupt ausgelesen
(was auch gut funktioniert hat). Aber da hier ja alle schreien, diese
Lösung wäre schlecht, wollte ich es besser machen.
Soviel zur Vorgeschichte.
Die hier unter Drehgeber empfohlenen Routinen sind für den Pollin
Drehgeber eher nicht zu gebrauchen. Zumindest funktionieren sie nicht
richtig, wenn man sie wie im Beispiel gezeigt verwendet.
Der Grund wird aus dem Bild deutlich (oben: Uhrzeigersinn, unten:
Gegenuhrzeigersinn, 16ms/div). Das von Hannes beschriebene asymmetrische
Verhalten ist ziemlich stark ausgeprägt. Durch die Rastung wird das
ganze noch verstärkt. Selbst wenn man langsam dreht (wenige Hz), dann
liegt der Abstand der beiden Signale nicht bei 90° wie im Idealfall,
sondern irgendwo im einstelligen Bereich !
Man müsste im Idealfall so schnell wie möglich nach der Flanke das
andere Signal abzutasten. In der Praxis muss man also mit mindestens
1kHz die Signale abtasten, damit das sicher funktioniert. Eine einfache
Entprellung nur durch eine geringe Abtastrate funktioniert also nicht
allzu sicher.
Damit es auch bei schnellem Drehen noch gut funktioniert musste ich die
Polling Frequenz auf >10kHz einstellen.
Daher meine Frage: Hat jemand schonmal eine gute Routine (abgesehen von
den anderen hier im Thread) für den Pollin Drehgeber geschrieben, die
ohne übertrieben hohe Abtastfrequenzen auskommen ?
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang