Forum: Mikrocontroller und Digitale Elektronik PIC + Encoder-abfrage funktioniert nicht richtig


von Mario (Gast)


Lesenswert?

Hallo,

die Suche brachte mich leider nicht zu dem Encoder den ich benötige.

Es ist also ein "Drehschalter" der 2 Ausgänge besitzt.
Von Stellung zu Stellung wechselt er von  0 0 auf 1 1, dann wieder auf 0 
0
entscheidend ist, welcher Ausgang zuerst das Signal wechselt. also 0 1 
oder 1 0 (in der Zwischenstellung)

Der Encoder ist an RC0 und RC1

Mein Ansatz sieht so aus:

read_encoder
        movf   PORTC,0        ;Port C nach W
        movwf   neu           ; aktuelle encoder-Stellung nach neu
        movlw   B'00000011'
        andwf   neu, 1    ;nur 1. und 2.Bit stehen lassen und speichern
        MOVF   alt      ;alt nach w
        xorwf   neu,0    ;alt und neu vergleichen, Wert bleibt in W

        ADDWF  PCL       ;PROGRAMMZEIGER ÄNDERN 0 BIS 4
          Goto weiter  ;W=0 (alt und neu ist gleich)
          Goto links   ;W=1 (1.bit gesetzt)
  Goto rechts  ;W=2 (2.Bit gesetzt)
  Goto weiter  ;W=3 (würde passieren wenn der zwischenschritt 
überspungen ist)

Irgend einen fehler muss ich mit der verknüpfung gemacht haben, da der 
Programmzeiger vermutlich an eine ganz andere Stelle springt sobald ich 
am Encoder drehe.

Am ende will ich dann noch in "links" und "rechts" prüfen ob die 
Stellung von 00 zu 11 oder umgekehrt stattgefunden hat um prellen zu 
verhindern.

Vielen Dank für einen Hinweis oder gar eine bessere Programmlösung.

von TK (Gast)


Lesenswert?

Ja - hallo auch,
also ich vermute mal folgendes:
Der 'computed goto' hat das Problem, dass PCLATH nicht richtig vorbelegt 
wird. Das passiert immer, wenn genau ein 256-Bytes Umbruch zwischen den
nachfolgenden GOTOs existiert. Daher muss man genau drauf achten, dass 
alle GOTOs immer in der 256-Bytes PAGE liegen, in der auch der ADDWF 
PCL,1 liegt.
Das wäre der erste Ansatz. Nun der nächste:
Wenn es sich bei der Routine 'read_encoder' um eine Unterfunktion 
handelt,
dann muss in den Routinen 'weiter', 'links' und 'rechts' ein 'return' 
stehen und nicht ein GOTO xyz. Das ist auch ein häufig gemachter Fehler.
Jetzt eine andere Frage:
Wieso nutzt du nicht den onChange-Interrupt um die Auswertung 
durchzuführen?

Irgendwo hier im Forum gibts auch eine 'Anleitung' zur Auswertung eines 
Encoders. Ist zwar für den ATMEL (muss man also nicht unbedingt 
verstehen) - aber die Logik ist für beide Controller die gleiche. Da 
kann man sich ja mal was abschauen.

Gru0
TK

von Mario (Gast)


Lesenswert?

Hallo TK

Also an der 256-Bytes PAGE liegt es nicht, hätte ich aber auch 
übersehen.
Nach Goto kommt dann allerdings wieder ein Goto, danach aber Return.

Was ich jetzt festgestellt habe, der Fehler tritt schon nach dem 
einschalten auf, wenn der Encoder in einer bestimmten Stellung steht (00 
oder 11 müste ich mal prüfen) sonnst erst wenn ich drehe.

Der Drehgeber sowie die serielle Schnittstelle werden in einer Schleife 
abgefragt. Der Drehgeber hat nicht die Priorität und ich wollte die 
Abfrage nicht mit einem interrupt unterbrechen, aber das wäre ja immer 
noch möglich wenn es funktionieren würde.

Wäre denn das Programm so logisch richtig?
Bin da leider nicht so der Profi.

Gruß Mario

von TK (Gast)


Lesenswert?

Jo, dann fragen wir uns jetzt mal, wie sich denn der Fehler äußert???
Der Code scheint generell zu funktionieren (soweit dies der 
Codeschnipsel zulässt).
Serielle Schnittstelle?
Fragst du die im Polling-Mode ab?
Jetzt fällt mir dann noch das 'Read-Modify-Write' Problem ein. Wobei das 
hier eigentlich nicht zum Tragen kommt, da RC0,1 ja immer ein INPUT ist, 
oder?

Gruß
TK

von TK (Gast)


Lesenswert?

Nachtrag:
VORSICHT: Die PAGE und die 256-Bytes Grenze sind NICHT das gleiche!!!
Eine PAGE kann bis zu 2k groß sein!
Hier muss man genau unterscheiden!

Gruß
TK

von Mario (Gast)


Lesenswert?

vielen Dank für die schnellen Antworten.

in der Programmzeile;
ADDWF  PCL       ;PROGRAMMZEIGER ÄNDERN 0 BIS 4
liegt der Code bei 0x54
das kann es also nicht sein.

Die anderen Programmteile laufen ohne Probleme.
An Port C ist derzeit auch nicht weiter drann oder im Programm schon was 
vorgesehen.
An Port B hängt ei Display und an RA0 ein Temp.-Fühler.

In das UP welches ich oben abgebildet habe, hatte ich vorher einen 
Programmcode von Sprut.de (angepasst). Vom Prinzip hat das auch 
funktioniert, nur das mein Encoder halt gleich 2x gezählt hatte wenn man 
langsamm dreht. Die andere Richtung ging mehr recht als schlecht.

Den Fehler sehe ich darann, das der Begrüßungstext plötlich in der 2. 
Zeile auftaucht. Also muss der Fehler irgendwie mit dem Programmzeiger 
zusammenhängen, denn ein Zählwert von dem Encoder sollte in der 2.Zeile 
zum testen erscheinen. Das macht er auch kurz, aber der Zähler wird 
nicht geändert, so das die UPs LINKS und RECHTS vermutlich gar nicht 
angesprungen werden.

Wenn ich direkt auf den Programmzeiger zugreife, passiert denn dann noch 
was? Der obere Schnipsel wird übrigens auch per Call angesprungen.

Die serielle Schnittstelle wollte ich per Polling abfragen, aber so weit 
bin ich noch nicht.

von Mario (Gast)


Lesenswert?

ich bins gerade noch mal durchgegangen

die Zeile wo ich den RCL ändere steht bei 0159h
W ist vermutlich 0 und er springt dann zu 0060h

das versteh ich nicht!

Ich kann die Simulation zwar nich im ganzen Programm laufen lassen, aber 
da käme genau das raus was ich im Display sehe, nämlich noch mal der 
Begrüßungstext.

von Mario (Gast)


Lesenswert?

hmmmm

Antworte ich mir mal selber.
Also wie oben schon beschrieben, lag es doch darann das ich in das UP 
per Call bin und das UP in einem anderen Block lag.

Vom Prinzip war es erst mal ok.

Nun habe ich den Code eingekürzt und das klappt auch sehr gut....aber 
andere UP brauchen zu lange damit ich keine Drehung "übersehe".

UND was noch viel schlimmer ist, ich warte in "weiter" darauf das der 
Encoder auf 11 oder 00 steht. Das sind zwar auch nur ms aber das ist 
nicht gerade schön. ABER IRGEND EINE ENTPRELLUNG / SICHERHEITSABFRAGE 
MUSS DA REIN.

Hier noch mal der neue Code:

read_encoder
        movf   PORTC,0         ;Port C nach W
        andLw    B'00000011'   ;rest ausblenden
        xorwf   alt,0      ;vergleiche mit alt
         ADDWF  PCL,1       ;PROGRAMMZEIGER ÄNDERN 0 BIS 4
              Return
              Goto links
              Goto rechts
              Goto weiter

rechts
        incf    counter, f              ; rechts:  increment counter
        goto    weiter
links
        decf    counter, f              ; links:  decrement counter

weiter  movf   PORTC,0                  ;Port C nach W

        andlw   B'00000011'
        ADDWF  PCL,1       ;PROGRAMMZEIGER ÄNDERN 0 BIS 4
           Goto ende
           Goto weiter     ;Encoder steht noch in mittelstellung
           Goto weiter     ;Encoder steht noch in mittelstellung
           Goto ende       ;könnte ich weglassen, nur zur verständniss

ende    movwf   alt        ; für nächsten Vergleich als alt speichern

        return

Also jede bessere Lösung ist Willkommen!!!!!

von TK (Gast)


Lesenswert?

Hallo Mario,

hatte gestern keine Zeit mehr.
Also folgendes:
Wenn der Programmzaehler bei $0159 steht und der goto auf $0060 springt,
liegt das am PCLATH-Register. Das ist nämlich noch $00 und daher geht 
der
goto in die Hose. Abhilfe: VOR dem ADDWF PCL,1 muss ein - sagen wir mal 
-
'movlw high(rechts)'
'movwf PCLATH'
stehen. Man muss jetzt noch gewährleisten, dass 'rechts', 'links' und
'weiter' in der GLEICHEN 256-Bytes-Page stehen. Dann geht der goto auch
nach $0160 und nocht nach $0060.

Gut, nächstes Problem:
Ich finde es überhaupt nicht lange, wenn einige ms gewartet wird, bis 
der
Encoder nicht mehr prellt. Man sollte mal im Datenblatt nachsehen, wie
gross die max. Prelldauer den ist. Das geht manchmal schom bis 200ms.
Also, wenn das keine 'Hochgeschwindigkeitsanwendung' werden soll, was ja
alleine schon wegen dem Display nicht geht, dann nimm die Zeit einfach
als gegeben hin.

Gruß
TK

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.