Forum: Mikrocontroller und Digitale Elektronik Drehencoder auswerten


von donald (Gast)


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...

von Klaus W. (mfgkw)


Lesenswert?

Es gibt hier bereits Artikel zu Encodern.
Schon gelesen?

von Klaus W. (mfgkw)


Lesenswert?


von Klaus W. (mfgkw)


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.

von Anton K. (antonius)


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.

von donald (Gast)


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!

von Anton K. (antonius)


Lesenswert?

Handelt es sich bei dem Encoder um einen Inkremetalgeber, der die beiden 
Spuren A&B um 90° phasenverschoben über dem Winkel (Position) ausgibt?

Oder handelt es sich um einen Gray-Encoder, der über eine Umdrehung 
absolute Winkel im Gray-Code ausgibt?

von Klaus W. (mfgkw)


Lesenswert?

offenbar inkremental...

von Anton K. (antonius)


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;

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.