mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Inkrementaler Drehgeber encoding


Autor: Dani M (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich bin seit geraumer Zeit daran für meinen Drehgeber eine Routine zu 
schreiben mit welcher ich die Drehrichtung bestimmen kann. Doch ich habe 
unglaublicherweise einfach keinen Erfolg. Der Drehgeber besitzt zwei 
Ausgangssignale, wobei das erste Signal ausgelöst wird sobald die Optik 
auf der inkrementscheibe von schwarz auf weiss oder weiss auf schwarz 
wechselt, das zweite signal folgt dem ersten mit 90° Phasenverschiebung. 
Mit diese Informationen muss es "anscheinend" möglich sein die Richtung 
zu bestimmen. Zuerst probierte ich die einfachste Variante:
Falls (SignalA = High AND SignalB Low) -> rechts
Falls (SignalA = High AND SignalB High) -> links
Ich bemerkte aber schon bald das sich dieses Verfahren bei leichtem hin 
und herbewegen des Drehgebers nicht bewährt. Ich habe nun schon 
unzählige Möglichkeiten probiert und theoretisch aufgezeichnet doch 
funktioiern tut alles nicht.

Weiss jemand wie man die Signale auswerten muss (Wahrheitstabelle), dass 
die Richtung immer und ohne Zweifel bestimmt werden kann?

Vielen Dank
Dani

Autor: Josef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DRG_INP:          ;Wartet auf Drehgeber-Impulse u.entscheidet l/r
            ;wartet, bis alle 2 Flanken auf high sind
;.................................................................
WAIT_DRG_HIGH:  LE  PIND, DREHG_UP    ;wartet auf high an beiden 
Drehgeber-Eingängen
    UE  PIND, DREHG_DWN    ;
    wdr
    brtc WAIT_DRG_HIGH    ;Schleife, bis alle Eingänge high sind
;.................................................................
WAIT_ON_LOW:  LNE  PIND, DREHG_UP    ;warte auf ein LOW an den 
Drehgebereingängen
    brts DRG_UP      ;

    LNE  PIND, DREHG_DWN    ;
    wdr
    brts DRG_DWN
    rjmp WAIT_ON_LOW    ;Schleife bis Eingang low ist
;..................................................................
DRG_UP:    LNE  PIND, DREHG_DWN    ;wartet bis 2-Kanal auch low ist !
    brts CNT_UP      ;falls ja, kann gezählt werden
    LE   PIND, DREHG_UP    ;falls 1.Kanal wieder high ist war es Spike
    brts WAIT_DRG_HIGH    ;Spike falls  PIN wieder high
    wdr
    rjmp DRG_UP
;...................................................................
DRG_DWN:  LNE  PIND, DREHG_UP    ;wartet bis 1-Kanal auch low ist !
    brts CNT_DWN      ;falls ja, kann gezählt werden
    LE   PIND, DREHG_DWN    ;falls 2.Kanal wieder high ist war es Spike
    brts WAIT_DRG_HIGH    ;wieder def.Lage suchen
    wdr
    rjmp DRG_DWN      ;Loop
;...............................................;aufwärts 
zählen........................
CNT_UP:    rcall INC_DG
    rjmp WAIT_DRG_HIGH    ;auf Low an beiden Eingängen warten
;................................................;abwärts 
zählen...........................
CNT_DWN:  rcall DEC_DG
    rjmp WAIT_DRG_HIGH    ;auf Low an beiden Eingängen warten
;*********************************************************************** 
*************

Autor: Dani M (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Josef

Vielen Dank für die schnelle Antwort, ich vergass jedoch zu erwähnen 
dass ich in Ansi-C codiere, darum ist es für mich nicht gerade einfach 
hinter die Lokig von deinem Code zu kommen. Ausserdem arbeite ich mit 
den Externen Interrupt von dem uC, d.h. bei den Fallenden Flanken möchte 
ich entscheiden in welche Richtung gedreht wird, ich habe dazu noch ein 
FlipFlop eingebaut um die Logik bei der letzten gestiegenen Flanke noch 
zur Verfügung zu haben, doch trotz all den Mitteln habe ich bis jetzt 
noch nicht die Richtige Abfrage gefunden.

Gruss
Dani

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht helfen die Infos auf http://dse-faq.e-online.de.

Autor: Peter Dannegger (peda)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Dani,

die Auswertung von Positionsgebern sollte man nicht mit 
flankengetriggerten Interrupts machen !

Steht der Geber zufällig genau auf einem Signalwechsel kann es zur 
Oszillation mit hoher Frequenz kommen (Vibration, Rückkopplung ?).

Dann bekommst Du Interrupts ohne Ende und Deine Hauptprogrammroutine 
kommt nicht mehr zum Zuge.

Deshalb habe ich die Abfrage mit einem Timerinterupt gelöst, da dann 
keine unzulässig hohe Interruptrate auftreten kann (ist ja konstant, da 
vom Timer).

Das die Timerfrequenz kleiner ist als solche Oszillationen, hat keinen 
Einfluß auf die Genauigkeit.
Sie muß nur immer größer sein, als die echte Positionsänderung.
In meiner Anwendung taste ich mit etwa 20kHz ab.


Der Code ist in C im Anhang.


Peter

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch ne Alternative: die Signale per Hardware dekodieren und getrennte 
Taktsignale bzw. Takt und Richtung an den MC senden.

Autor: Josef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wichtig ist, dass dein Programm erkennt, wenn der Drehgeber steht 
bzw.ein vorangegangenes Zählen abgeschlossen wurde, also kein Signal auf 
beiden Ausgängen von ihm ausgegeben wird (beide Ausgänge high). Das ist 
immer (!) dein Ausgangspunkt. Sobald eine Flanke kommt, wird abgefragt 
welche (entscheidet links oder rechts).War sie zB rechts als erstes da, 
verzweigst du
in die "Rechtsroutine". In dieser wartest du auf den zweiten Eingang. 
Dann kannst du 1 Impuls zählen.
Danach wartest du wieder, bis alle 2 Ausgänge wieder auf high sind 
(Drehgeber steht bzw 1 Impuls vorbei)

Ob Interrut oder Timer ist nicht so wichtig. Für den Anfang wäre es 
besser, die Pins zu pollen. Nur so ist
die höchstmögliche Arbeitsgeschwindigkeit möglich. Meisten muss man die 
gezählten Impulse vom Drehgeber noch durch einen Faktor teilen um ein 
Ergebnis zu erhalten, dass weiterverarbeitet werden kann.


Gutes Gelingen Josef

Autor: Dani (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute

Ich habe mir nun die Gray.c51 Software von Peter zu gemüte geführt. Das 
ganze funktioniert einwandfrei (copy-paste)!! Und ich habe mich 
tagelange mit einer Lösung über die Externen Interrupts rumgeschlagen. 
Ich habe allerdings zuerst mal auf den Timerinterrupt verzichtet und mit 
die Rutine einfach ins Main gehängt, dass funktioniert aber so gut, dass 
ich es dabei belassen werde.

Also nochmals vielen Dank an euere Hilfe und die geniale C-Source von 
Peter

Dani

Antwort schreiben

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

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.