Forum: Mikrocontroller und Digitale Elektronik Drehgeber auswerten - Zählproblem


von Wuhu W. (wuhuuu2)


Lesenswert?

Hallo zusammen,

ich hab folgenden Code geschrieben, mit Hilfe der bekannten Threats von 
dem Thema.
Er funktioniert auch weitestgehenst....

Problem:
Beim Hochzählen pendelt er immer zwischen zwei Werten.
(Runterzählen funktioniert problemlos)

Falls mir jemand den Fehler sagen kann (oder sagen das kein Fehler 
drinnen ist und dieser woanders liegen muss) wäre ich sehr dankbar.


Randinformationen:
Atmega2560
KEY_PIN is PINL
Increment_A = 5
Increment_B = 3
F_CPU = 14745600
1
main-schleife
2
3
wert += enc_get()
4
5
wert an Uart senden
6
7
8
/***********************************************************************************/
9
10
// -128 .. +127
11
volatile  uint8_t  enc_last_state;  // "letzter Zustand"
12
volatile  uint8_t  enc_last_count;  // "Bitcombination beim letzten zählen"
13
volatile  uint8_t  enc_new_state;
14
volatile  int8_t  enc_delta;
15
16
17
void init_incremental_encoder()
18
{
19
  //Initializing 8-Bit Timer2 - incremental encoder
20
21
  TCCR2A = 0x00;    // normal mode
22
  TCCR2B = 0x04;  //prescaler 64 = 0x04
23
  TIMSK2 = 0x01;    // enable timer overflow Interrupt
24
  //TCNT2 = 0x00;    // count-parameter
25
26
enc_delta = 0;
27
enc_last_count = KEY_PIN & ((1<<Increment_A ) | (1<<Increment_B ));
28
29
return;
30
}
31
32
33
34
35
36
ISR( TIMER2_OVF_vect )
37
{
38
39
enc_new_state = KEY_PIN & ((1<<Increment_A ) | (1<<Increment_B ))  ;  // save state
40
41
// Change in State on both important positions?
42
if (  (enc_new_state ^ enc_last_count) == ((1<<Increment_A )|(1<<Increment_B))    ) 
43
  {
44
    // right or left turn?
45
    if(  (enc_new_state ^ enc_last_state) == (1<<Increment_B ) )
46
      {enc_delta += 1;}
47
    else
48
      {enc_delta -= 1;}
49
50
    enc_last_count = enc_new_state;    // save Bitcombination of last count
51
  }
52
enc_last_state = enc_new_state;        // save last state
53
54
}
55
56
57
58
59
60
int8_t enc_get()
61
{
62
  int8_t val;
63
  cli();
64
  val = enc_delta;
65
  enc_delta = 0;
66
  sei();
67
  return val;
68
}

von Wuhu W. (wuhuuu2)


Lesenswert?

Es gibt einen unerwünschten zustand, der bei jeder 2. umdrehung 
auftritt.
dabei wird
new_stat ^ last_state = 11
(nicht 01 oder 10 was normalerweise vorkommen sollte)

von MaWin (Gast)


Lesenswert?

Wuhu W. schrieb:
> (enc_new_state ^ enc_last_count) == ((1<<Increment_A )|(1<<Increment_B))

Eher

(enc_new_state ^ enc_last_count) & ((1<<Increment_A ) | (1<<Increment_B 
))

ist dann ungleich 0

Ganz allgemein würde ich
enc_new_state ^ enc_last_count)
weil es 2 mal benutzt wird in eine Variable tum

enc_change_state = (enc_new_state ^ enc_last_count)

denn es könnte sich (volatile) mittendrin ändern.

von Wuhu W. (wuhuuu2)


Lesenswert?

Hallo MaWin,

ich frage new_state und last_count nur einmal ab, das andere ist 
new_state und last_state.

Ich hab das mal versucht, aber es hat nicht geholfen, eher 
verschlimmert.
Denn dann wird ja auch in die Schleife gesprungen wenn nur eins von den 
beiden gesuchten bits gesetzt ist.

Trotzdem danke (=

von Wuhu W. (wuhuuu2)


Lesenswert?

Lösung gefunden.
Der Encoder hat folgenden "Graycode": 00-10-11-00-10-11-00
(ddm 427)

Lösungsweg:

Auswerten des vorherigen absoluten zustandes (o oder 1), um dann die 
Drehrichtung zu bestimmen

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Wuhu W. schrieb:
> Der Encoder hat folgenden "Graycode": 00-10-11-00-10-11-00

Das ist kein Gray, der sich dadurch auszeichnen würde, das bei jeder 
Zustandsänderung nur ein Bit wechselt. Entweder hat der Encoder einen 
Defekt (der Zustand 01 scheint ja nicht aufzutauchen), oder irgendwas 
anderes ist faul.

von Teo D. (teoderix)


Lesenswert?

Pin am Encoder vertauscht!

von Walter (Gast)


Lesenswert?

Teo Derix schrieb:
> Pin am Encoder vertauscht!

dann kommt nach 11 immer noch 00

von Teo D. (teoderix)


Lesenswert?

Walter schrieb:
> Teo Derix schrieb:
>> Pin am Encoder vertauscht!
>
> dann kommt nach 11 immer noch 00

Wenn Du das sagst, glaub ich das mal :)
(kein Sarkasmus! bin zu faul das durch zu denken :)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Wuhu W. schrieb:
> Threats
=Bedrohungen...
Thread=Faden

Walter schrieb:
>> Teo Derix schrieb:
>> Pin am Encoder vertauscht!
> dann kommt nach 11 immer noch 00
Dann zeig doch mal ein paar Fotos von deinem Aufbau. Wenn der Encoder so 
zählt  wie du dad geschrieben hast, kommt mit der geposteten Routine 
nichts sinnvolles raus. Die erwartet nämlich richtigen Graycode:
00-01-11-10-00-...

von Wuhu W. (wuhuuu2)


Angehängte Dateien:

Lesenswert?

Sorry das es so lang gedauert hat, hier meine funktinierende Lösung:

Wenn es um 2 stellen springt, also 00->11 oder 11->00, dann ergibt sich 
aus meiner links/rechts abfrage für beides eine 1, ich gehe zum else. 
Dort wird die letzte Absolute Position überprüft.

(Wenn er dann nur zwischen 2 zahlen pendelt, muss ich pins tauschen/ bzw 
+- in dieser else routine vertauschen)

Ich hoffe ihr versteht was ich mein

@Lothar Miller,  danke ;)

1
  
2
  // Change in State on both important positions?
3
  if (  (enc_1.buffer_new_state ^ enc_1.last_count) == ((1<<Increment_1_A )|(1<<Increment_1_B))    )
4
    {
5
      enc_1.time2 ++;    // for fast counting
6
7
      // right or left turn?
8
      if    (  (enc_1.buffer_new_state ^ enc_1.last_state) == (1<<Increment_1_B ) )
9
        {enc_1.delta += enc_1.add;}
10
11
      else if  (  (enc_1.buffer_new_state ^ enc_1.last_state) == (1<<Increment_1_A ) )
12
        {enc_1.delta -= enc_1.add;}
13
      else
14
      /**/
15
      //  This Part is normaly not required.But the rotary encoder in use has this Graycode: 00-10-11-00-10-11-00
16
      //  Therefore it evaluetes the last position to determine the turn-direction
17
      //  In case of failure, change + and - in the following
18
      /**/
19
        {
20
          if(enc_1.last_state != 0)
21
          enc_1.delta += enc_1.add;
22
          else
23
          enc_1.delta -= enc_1.add;  
24
        }
25
26
      enc_1.last_count = enc_1.buffer_new_state;    // save Bitcombination of last count
27
    }//if
28
29
  enc_1.last_state = enc_1.buffer_new_state;        // save last state

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.