Drehgeber auswerten - Zählproblem

OP #3974514
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
}
Gast #3975025
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.
OP #3976101
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 (=
Moderator (Firma: Titel) Persönliche Seite #3977378
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-...
OP #3986808
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
Angehängte Dateien:

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 11 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.