Hi Zusammen
Neues Jahr, neue Fragen :)
Ich habe mich hier ein wenig erkundigt bezüglich Drehgeber auslesen,
habe mich dann aber entschieden mir selber etwas zu überlgen.
Allerdings ist der Code recht knapp geworden und wenn ich so vergleiche
mit Codebeispielen, kommt mir meine Lösung etwas provisorisch vor.
Der Code funktioniert meiner Meinung nach einwandfrei, die gewünschte
Funktion wird vollauf erfüllt. Da ich aber in späteren Projekten gerne
den gleichen Code verwenden will, wollte ich hier mal den Code posten um
zu sehen ob vielleicht jemand eine potenzielle Fehlerquelle darin
entdeckt.
1
intbla=0;//Variable zur Zeitverzogerung
2
3
if(forw)//Drehgeber rechts drehen
4
{
5
if(rechts<128){
6
rechts++;}
7
while(forw||backw){
8
bla++;
9
bla--;
10
}
11
}
12
13
14
15
if(backw)//Drehgeber links drehen
16
{
17
if(rechts>0){
18
rechts--;}
19
while(backw||forw){
20
bla++;
21
bla--;
22
}
23
}
Es soll einfach eine Variable rauf und runtergezählt werden (in diesem
Falle die Variable "rechts").
Auf Interrupt habe ich verzichtet, forw und backw sind einfach die Pins,
an die der Drehgeber angeschlossen ist.
Ich freue mich auch eure Inputs und Verbesserungsvorschläge.
MFG
Dave
Was hast du denn für Drehgeber?
Normalerweise wechseln die Pins ihren Zustand von einer Rastung zur
nächsten nicht von 00 (über 01, 11, 10 ) wieder zu 00.
D.h. dein Code hängt hier
1
while(backw||forw){
in der Schleife fest, bis sich der Benutzer dazu entschliesst, dann doch
bis zur nächsten Rastung weiterzudrehen. Alles was dann nicht über
Interrupts in deinem Programm gelöst ist (also alles was etwas länger
dauern wird, wie zb UART AUsgaben, LCD Ausgaben, aufwändigere
Berechnungen etc) steht dann solange.
Was ist an den bewährten dokumentierten Lösungen falsch, dass du sie
nicht benutzen willst?
Achso, das habe ich vergessen zu erwähnen.
Ein hängen in dieser Schleife ist (sofern kein Defekt vorliegt) nicht
möglich, da der Drehgeber nur kurze Impulse gibt, sprich nicht im high
Zustand hängen bleibt.
Karl Heinz Buchegger schrieb:> Was ist an den bewährten dokumentierten Lösungen falsch, dass du sie> nicht benutzen willst?
Falsch ist meines Erachtens nach nichts, aber ich wollte einfach selber
was ausprobieren, da ich noch in der Ausbildung bin. Der Weg ist das
Ziel :)
@ Dave Chappelle (dave_chappelle)
>Ich habe mich hier ein wenig erkundigt bezüglich Drehgeber auslesen,>habe mich dann aber entschieden mir selber etwas zu überlgen.
Also das Rad neu erfinden, nur sechseckig?
>Allerdings ist der Code recht knapp geworden und wenn ich so vergleiche>mit Codebeispielen, kommt mir meine Lösung etwas provisorisch vor.
Ist sie auch.
>Der Code funktioniert meiner Meinung nach einwandfrei,
Meinungen gibt es wie Sand am Meer.
Einen WASSERDICHTEN NACHWEIS selten.
>zu sehen ob vielleicht jemand eine potenzielle Fehlerquelle darin>entdeckt.
Ich hab keine Lust auf dei hunderttausendste Erklärung. Kurz, dein Code
taugt nix.
>Ein hängen in dieser Schleife ist (sofern kein Defekt vorliegt) nicht>möglich,
Schöner Satz . . .
> da der Drehgeber nur kurze Impulse gibt, sprich nicht im high> Zustand hängen bleibt.
Komischer Drehgeber, wahrscheinlich flasch angschlossen oder defekt.
Oder ein Missverständniss deinerseits, was mir am wahrscheinlichsten
ist.
>Falsch ist meines Erachtens nach nichts, aber ich wollte einfach selber>was ausprobieren, da ich noch in der Ausbildung bin.
Prinzipiell richtig, aber nicht wenn es um Grundlagen geht. Die kann
keiner besser machen. Die sollte man studieren und VERSTEHEN. Dann kann
man vielleicht was besser machen.
MFG
Falk
Wenn dein Drehgeber einer von der Sorte ist, die Vorwärts-/Rückwärts-
impulse ausgeben (sehr selten), stimmt deine Lösung prinzipiell,
allerdings fehlt eine Entprellung.
Die allermeisten Drehgeber liefern aber nicht direkt die Vorwärts-/Rück-
wärtsimpulse, sondern zwei Rechtecksignale, die unabhängig von der Dreh-
richtung beide phasenversetzt ausgegeben werden. Aus der Reihenfolge
der steigenden bzw. fallenden Flanken beider Signale wird per Software
die Drehrichtung ermittelt. Diese Drehgeber funktionieren — die richtige
Auswertung vorausgesetzt — zuverlässiger. Diejenigen mit Vorwärts-/Rück-
wärtsimpulsen haben prinzipbedingt Schwierigkeiten, wenn der Drehgeber
langsam und mit zitternden Händen von einer Position in die nächste
gedreht werden. Da wird schnell mal eine Raste mehrfach gezählt.
Nimm einen "normalen" Drehgeber, dann hast du dieses Problem nicht, und
du kannst fertigen und getesteten Auswertecode verwenden.
> Der Code funktioniert meiner Meinung nach einwandfrei
Meiner Meinung nach funktioniert er gar nicht.
Es gibt keine Schleife, nach ein mal forw und
ein mal backw ist der code durchgelaufen und
wird nie wieder ausgeführt. Du hast absichtlich
wichtigen Code drumrum weggelassen, und somit
unterliegt die Verwendung des Codes der Beliebigkeit,
und somit kann er auch falsch verwendet werde.
> jemand eine potenzielle Fehlerquelle darin entdeckt.
Zeitverzögerung ist in Programmen prinzipiell immer schlecht,
im Ergebnis kaufen sich Leute ständig schnellere Prozessoren.
Dein "Drehgeber" ist wie schon die anderen geschrieben haben
offenbar exotisch, er enthält eigentlich schon die
Encoder-Auswertung aus gray-code die forw/backw Impulse zu
formen, und liefert hoffentlich diese Impuls auch entprellt
ab, denn sonst funktioniert dein code eh nicht,
also kein Wunder daß dein Programm keinen wichtigen code
mehr besitzt, es wurde schon alles von der Hardware getan.
Vielleicht hast du deinen Encoder aber auch einfach nur
falsch verstanden.
Poste doch mal deinen gesamten Code. Also wo wird denn dein oben
abgebildeter Code ausgeführt?
Einen Encoder kann man sich als Statemachine vorstellen. Es gibt vier
verschiedene Zustände. Nun würde ich die Zustandsübergänge ansehen.
Nun muss, es wie bei einem Mealy-Automaten ist, eine Ausgabe während der
Zustandsänderung erfolgen. Aus der Folge der Zustände schließt du dann
auf die Drehrichtung.
Zustandsänderungen gibt es vier:
1
1 2 3 4 ...usw...
2
| | | |
3
V V V V
4
___ ___
5
A ___| |___| ...usw...
6
___ ___
7
B _| |___| |_ ...usw...
Links- oder Rechtsherum wird nur durch die Abfolge der Zustände
definiert.
Um eine Änderung zu erfassen, kann man z.B. so vorgehen:
Jedesmal, wenn man den Encoder ausliest(das kann man auch in einen
Pinchange-Interrupt packen, dann aber die Statusvariable ui_oldstate
volatile machen, Masken setzen etc.) addiert man den Rückgabewert der
Funktion auf seine zu modifizierende Variable.
1
uint8_tmeine_mod_variable=encoder();
Über Entprellung musste ich mir bei dem obigen Code keine Gedanken
machen, da der meinige Encoder das schon eingebaut hatte.
Wenn der Encoder mehr Flankenwechsel pro Rastung liefert, kann man das
in eine zweite Funktion rein tun, die eben geeignet herunterteilt.
MaWin schrieb:> Dein "Drehgeber" ist wie schon die anderen geschrieben haben> offenbar exotisch, er enthält eigentlich schon die> Encoder-Auswertung aus gray-code die forw/backw Impulse zu> formen, und liefert hoffentlich diese Impuls auch entprellt> ab, denn sonst funktioniert dein code eh nicht,
Ich hab auch so ein Teil, welches tatsächlich Pulse liefert (konnte das
am Anfang gar nicht glauben bis mir das eine LED gezeigt hat). Es ist
ein Alps Drehgeber.
Das Problem war dann: Dreht man den Drehgeber eben nicht bis zur
nächsten Rastung durch sondern 'ruckelt' am Knopf in der Rastposition
ein wenig rumm, kann man den ganz toll zum Zählen bringen. Der Puls
kommt und der Benutzer lässt den Knopf aus der minimalen Auslenkung
wieder in die Rastposition zurückfallen. Eigentlich sollte dann meinem
Verständnis nach nix gezählt werden. Wird es aber, wenn man es so macht
wie der TO.
Oke, ich glaube nicht, dass jemand das so verstanden hat wie ich es
gemeint habe.
Der Drehgeber gibt natürlich immer 2 Signale aus. Und natürlich sind
auch diese Signale verschoben. Nur bleibt der Encoder einfach nicht im
High Zustand.
Beispiel ich drehe rechts bis zur ersten Einrasterung:
1
Pin1 _ _ _ - - - _ _ _
2
3
Pin2 _ _ _ _ - - - _ _ _
Falk Brunner schrieb:> Ich hab keine Lust auf dei hunderttausendste Erklärung. Kurz, dein Code> taugt nix.
Sehe ich nicht so, da er funktioniert.
Falk Brunner schrieb:> Komischer Drehgeber, wahrscheinlich flasch angschlossen oder defekt.> Oder ein Missverständniss deinerseits, was mir am wahrscheinlichsten> ist.
Oder einfach ausserhalb deines Repertoires..
Falk Brunner schrieb:> Prinzipiell richtig, aber nicht wenn es um Grundlagen geht.
U = R * I ist ne Grundlage.
Yalu X. schrieb:> allerdings fehlt eine Entprellung.
Da hast du recht, die mache ich aber wahrscheinlich per Hardware, da der
benötigte IC sowieso schon drauf ist und noch den einen oder anderen
freien Pin hat.
Ich hoffe ich konnte ein wenig Licht ins Dunkel bringen.
Edit: Habe festgestellt, dass meine Darstellung irgenwie umformatiert
wurde.
Diese Soll einfach 2 kurze Impulse darstellen, die Phasenverschoben
sind.
Dave Chappelle schrieb:> Da hast du recht, die mache ich aber wahrscheinlich per Hardware, da der> benötigte IC sowieso schon drauf ist und noch den einen oder anderen> freien Pin hat.
Brauchst du nicht, wenn du die Software-Auswertung richtig machst. Die
Port Abfolge muss 00 01 11 10 00 sein, wenn gedreht wird (bzw. in der
anderen Reihenfolge in der anderen Richtung) und nur dann, wenn diese
Folge durchlaufen wird, gilt das auch als um eine Rastung gedreht.
Klassischer Fall für zb eine kleine State-Maschine. Prellen ändert daran
genau gar nichts und wird durch die vorgegebene Reihenfolge automatisch
eliminiert.
Karl Heinz Buchegger schrieb:> Klassischer Fall für zb eine kleine State-Maschine.
Oke, das habe ich ehrlich gesagt nicht ganz verstanden. Kannst du das
etwas genäuer ausführen? Wäre mir natürlich auch recht, wenn ich es per
Software hinbekommen würde :)
Karl Heinz Buchegger schrieb:> Prellen ändert daran> genau gar nichts
Hast ja recht. Zappeln würde bei mir auch durch +1 -1 +1... dargestellt.
Außerdem ist es ja ein 2bit-Graycode.
Was ich vergaß zu meinem Code zu sagen: es ist bestimmt nicht der
platzsparendste(Flash und RAM), dafür ist es egal, wo auf einem Port die
beiden Encoderanschlüsse liegen.
mfg mf
PS: Überschneidung -.-
Dave Chappelle schrieb:> State-Maschine.>> Oke, das habe ich ehrlich gesagt nicht ganz verstanden.
Der zuletzt erfasste Zustand wird in einer Variable zwischengespeichert.
Beim erneuten Durchlauf kann man "alt" mit "neu" vergleichen und daraus
ggf. Drehrichtung und Zählung ableiten. Eine Statemachine ist erstmal
ein Rückgekoppelter Zustandsspeicher wie eine Reihe paralleler
D-Flipflops.
Diese Maschine kann eine Reihe vorher festgelegter Zustände einnehmen.
Eine Zustandsübergangs-Funktion oder -Auswertung gibt den Folgezustand
an.
Zusätzlich gibt es je nach Definition ein "Eingangs-Schaltnetz" und/oder
ein "Ausgangs-Schaltnetz", das ist nichts weiter als eine Reihe
logischer Verknüpfungen, die die Zustandsübergänge und die Ausgabedaten
beeinflussen und/oder bestimmen können.
Dave Chappelle schrieb:> Falk Brunner schrieb:>> Ich hab keine Lust auf dei hunderttausendste Erklärung. Kurz, dein Code>> taugt nix.>> Sehe ich nicht so, da er funktioniert.
Wenn die Zuordnung zwischen "funktioniert" und "taugt was" so einfach
wäre, wären viele Probleme im Alltag gelöst.
Entprellung bei einem Drehgeber in Hardware zu machen ist m.M.n.
peinlich, da es der beste Hinweis auf eine schlechte Software ist.
Begründungen wurden ja oben schon aufgeführt.
Versteh uns alle hier nicht falsch: Ich habe auch schon mal ganz am
Anfang sowas programmiert. Sogar mit Interrupts. Das hat auch
funktioniert. Aber wenn du mal hier herumschaust (Forum, Artikel
Drehgeber), wirst du feststellen, dass dies die schlechtmöglichste
Variante ist, um einen Drehgeber auszulesen.
Ich habe also meine Lektion gelernt (Ich hoffe, du machst es auch in
diesem Fall) und habe mich nach bewiesen robusterem Code umgesehen und
da gibt es quasi nur die "Standardlösung" von Peter Dannegger, auf die
dies zutrifft.
Was ich für mich noch getan habe, ist die PeDa Variante nachvollzogen
(Das hat ein Weilchen gedauert ;-)) und mit meinen "eigenen Worten" in
Code umgesetzt.
Dave Chappelle schrieb:> Der Drehgeber gibt natürlich immer 2 Signale aus. Und natürlich sind> auch diese Signale verschoben.
Ok, dann ist es also doch ein hundsgewöhnlicher Drehgeber, was schon mal
sehr gut ist. Die Bezeichungen forw und backw für die Signale sind
vielleicht etwas verwirrend.
> Nur bleibt der Encoder einfach nicht im High Zustand.
D.h. die Rastpunkte liegen an den Stellen, wo beide Signale low sind.
Alles spricht also dafür, die Auswertung so zu machen, wie im Artikel
Drehgeber gezeigt. Wie Karl Heinz schon geschrieben hat, kannst du
dir
dann die externe Entprellung sparen.
> Sehe ich nicht so, da er funktioniert.
Nein, er funktioniert nicht, wenn du den Drehgeber von einer Raste etwa
eine halbe Rastbreite weiter- und dann wieder zurückdrehst. Obwohl er am
Ende an der gleichen Raste steht, ist der Zähler inkrementiert bzw. de-
krementiert worden.
Selbst wenn das richtig gehandhabt würde, wäre der Mikrocontroller immer
so lange in der Schleife gefangen wie der Drehgeber zwischen zwei Rasten
steht. Wird also der Drehgeber sehr langsam gedreht, gibt es längere
Zeitperioden, in denen der Mikrocontroller für andere Aufgaben nicht zur
Verfügung steht.
> Der Drehgeber gibt natürlich immer 2 Signale aus. Und natürlich sind> auch diese Signale verschoben. Nur bleibt der Encoder einfach nicht im> High Zustand.> Beispiel ich drehe rechts bis zur ersten Einrasterung:> Pin1 _ _ - - - _ _> Pin2 _ _ _ - - - _ _
Wie man erkennen kann, ist es also ein ganz normaler Drehgeber mit gray
code Ausgang, nur hast du seine Funktion nicht verstanden.
Man behandelt ihn mit normalem Programmcode:
Mir war von Anfang an klar, dass der oben gennante Code "Bulletproof"
ist.
Natürlich war mir auch klar, dass dieser um längen besser ist als mein
"Bastel". Allerdings stehe ich noch am Anfang des Programmierens, habe
noch nie mit Interrupts gearbeitet und das war es auch was mich
abgeschreckt hat.
Mir ist bewusst, dass es immer eine bessere Variante gibt aber wenn ich
nicht verstehe wie der Code funktioniert, nützt er mir momentan nichts,
da ich nicht einfach ein Bastler sein will, der Schaltungen und Codes
zusammenklaubt und einfügt ohne wirklich zu verstehen was da so abgeht.
D.h. ich möchte mich gerne "Hocharbeiten" von meinem Provisorium zum
Niet- und Nagelfestem Code wie oben beschrieben.
So genug gerechtfertigt ich werde mein Projekt mit meiner Bastelweise
fertigmachen (da ich eh schon nah am Ende bin) und werde danach mal
einfachste Aufgaben mit Interrupts und richtigen Delays und all dem
lösen.
Danke für eure Hilfe bis jetzt, ich melde mich wieder wenn ich in meinem
weiteren Studium Fragen habe (was ziemlich ziemlich sicher der Fall sein
wird :))
MFG
Dave
Yalu X. schrieb:>> Nur bleibt der Encoder einfach nicht im High Zustand.>> D.h. die Rastpunkte liegen an den Stellen, wo beide Signale low sind.
Solange die Rastung korrekt funktioniert.
citb
Dave Chappelle schrieb:> D.h. ich möchte mich gerne "Hocharbeiten" von meinem Provisorium zum> Niet- und Nagelfestem Code wie oben beschrieben.
Na, dann analysier den 3 Zeiler. Das Geheimnis liegt im 4*4 Array und
den Zahlenwerten.
Einfach mal mit angenommen Input Port Werten auf dem Papier
durchspielen. Du kannst einiges dabei lernen.