Guten Abend,
für ein aktuelles Projekt möchte ich das erste Mal in meinem
Elektronikerleben einen Drehgeber einbauen. Bisher hat mich die
Auswertung davon etwas abgeschreckt, heute habe ich mich doch mal
reingearbeitet.
Wäre jemand so nett, meine Idee zu prüfen? Verwendet werden soll ein
Attiny2313 mit INT0 und INT1.
Spur A hängt auf INT0 und Spur B auf INT1. Der Verständlichkeit halber
nenne ich INT0 "INT A" und INT1 "INT B".
Das Problem mit dem Prellen möchte ich auf der Annahme lösen, dass nach
einer Änderung auf einer Spur (z.B. A) immer erst eine Änderung auf der
anderen Spur (z.B. B) passiert, bevor sich Spur A wieder ändern kann.
Also kann ich nach dem Interrupt auf einer Spur für diese Spur den
Interrupt abschalten und den für die andere Spur wieder aktivieren.
INT A und INT B werden als "changing" gesetzt.
Innerhalb von INT A und INT B gibt es ein if-else, mit dem ich zwischen
LOW-HIGH (Pin=1) und HIGH-LOW (Pin=0) unterscheide.
Deshalb würde ich drei Fälle definieren:
1
1. INT A: LOW → HIGH
2
a) INT A deaktivieren
3
b) INT B aktivieren
4
c) A = 1
5
6
2. INT A: HIGH → LOW
7
a) INT A deaktivieren
8
b) INT B aktivieren
9
c) A = 0
10
11
3. INT B: HIGH → LOW
12
a) INT B deaktivieren
13
b) INT A aktivieren
14
c) Wenn A = 1 dann RECHTS = 1 und LINKS = 0
15
ELSE RECHTS = 0 und LINKS = 1
16
17
4. INT B: LOW → HIGH
18
a) INT B deaktivieren
19
b) INT A aktivieren
20
c) Wenn A = 0 dann RECHTS = 0 und LINKS = 1
21
ELSE RECHTS = 1 und LINKS = 0
Habe ich hier einen (groben) Denkfehler oder kann ich das (in Bascom) so
umsetzen?
Danke und schönen Abend!
Einen Drehgeber mit Flankeninterrupts auszuwerten ist keine gute Idee,
denn die Dinger prellen.
Starte einen Timer, welcher alle 0,1 - 1ms einen IRQ auslöst.
Lies die beiden Bits ein und zusammen mit den beiden Bits vom vorherigen
IRQ hast Du 4 Bit, welche eine Zahl von 0-15 representiert.
In einem eindimensionalen Array hast Du eine Tabelle, welche entweder 0,
1 oder -1 enthält. Diesen Wert summierst Du zu einer Variablen, welche
dann außerhalb des IRQs ausgelesen werden kann. Sie enthält die Position
des Gebers.
Gruß
Jobst
Jobst M. schrieb:> denn die Dinger prellen.
Deshalb die Idee, den prellenden Interrupt nach dem ersten Auslösen
sofort zu deaktivieren und erst durch den anderen Interrupt (wenn also
nichts mehr prellt) wieder zu aktivieren.
Dein Vorschlag klingt aber auch interessant. Ich versuche das mal zu
verstehen.
praktiker schrieb:> Deshalb die Idee, den prellenden Interrupt nach dem ersten Auslösen> sofort zu deaktivieren und erst durch den anderen Interrupt (wenn also> nichts mehr prellt) wieder zu aktivieren.
Und was passiert, wenn der Bediener gar nicht mehr so weit dreht und
wieder zurück dreht? ;-)
Gruß
Jobst
Wenn der Drehgeber sich in beide Richtungen drehen kann, ist die
Annahme, dass erst auf dem anderen Interrupt was passieren muss, bevor
sich auf dem ersten wieder etwas ändert, falsch. Man kann beispielsweise
bei einer Rechtsdrehung die L/H-Flanke von Interrupt A überfahren und
anschließend bei einer Linksdrehung kommt die H/L-Flanke von A ohne dass
sich bei Interrupt B etwas geändert hat.
Eigentlich ist es ganz einfach. Man betrachtet die 4 Ereignisse L/H-
oder H/L-Flanke auf Interrupt A und L/H- oder H/L-Flanke auf Interrupt
B. In allen 4 Fällen schaut man ob der andere Interrupt gerade auf L
oder H steht. Ergibt 8 Möglichkeiten, bei 4 von ihnen war es ein Schritt
nach links und bei 4 ein Schritt nach rechts. Die Entprellung geschiet
ganz automatisch dadurch, dass die Interruptbearbeitung etwas Zeit
benötigt. Im schlimmsten Fall gibt es halt noch mal einen Schritt vor
und einen zurück.
Ich hab das ganze mal für einen PIC programmiert.
Bernd
Nur einen Interrupt benutzen, darin den Zweiten Pin abfragen um die
Richtung zu bestimen und den Int sperren bis die Main es ausgewertet
hat. (Oder ohne Auwertung rausspringen bis die Main es verarbeitet hat)
praktiker schrieb:> oder kann ich das (in Bascom) so> umsetzen?
Mal eine Frage, würde das in Bascom mit der Funktion Encoder auch
funktionieren.
Du verwendest allerdings einen Assbach Uralt Controller.
In der Bascom Hilfe steht.
Most new processors support the pin change interrupt. This means that
an interrupt occurs when the logic level of a pin changes. you can use
this interrupt to call the encoder function. This way you can be sure
you will
Das Beispiel dazu sieht so aus:
$regfile = "m128def.dat" ' specify the
used micro
$crystal = 4000000 ' used
crystal frequency
$baud = 19200 ' use baud
rate
$hwstack = 32 ' default
use 32 for the hardware stack
$swstack = 10 ' default
use 10 for the SW stack
$framesize = 40 ' default
use 40 for the frame space
Print "Encoder test"
Dim B As Byte
'we have dimmed a byte because we need to maintain the state of the
encoder
Portb = &B11 ' activate
pull up registers
Do
B = Encoder(pinb.0 , Pinb.1 , Links , Rechts , 1)
' ^--- 1 means wait for
change which blocks programflow
' ^--------^---------- labels which are
called
' ^-------^---------------------------- port PINs
Print B
Waitms 10
Loop
End
'so while you can choose PINB0 and PINB7,they must be both member of
PINB
'this works on all PIN registers
Links:
Print "left rotation"
Return
Rechts:
Print "right rotation"
Return
End
Schau bitte in der Hilfe das an, hier gibt es wohl ein Problem mit Text
einfügen.
praktiker schrieb:> für ein aktuelles Projekt möchte ich das erste Mal in meinem> Elektronikerleben einen Drehgeber einbauen. Bisher hat mich die> Auswertung davon etwas abgeschreckt, heute habe ich mich doch mal> reingearbeitet.> Wäre jemand so nett, meine Idee zu prüfen? Verwendet werden soll ein> Attiny2313 mit INT0 und INT1.
Warum?
RTFM!
Einfach das Kapitel 7.46 ENCODER lesen.
praktiker schrieb:> Deshalb die Idee, den prellenden Interrupt nach dem ersten Auslösen> sofort zu deaktivieren und erst durch den anderen Interrupt (wenn also> nichts mehr prellt) wieder zu aktivieren.
So so, den Unsinn hast du unter einem anderen Namen doch schon mal zu
verbreiten gesucht:
Beitrag "Drehgeber an Arduino, external interrupt ISR wird doppelt ausgeführt"
Es war mühsam, aber nach dem man die Zählfehler der Routine aufgedeckt
hatte, gab der Troll erstmal Ruhe.
Nun also schon wieder einer auf dem Holzweg.
praktiker schrieb:> für ein aktuelles Projekt möchte ich das erste Mal in meinem> Elektronikerleben einen Drehgeber einbauen.> Das Problem mit dem Prellen möchte ich auf der Annahme lösen, dass nach> einer Änderung auf einer Spur (z.B. A) immer erst eine Änderung auf der> anderen Spur (z.B. B) passiert, bevor sich Spur A wieder ändern kann.> Also kann ich nach dem Interrupt auf einer Spur für diese Spur den> Interrupt abschalten und den für die andere Spur wieder aktivieren.
Warum nimmst Du nicht gleich die sog. Zustandsauswertung, bei der
das Prellen keine Rolle spielt? Siehe auch dse-faq.
praktiker schrieb:> Also kann ich nach dem Interrupt auf einer Spur für diese Spur den> Interrupt abschalten und den für die andere Spur wieder aktivieren.
Das ist vermutlich die Variante, die in vielen kommerziellen Geräten
implementiert ist und für maximalen Frust bei den Benutzern sorgt. Die
prellt ohne Ende.
Wichtig ist, daß man sich den alten Zustand merkt und keinen Interrupt
disabled. Dann kann bei einem Preller der nächste Flankeninterrupt
sofort wieder zurück zählen, d.h. der Preller wird kompensiert.
praktiker schrieb:> Wäre jemand so nett, meine Idee zu prüfen? Verwendet werden soll ein> Attiny2313 mit INT0 und INT1.> Spur A hängt auf INT0 und Spur B auf INT1. Der Verständlichkeit halber> nenne ich INT0 "INT A" und INT1 "INT B".
Nicht schon wieder! NEIN! Wie es richtig geht, siehe Drehgeber, das
geht auch in BASCOM. Dort gibt es sogar schon einen Befehl dafür, den
man nur periodisch in einem Timer-Tinerrupt aufrufen muss!
praktiker schrieb:> Das Problem mit dem Prellen möchte ich auf der Annahme lösen, dass nach> einer Änderung auf einer Spur (z.B. A) immer erst eine Änderung auf der> anderen Spur (z.B. B) passiert, bevor sich Spur A wieder ändern kann.
Diese Annahme ist falsch. Also ist logischerweise das gesamte darauf
aufbauende Konzept auch falsch.