mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem bei Drehgeber auswertung


Autor: Sebastian Engel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich hab mal versucht, einen Drehgeber (Handbetrieben) auszuwerten.
Und zwar sollte die Drehbewegung in je ein Impuls pro Rastung 
ausgegegebn werden, getrennt für rechts und links.

Ich verwende einen ATtiny26 mit 1MHz interner Taktung.

Den Drehgeber habe ich an PB6 und PB5 angeschlossen.
2 LEDs sind an PA0 und PA1 angeschlossen.
PB6 ist als externer Interrupt eingestellt auf "Pin Change".

Hier der code:
;#################################
;# Project: Drehgeber auswerten mit Interrupt
;# Date: 20.3.07
;# Version: 0.1
;# Controller: ATtiny26
;# Frequency: 1Mhz intern
;#################################
.include "tn26def.inc"

  rjmp main      ;Power-on-reset
  rjmp subroutine    ;external interrupt
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti

;#################################
;# main
;#################################

  main:  ldi r16,low(ramend)
      out SP,r16

      clr r16
      out DDRB,r16
      ser r16
      out PORTB,r16
      out DDRA,r16

      ldi r16,0b01000000
      out GIMSK,r16    ;external interrupt on
      ldi r16,0b00000001
      out MCUCR,r16    ;ext. int at "any change"
      sei          ;global interrupt enable

; Mainloop
  loop:  rjmp loop

; Interrupt program
  subroutine:
      in r16,PINB
      mov r17,r16
      ror r17
      andi r16,0b01000000
      andi r17,0b01000000
      cp r16,r17
      brne rechts
      sbi PORTA,1
      rcall wait
      cbi PORTA,1
      reti
  rechts:  sbi PORTA,0
      rcall wait
      cbi PORTA,0
      reti

; Warteschleife
  wait:  ser r20
  wait0:  dec r20
      brne wait0
      ret

Das Ergebnis: Es werden abwechselnd PA0 und PA1 angesteuert, egal wie 
rum ich den Drehgeber drehe. Mnachmal werden beide gleichzeitig 
angesteuert.

Meine Frage ist nun: Findet jemand spontan einen Fehler?
Fehlt nur eine entprellung, oder kleine warteschleifen?
Ich bin ratlos.

Mfg
 Sebastian Engel

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
s werden abwechselnd PA0 und PA1 angesteuert, egal wie
rum ich den Drehgeber drehe. Mnachmal werden beide gleichzeitig
angesteuert...

Aber du weißt wie ein Drehgeber funktioniert?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich nutze einen handbetätigten Drehgeber am Mega8535 mit folgender 
Routine:

;Relevante Deklarationen:
.equ tap=pind               ;Eingangs-Port Tasten
    .equ tli=7                  ;Taste links
    .equ tho=6                  ;Taste hoch
    .equ tru=5                  ;Taste runter
    .equ tre=4                  ;Taste rechts
    .equ ths=3                  ;Taste Handschuss
    .equ tdg=2                  ;Taster vom Drehgeber
.equ dgp=pinb               ;Eingangsport Drehgeber
    .equ dgmsk=0b00001100       ;Maske auf benutzte Bits von 'dgp'
    .equ dgprell=0b00010101     ;Maske auf Togglebits in 'drg'

.def drg=r5                 ;Drehgeber-Entprellvariable
.def tas=r13                ;entprellter Tastenstatus (gültig)
.def haschunu=r17           ;Handschussnummer per Drehgeber
.def wl=r24                 ;Working L

;Routine, zyklischer Job der Mainloop alle 1ms:
drehgeber:              ;Drehgeber-Entprellung und -Abfrage (alle 1ms)
;diese Routine wird von der Mainloop aufgerufen, wenn mindestens eine 
;Millisekunde seit des letzten Aufrufs vergangen ist. Der Aufruf erfolgt
;mit 'rjmp', damit auch andere Mainloop-Jobs zum Zuge kommen, ehe der
;Controller am Ende der Mainloop in den Sleep fällt. Das zugehörige
;Jobflag (Synchronisation mittels Timer) wird in der Routine 'lcd_update'
;gelöscht.
 rcall lcd_update           ;ein Zeichen aus Bildscirmspeicher an LCD ausgeben
 in wl,dgp                  ;Drehgeber einlesen
 andi wl,dgmsk              ;nur Drehgeber-Bits (Bit 3:2)
 swap wl                    ;nach oben (Bit 7:6)
 or drg,wl                  ;neuen Zustand übernehmen
 mov wl,drg                 ;Bitmuster merken (neu, alt, älter, uralt)
 lsr drg                    ;Bitmuster nach unten schieben
 lsr drg                    ;(leer, neu, alt, älter)
 eor wl,drg                 ;Änderungen erfassen
 andi wl,dgprell            ;nur Änderungsbits stehen lassen
 cpi wl,1                   ;nur ältestes Änderungsbit gesetzt?
 brne drehgeber3            ;nein, kein neuer stabiler (entprellter) Zustand...

 ldi wl,1                   ;ja, erstmal normale Schrittweite
 sbrc tas,tdg               ;Shift-Taste (Drehgeber-Taste) betätigt? - nein...
 ldi wl,32                  ;ja, Geräte-Schrittweite
 sbrs drg,0                 ;steigende Flanke? - ja...
 rjmp drehgeber1            ;nein...
 sbrs drg,1                 ;Richtung 1? nein...
 add haschunu,wl            ;ja, adieren
 sbrc drg,1                 ;Richtung 2? nein...
 sub haschunu,wl            ;ja, subtrahieren
drehgeber1:
 sbrc drg,0                 ;fallende Flanke? - ja...
 rjmp drehgeber2            ;nein...
 sbrs drg,1                 ;Richtung 1? nein...
 sub haschunu,wl            ;ja, subtrahieren
 sbrc drg,1                 ;Richtung 2? nein...
 add haschunu,wl            ;ja, adieren
drehgeber2:
drehgeber3:
;Das folgende Ausgeben des veränderten Wertes ist nur möglich, weil die
;Ausgabe über einen Bildschirm-Speicher im AVR-SRAM erfolgt. Dem ist es
;recht egal, wenn er schneller beschrieben wird, als es ins LCD kopiert
;wird. Mit herkömmlichen LCD-Routinen geht das natürlich nicht.
 locate 6,21
 push xl
 mov xl,haschunu            ;Kopie von Handschussnummer
 rcall lcd_printsnr         ;Aufruf... (dreistellige Ausgabe 'A00'..'H31')
 pop xl
 rjmp mainloop              ;fertig, weitere Jobs der Mainloop abarbeiten...

Das müsste auch am Tiny26 funktionieren.

...

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Sebastian Engel

>ich hab mal versucht, einen Drehgeber (Handbetrieben) auszuwerten.

Alle Jahre wieder, komt nciht nur das Christuskind, sondern auch das 
Thema Drehgeber.

Guggst du hier.

Beitrag "Drehgeber auslesen"
http://www.mikrocontroller.net/articles/Drehimpulsgeber

>PB6 ist als externer Interrupt eingestellt auf "Pin Change".

Was schonmal kein guter Ansatz ist. Auswertung per Flankeninterrupt ist 
schlecht, periodische Abtastung per Timerinterrupt ist das Mittel der 
Wahl.

MfG
Falk

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk
>Auswertung per Flankeninterrupt ist
>schlecht, periodische Abtastung per Timerinterrupt ist das Mittel der
>Wahl.

Warum nicht mit Interrupt ?


Grüße
Dirk

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Dirk

>>Auswertung per Flankeninterrupt ist
>>schlecht, periodische Abtastung per Timerinterrupt ist das Mittel der
>>Wahl.

>Warum nicht mit Interrupt ?

Das ist lang und breit und hundertmal im angegebenen Link erklärt.

MfG
Falk

Autor: Sebastian Engel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal:
Ja, mir ist bekannt was ein Drehgeber ist. Das Datenblatt habe ich 
ausführlich durchgeforstet

Zu den Links:
Ich habe hier schon fast alle Drehgeber Threads durchgestöbert,
aber ich dachte mir probierstes mal selber.

Zum interrupt:
So eine Lösung würde im Datenblatt vorgeschlagen.
Also ganz simpel:
positive Flanke triggert -> pin A & B vergleichen -> Wenn gleich 
"rechts" / Wenn ungleich "links" -> trigger auf fallende flanke stellen 
-> anfang ->

Ich dachte das hätte ich richtig in der Software umgesetzt.

Sonst muss ich halt nochmal die alten Threads durchstöbern.

Danke für die flotten antworten

 Mfg
 S. Engel

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du vielleicht richtig programmiert, doch das Prellen wird das 
Genick brechen... Ohne "schlauere" Routinen geht es vielleicht bei 
optischen Gebern, aber bei mechanischen wird es zum Glückspiel.

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Sebastian Engel

>Ich habe hier schon fast alle Drehgeber Threads durchgestöbert,
>aber ich dachte mir probierstes mal selber.

Prinipiell OK, aber leider machen dabei die meisten Leute genau den 
Fehler, den hunderttausende vor ihnen schon gemacht haben.

>Zum interrupt:
>So eine Lösung würde im Datenblatt vorgeschlagen.
>Also ganz simpel:
>positive Flanke triggert -> pin A & B vergleichen -> Wenn gleich
>"rechts" / Wenn ungleich "links" -> trigger auf fallende flanke stellen
>-> anfang ->

Daran sieht man, dass auch Datenblätter manchmal Müll enthalten.

>Ich dachte das hätte ich richtig in der Software umgesetzt.

Kann sein, sit aber dennoch falsch, weil es nur zu 90% sauber läuft.

>Sonst muss ich halt nochmal die alten Threads durchstöbern.

Das musst du. Kleiner Tip. Stell dir mal vor, der Drehgeber kommt genau 
auf einer Flanke zum Stehen und schwingt dann lustig vor und zurück (das 
ist ein realer Fall!).

Was passiert mit deinem Controller, wenn er auf steigende/fallende 
Flanke triggert?
Was passiert mit dem Controller, wenn er nur alle 10ms abtastet?

@Thomas

>Genick brechen... Ohne "schlauere" Routinen geht es vielleicht bei
>optischen Gebern, aber bei mechanischen wird es zum Glückspiel.

Auch bei optischen ist es das gleiche Problem.

MFG
Falk

Autor: Gugge 73 (gugge73)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Sebastian

Laß dir keinen Müll erzählen, auch im flankengesteurten Interrupt kann 
man erfolgreich Drehgeber auswerten/abfragen. Hab bei mir zu Hause auch 
zwei Teile im Einsatz, die seit zehn Jahren funktionieren. Damals war 
mir Peters Timerroutine noch gar nicht bekannt, und ob es dieses Forum 
hier schon gab, kann nicht sagen.

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Gugge 73

>Laß dir keinen Müll erzählen, auch im flankengesteurten Interrupt kann
>man erfolgreich Drehgeber auswerten/abfragen. Hab bei mir zu Hause auch

Man kann auch 20 Jahre ohne Sturzhelm Moped fahren und es passiert nix.

>zwei Teile im Einsatz, die seit zehn Jahren funktionieren. Damals war
>mir Peters Timerroutine noch gar nicht bekannt, und ob es dieses Forum
>hier schon gab, kann nicht sagen.

Der Aufstieg und Fall der Elektronikbranche wird wohl kaum an dieser 
Webseite hängen ;-)
Und auch wenn es Peters Routine noch nciht gab, so gab es schon Leute 
die wussten wie man Drehgeber richtig auswertet. Aber bestimmte Mythen 
sind eben sehr zäh.

MFG
Falk

P.S. Stell dir bitte auch mal die Fragen aus meinem vorherigen Posting. 
Was passiert mit dem Controller? Die Antwort ist auch im verlinkten 
Thread zu finden.

Autor: Sebastian Engel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert


;#################################
;# Project: Drehgeber auswerten mit Interrupt
;# Date: 20.3.07
;# Version: 0.1
;# Controller: ATtiny26
;# Frequency: 1Mhz intern
;#################################
.include "tn26def.inc"

  rjmp main      ;Power-on-reset
  rjmp subroutine    ;external interrupt
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti
  reti

;#################################
;# main
;#################################

  main:  ldi r16,low(ramend)
      out SP,r16

      clr r16
      out DDRB,r16
      ser r16
      out PORTB,r16
      out DDRA,r16

      ldi r16,0b01000000
      out GIMSK,r16    ;external interrupt on
      ldi r16,0b00000001
      out MCUCR,r16    ;ext. int at "any change"
      sei          ;global interrupt enable

; Mainloop
  loop:  rjmp loop

; Interrupt program
  subroutine:
      rcall wait           ;<---- Das ist NEU
      in r16,PINB
      mov r17,r16
      rol r17              ;<---- ror durch rol ersetzt, der eigendliche Fehler
      andi r16,0b01000000
      andi r17,0b01000000
      cp r16,r17
      brne rechts
      sbi PORTA,1
      rcall wait
      cbi PORTA,1
      reti
  rechts:  sbi PORTA,0
      rcall wait
      cbi PORTA,0
      reti

; Warteschleife
  wait:  ser r20
  wait0:  dec r20
      brne wait0
      ret

Hab nur die beiden oben genannten dinge geändert, und schon läufts.

Funktioniert zu 98,7% :-)
Ab und zu kommt ein "Fehlimpuls".
Zum testen habe ich anstatt 2 pins zu toggeln, einfach an Port A durch 
LEDs  ein Register ausgegeben, welches man durch drehen +1 / -1 
durchzählen kann.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, Warteschleife in der ISR ist nicht mein Ding, aber wenn Du damit 
klar kommst, dann nur zu...

...

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Funktioniert zu 98,7% :-) Ab und zu kommt ein "Fehlimpuls".

Mach mal je 33nF Keramikkondensatoren von jedem der beiden Drehgeberpins 
nach Masse. Das schluckt einen Großteil der Prellimpulse, flacht aber 
die Flanken ab. Es könnte die Fehler aber auf nahezu 0 reduzieren. Trotz 
aller Deiner Argumente würde ich aber nie einen Interrupt an einem 
externen Schaltelement anbinden. Das sorgt im Zweifelsfalle (schnelle 
Betätigungen) für Instabilität im Programm.

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.