Forum: Mikrocontroller und Digitale Elektronik Mausrad Drehgeber


von Vlad T. (vlad_tepesch)


Lesenswert?

Hi,
Ich habe hier einen mechanischen Drehgeber aus einem Mausrad, den ich 
gerne recyclen möchte.

das Ding hat 3 Füße.
Ich habs jetzt einfach so angeschlossen, dass ich an den Mittleren masse 
lege und mit die anderen jeweils an einen Pin meines mega8 mit 
aktiviertem internenen Pullup.

dann habe ich das Muster geloggt, was sich ergibt, wenn man den 
Drehgeber in die eine oder die andere Richtung dreht.

Folgendes kommt dabei raus:
1
/*
2
  Note:
3
   _      _____
4
  | |    |     |  > rechts
5
  | |=   |  O  |
6
  |_|    |_____|  > links
7
  |      |  |  |
8
  |      |  |  |
9
         0  G  1
10
11
12
  (rechts rum: 11 -> 10   ->   00 -> 11)
13
  (links  rum: 11 -> 00   ->   10 -> 11)
14
15
       turn right  turn right     turn left   turn left
16
           |  |     |  |            |  |        |  | 
17
    _______           _______________              _______
18
  0        |_________|               |____________|
19
    _________         _______________            __________
20
  1          |_______|               |__________|
21
22
23
-->
24
25
   \n| 0  0  1  1
26
   o\| 0  1  1  0
27
  ---+------------
28
  00 | x  l  r  
29
  01 |           
30
  11 | l  r  x   
31
  10 |
32
 */
Anstatt des loggings hab ich in der ISR (selbe Frequenz) nun die 
Auswertung versucht um im Programm rechts/links auswerten zu können und 
dazu obige Tabelle umgesetzt:
1
typedef enum Wheel
2
{
3
  Wheel_none,
4
  Wheel_left,
5
  Wheel_right
6
}Wheel;
7
8
static volatile Wheel s_wheel;
9
10
ISR(TIMER0_OVF_vect)
11
{
12
  static uint8 old=3;
13
  if( s_wheel == Wheel_none ){
14
    uint8 newVal = (PIND>>2)&3;
15
    if(    ((old == 0)  && (newVal == 2))
16
        || ((old == 3)  && (newVal == 0))
17
       ){
18
       s_wheel = Wheel_left;
19
    }else if(     ((old == 0)  && (newVal == 3))
20
               || ((old == 3)  && (newVal == 2)) 
21
             ){
22
       s_wheel = Wheel_right;
23
    }
24
    old = newVal;
25
  }
26
27
28
}



Mein Problem ist nun, dass ich immer nur Wheel_right bekomme.

Ich bin langsam ratlos
Wär nett, wenn von euch mal jemand drüber schaut.
Ist wahscheinlich ein total sinnloser Fehler, aber ich kriegs nicht.

Danke im Voraus!
Vlad

von MaWin (Gast)


Lesenswert?

Aus irgendeinem grund evrstehe ich deine durchaus sehr ausführliche 
Beschreibung nicht, vielleicht liegt's daran.

       turn right  turn right     turn left   turn left
           |  |     |  |            |  |        |  |
    ______         ___________________            ______
  0        |_______|                   |__________|
    _________         _____________            _________
  1           |_______|             |__________|

   \n| 0  0  1  1
   o\| 0  1  1  0
  ---+------------
  00 | 0  l  X  r
  01 | r  0  l  X
  11 | X  r  0  l
  10 | l  X  r  0


 ISR(TIMER0_OVF_vect)
{
    static uint8 old=3;
    uint8 newVal = (PIND>>2)&3;
    if(((old == 0)  && (newVal == 1))
    || ((old == 1)  && (newVal == 3))
    || ((old == 3)  && (newVal == 2))
    || ((old == 2)  && (newVal == 0)))
    {
       pos++;
    }
    else if(((old == 0)  && (newVal == 2))
         || ((old == 1)  && (newVal == 0))
         || ((old == 3)  && (newVal == 1))
         || ((old == 2)  && (newVal == 3)))
    {
       pos--;
    }
    else if(newVal != old) ; // Fehlerkondition

    old = newVal;
  }

von Vlad T. (vlad_tepesch)


Lesenswert?

Also das Diagramm war richtig:
1
/*
2
       turn right  turn right     turn left   turn left
3
           |  |     |  |            |  |        |  | 
4
    _______           _______________              _______
5
  0        |_________|               |____________|
6
    _________         _______________            __________
7
  1          |_______|               |__________|
8
9
*/
Der bereich zwischen zwei den |  | kennzeichnet den Vorgang wärend de 
Drehens um eine Stufe.

wenn ich eine Einrastung (hört sich doof an, wie nennt man das?) nach 
rechts drehe, gibts diese stufe, dannch bleiben beide low.

wenn ich dann eine weitere Einrastung drehe, gehen beide sofort auf high

Bei links rum ist es logischer weise genau umgedreht.

Die Tabelle habe ich nicht komplett ausgefüllt, da von den Stufen nur 
die erste Flanke erkennen wollte, was ja eindeutig sein sollte.
rechts rum:
von  11 -> 10  oder von 00 -> 11

links rum:
von 11 -> 00 oder von 00 -> 10


Nach deinem Code würde er an einer Sufe immer 2 Positionen zählen

von Klaus W. (mfgkw)


Lesenswert?

Da vermute ich doch, daß deine mechanische "Einrastung" zu grob ist.
Ich gehe davon aus, daß bei einmal Rasten gelegentlich auch gleich
zwei optische Positionssprünge erfolgen.

Du hast in deinem Diagramm zwar gelegentlich beide Pegelwechsel
direkt übereinander gezeichnet, aber in Wirklichkeit sind die leicht
versetzt. Bei den Encodern gibt es zu einem Zeitpunkt nur einen
Pegelwechsel.

Wenn du (zeitlich) genauer hinschaust, wirst du das sehen (so
wie MaWin das gezeichnet hat)...

von Vlad T. (vlad_tepesch)


Lesenswert?

>Ich habe hier einen mechanischen Drehgeber aus einem Mausrad, den ich
>gerne recyclen möchte.
nix optik, das ding ist rein mechanisch.

also dieses Signal bekomme ich recht eindeutig.
wenn es daran liegen würde müsste ich bei mehreren Versuchen 
unterschiedliche Werte bekommen. Dem ist nicht so.

ich hab 12Mhz quarz und nen timerprescaler von 64. macht eine Samplerate 
von 732, das ist nicht so viel, allerdings sind die Stufen so 5-7 
Samples breit, also bin ich davon ausgegangen, das da auf der anderen 
Seite wirklich nix ist.


Und da die Auswertung in der Selben ISR mit gleicher Frequenz wie vorher 
das Logging gemacht wird, sollte es doch gehen, oder nicht?

Werd dann aber noch mal den anderen Timer frei machen und es mit nem 
prescaler von 16 Probieren. Bei 8 läuft der Puffer über, da kommt das 
SD-logging nicht hinterher


Aber danke erstmal
MfG,
Vlad

von Klaus W. (mfgkw)


Lesenswert?

Du musst unbedingt jeden Pegelwechsel mitbekommen.
Mit einer festen Frequenz abfragen ist vielleicht suboptimal, weil
du viel Rechenzeit verbrätst und dann doch mal einen Wechsel
übersiehst.
Geschickter ist es, auf die beiden Pegel einen Interrupt anzusetzen
und das Zählen in der/n Interruptroutine(n) zu machen.

von gast (Gast)


Lesenswert?

die mechanischen sind soweit ich weiß alle meist nach dem greycode  in 
ihrer funktion
also so wie jeder belibige andere drehencoder auch

von Vlad T. (vlad_tepesch)


Lesenswert?

Klaus Wachtler schrieb:
> Du musst unbedingt jeden Pegelwechsel mitbekommen.
> Mit einer festen Frequenz abfragen ist vielleicht suboptimal, weil
> du viel Rechenzeit verbrätst und dann doch mal einen Wechsel
> übersiehst.
> Geschickter ist es, auf die beiden Pegel einen Interrupt anzusetzen
> und das Zählen in der/n Interruptroutine(n) zu machen.

Ich wollts erst mal überhaupt hinbekommen.
Hab auch schon darüber nachgedacht, das an einen ext. INT zu hängen, 
aber da gibt es dann das Problem der Synchronisation der routinen.
Außerdem wollt ich mir zumindest einen der Int-Pins möglichst frei 
halten.
Mit der derzeitigen Abtastfrequenz könnt ich noch leben, wenn ich das 
ding polle. würd dann die ISR noch optimieren und eventuell in asm 
schreiben.

ich hab vor, das ding als eingabegerät zu benutze (menu-avigation, 
eisntellung von werten). Ich will das so montiernen, dass man einen 
drehknopf hat, den man dann noch drücken kann.

konnt solche Knöpfe nirgends finden (zumindest nicht zu vertretbaren 
Preisen)

>die mechanischen sind soweit ich weiß alle meist nach dem greycode  in
>ihrer funktion
>also so wie jeder belibige andere drehencoder auch

Hab sowas noch nie benutzt, bin mir auch nicht sicher, ob ich den 
richtig angeschlossen habe. Hab leider das PCB nicht mehr um 
rachzuschauen.

aussehen tut er in etwas so:
http://www.fdm-ware.de/powermate/pm3.jpg

von Klaus W. (mfgkw)


Lesenswert?

Man kann auch mit einem externen Int. auskommen und dementsprechend
nur eine ISR nehmen, wenn man die beiden Signalketten an beliebige
Pins hängt, und an Int0 oder Int1 einfach das XOR der beiden
Signale.
Den Interrupt aktiviert man nun für sowohl steigende als auch fallende
Flanke (geht bei neueren AVR wie Mega8, nicht bei den alten wie
At90S2313). Die ISR wird dann bei jedem Wechsel eines der beiden
Signale aktiviert, liest die beiden eigentlichen Signale und zählt
entsprechend.

Encoder zur Eingabe mit Drehknöpfen gibt es abgesehen davon auch
fertig zu kaufen, inkl. Drucktaster...

von Vlad T. (vlad_tepesch)


Lesenswert?

>Encoder zur Eingabe mit Drehknöpfen gibt es abgesehen davon auch
>fertig zu kaufen, inkl. Drucktaster...

nenn mir mal ein paar quellen
Ich hab keine gefunden (reichelt, Conrad, Pollin, westfalia).
Ich hätt halt schon gern was mechanisches, da die optischen ja selbst 
auch wieder strom verbrauchen.

von P. S. (Gast)


Lesenswert?

"Drehimpulsgeber" bei Reichelt, 15 Treffer. Grob die Haelfte davon sind 
welche, der Rest Knoepfe und Zubehoer.

Btw: Versuch bei deinem Drehgeber mal andere Beschaltungsvarianten zu 
messen und zeig mal die Impulsdiagramme davon. Vieleicht ist er doch nur 
falsch angeschlossen.

von spess53 (Gast)


Lesenswert?

Hi

>nenn mir mal ein paar quellen

reichelt, Conrad, Pollin

Suche mal 'Drehimpulsgeber', 'Encoder', 'inkremental Drehgeber'.

MfG Spess

von Guido Körber (Gast)


Lesenswert?

Dann nimm doch mal Elektronikhändler statt Resteverwerter: Segor, 
Farnell, RS...

von Klaus W. (mfgkw)


Lesenswert?


von Falk B. (falk)


Lesenswert?

@  Klaus Wachtler (mfgkw)

>Man kann auch mit einem externen Int. auskommen und dementsprechend
>nur eine ISR nehmen, wenn man die beiden Signalketten an beliebige
>Pins hängt, und an Int0 oder Int1 einfach das XOR der beiden
>Signale.
>Den Interrupt aktiviert man nun für sowohl steigende als auch fallende
>Flanke (geht bei neueren AVR wie Mega8, nicht bei den alten wie
>At90S2313). Die ISR wird dann bei jedem Wechsel eines der beiden
>Signale aktiviert, liest die beiden eigentlichen Signale und zählt
>entsprechend.

Genau DAS macht man NICHT! Warum? Siehe Drehgeber

MFG
Falk

von Vlad T. (vlad_tepesch)


Lesenswert?

> Suche mal 'Drehimpulsgeber', 'Encoder', 'inkremental Drehgeber'.
ja die Begriffe haben mir gefehlt, weswegen ich direkt über die 
Kategorien gesucht hatte

ich hab natürlich nicht unter "Potis und Trimmer" gesucht. sondern 
"drehschalter"

http://www.reichelt.de/?;ACTION=3;LA=444;GROUP=B29;GROUPID=3714;ARTICLE=73923;START=0;SORT=user;OFFSET=100;SID=153g2D5qwQAQ8AABqIRkM18664388e8b35288c4e28f4574133fe0

sieht ganz gut aus.
Danke!

>Btw: Versuch bei deinem Drehgeber mal andere Beschaltungsvarianten zu
>messen und zeig mal die Impulsdiagramme davon. Vieleicht ist er doch nur
>falsch angeschlossen.

Ich hab jetzt mal alle drei Kombinationen durchprobiert. und Tatsächlihc 
in einer (natürlich der letzt gewählten) gibt er folgendes aus 
(Drehrichtung rechts)

11    -> 10 ->     00
oder
00    -> 01 ->     11


für links halt jeweils umgedreht.

mein Code gibt trotzdem nur rechts aus:
1
ISR(TIMER0_OVF_vect)
2
{
3
  static uint8 old=3;
4
  uint8 newVal = (PIND>>2)&3;
5
  if( s_wheel == Wheel_none ){
6
    if(    ((old == 0)  && (newVal == 1))
7
        || ((old == 3)  && (newVal == 2))
8
       ){
9
       s_wheel = Wheel_right;
10
    }else if(     ((old == 0)  && (newVal == 2))
11
               || ((old == 3)  && (newVal == 1)) 
12
             ){
13
       s_wheel = Wheel_left;
14
    }
15
    old = newVal;
16
  }
17
}


Überlegung im Code war halt, das jede der Flanken eindeutig ist und ich 
nur die erste auswerten muss.
Würd ich beide auswerten, würde ich mit drehen um reine Rastung ja immer 
zwei impulse kriegen (falls das Hauptprogramm schnell genug die Variable 
zurücksetzt).

von MaWin (Gast)


Lesenswert?

> Also das Diagramm war richtig:

In dem Sinne, daß sich an einer Stelle beide Signale gleichzeitig (na 
gut, gleichzeitig gibt es nie, nur mal der eine kurz vor dem anderen, 
und mal der andere kurz vor dem einen) ändern ?

Dann ist dein Drehgeber kaputt.

> Überlegung im Code war halt,
> das jede der Flanken eindeutig ist
> und ich nur die erste auswerten muss.

Und was lernst du jetzt daraus,
daß dein Programm nicht richtig zählt?

Genau, deine Überlegung war halt einfach falsch.

von Vlad T. (vlad_tepesch)


Lesenswert?

Ahhhhh

kopf gegen Wand schlag



meine ISR ist richig und funktioniert super!

ich hab im hauptprogramm die Variable vor der Auswertung auf Wheel_none 
gesetzt.
1
    if(s_wheel != Wheel_none)
2
    {
3
      // s_wheel = Wheel_none; <- hab ich dämlicherweise hier gemacht
4
      if( s_wheel==Wheel_left ){
5
        --number;
6
      }else{
7
        ++number;             // und damit immer hochgezählt
8
      }
9
      s_wheel = Wheel_none;   // anstatt  hier
10
      lcd_init(LCD_DISP_ON);
11
      utoa(number, (char*)s_logBuf, 10); 
12
      lcd_puts((char*)s_logBuf);        
13
    }

Edit:

Noch mal danke an Alle!

Vor allem für die Hilfe bei der Suche nach kaufbaren encodern - Ich wär 
nie darauf gekommen, die dinger bei "Potis und Trimmer" zu suchen


Danke!
Vlad

Edit:
http://www.pollin.de/shop/shop.php?cf=detail.php&pg=NQ==&a=Njg2OTU3OTk=

von Klaus W. (mfgkw)


Lesenswert?

Falk Brunner schrieb:
> @  Klaus Wachtler (mfgkw)
>
>>Man kann auch mit einem externen Int. auskommen und dementsprechend
>>nur eine ISR nehmen, wenn man die beiden Signalketten an beliebige
>>Pins hängt, und an Int0 oder Int1 einfach das XOR der beiden
>>Signale.
>>Den Interrupt aktiviert man nun für sowohl steigende als auch fallende
>>Flanke (geht bei neueren AVR wie Mega8, nicht bei den alten wie
>>At90S2313). Die ISR wird dann bei jedem Wechsel eines der beiden
>>Signale aktiviert, liest die beiden eigentlichen Signale und zählt
>>entsprechend.
>
> Genau DAS macht man NICHT! Warum? Siehe Drehgeber
>
> MFG
> Falk

Wenn man entprellen will/muß, darf man das nicht machen; eingesehen.
Bisher hatte ich einmal einen einfachen Drehgeber zur Menüsteuerung
in der Hand, da ging es gut ohne (vielleicht weil man nicht viel
dreht?). Bei den "echten" teuren Drehgebern mit optischer Abtastung
und eigener Logik war dagegen das Signal bisher immer so sauber,
daß es kein Gezappel gab.

Insofern würde ich es nicht so pauschal sagen, wie man es IMMER
oder NIE macht.

Daß es im Einzelfall falsch sein kann, glaube ich dir dagegen
durchaus.

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.