Forum: Compiler & IDEs Drehencoder auswerten


von F. X. (ddsram)


Lesenswert?

Hallo,

ich habe hier mehrere ALPS drehencoder die ich nicht auswerten kann bzw. 
nicht weß wie...
Mein erster versuch war es einfach die Schritte von Phase A und B zu 
zählen und der Wert mit meisten Schritten hatte dann die drehrichtung 
ebstimmt.
Das Problem war nachher das der Encoder auch gependelt hat hat und diese 
Methode dann ab und an komsiche Sachen gemacht hat.
Dann habe ich den code von Peter Danneger ausprobiert der zwar die LEDS 
perfekt angesprochen hatte und man dann im Binären zahlensystem schön 
ablesen konnte: 1,2,3,4,5,6 usw. und beim zurückdrehen eben 6,5,4,3,1,0.
Ich musste dann aber feststellen das hier der Encoder auch mal pendelt 
also habe ich dann den anderen Code genohmen den ich jedoch nicht 
kompilieren konnte weil irgendwas mit dem array falsch ist.

Siehe auch hier: http://www.mikrocontroller.net/articles/Drehgeber

so richtig nachvollziehen konnte ich den Code auch nicht...
Beschäftige mich auch erst seit kurzem mit MicroControllern und verstehe 
deshalb nicht alles sofort auf Anhieb ich würde mich dennoch auf Hilfe 
freuen.

mfg

von Floh (Gast)


Lesenswert?

Wo ist deine Frage?

von F. X. (ddsram)


Lesenswert?

Wie ich den auswerten könnte... oder eine Erklärung was der Herr Dannger 
in seinem Code gemacht hat.

von Karl H. (kbuchegg)


Lesenswert?

F. X. schrieb:

> also habe ich dann den anderen Code genohmen den ich jedoch nicht
> kompilieren konnte weil irgendwas mit dem array falsch ist.

Was soll denn das sein, dass 'iregendwas mit dem Array falsch ist'


> so richtig nachvollziehen konnte ich den Code auch nicht...
> Beschäftige mich auch erst seit kurzem mit MicroControllern und verstehe
> deshalb nicht alles sofort auf Anhieb

Das tut niemand.
Deshalb wurde Papier und Bleistift erfunden, auf dem man sich Notizen 
machen kann und mit dessen Hilfe man eine unbekanntes Programmstück mal 
mit simulierten (angenommenen) Zahlenwerten durchspielen kann.
Daraus gewinnt man dann Erkentnisse, die man im Code so nicht sieht und 
auf einmal macht es Plop, und man hat die Idee, die im Code steckt 
verstanden.

von Peter D. (peda)


Lesenswert?

Atze L. schrieb:
> ich habe hier mehrere ALPS drehencoder

Schön.
Gib mal Typ und Link zum Datenblatt an.
Oder probier aus, wo die Rastung sitzt.

Manche Encoder haben die Rastung genau auf einem Phasenwechel. Dann muß 
man den Startwert (Variable new) so wählen, daß dort keine (sichtbare) 
Zählung erfolgt.
Rastende Encoder schalten ja nach 2 oder 4 Phasen.


Peter

von Karl H. (kbuchegg)


Lesenswert?

F. X. schrieb:
> Wie ich den auswerten könnte... oder eine Erklärung was der Herr Dannger
> in seinem Code gemacht hat.

Spiel den Code durch.

Nimm an, dass dein Encoder in einer Position steht. Die Einganspins 
haben daher welche Werte? Die Variablen haben welche Werte?

Jetzt wird die ISR (in deinen Gedanken) aufgerufen. Du bist Computer 
(und dein Papier ist dein Speicher, auf dem du dir die Werte für 
Variablen notieren kannst) und gehst das Programmstück Zeile für Zeile 
durch und machst genau die Operationen die dort stehen. Wenn in einem 
Ausdruck Variablenwerte gebraucht werden, dann liest du die von deinem 
Papier ab. Wenn Variablen einen neuen Wert zugewiesen bekommen, dann 
änderst du auf dem Papier den Wert der jeweiligen Variablen.

Überzeug dich durch einen 2.ten simulierten Aufruf der ISR, dass alles 
ruhig ist und sich enc_delta nicht verändert.

Dann drehst du deinen gedachten Encoder mal ein bischen. Wie verändern 
sich dadurch die Eingangspins?
Mit dieser veränderten Belegung der Eingangspins spielst du jetzt wieder 
das Codestück durch und siehst dir an was passiert.

Dann drehst du deinen gedachten Enocder wieder ein Stückchen weiter. Was 
machen jetzt die Eingangspins? Wie wirkt sich das beim nächsten 
simulierten ISR Aufruf aus?

Dann drehst du den Encode in Gedanken mal ein bischen zurück, so dass 
sich die vorhergehende Situation an den Eingangspins ergibt. Was pssiert 
jetzt in der ISR?

usw. usw.
so analysiert man Code.
Rein nur durch Hinschauen erschliesst sich einem nur in den wenigsten 
Fällen, wie und warum ein Codestück arbeitet.

Da musst du durch. Das mussten wir alle. Die Fähigkeit ein unbekanntes 
Codestück zu analysieren ist eine der grundlegenden Fähigkeiten, die man 
lernen muss. Niemand kann das von Anfang an. Aber man kann es lernen und 
jeder entwickelt im Laufe der Zeit seine eigene Technik, wie er im 
Detail Code analysiert. Und ja, im Laufe der Zeit verlagert sich mehr 
und mehr dieser Analysetätigkeit vom Papier in den Kopf. Aber bei den 
meisten, die sowas noch nie gemacht haben, funktioniert die Methode 
'Papier' sehr gut.
Und ja: Das ganze ist wie radfahren - Du musst es selber tun um es zu 
lernen.

von Steffen (Gast)


Lesenswert?

Hallo F.X. ich hatte auch einige Schwierigkeiten den Encoder zum laufen 
zu bringen. Bei mir lag es an dem richtigen Takt. Ich mach es in dem ich 
per Timer die Zustände der beiden Eingänge abfrage. Ist der Timer zu 
schnell, dann macht der Zähler bei mir einen riesen Sprung. Ist der 
Timer zu langsam
dann muss ich zu oft drehen um überhaupt einen Schritt zu machen. 
Derzeit lasse ich den Timer mit knapp 900Hz laufen.
Gruß Steffen

von F. X. (ddsram)


Lesenswert?

Vielen Dank für die vielen Antworten! :)

Wenn ich den Code kompilieren möchte erhalte ich die Fehlermeldung:
"variable "table" must be const in order to be into read-only section by 
means of '_attribute_((progmen))'
Die Fehlermeldung bekomme ich bei dme Code für Drehencoder mit 
wackeligen rastpunkt.
Daher die schwamige aussage.
Aktuell steh ich komplett auf dem Schlauch.
Manche Code Stellen versthe ich nicht etwa:

^=
1
 
2
ISR( TIMER0_COMP_vect )             // 1ms for manual movement
3
{
4
  int8_t new, diff;
5
 
6
  new = 0;
7
  if( PHASE_A )
8
    new = 3;
9
  if( PHASE_B )
10
    new ^= 1;                   // convert gray to binary
11
  diff = last - new;                // difference last - new
12
  if( diff & 1 ){               // bit 0 = value (1)
13
    last = new;                 // store new as next last
14
    enc_delta += (diff & 2) - 1;        // bit 1 = direction (+/-)
15
  }
16
}

Wenn das Interrupt ausgelöst wird prüft er ob Phase A aktiv ist , wenn 
ja setzt er new auf 3.
Dann prüft er ob Pahse B aktiv ist und da hört es dann bei mir auf... :(

Der Drehencoder ist folgender:

http://www.reichelt.de/Drehimpulsgeber/STEC11B02/3/index.html?;ACTION=3;LA=446;ARTICLE=73912;GROUPID=3714;artnr=STEC11B02;SID=13UGQLEn8AAAIAACzw@Ro0d4a3a09a926a8957d47696628fc7251

ALPS STEC11B Drehimpulsg., 15/30, horiz.

mfg

von Peter D. (peda)


Lesenswert?

F. X. schrieb:
> Der Drehencoder ist folgender:
>
> http://www.reichelt.de/Drehimpulsgeber/STEC11B02/3...
>
> ALPS STEC11B Drehimpulsg., 15/30, horiz.

Das ist so ein Encoder mit Wechsel direkt auf der Rastung.
Die automatische Erkennung der Ruhelage in encode_init() schlägt dann 
fehl.

"new" muß auf einen festen Wert (0, 1 probieren) gesetzt werden und nach 
einigen Timerinterrupts ein dummy encode_read2() zum 0 setzen erfolgen.
Dann ist es stabil.


Peter

von MaWin (Gast)


Lesenswert?

> Wenn das Interrupt ausgelöst wird

Also alle paar Millisekunden im zeitlich festen Raster

> prüft er ob Phase A aktiv ist , wenn ja setzt er new auf 3.
> Dann prüft er ob Pahse B aktiv ist und da hört es dann bei mir auf... :(

Wieso, er kombiniert nur die beiden Bits aus 2 Eingängen zu einer 
einzelnen Zahl von 0 bis 3, damit die Zuordnung der Eingänge an den 
Encoder nicht die Bedeutung der Bits intern beeinflusst.

Es ist korrekter code und ein korrektes Verfahren. Alternativ etwas 
schneller ist der C-Code hieraus:

http://www.dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29

von Andreas K. (necromancer1982)


Lesenswert?

Hallo zusammen,

meiner Meinung nach ist die einfachste Möglichkeit einen Drehgeber 
auszuwerten die, mit einer State-Machine zu arbeiten:

Wenn die Ausganssignale beispielsweise wie folget aussehen:

A:  ___      ____      ____      ___
        |____|    |____|    |____|

B:     ___      ____      ____      
    __|    |____|    |____|    |____|

ergeben sich die folgenden Bitmuster (1. Bit: A; 2. Bit: B):

10 11 01 00 10 11 01 00...

Diese Bitfolge ist dem Graycode sehr ähnlich, es ändert sich nämlich 
immer nur ein Bit von State zu State => indirekte Fehlerkorrektur.

Man legt beispielsweise fest, daß
10 State 1 ist
11 State 2 ist
01 State 3 ist
00 State 4 ist

Die Abfrage ist eigentlich auch recht einfach:

1.) Initialisierung
Der aktuelle "Code" wird ausgelesen und in einer Variable 
zwischengespeichert (=> Start-State).

2.) Abfrage über Interrupt (beider Ausgänge des Gebers):
-   für jeden möglichen Start-State gibt es zwei Folge-States (z.B. 
Start in State 2 => Wechsel nur nach State 1 oder 3 möglich)
=> für jeden möglichen Start-State werden zwei If-Abfragen angelegt
(z.B. für State 2: wenn Folge-State = State 1 dann eins zurück zählen; 
wenn Folge-State = State 2 dann eins vor zählen)
- Zu guter Letzt muß dann natürlich der Folge-State wieder als neuer 
Start-State gespeichert werden.

Möchte man den Drehgeber dann noch "unempfidlicher" machen kann mann zum 
Beispiel immer nur bei jedem 2. oder 3. "vor" bzw. "zurück" zählen.

Auf diese Weise frage ich meine Drehgeber immer ab. Funktioniert 
einwandfrei und ohne jegliches "Springen".

Gruß Andreas

von Peter D. (peda)


Lesenswert?

Andreas K. schrieb:
> Auf diese Weise frage ich meine Drehgeber immer ab.

Du hast bisher nicht mitgelesen.
Genau das macht nämlich der Code, um den es die ganze Zeit geht:

http://www.mikrocontroller.net/articles/Drehgeber#Solide_L.C3.B6sung:_Beispielcode_in_C


Andreas K. schrieb:
> Funktioniert
> einwandfrei und ohne jegliches "Springen".

Stimmt.
Man muß nur den Startwert entsprechend festlegen.


Peter

von Frogger (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Deshalb wurde Papier und Bleistift erfunden, auf dem man sich Notizen
>
> machen kann und mit dessen Hilfe man eine unbekanntes Programmstück mal
>
> mit simulierten (angenommenen) Zahlenwerten durchspielen kann.
>
> Daraus gewinnt man dann Erkentnisse, die man im Code so nicht sieht und
>
> auf einmal macht es Plop, und man hat die Idee, die im Code steckt
>
> verstanden.

Interessante Theorie! Scheint viele zu geben, die so denken, dass man 
Software dadurch versteht, dass man sie durchsimuliert. Doku machen die 
dann genau deshalb nicht.

von MaWin (Gast)


Lesenswert?

> Doku machen die dann genau deshalb nicht.

Der Programmcode IST die Doku, nämlich die kürzeste präzisieste Form der 
Beschreibung dessen was passiert.

Es fehlt höchstens eine Erklärung WARUM etwas passiert, aber Auswertung 
eines Drehencoders sagt das Warum.

von Karl H. (kbuchegg)


Lesenswert?

F. X. schrieb:
> Vielen Dank für die vielen Antworten! :)
>
> Wenn ich den Code kompilieren möchte erhalte ich die Fehlermeldung:
> "variable "table" must be const in order to be into read-only section by
> means of '_attribute_((progmen))'
> Die Fehlermeldung bekomme ich bei dme Code für Drehencoder mit
> wackeligen rastpunkt.

Na ja.
In der Fehlermeldung steht aber schon, was denn das syntaktische Problem 
ist.

variable "table"               aha, so heißt also die Variable

must be const                  der Compiler hätte also einen 'const'
                               Modifier erwartet und nicht vorgefunden.

in order to be into            da gehts also um irgendwas mit progmem.
read-only section by           progmem mhat mit dem Flash zu tun.
means of                       Und vom Flash wissen wir, dass die
_attribute_((progmem))         Werte da drinn zur Laufzeit nicht
                               veränderbar sind. Man kann sie zwar
                               auslesen (daher auch read-only)
                               aber man kann sie nicht verändern.

Der Compiler spricht also hiervon:
1
int8_t table[16] PROGMEM = {0,0,-1,0,0,0,0,1,1,0,0,0,0,-1,0,0};
Das ist ein Array welches im Flash liegt. Und weil es im Flash liegt, 
sind die Arraywerte per Programm nicht änderbar.
Nur hindert jetzt nichts und niemand einen Programmierer daran, das hier 
zu schreiben
1
    table[5] = 8;
Das kann  natürlich nicht funktionieren, denn das Flash kannst du so zur 
Laufzeit nicht ändern. Um genau sowas schon auf Syntax-Ebene zu 
verhindern und für den Compiler prüfbar zu machen, gibt es in C die 
Möglichkeit Variablen als 'const' zu definieren.
1
  const i = 8;
2
  i = 9;
Die Zuweisung ist damit illegal geworden, denn an etwas, was du vorher 
als immer und ewig konstant ausgewiesen hast, kannst du nichts zuweisen.

Hmm. Das erinnert aber ein wenig an die Situation im Flash. Auch dort 
kann man einer Variablen, die im Flash liegt nichts zuweisen. Zwar aus 
anderen Gründen, aber das spielt ja keine Rolle. Nicht zuweisbar ist 
nicht zuweisbar.
Nur: Davon weiß der restliche Code nichts. Die C-Methode etwas als nicht 
veränderbar zu definieren, besteht darin, dass man es 'const' macht und 
nicht darin, dass über irgendwelche dubiose Kanäle und Schlüsselwörter 
und attribute implizit diese Nicht-Veränderbarkeit angezeigt wird.

Und genau das hat dem Compiler gefehlt:
Durch das PROGMEM hat er zwar gewusst, dass table im Prinzip nicht 
veränderbar ist, aber das eigentlich dafür zuständige Schlüsselwort 
'const' hat ihm gefehlt.

Mach ein
1
const int8_t table[16] PROGMEM = {0,0,-1,0,0,0,0,1,1,0,0,0,0,-1,0,0};
draus und alles ist gut.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:

> Mach ein
1
const int8_t table[16] PROGMEM = {0,0,-1,0,0,0,0,1,1,0,0,0,0,-1,0,0};
> draus und alles ist gut.

Ich hab's im Wiki-Artikel auch mal nachgezogen.

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.