Hallo,
ich möchte einen Inkremental drehgeber RI38 welle 38 mm von Firma rs mit
atmega8 auswerten.
meine Beiden Pin A und pin B habe ich jeweils an pin 1 und 3 an port c .
Das Programm von peter habe ich für atmega8 angepasst. (s. unten)
1 | #ifndef F_CPU
|
2 | #define F_CPU 4000000L // Systemtakt in Hz - define as long>> Without errors in the computation
|
3 | #endif
|
4 |
|
5 | #define PHASE_A (PINC & 0x01)
|
6 | #define PHASE_B (PINC & 0x04)
|
7 |
|
8 | #define LEDS_DDR DDRB
|
9 | #define LEDS PORTB // LEDs against VCC
|
10 |
|
11 | volatile int8_t enc_delta; // -128 ... 127
|
12 | static int8_t last;
|
13 |
|
14 |
|
15 | void encode_init( void )
|
16 | {
|
17 | int8_t new;
|
18 |
|
19 | new = 0;
|
20 | if( PHASE_A )
|
21 | new = 3;
|
22 | if( PHASE_B )
|
23 | new ^= 1; // convert gray to binary
|
24 | last = new; // power on state
|
25 | enc_delta = 0;
|
26 | //interrupt
|
27 | TCNT0 = 5; //Set Timer/counter
|
28 | TIMSK |= (1<<TOIE0); //Enable Timer/counter0 overflow interrupt
|
29 | TCCR0 |= (1<<CS01);
|
30 | TCCR0 |= (1<<CS00); //Select the clock source to be used by the timer/counter --> CPU Takt --> 4MHz/64
|
31 | TIFR |= (1<<TOV0); //interrupt starts with each overflow
|
32 | }
|
33 |
|
34 |
|
35 | ISR( TIMER2_COMP_vect ) //1ms for manual movement
|
36 | {
|
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 | int main(void)
|
64 | {
|
65 |
|
66 | int32_t val = 0;
|
67 |
|
68 | DDRC = 0x00; // PORTB auf Eingang
|
69 | PORTC = 0xFF; // pull ups for key inputs PortC1 and portC3
|
70 |
|
71 | LEDS_DDR = 0xFF; // outputs for LEDs
|
72 | encode_init();
|
73 | sei();
|
74 |
|
75 | for(;;)
|
76 | {
|
77 | val += encode_read1(); // read a single step encoder
|
78 | LEDS = val;
|
79 | }
|
80 |
|
81 | }
|
von peter:
>"Die Auswertung eines Drehgebers macht man am besten in einem Timer
>Interrupt, der mit einer festen Frequenz ausgeführt wird. Die
>Abtastfrequenz >muss so hoch sein, dass bei maximaler Drehzahl zwischen
>zwei Codewechseln >mindestens 1 Abtastung erfolgt, besser jedoch mehr. "
Frage:
1.verstehe ich nicht ganz gut wie ich meine Frequenz einstellen muss.
drehgeber hat:
1000 Impulse pro umdrehung
drehzahl max. 10000 1/s
max Impulsfrequenz 200 khz
2. messe ich dann mein Signal am ozi und kriege sinus kurven und weiss
nicht wie ich den interpretieren muss um meine Drehrichtung zu
bestimmen.
Ich möchte eigentlich mit meinem Drehgeber Entfernungsrechnen, bei recht
drehung immer die länge addieren und bei links drehung dekrementieren.
Anfängerin in Mikrokontrollerwelt, kann mir jemand dazu ein paar tipp
geben.
danke
gruß