mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem beim Einlesen eines Drehgebers


Autor: Tobias Binkowski (tc-soundnlight)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier erstmal mein momentaner Code in Assembler:
.include "m8515def.inc"

.set maske = 0b00001100      ; Drehgeber Bits
.set DrehPort = PIND      ; Drehgeber Port

.def merker = r16
.def temp = r17
.def merker2 = r18
.def alt = r20
.def zahl = r21

  ldi temp, LOW(ramend)
  out SPL, temp
  ldi temp, HIGH(ramend)
  out SPH, temp

  ldi temp, 0x00        
  out DDRD, temp        ; Port D als Eingang
  mov merker2, temp      ; Alt auf 0
  
  
  ldi temp, 0xff
  out DDRB, temp        ; Port B als Ausgang
  out PORTD, temp        ; PullUP Aktivieren

main:
  mov alt, merker2      ; Alt auf "alten" Zustand setzen
  in temp, DrehPort      ; DrehPort einlesen
  com temp          ; Invertieren -> Bessere Anschaulichkeit
  andi temp, maske      ; Ausmaskieren der Drehgeber Bits
  mov merker, temp      ; Sichern
  mov merker2, temp      ; Sichern
  cp alt, merker        ; Vergleiche merker mit alt
  brne gedreht        ; Wenn ungleich wurde gedreht
  rjmp main          ; Wenn gleich -> Dauerschleife

gedreht:

  dec zahl
  out PORTB, zahl
  rjmp main

;  ldi temp, maske  
;  cp merker, temp        ; Beide Werte 1 ?  
;  brne ungleich_1
;  rjmp weiter

;ungleich_1:
;  ldi temp, 0x00
;  cp temp, merker        ; Beide Werte 0 ?
;  brne ungleich    
;  rjmp weiter
;  
;ungleich:
;  com merker          ; Invertieren
;  andi merker, maske
;  rjmp weiter  
;
;weiter:
;  eor merker, alt
;  ldi temp, 0b00001000
;  cp merker, temp
;  brne rechts
;  rjmp links
;
;rechts: 
;  mov alt, merker2
;  inc zahl
;  out PORTB, zahl
;  rjmp main
;
;links:
;  mov alt, merker2
;  dec zahl
;  out PORTB, zahl
;  rjmp main

Ich habe ihn momentan zum Testen vereinfacht.
Es soll einfach nur wenn ich eine Taste drücke EINMAL weitergezählt 
werden.
Da ab dann der Wert "alt" mit dem Akutellen übereinstimmt sollte er 
eigentlich solang in der Main-Schleife im Kreis springen bis sich etwas 
ändert!

Im Debugger von AVR-Studio macht er das auch alles so wie es soll...
Wenn ich es aber auf den Controller schreibe und dort Teste, zählt er 
solange ich eine Taste drücke (also sich eigentlich nichts verändert?!) 
- Wenn ich loslasse gehen alle LED's wieder An (also PortB - 0x00)

Ich benutze das STK500

Was muss ich noch beachten oder was ist in meinem Code falsch?!

Achso, falls jemand "einfachere" oder bessere Methoden hat einen 
Drehgeber auszulesen bin gerne offen für - aber ich wollte erstmal 
meinen eigenen Weg verfolgen - Learning by doing :-)

Vielen Dank für Antworten

Greez Tobi

Autor: Stefan M. (celmascant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Suche hier im Forum mal nach Drehgeber oder bei Google nach Rotary 
Encoder.
Da gibt es einige Beispiele wie man einen Drehgeber auslesen kann.
Eine der besten Methoden findest du hier im Forum von Peter Danegger:
Beitrag "Drehgeber auslesen"

Gruss Stefan

Hab noch vergessen, der Code ist in C!

Autor: Tobias Binkowski (tc-soundnlight)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat mir trotzdem jemand eine Antwort warum mein programm nicht will???

Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hat mir trotzdem jemand eine Antwort warum mein programm nicht will???

Ich sehe ein DEC zahl.

Inkrementiert wird gar nicht.

Was soll da funktionieren ?

Im Übergang von einem Zustand zum anderen ändert sich wegen prellen der 
Kontakte das Signal mehrmals. Dann dekrementierst du mehrmals.

> Im Debugger von AVR-Studio macht er das auch alles so wie es soll...

Da prellen Kontakte auch nicht, es sei denn, du simulierst das, durch 
wiederholtes Ein- und Ausschalten.

Aber warum machen eigentlich immer alle Leute dieselben Fehler ?

Ist es so schwer, vorher mal zu gucken, wie es richtig geht?

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

Autor: Stefan M. (celmascant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei deinem Link ist es richtig erklärt, jedoch ist folgendes falsch:
    0: ab (Spur A LOW, Spur B LOW)
    1: Ab (Spur A HIGH, Spur B LOW)
    2: aB (Spur A LOW, Spur B HIGH)
    3: AB (Spur A HIGH, Spur B HIGH)
Zustand 2 und 3 der Signale sind vertauscht.

Richtig wäre die Bitfolge so:
    0: ab (Spur A LOW, Spur B LOW)
    1: Ab (Spur A HIGH, Spur B LOW)
    2: AB (Spur A HIGH, Spur B HIGH)
    3: aB (Spur A LOW, Spur B HIGH)
An sonsten ist das eine sehr gute Erklärung!
Es gibt auch Drehgeber die Zusätzlich noch eine "Null"-Markierung haben. 
Da wird ein 3. Ausgang 1x pro Umdrehung gesetzt, zum Abgleich mit den 
Softwarezählern. Da kann dann (fast) nichts mehr schief gehen und es ist 
auch nicht so schlim wenn man mal 1 oder 2 Schritte/U nicht mitgezählt 
hat, denn es wird ja nach jeder Umdrehung abgeglichen ;)

Gruss Stefan

Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Beschreibung passt schon, denn es ist zunächstmel eine Aufzählung 
der möglichen Zustände, nicht die Reihenfolge beim Drehen. Derzeit ist 
die Reihenfolge nach binärer Wertigkeit der Eingänge.

Die Frage wäre, ob zu dieser Definition die Beschreibnng darunter passt. 
Sie passt. Also ist die Zustandsbeschreibung korrekt.

Ich kann zur Kenntnis nehmen, dass du die Auflistung der möglichzen 
Zustände schon in der Reihenfolge der Zustände beim Drehen sehen willst. 
Das hat was für sich, zumindest wennn man gleich daneben zeichnet, bei 
welcher Drehrichtung es sich ergibt.

Autor: Stefan M. (celmascant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, wenn man die Zustände schon Durchnummeriert, sollten sie (meiner 
Meinung nach)auch in der richtigen Reihenfolge da stehen, sonnst gibt es 
hinterher vieleicht Verständnissprobleme.
Ein "Neuling" (der nicht in sein Datenblatt geschaut hat) wird dann auch 
nicht interpretieren können, wie er die Drehrichtung auswerten kann.

Gruss Stefan

Autor: Tobias Binkowski (tc-soundnlight)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Übergang von einem Zustand zum anderen ändert sich wegen prellen der
Kontakte das Signal mehrmals. Dann dekrementierst du mehrmals.

Ein Taster prellt aber nicht 10sec lang :-)

Warum ich nicht Inkrementiere?

Weil ich wie gesagt das Programm wegen diesem Problem verkürzt hab und 
einfach nur sehen wollte wo er nicht das tut was ich will ...

Und ich sehe das er auch wenn keine Änderung zum vorigen Zustand (trotz 
Prellen - welches aber niemals SOOO lange und SOOO oft ist) 
weiterzählt...

Danke aber für die Links und erklärungen - will aber trotzdem schaffen 
meienn Ansatz weiter zu bekommen - und ich denke das Prellen kann ich 
ausschließen ... wo könnte der fehler noch liegen?!

Danke :-)

Autor: Stefan M. (celmascant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab dein Programm mal kopiert und im Simulator getestet. Da sieht es 
wirklich gut aus, also theoretisch funktioniert es.
Mess doch mal die Spannungen an den beiden Eingängen. wenn kein Taster 
gedrückt, sollte sich die Spannung bei ca. 4,9V befinden.
Bei gedrücktem Taster sollten 0V anliegen.
Wenn irgendwas dazwischen gemessen wird, stimmt entweder die Schaltung 
nicht (Taster muss gegen GND schalten^^) oder dein Taster ist nicht in 
Ordnung, also hochomig. Im Datenblatt des MC steht, ab welcher Spannung 
High und unter welcher Spannung Low erkannt wird. Alles dazwischen ist 
unzulässig, denn dann wäre ein unbestimmter (zufälliger) Zustand im 
Register PinD. Dadurch würde sich die Zählerei erklären.

Was passiert denn, wenn du die Taster komplett abhängst und nur die 
Pull-Ups einschaltest? Zählt er dann immer noch?

Gruss Stefan

Autor: geb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab einen Drehgeber mal ausgelesen mit einem Siemens C161. Der Hatte 
externe Interrups mit fallender und steigender Flanke.Den hab ich an 
Ausgang A des drehgebers gelegt. B an einen anderen Pin.
Es geht auch mit 2 Interrupteingängen wenn nur auf eine Flanke 
getriggert werden kann.

void resolver_trap(void) interrupt 0x1A//bei pos. und neg. Flanke von A
{
#define TIM_COUNT 0xFFFF-18430
static uint old_system_counter;
static uint old_tim_counts;
uint system_counts;
static ulong speed_counts;
if((P2&0x0400)==0){//A=0?
    if((P3&0x0010)==0)res_pos--;//A=0,B=0,runterzählen
    else res_pos ++;//A=0,B=1,raufz.
          }
else{if((P3&0x0010)==0)res_pos++;//A=1,B=0,raufzählen
     else res_pos --;//A=1,B=1,runterz.
          }

system_counts=(system_counter-old_system_counter);
speed_counts=(ulong)((ulong)(T2-old_tim_counts)+(ulong)(TIM_COUNT*system 
_counts));
old_system_counter=system_counter;
old_tim_counts=T2;
}

Grüße Gebhard

Autor: Tobias Binkowski (tc-soundnlight)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für deinen Tipp...

Das ist es aber leider nicht.. wie gesagt nutze ich z.Z. das STK500 - 
Hab die OnBoard verfügbaren Taster genommen - und die auch mal überprüft 
- Funktionieren einwandfrei oO ...

Dann hab ich auch mal externe Taster genommen - da auch - sobald ich 
etwas drücke Zählt er wenn ich nichts Drücke passiert auch nichts...

Auch wenn ich einfach einen Drehgeber einbaue funktioniert es nicht...

*verwirrt bin und nachher nommal ne Stunde rumprobier -.- *

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann an dem Programm auch nichts finden, was mich stören würde. Meiner 
Meinung nach müsste es funktioniereen.
Bist du sicher, dass du das richtige Programm geflasht hast?

Ansonsten lass dir doch einfach mal alt oder merker am Port ausgeben und 
sieh nach, was sich da ständig ändert, wenn du eine Taste drückst.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vieleicht hat auch der Drehgeber ne Macke? Ich hab mal EWIG (gefühlt) 
nach dem Fehler in einer Verstärkerschaltung gesucht warum der eine 
Kanal (obwohl identisch aufgebaut) nicht funktionieren wollte, bis ich 
dann einfach mal ein anderes Stereopoti genommen habe und auf einmal 
alles lief ;)

Autor: Tobias Binkowski (tc-soundnlight)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab jetzt mal den merker2 komplett raus getan weil ich gemerkt habe, 
dass dieser unnötig ist - jetzt zählt er sozusagen kurz eins hoch 
(taster bleibt gedrückt) und geht sofort wieder auf null...

Irgendwo wird "zahl" resettet aber wo und warum?!

Nochmal der Quellcode:
.include "m8515def.inc"

.set maske = 0b00001100      ; Drehgeber Bits
.set DrehPort = PIND      ; Drehgeber Port

.def temp = r16
.def merker = r17
.def alt = r18
.def zahl = r19

  ldi temp, LOW(ramend)
  out SPL, temp
  ldi temp, HIGH(ramend)
  out SPH, temp

  ldi temp, 0x00        
  out DDRD, temp        ; Port D als Eingang
  mov merker, temp      ; Alt auf 0
  
  
  ldi temp, 0xff
  out DDRB, temp        ; Port B als Ausgang
  out PORTD, temp        ; PullUP Aktivieren
  mov zahl, temp
  out PORTB, zahl

main:
  in temp, DrehPort      ; DrehPort einlesen
  com temp          ; Invertieren -> Bessere Anschaulichkeit
  andi temp, maske      ; Ausmaskieren der Drehgeber Bits
  mov merker, temp      ; Sichern
  cp alt, merker        ; Vergleiche merker mit alt
  brne gedreht        ; Wenn ungleich wurde gedreht
  rjmp main          ; Wenn gleich -> Dauerschleife

gedreht:

  mov alt, merker
  inc zahl
  out PORTB, zahl
  rjmp main

Natürlich noch gekürzt weil erstmal die Grundfunktion laufen soll danach 
kommt dann irgenwann der Teil mit dem eigentlichen Drehgeber...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias Binkowski schrieb:
> Ich hab jetzt mal den merker2 komplett raus getan weil ich gemerkt habe,
> dass dieser unnötig ist - jetzt zählt er sozusagen kurz eins hoch
> (taster bleibt gedrückt) und geht sofort wieder auf null...

Die einzige Möglichkeit, wo Zahl auf einen bestimmten Wert gesetzt wird, 
ist am Anfang in der Initialisierung.

D.h. die Initialisierung wird erneut durchlaufen, was wiederrum heißt, 
dass dein µC das Programm von vorne abarbeitet, was wiederrum bedeutet 
das der µC resettet wurde. Das könnte zb sein, wenn du mit dem Taster 
einen Kurzen gebaut hast.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Darstellung von Zahlen im 2-er Komplement hat eine sehr nützliche 
Eigenschaft. Differenzen funktionieren immer, auch bei Überlauf.

Nehmen wir als Beispiel den Überlauf von 127 nach -128, jetzt rechnen 
wir also: -128 - 127 = 0x80 - 0x7F = 1

D.h. wenn wir 2 aufeinanderfolgende Zahlen subtrahieren, stimmt das 
Ergebnis immer.

Nun gibt es ne kleine Aufgabe, ein Encoder liefert keine Binärzahlen, 
sondern Graycode. Das hat den Vorteil, daß es keine falschen Codes gibt.

Schauen wir uns also mal 2 Bit als Graycode und als Binärzahl an:
Gray  Binär
0 0   0 0
0 1   0 1
1 1   1 0
1 0   1 1

Wie man leicht sieht, läßt sich Gray sehr einfach nach binär umwandeln, 
einfach das 0. Bit umdrehen, wenn das 1. gesetzt ist.

Das ist das ganze Geheimnis meines sehr einfachen Codes und warum er 
sicher entprellt.


Peter

Autor: Tobias Binkowski (tc-soundnlight)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah wie geil - Ich flipp gleich aus...

Es lag nicht an den Tastern und nicht am Code...

Bah eigentlich sollte ich solche fehler aus erfahrung immer als erstes 
ausschließen aber ich hab nicht dran gedacht.. mein ATMega (der schon 
laaange zeit als experimentier stein herhält) hat irgend einen Schuss 
gehabt - IC getauscht - Funktioniert -.- oh man .. :-) *jetz dafür 
rumjubel*

Trotzdem allen ein Danke die mir den ein oder anderen neuen Link gezeigt 
haben...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.