Forum: Mikrocontroller und Digitale Elektronik Rotary Encoder entprellen


von MyCo (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich habe ein Problem beim Entprellen von Drehgebern (Bourns Rotary
Encoder mit graycode). Ich bastel gerade an 2 Projekten damit. Bei dem
einen will ich das eine Taktsignal an den Interrupt1 und das andere
Taktsignal an PD4  eines Atmega8 hängen. Der Bascom-Quelltext, den ich
bisher habe ist im Anhang.

Das ist bisher nur zum Testen. Leider zählt die Variable c völlig
wahllos. Wenn ich in eine Richtung drehe, zählt er mal rauf und mal
runter, ausserdem sind die Sprünge zwischen den Werten auch bei einem
einzelnen Klick unterschiedlich gross. Die Drehgeschwindigkeit ist da
auch völlig egal. Ich brauche allerdings die Abfrage per Interrupt, da
das Hauptprogramm sehr zeitintensiv wird. Es wird daher auch per
Assembler geschrieben sein.
Ich habe auch schon versucht, den Interrupt einfach abzuschalten, damit
er nicht mehrfach aufgerufen wird. Nur irgendwie scheint der AVR die
zwischenzeitlichen Interrupt-Aufrufe zu speichern, um sie später
nachzuholen.

Ich hoffe ihr könnt mir helfen, da ich mich jetzt schon ein paar
Stunden damit herumgequält habe und nun nicht mehr weiter weiss.

Danke!
Maik

von Andi (Gast)


Lesenswert?

Du mußt den Zustand eines Drehgeber-Pins in einer Variablen "merken"
und vor der Auswertung auf Veränderung prüfen, z. B. Kanal A.
Erst wenn sich Kanal A verändert hat hat der Nutzer den Drehgeber
betätigt und darauf hin dann die Auswertung "IF PinD.3=0 then" etc.

Noch mal der Ablauf:
 If Gemerkt <> PinD.3 dann
   If PinD.3 = PinD.4 dann
     .....
   else
     .....
   EndIf
   Gemerkt = PinD.3
 EndIf

MfG
Andi

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Für eine zuverlässige Auswertung muss sich das Programm die Zustände
beider Ausgänge merken, dann kann man sich das Entprellen auch i.d.R.
sparen.

http://www.mikrocontroller.net/forum/read-4-37992.html#87902

von MyCo (Gast)


Lesenswert?

Naja... wenn ich das so machen würde, könnte ich mein Projekt gleich
abhaken. Bei der ersten Lösung würde ich 10-20 Zyklen alleine im
Hauptprogramm mehr haben, und bei der 2. wären diese 10-20 Zyklen
regelmässig beim Timeraufruf.
Bei mechanischen Drehgebern muss man nicht alle 4 Stadien der Ausgänge
auswerten. Da der Regler ja selbst rastet, würde man so eh pro Klick um
2 werte nach oben zählen.

@Andi: Die Lösung funktioniert wenn überhaupt, nur mit einem bereits
hardwaremässig-entprellten Drehgeber.

von Benedikt (Gast)


Lesenswert?

Bei mir ging es ganz einfach:
Pullups des uC aktivieren, 10nF nach Masse zur Entprellung und ein
Ausgang des Inkrementgebers an einen Interrupt. In der Interruptroutine
wird der Zustand des zweiten Pins abgefragt: Ist der High wurde vorwärts
gedreht, ist es Low wurde rückwärts gedreht.
Fragt micht nicht wiso das so ist, ich weiß nur dass es einwandfrei bei
mir läuft.

von Peter D. (peda)


Lesenswert?

@MyCo

"Naja... wenn ich das so machen würde, könnte ich mein Projekt gleich
abhaken. Bei der ersten Lösung würde ich 10-20 Zyklen alleine im
Hauptprogramm mehr haben, und bei der 2. wären diese 10-20 Zyklen
regelmässig beim Timeraufruf."


Das must Du aber schon näher erläutern !

20 Zyklen in einem Timer z.B. alle 200µs (5kHz) sind bei 8MHz
20/1600=1,25% CPU-Last.

Du must also die Quarzfrequenz nur um 1,25% erhöhen und Du hast genau
die gleiche Leistung wie ohne Drehgeber auslesen.

Ich kenne jedenfalls keine Anwendung, die bei 1,25% CPU-Last schon in
die Knie geht.


Peter

von MyCo (Gast)


Lesenswert?

Ich will den Atmega als "stellbaren" Taktgeber einsetzen, mit
Frequenzen zwischen 2MHz und 50Hz, wobei Low- und High-Zeit getrennt
geregellt werden kann. Das wichtige dabei ist, dass wenn die Frequenz
einmal gestellt ist, der Taktgeber 100% genau laufen soll. Ein
Timer-Interrupt der immer mal das Hauptprogramm unterbricht würde so
zB. das ganze Prinzip kaputt machen.

Der µC läuft schon mit einem 16MHz Quarz, ein Erhöhung der Taktrate
bringt dann nur noch mehr Fehler.

von ...HanneS... (Gast)


Lesenswert?

2MHz??

Hut ab, das ist ein hohes Ziel!
Und denn noch 100% genau...
Da wird ein AVR arg zu knabbern haben, selbst bei Verwendung der
Hardware-PWM.

...

von Peter D. (peda)


Lesenswert?

"Ich will den Atmega als "stellbaren" Taktgeber einsetzen, mit
Frequenzen zwischen 2MHz und 50Hz, wobei Low- und High-Zeit getrennt
geregellt werden kann."


Und warum nimmst Du nicht die PWM (Mode 14 oder 15) ?

Die macht das doch voll in Hardware, da stört ein Interrupt überhaupt
nicht.

Und unter 245Hz nimmst Du eben die Pin-Set und Clear-Funktion des
Timers.


Peter

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Es zwingt dich doch niemand dazu die Auswertung im Timerinterrupt zu
machen, das geht genau so gut in der Hauptschleife.

von MyCo (Gast)


Lesenswert?

Ich habe bisher pwm noch nicht dazu bekommen, das zu tun was ich will...
die Dokumentation in Bascom bringt einem nicht weiter, und mit ASM bin
ich auch noch nicht so weit...

Software-mässig bekomme ich mit meinem ASM-Code bisher etwa 1,5MHz
konstant

Aber es geht mir auch darum, einen Drehgeber abzufragen, ohne dafür die
Pins abzufragen. Es soll also nur der Drehgeber abgefragt werden, wenn
bereits feststeht, dass er bewegt wurde.

von Peter D. (peda)


Lesenswert?

"Ich habe bisher pwm noch nicht dazu bekommen, das zu tun was ich
will... die Dokumentation in Bascom bringt einem nicht weiter"

Die Doku im Datenblatt aber schon.

Es schad nix, wenn man sich mal mit den internen Registern und
Funktionen der CPU beschäftigt und sich nicht blindlings auf die
vorgefertigten Black-Boxes in Bascom verläßt.
Ich finds sogar interessanter, wenn man weiß, wie etwas funktioniert.



"Software-mässig bekomme ich mit meinem ASM-Code bisher etwa 1,5MHz
konstant"

Wie machst Du denn da die Einstellung des Tastverhältnisses ?



"Es soll also nur der Drehgeber abgefragt werden, wenn
bereits feststeht, dass er bewegt wurde."

Ginge im Prinzip auch (beide Pins auf beide Interrupts und dann bei
beiden Flanken auslösen). Beide Interrupthandler rufen dann die Routine
auf.

Trotzdem wirst Du dann aber ohne die PWM Signalstörungen haben, auch
wenns nur beim Drehen ist.


Peter

von MyCo (Gast)


Lesenswert?

Der Hauptteil des Taktgebers ist:

   mainloop:
     cbi $15,0
     movw Temp,LTimeH
      dlya:
         sbiw Temp,1
         brne  dlya

      sbi $15,0
      movw Temp,HTimeH


      dlyb:
         sbiw Temp,1
         brne  dlyb

   rjmp mainloop


Im Interrupt soll dann per Drehgeber LTimeH, LTimeL, HTimeH und HTimeL
gesetzt, und der Hauptteil macht dann automatisch den Rest.

Wie gesagt, die PWM-Beschreibung ist mir im Moment zu schwer zu
verstehen, da ich ASM noch nicht so gut kann. Den Hauptteil habe ich
gerade so zusammenbekommen. Vielleicht kann mir jemand eine PWM-Version
geben, die ähnliches erzielt, wie mein Hauptteil. Aus Quelltext kann ich
besser lernen, als aus trockenen Dokumentationen.

von Uwe (Gast)


Lesenswert?

Hi!
Also sowas sollten unbedingt der/die Timer selber machen.
Beschäftige dich mal mit Output Compare A+B. Du wirst sehen dein
Zeitproblem löst sich in Luft auf. Mal so als Tip OC1A macht Low-Teil,
OC1B macht High-Teil deiner Freq. Aber um's Datenblatt kommst du nicht
herum.

MFG Uwe

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.