encoder STEC12E08

Gast #2540951
Lesenswert?

Hallo,
Ich nutze die Encoder-Funktion von Peter Dannegger zusammen mit einem
Drehencoder vo Reichelt,Aber leider zählt er nicht richtig,pro Rastung 
sind manchmal Sprünge von 100 drin.
Den Encoder-Wert gebe ich erstmal nur zum Terminal aus.
kann mir da einer Weiterhelfen
mfg

Leider kann ich das Datenblatt nicht Anhängen
1
/************************************************************************/
2
/*                                                                      */
3
/*                      Reading rotary encoder                     */
4
/*                      one, two and four step encoders supported  */
5
/*                                                                      */
6
/*              Author: Peter Dannegger                                 */
7
/*                                                                      */
8
/************************************************************************/
9
#include <avr\io.h>
10
#include <avr\interrupt.h>
11

12
        // target: ATmega16
13
//------------------------------------------------------------------------
14

15
#define  XTAL    8e6      // 8MHz
16

17
#define PHASE_A    (PINA & 1<<PA1)
18
#define PHASE_B    (PINA & 1<<PA3)
19

20

21

22

23
int8_t enc_delta;        // -128 ... 127
24
 uint8_t sec = 0;
25

26
void encode_init( void )
27
{
28
  TCCR0 = 1<<WGM01^1<<CS01^1<<CS00;    // CTC, XTAL / 64
29
  OCR0 = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5);  // 1ms
30
  TIMSK |= 1<<OCIE0;
31
}
32

33

34
ISR( TIMER0_COMP_vect )        // 1ms for manual movement
35
{
36
  static int8_t last;
37
  int8_t new, diff;
38

39
  new = 0;
40
  if( PHASE_A )
41
    new = 3;
42
  if( PHASE_B )
43
    new ^= 1;          // convert gray to binary
44
  diff = last - new;        // difference last - new
45
  if( diff & 1 ){        // bit 0 = value (1)
46
    last = new;          // store new as next last
47
    enc_delta += (diff & 2) - 1;    // bit 1 = direction (+/-)
48
  }
49
}
50

51

52
int8_t encode_read1( void )      // read single step encoders
53
{
54
  int8_t val;
55

56
  cli();
57
  val = enc_delta;
58
  enc_delta = 0;
59
  sei();
60
  return val;          // counts since last call
61
}
62

63

64
int8_t encode_read2( void )      // read two step encoders
65
{
66
  int8_t val;
67

68
  cli();
69
  val = enc_delta;
70
  enc_delta &= 1;
71
  sei();
72
  return val >> 1;
73
}
74

75

76
int8_t encode_read4( void )      // read four step encoders
77
{
78
  int8_t val;
79

80
  cli();
81
  val = enc_delta;
82
  enc_delta &= 3;
83
  sei();
84
  return val >> 2;
85
}
86

87

88
int main( void )
89
{
90
  int32_t val = 0;
91
  char encBuffer[10];
92
  encode_init();
93
  sei();
94

95
  for(;;){
96

97
   val += encode_read1();
98

99
  if(val > 0){
100
    val--;
101
    sec--;
102
  }else if(val < 0){
103
    val++;
104
    sec++;
105
   sprintf( encBuffer, "%3d", sec );
106
   uart_puts( encBuffer );    
107
  }
108
}
Gast #2541024
Lesenswert?

Na Falk, jetzt nicht mehr Bildformate sondern Netiquette? Ist das 
überhaupt ein Wort?

>>Selber schuld, wenn man den Code abtippt, anstatt ihr einfach 1:1 zu
>>kopieren.<<

Wer anderen eine Grube gräbt. Mann soll also nett sein und sich auch 
noch dumm belehren lassen - was ist hier nur los?
Komm mal langsam wieder runter - das kommt davon wenn man hier zu lange 
im Forum ist, das macht krank!

@Wolfgang
Wenn er teilweise springt oder 2 Schritte zählt, liegt das an den 
mechanischen Rastungen. Du solltest dann mal den code mit Tabelle 
nutzen. Steht auch im tutotrial.

Hast du den code aus dem Tut oder aus dem Thread? Lies mal das tut.

Gruß,
JJ

PS.: wo das springen um 100 her kommt, kann ich nun aus dem stehgreif 
auch nicht sagen, bedenke dass der Zähler vorzeichenbehaftet ist!
Gast #2541098
Lesenswert?

Die Hardware Funktioniert,Pull-Ups habe ich aktiviert trozdem hauts 
nicht hin.

1
************************************************************************/
2
/*                                                                      */
3
/*                      Reading rotary encoder                      */
4
/*                      one, two and four step encoders supported   */
5
/*                                                                      */
6
/*              Author: Peter Dannegger                                 */
7
/*                                                                      */
8
/************************************************************************/
9
#include <avr/io.h>
10
#include <avr/interrupt.h>
11
#include "uart.h"
12
                // target: ATmega16
13
//------------------------------------------------------------------------
14
 
15
#define XTAL        8e6         // 8MHz
16
 
17
#define PHASE_A     (PINA & 1<<PA1)
18
#define PHASE_B     (PINA & 1<<PA3)
19
 
20
 
21
volatile uint8_t sec ;  
22
volatile int8_t enc_delta;          // -128 ... 127
23
static int8_t last;
24
 
25
 
26
void encode_init( void )
27
{
28
  int8_t new;
29
 
30
  new = 0;
31
  if( PHASE_A )
32
    new = 3;
33
  if( PHASE_B )
34
    new ^= 1;                   // convert gray to binary
35
  last = new;                   // power on state
36
  enc_delta = 0;
37
  TCCR0 = 1<<WGM01^1<<CS01^1<<CS00;     // CTC, XTAL / 64
38
  OCR0 = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5);   // 1ms
39
  TIMSK |= 1<<OCIE0;
40
}
41
 
42
 
43
ISR( TIMER0_COMP_vect )             // 1ms for manual movement
44
{
45
  int8_t new, diff;
46
 
47
  new = 0;
48
  if( PHASE_A )
49
    new = 3;
50
  if( PHASE_B )
51
    new ^= 1;                   // convert gray to binary
52
  diff = last - new;                // difference last - new
53
  if( diff & 1 ){               // bit 0 = value (1)
54
    last = new;                 // store new as next last
55
    enc_delta += (diff & 2) - 1;        // bit 1 = direction (+/-)
56
  }
57
}
58
 
59
 
60
int8_t encode_read1( void )         // read single step encoders
61
{
62
  int8_t val;
63
 
64
  cli();
65
  val = enc_delta;
66
  enc_delta = 0;
67
  sei();
68
  return val;                   // counts since last call
69
}
70
 
71
 
72
int8_t encode_read2( void )         // read two step encoders
73
{
74
  int8_t val;
75
 
76
  cli();
77
  val = enc_delta;
78
  enc_delta = val & 1;
79
  sei();
80
  return val >> 1;
81
}
82
 
83
 
84
int8_t encode_read4( void )         // read four step encoders
85
{
86
  int8_t val;
87
 
88
  cli();
89
  val = enc_delta;
90
  enc_delta = val & 3;
91
  sei();
92
  return val >> 2;
93
}
94
 
95
 
96
int main( void )
97
{
98
  int32_t val = 0;
99
 char encBuffer[10];
100
 //Pull-Up einschalten
101
  DDRA  &= ~(1<<PHASE_A);  
102
  PORTA |= (1<<PHASE_A);   
103
  DDRA  &= ~(1<<PHASE_B);  
104
  PORTA |= (1<<PHASE_B);   
105
  encode_init();
106
  sei();
107
 
108
  for(;;){
109
  val += encode_read1();
110

111
  if(val > 0){
112
    val--;
113
    sec--;
114

115
  }  else if(val < 0){
116
     val++;
117
     sec++;
118

119
 }
120
 
121
  sprintf( encBuffer, "%3d", sec );
122
  uart_puts( encBuffer );  }
123
}
#2541136
Lesenswert?

@  wolfgang (Gast)

>Die Hardware Funktioniert,Pull-Ups habe ich aktiviert

Nö.


>#define PHASE_A     (PINA & 1<<PA1)
>#define PHASE_B     (PINA & 1<<PA3)

> //Pull-Up einschalten
>  DDRA  &= ~(1<<PHASE_A);
>  PORTA |= (1<<PHASE_A);
>  DDRA  &= ~(1<<PHASE_B);
>  PORTA |= (1<<PHASE_B);

besser so.

1
  // Inputs
2
  DDRA  &= !((1<<PA1) | (1<<PA3));  
3
  PORTA |= (1<<PA1) | (1<<PA3);

Siehe auch Bitmanipulation. Hier ist leider eine Mischung aus den 
Bitdefinitionen drin.

http://www.mikrocontroller.net/articles/Bitmanipulation#Bitmanipulation_beim_MSP430

MFG
Falk
Gast #2541312
Lesenswert?

aus dem Artikel:

Im wahren Leben gibt es immer wieder Dinge, welche der Theorie zwar 
widersprechen, dennoch weit verbreitet sind. Da machen Drehgeber keine 
Ausnahme. Gerade die heute so beliebten Drehgeber für manuelle Bedienung 
sind in großer Anzahl von verschiedenen Herstellern verfügbar. Umso 
merkwürdiger ist es, dass hier die Rastpunkte oft genau auf dem 
Pegelwechsel einer Spur liegen, meist Spur B. So zum Beispiel beim 
Drehgeber EC11E15244B2 von Alps, welcher u.a bei Pollin ehältlich ist.

Bei diesem Drehgeber kommt es bei der klassischen, eigentlich soliden 
Auswertung zu dem Effekt, dass der Drehgeber in Ruhelage auf einem 
Rastpunkt pendeln kann. Damit erhält das Programm sporadisch einen 
Schritt vor und zurück. Auch wenn sich die Auswertung daran nicht 
verschluckt, so ist dieses Pendeln doch ärgerlich, denn eine 
Menusteuerung würde dann komische Sachen machen.


Schau dir mal das zweite Codeposting mit dieser:

int8_t table[16] PROGMEM = {0,0,-1,0,0,0,0,1,1,0,0,0,0,-1,0,0};

Tabelle an.

Springt er um 100 oder vielleicht 127? Wie sieht deine Konvertierung von 
int8 auf die serielle ss aus?

JJ
#2541388
Lesenswert?

wolfgang schrieb:
> Aber leider zählt er nicht richtig,pro Rastung
> sind manchmal Sprünge von 100 drin.

Das glaube ich Dir nicht. Wo soll die 100 denn herkommen?
Vermutlich ein Ablesefehler, da Du die Ausgaben ohne einen Trenner 
aneinander reihst.
Versuch mal:
1
  sprintf( encBuffer, "%4d\n", sec );
2
  _delay_ms( 200 );

Rastende Enkoder machen 2 oder 4 Phasenwechsel, nimm also die dazu 
passende Auslesefunktion.


Peter
#2541392
Lesenswert?

@  Peter Dannegger (peda)

>Warum sind 4 Bytes mehr Code besser?

Lies mal das Original vom OP. Dort wird doppelt gemoppelt Bits 
geschoben, nicht wirklich im Sin des Erfinders.

>Und außerdem ist das falsch.
>Der ! Operator liefert nur 0 oder 1.

Jaja, Flüchtigkeitsfehler.

1
   DDRA  &= ~((1<<PA1) | (1<<PA3));
2
   PORTA |= (1<<PA1) | (1<<PA3);

MFG
Falk
#2541411
Lesenswert?

Falk Brunner schrieb:
> Lies mal das Original vom OP. Dort wird doppelt gemoppelt Bits
> geschoben, nicht wirklich im Sin des Erfinders.

Ja, der ist schlichtweg falsch.
Richtig:
1
 //Pull-Up einschalten
2
  DDRA  &= ~(1<<PA1);  
3
  PORTA |= (1<<PA1);   
4
  DDRA  &= ~(1<<PA3);  
5
  PORTA |= (1<<PA3);

Dann sinds 2 CBI und 2 SBI, also 2 Befehle gespart gegenüber IN+ORI+OUT, 
IN+ANDI+OUT.


Peter
Gast #2542373
Lesenswert?

Guten Morgen
Vielen Dank für eure Hilfe und es lag bei mir doch am Aufbau.
Wenn ich 2Encoder auswerten will muss ich doch für den zweiten Encoder 
alle Routienen einen anderen Namen geben auch die im Interrupr, oder bin 
ich da jetz falsch.
mfg

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren