07.12.2011
|
Drehgeber
am Atmega 32 anschließen !
|
Ein
Drehgeber sieht in
seiner einfachsten Form in der Regel wie ein Potentiometer aus ,also
etwa
wie ein Lautstärkeregler
am Radio, nur besteht der Drehgeber nicht wie das
Potentiometer aus
einen Widerstand sondern im einfachsten Fall aus einen
oder auch
mehreren Schalter (Kontakte) die bei einer
Umdrehung immer wieder geöffnet und
geschlossen werden .
So
entstehen
bei einer Achsen Umdrehung eine genau festgelegte Anzahl von Impulse.
Der von mir verwendete Drehgeber weist aber zwei interne Schalter
auf, deren Kontakte mit Kanal A und Kanal B bezeichnet sind
die genau um
90° versetzt Öffnen und Schließen, so kann der
Prozessor durch
geschickte Auswertung erkennen ob der Drehgeber
links oder rechts
herum dreht und anhand der vom Hersteller festgelegte feste Anzahl von
Impulse pro Umdrehung ist es auch
möglich eine
Streckenmessung damit
vorzunehmen.

|
|
Die
meisten Drehgeber in ihrer einfachsten Ausführung besitzen zwei
Schalter und somit drei Anschlüsse.
Kontaktmitte , Kanal A und Kanal B.
Die Kontakte sind genau um 90°
versetzt.
Mein erster
Versuch den Drehgeber an einen normalen Pin
anzuschließen hat keinen großen Erfolg weil die
Zählung sehr ungenau ist,
so das man mit den Impulse nicht viel
anfangen kann weil der Drehgeber beispielsweise eine 1 hat und beim
Schaltvorgang nur sehr
kurzzeitig auf 0 und dann wieder auf 1 springt,
ist der Prozessor nicht immer in der Lage den kurzzeitigen Unterschied
zu registrieren , weil er ja erst die Loop Phase
( also die eigentliche
Programmschleife ) komplett durchlaufen muss,
und
je nach dem wann er in seiner Schleife den Pin abfragt, er einmal den
Wechsel registriert und ein anderes mal eben nicht .
|
Also versuche ich die
Möglichkeit mit
externen Interrupts die Sache zu realisieren.
Der Atmega 32 stellt zwei
Interrupt Eingänge für Externe Interrupts zu Verfügung,
und zwar an den Anschlussbeinchen 16 (Interrupt 0) und 17 (
Interrupt 1).
Bei den Interrupt Eingänge wird nicht wie bei den
Standard Eingänge der Eingang innerhalb einer Schleife
ständig abgefragt, sondern sie arbeiten völlig
unabhängig der
Programmschleife, und halten die Programmschleife
bei Aktivierung sofort an und springen in das für sie vorgesehenes
Unterprogramm arbeitet dieses ab,
und lassen dann die Programmschleife
wieder laufen.
Das hat den Vorteil das sie sehr schnell und direkt
Einfluss auf das Programm nehmen.
|

|

|
Programmzeile
|
Beschreibung |
$regfile
"m32def.dat"
|
Definiert den Atmega als
Atmega 32 |
$crystal
=
1000000 |
Gibt die Quarzfrequenz an in
Herz |
$hwstack
=
32
|
Defaultwert 32 für
den Hardware Stack |
$swstack
=
10
|
Default 10 für den
Software Stack
|
Config
Lcd = 16 * 2 |
Definiert das LCD Display
als 2 Zeilen mal 16 Zeichen
|
Config
Lcdpin = Pin ,
Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.6 , Db7 = Portc.7 , Rs =
Portc.5 , E = Portc.4 |
Konfiguration fürs
Display Pin Anschlüsse
|
Dim
Kanal_aa As Byte |
Variable für Kanal A
|
Dim
Kanal_bb As Byte |
Variable für Kanal B
|
On
Int0
Kanal_a |
Interrupt Routine für
Interrupt 1 festlegen |
On
Int1
Kanal_b
|
Interrupt Routine für
Interupt 2 festlegen |
Portd
=
&B00001100 |
Pull Down an für
Interrupt Eingänge
setzen
|
Mcucr
=
&B00001010 |
Interrupts sollen auf H/L
Flanke reagieren |
Gicr =
&B11000000 |
Interrupt 0 und 1 einschalten |
Sreg.7
=
1 |
Interrupts Global freischalten |
Do |
Anfang Hauptprogramm
|
Gosub
Anzeige |
|
............
|
Platz für weitere
Programmzeilen
|
Loop |
Ende Hauptprogramm
|
|
|
Anzeige: |
Unterprogramm Displayanzeige
|
Cls
|
Display Löschen |
Locate
1 , 1 |
Definiert Displayausgabe Zeile
1 Spalte 1
|
Lcd "A
= " ; Kanal_aa |
Displayausgabe der Variable
für Kanal A
|
Locate
1 , 10 |
|
Lcd "B
=" ; Kanal_bb |
|
Locate
2 , 1 |
|
Waitms
50 |
|
Return |
Unterprogramm Ende und
zurück zum Aufruf
|
|
|
Kanal_a:
|
Unterpogramm wird bei
Interrupt 0 angesprungen
|
Kanal_aa
=
Kanal_aa
+
1
|
|
If
Pind.2 = 0 And Pind.3 = 1 Then Kanal_aa = Kanal_aa - 1
|
|
If
Pind.2 = 0 And Pind.3 = 0 Then Kanal_aa = Kanal_aa + 1
|
|
Return
|
Unterprogramm Ende
|
|
|
Kanal_b: |
Unterprogramm wird bei
Interrupt 1 angesprungen
|
Kanal_bb
=
Kanal_bb
-
1 |
|
Return |
Unterprogramm Ende
|
Drehrichtung des
Drehgebers feststellen !
|
|
Wie erkennt man nun
ob der Regler rechts oder links herum gedreht wird ?
Wie gehen einmal von einen fiktiven Anfangswert aus, beispielsweise die
grüne senkrechte gepunktete Linie, weiter haben wir im Programm
angegeben das
die Erkennung des Schaltvorganges vor sich gehen soll wenn eine Flanke
von 1 nach 0 statt findet.
Wie gehen also davon aus das wir den Drehregler links herum drehen,
dann wird die nächste Flanke von H nach L an der Blauen
senkrechten
Linie erkannt, wenn wir dann minimal weiter drehen, haben
wir am Kanal A=0 und Kanal B=0
Würden wir von der Grünen Linie aus rechts herum drehen so
würde die nächste Flanke von 1 nach 0 an der Roten Linie
erkannt und wir
hätten im weiteren Verlauf am Kanal A =0 und am
Kanal B=1
Wir stellen also fest !
Liegt an Kanal A eine Null und an Kanal B eine Null , so
drehen wir links herum, haben wir am Kanal A eine Null und am Kanal B
eine Eins dann drehen wir rechts
herum.
Beim auswerten des Drehgebers der im allgemeinen auch als
Incrementalgeber bezeichnet wird, passieren oft Auswertungsfehler
dadurch das die Schalter ja rein mechanisch sind
und somit zum prellen neigen. Ja nach Software und auch nach Hardware wird das prellen dann mitgezählt.
Dies kann man verhindern indem man Softwaremäßig die Auswertung etwas
verzögert , eben so lange bis das prellen beendet ist, oder
man setzt parallel zu den Kontakten einen kleinen Kondensator, so von etwa 10 nF.
|
Aktualisiert 01.09.2023
|
Copyright by ms 2009
|