Drehencoder auswerten

Gast #1677688
Lesenswert?

Ich habe hier grad ein kleines Verständnis-Problem beim Auswerten zweier 
Drehencoder an meiner Schaltung.

Ich bekomme die Daten vom Betriebssystem in meinem Programm rein und 
zwar jeweils in einer Variable für A und B der beiden Drehencoder:
1
char left[2];
2
char right[2];
In den beiden Variablen stehen auch die richtigen Werte drin.

Doch mein Encoder gibt, im optimal-Fall, 4 Werte aus pro "Klick". So 
zieht das bei meinem Test-Programm aus:
1
(drehung links herum)
2
A:1  B:1
3
A:0  B:1
4
A:0  B:0
5
A:1  B:0
6

7
(drehung rechts herum)
8
A:0  B:1
9
A:1  B:1
10
A:1  B:0
11
A:0  B:0

Nun weiss ich nicht genau wie ich das Auswerten kann, dass er mir nach 
der vierten Umdrehung in eine Variable schreibt, in welche Richtung er 
gedreht wurde.

Achja, Code wäre zwar schön, brauche aber nicht. Das Programmieren an 
sich ist nicht das Problem, ich weiss nur nicht genau wie ich das machen 
kann/soll...
#1677708
Lesenswert?

Bei nochmaligem Lesen fällt mir erst auf, daß du von einem Betrübsystem 
redest.

Dann kann man das vielleicht abkürzen mit der Info:
Es geht mutmaßlich um inkrementelle Encoder. Aus denen bekommst du
immer eine Änderung der Position und musst ab einem Startwert
mitzählen.

D.h. du brauchst für jeden Encoder noch eine ganzzahlige Variable
(mit Vorzeichen, da der Wert auch negativ werden kann).
Die steht dann erst für die Position.
Zu Anfang wird sie mit 0 bspw. initialisiert.
Die Signale A und B werden jetzt nur genutzt, um diese Variable
jeweils um 1 zu erhöhen oder zu erniedrigen bei jeder Änderung.
#1677738
Lesenswert?

In den beiden Tabellen (Drehung links bzw. rechts herum) hast Du die 
vier Zustände von A und B aufgelistet. Jetzt geht's doch nur noch um die 
Auswertung: Bei welchem Zustandswechsel muss die Position um 1 erhöht 
und bei welchem vermindert werden.

Wenn Du Dir den letzten Zustand von A und B merkst, dann kannst Du mit 
drei XOR-Befehlen herausfinden, ob links- oder rechtsherum gedreht 
wurde.

Die Position muss nicht zwangsläufig vorzeichenbehaftet sein. Dies ist 
nur eine Frage der Interpretation.
Gast #1677792
Lesenswert?

Hmmmm so ganz hab ichs immer noch nicht verstanden, ich weiss wie die 
Werte aussehen, was sie zu sagen haben. Aber wie ich das im Programm 
hinbekomme, ist mir noch unklar.

Ich habs jetzt aber mit dem Code von Peter Danneger hinbekommen:
1
        int fd = open("/dev/drehgeber", 0);
2
        if (fd < 0) { perror("open device drehgeber"); exit(-1); }
3

4
        unsigned char last[2];
5
        char new[2], diff[2];
6
        char enc_delta[2];
7

8
        char vals[4];
9
        char left[2], right[2];
10
        int j;
11
        while(1) {
12
                read(fd, vals, 4);
13
                for(j = 0; j < 4; j++) vals[j] &= 0x01;
14
                left[0] = vals[0];
15
                left[1] = vals[2];
16
                right[0] = vals[1];
17
                right[1] = vals[3];
18

19
                new[LEFT] = 0;
20
                if( left[0] ) new[LEFT] = 3;
21
                if( left[1] ) new[LEFT] ^= 1;                                   // convert gray to binary
22
                diff[LEFT] = last[LEFT] - new[LEFT];                            // difference last - new
23
                if( diff[LEFT] & 1 ){                           // bit 0 = value (1)
24
                        last[LEFT] = new[LEFT];                                 // store new as next last
25
                        enc_delta[LEFT] += (diff[LEFT] & 2) - 1;                // bit 1 = direction (+/-)
26
                }
27

28
                new[RIGHT] = 0;
29
                if( right[0] ) new[RIGHT] = 3;
30
                if( right[1] ) new[RIGHT] ^= 1;                                   // convert gray to binary
31
                diff[RIGHT] = last[RIGHT] - new[RIGHT];                            // difference last - new
32
                if( diff[RIGHT] & 1 ){                           // bit 0 = value (1)
33
                        last[RIGHT] = new[RIGHT];                                 // store new as next last
34
                        enc_delta[RIGHT] += (diff[RIGHT] & 2) - 1;                // bit 1 = direction (+/-)
35
                }
36

37
                printf("left %d right %d\n", enc_delta[LEFT], enc_delta[RIGHT]);
38
        }

Danke für eure Mühe!
#1677923
Lesenswert?

Wenn inkremental, dann probier's mal mit diesem einfachen Code:
1
bool  altA, neuA;
2
bool  altB, neuB;
3
bool  links;
4
int  position = 0;
5

6
// Initialisierung:
7
altA = read(A);  // aktueller Wert der Spur A vom Inkrementalgeber
8
altB = read(B);  // aktueller Wert der Spur B vom Inkrementalgeber
9

10
// nach jeder Signaländerung:
11
neuA = read(A);  // aktueller Wert der Spur A vom Inkrementalgeber
12
neuB = read(B);  // aktueller Wert der Spur B vom Inkrementalgeber
13

14
links = (altB XOR neuB) XOR (neuB XOR neuA)
15
if (links) {
16
  position +=1;
17
} else {
18
  position -=1;
19
}
20
altA = neuA;
21
altB = neuB;

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