Forum: Mikrocontroller und Digitale Elektronik Dreahimpulsgeber auswertung


von Ephraim H. (ephi)


Lesenswert?

Ich bin gerade etwas am verzeifeln mit meinem Drehencoder.
Es handelt sich um den STEC12 von reichelt (ALPS).

Ich versuche mich mit Peter Dannegers routinen aus dem Artikel.

Hier meine Umsetzung:
1
// rotary encoder header
2
#define ENC_PORT    PORTC
3
#define ENC_DDR      DDRC
4
#define ENC_PIN      PINC
5
#define ENC_A      6
6
#define ENC_B      7
7
#define PHASE_A      (ENC_PIN & 1<<PC6)
8
#define PHASE_B      (ENC_PIN & 1<<PC7)
9
10
// abschnitt der init routine
11
ENC_DDR &= ~(1<<ENC_A) | ~(1<<ENC_B);  // rotary encoder pins as inout
12
ENC_PORT |= (1<<ENC_A) | (1<<ENC_B);  // pull ups on
13
  
14
uint8_t new = 0;
15
if(PHASE_A)
16
  new = 3;
17
if(PHASE_B)
18
  new ^= 1;
19
last = new;
20
enc_delta = 0;
21
22
TCCR1B = (1<<WGM12) | (1<<CS12) | (1<<CS10);  // CTC Mode, F_CPU/1024
23
OCR1A = (uint16_t)(F_CPU / 1024 * 1e-3 - 0.5);  // 1ms
24
TIMSK1 = (1<<OCIE1A);        // enable timer interrupt
25
26
27
// ISR
28
ISR(TIMER1_COMPA_vect)
29
{  
30
  int8_t new = 0, diff;
31
  
32
  if(PHASE_A)
33
    new = 3;
34
  if(PHASE_B)
35
    new ^= 1;            // convert gray to binary
36
  diff = last - new;          // difference last - new
37
  if(diff & 1)
38
  {                  // bit 0 = value (1)
39
    last = new;            // store new as next last
40
    enc_delta += (diff & 2) - 1;  // bit 1 = direction (+/-)
41
  }
42
  
43
  // 7 segment multiplexing
44
  switch(tr)
45
  {
46
    case 0:
47
      PORT_TRANS |= (1<<TRANS_4);
48
      PORT_DISP = digit[1];
49
      PORT_TRANS &= ~(1<<TRANS_1);
50
      tr = 1;
51
      break;
52
    case 1:
53
      PORT_TRANS |= (1<<TRANS_1);
54
      PORT_DISP = digit[0];
55
      PORT_TRANS &= ~(1<<TRANS_2);
56
      tr = 2;
57
      break;
58
    case 2:
59
      PORT_TRANS |= (1<<TRANS_2);
60
      PORT_DISP = digit[2];
61
      PORT_TRANS &= ~(1<<TRANS_3);
62
      tr = 3;
63
      break;
64
    case 3:
65
      PORT_TRANS |= (1<<TRANS_3);
66
      PORT_DISP = digit[3];
67
      PORT_TRANS &= ~(1<<TRANS_4);
68
      tr = 0;
69
      break;
70
  }
71
}
72
73
// regelmäßige Abfrage in der Hauptschleife:
74
tmr = (uint8_t)encode_read1();

Hab es auch schon mit encode_read2 und 4 versucht.
tmr bleibt immer 0.

Eigentlich möchte ich mit dem encoder in tmr nur einen wert von 0...30 
einstellen können. geht das irgendwie auch einfacher?

Es handelt sich um einen ATMega644p mit 16Mhz externem Quarz.


Kann mir jemand helfen?

von Boris H. (eddi)


Angehängte Dateien:

Lesenswert?

Bei mir sieht das Ganze für eine Lampensteuerung mit PWM so aus.
Einstellbar ist der Wert pwm von 0 bis enc_end

von Ephraim H. (ephi)


Lesenswert?

okay, nach deiner Methode funktionierts, danke!

von Peter D. (peda)


Lesenswert?

Ephraim Hahn schrieb:
> Hab es auch schon mit encode_read2 und 4 versucht.
> tmr bleibt immer 0.

Das Problem ist, daß der GCC in den Standardeinstellungen kleine 
Funktinen inlined und dann muß man enc_delta als volatile definieren, 
sonst wird das neu lesen wegoptimiert.


Peter

von Ephraim H. (ephi)


Lesenswert?

enc_delta war bei mir aber volatile (hab die definitionen vergessen zu 
posten)

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.