Forum: Mikrocontroller und Digitale Elektronik Drehencoder auf I2C


von Timo (Gast)


Lesenswert?

Hallo zusammen,

ich benötige eine Software, die einen Drehencoder auswertet und auf 
I2C-Bus legt.
Gibt es da schon was fertiges, hat da jemand was vorzeigbares? Der 
verwendete AVR-Controller ist relativ egal, kleinstmöglich wäre sinnvoll 
- ich bin da flexibel...


Gruß

Timo

von Rudolph (Gast)


Lesenswert?

Na, das müsste doch mit einem Tiny25/Tiny45 zu machen sein.
Was ich nur überhaupt noch nicht gebraucht habe ist I2C.

Aber Drehencoder an sich ist ja nicht so wild.
Wenn man die Signale etwas filtert und vielleicht noch einen 
Schmitt-Trigger spendiert.

Im einfachsten Fall liest man in seiner while(1) Schleife die beiden 
Portpins immer wieder ein und wartet auf eine Änderung eines Pins.
Wenn sich das Signal ändert, man also einen Flanken-Wechsel feststellt,
dann sieht man sich an, ob das andere Signal gerade Low oder High hat.

Das hier habe ich mal für einen Mega16 geschrieben:

---
 while(1)
 {
  data_new = PIND; // read data from PORTD

  // check the rotary encoder
  if(data_new & (1<<PIND3)) // check if PD3 is high
  {
   if((data_old & (1<<PIND3)) == 0) // if it was low before ...
   {
    data_old |= (1<<PIND3);
    if((data_new & (1<<PIND2)) == 0) // rotate left
    {
     encoder_count = 1;
    }
    else // rotate right
    {
     encoder_count = -1;
    }
   }
  }
  else // PD3 is low
  {
   if((data_old & (1<<PIND3)) != 0) // if it was high before
   {
    data_old &= ~(1<<PIND3);
    if((data_new & (1<<PIND2)) != 0) // rotate left
    {
     encoder_count = 1;
    }
    else // rotate right
    {
     encoder_count = -1;
    }
   }
  }
 }
---

Bei dem verwendeten Drehencoder musste ich beide Flanken auswerten da 
ich sonst nur einen Impuls für zwei Rastungen erhalten hätte.
Und "encoder_count = 1" statt "encoder_counter++" sorgt dafür, dass es 
keinen Überlauf gibt falls jemand wie wild am Rad dreht.

Mit Pin-Interrupt geht das bestimmt eleganter aber mit Interrupt fähigen 
Pins ist der Mega16 ja nun nicht gerade üppig ausgestattet...

von Falk B. (falk)


Lesenswert?

@ Rudolph (Gast)

>Im einfachsten Fall liest man in seiner while(1) Schleife die beiden
>Portpins immer wieder ein und wartet auf eine Änderung eines Pins.
>Wenn sich das Signal ändert, man also einen Flanken-Wechsel feststellt,
>dann sieht man sich an, ob das andere Signal gerade Low oder High hat.

NEIN!

Drehgeber


>Mit Pin-Interrupt geht das bestimmt eleganter aber mit Interrupt fähigen
>Pins ist der Mega16 ja nun nicht gerade üppig ausgestattet...

NEIN!

Siehe Link.

MFG
Falk

von Falk B. (falk)


Lesenswert?

@ Timo (Gast)

>ich benötige eine Software, die einen Drehencoder auswertet und auf
>I2C-Bus legt.

Ausserdem, wenn es nur um EINEN Drehencoder geht, ist die Umsetzng auf 
I2C wahrscheinlich nicht sehr sinnvoll. I2C braucht zwei Pins, ein 
Drehencoder ebenso. Und das bisschen an Rechenleistung, das ein 
langsamer Drehencoder braucht schafft so ziemlich jeder Prozessor 
nebenbei. Anders ist es nur, wenn du sowieso schon I2C hast und der 
Encoder relativ schnell dreht.

MfG
Falk

von Timo (Gast)


Lesenswert?

Hi,

so ist es! Ich habe einen Hausbus, der relativ langsam per I2C bedient 
wird. Der Encoder ist weiter weg und ich würde daher die Informationen 
über den Bus übertragen (mit dem ich eh schon das Haus vernetzt habe)
Die Anzahl der Pins ist also nicht das Problem.


Timo

von Rudolph (Gast)


Lesenswert?

Ein einfacher Drehimpulsgeber erzeugt einfach nur zwei 90° 
Phasenverschobene Signale.
Encoder würde ich sowas noch nichtmal nennen, darum gilt wohl:

Drehencoder != Drehimpulsgeber

Damit hätte ich mich vertan, okay, falsches Teil.


Komischerweise nennt Alps sein STEC11B zum Beispiel auch "rotary 
Encoder".
Nur kodiert ist da nichts, es kommen nur zwei um 90° verschobene 
Signale.
http://docs-asia.electrocomponents.com/webdocs/002a/0900766b8002ae2b.pdf

Eine Positions-Erkennung ist mit dem Ding nicht möglich, eben für die 
bekannten "Endlos-Potis" die inzwischen überall verbaut werden.

Und für sowas reicht es sehr wohl aus nur das eine Signal auf 
Flanken-Wechsel zu beobachten und bei der Erkennung eines solchen Anhand 
des Pegels des anderen Signals festzustellen, ob das ein Rechts- oder 
Links-Impuls war.

steigende Flanke + Low = Links
steigende Flanke + High = Rechts

Und da der STEC11B 15 Impulse macht bei 30 Rastungen per Umdrehung 
braucht man auch noch die fallende Flanke für 30 Zählschritte pro 
Umdrehung:

fallende Flanke + High = Links
fallende Flanke + Low = Rechts


Weil das Ding billig da mechanisch ist hilft die Aussage aus dem Link 
überhaupt nicht, dass man die nicht entprellen müsste.

von Falk B. (falk)


Lesenswert?

@ Rudolph (Gast)

>Encoder würde ich sowas noch nichtmal nennen, darum gilt wohl:

>Drehencoder != Drehimpulsgeber

FALSCH!

>Komischerweise nennt Alps sein STEC11B zum Beispiel auch "rotary
>Encoder".
>Nur kodiert ist da nichts, es kommen nur zwei um 90° verschobene
>Signale.

Doch, er kodiert die Drehrichtung. Nennt sich auch Incrementalgeber. Als 
Gegenstück zum Absolutwertgeber.

>Eine Positions-Erkennung ist mit dem Ding nicht möglich, eben für die

Doch, mit Index-Spur. Haben die nicht, aber viele andere.

>bekannten "Endlos-Potis" die inzwischen überall verbaut werden.

>Und für sowas reicht es sehr wohl aus nur das eine Signal auf
>Flanken-Wechsel zu beobachten und bei der Erkennung eines solchen Anhand
>des Pegels des anderen Signals festzustellen, ob das ein Rechts- oder
>Links-Impuls war.

>steigende Flanke + Low = Links
>steigende Flanke + High = Rechts

FALSCH!

Ich empfehle dir DRINGEND das Studium der folgenden Links.
Lass dir Zeit dabei.

Drehgeber
http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29
Beitrag "Drehgeber auslesen"
Beitrag "Drehimpulsgeber mit Rasterstellung bei 00/11 auswerten"

>Weil das Ding billig da mechanisch ist hilft die Aussage aus dem Link
>überhaupt nicht, dass man die nicht entprellen müsste.

Doch. Aber das verstehst du erst, wenn du dich vo deiner irrtümlichen 
Flankenauswertung verabschiedet hast.

MFG
Falk

von Rudolph (Gast)


Lesenswert?

Ja, ist ja schon recht, State-Machine, toll.
Was anderes macht das auch nicht wirklich, vorher nachher Vergleich, 
schön.
Filtert "nur" auch gleich ungültige Zustände raus.

Meine Lösung funktioniert auch einwandfrei und zwar, weil ich die 
Signale vom Drehimpulsgeber entprellt habe.
Wenn die Signale flattern würden hätte ich ein Problem, da keine 
ungültigen Zustände erkannt werden können.
Aber mit sauberen Signalen gibt es erst gar keine ungültigen Zustände.

von Falk B. (falk)


Lesenswert?

@ Rudolph (Gast)

>Ja, ist ja schon recht, State-Machine, toll.

Du hast es nicht verstanden. Lies es nochmal und denk drüber nach. Und 
vergiss die Flanken. Es sind 4 Zustände, im Gray-Code.

MFG
Falk

von Rudolph (Gast)


Angehängte Dateien:

Lesenswert?

>Du hast es nicht verstanden. Lies es nochmal und denk drüber nach.

Also, beleg doch Du mal, warum meine Lösung nicht funktionieren können 
soll.
Bis auf Links und die Ansage, dass es nicht gehen soll hast Du ja bisher 
nichts konstruktives zur Diskussion beigetragen.
Bisher habe ich nur den Eindruck, dass Du einfach nur abblockst ohne 
verstehen zu wollen, was da überhaupt passiert.

>Und vergiss die Flanken. Es sind 4 Zustände, im Gray-Code.

Oh weia, ob man das jetzt Flanken-Erkennung oder eine Erkennung eines
Zustands-Wechsels nennt ist doch völlig egal.

Es funktioniert nicht, wenn man nur den aktuellen Zustand betrachtet,
man muss immer auch wissen, was vorher passiert ist.

Wann die Flanke genau kommt ist nicht so wichtig, Hauptsache man bekommt 
mit, dass da eine war, dass der Zustand des Signals sich geändert hat.

Sehen wir uns doch mal das angehängte Bild an.
Saubere Signale, keine ungültigen Zustände.

Wechselt 'A' von 0 auf 1 und ist 'B' dabei 0 drehen wir uns im 
Uhrzeigersinn.
Wechselt 'A' von 1 auf 0 und ist 'B' dabei 1 drehen wir uns im 
Uhrzeigersinn.

von Falk B. (falk)


Lesenswert?

@ Rudolph (Gast)

>Also, beleg doch Du mal, warum meine Lösung nicht funktionieren können
>soll.
>Bis auf Links und die Ansage, dass es nicht gehen soll hast Du ja bisher
>nichts konstruktives zur Diskussion beigetragen.

Immer sachte mit den jungen Pferden. Mein Beitrag ist der Link auf 
MEHRERE Seiten, auf denn recht klar beschrieben ist, warum man die 4 
States auswerten muss und wieso die Idee der Flankenauswertung nciht 
läuft. Soll ich die abschreiben?

>Bisher habe ich nur den Eindruck, dass Du einfach nur abblockst ohne
>verstehen zu wollen, was da überhaupt passiert.

Dein Verhalten ist psychiologisch sehr interessant.

>Und vergiss die Flanken. Es sind 4 Zustände, im Gray-Code.

>Oh weia, ob man das jetzt Flanken-Erkennung oder eine Erkennung eines
>Zustands-Wechsels nennt ist doch völlig egal.

Irrtum. Man muss eine eindeutige Sprache verwenden, um komplexe 
technische Sachverhalte ein-eindeutig darzustelle (kein Schreibfehler!).

>Es funktioniert nicht, wenn man nur den aktuellen Zustand betrachtet,
>man muss immer auch wissen, was vorher passiert ist.

Das hat doch niemand bestritten.

>Wann die Flanke genau kommt ist nicht so wichtig, Hauptsache man bekommt
>mit, dass da eine war, dass der Zustand des Signals sich geändert hat.

>Sehen wir uns doch mal das angehängte Bild an.
>Saubere Signale, keine ungültigen Zustände.

Die ungültigen Zustände entstehen, wenn deine Auswertung z.B. per 
Interrupt auf die steigende Flanke von A wartet und dann den Pegel von B 
ausliest umd die Drehrichtung zu bestimmen. So wie du es vorgeschlagen 
hast.

"Und für sowas reicht es sehr wohl aus nur das eine Signal auf
Flanken-Wechsel zu beobachten und bei der Erkennung eines solchen Anhand
des Pegels des anderen Signals festzustellen, ob das ein Rechts- oder
Links-Impuls war.

steigende Flanke + Low = Links
steigende Flanke + High = Rechts"

Einige Leute halten das für sehr clever, es ist aber schlicht falsch, 
und leicht aus dem Tritt zu kriegen. Wie? Ganz einfach. Stell dir vor, 
der Encoder pendelt zwischen den Zuständen aB und AB. Dann würde diese 
Ausertung immer steigende Flanken detektieren, einen Interrupt auslösen 
und einen Schrit nach links machen. Das wäre falsch!

Eine Abtastung der Signale im festen Zeitraster wie in den Links 
angegeben kann dies gar nichts anhaben, es würde lediglich einen Schrit 
vor und zurück pendeln (so wie es der Encoder ja real macht).

MfG
Falk

von Rudolph (Gast)


Lesenswert?

>Die ungültigen Zustände entstehen, wenn deine Auswertung z.B. per
>Interrupt auf die steigende Flanke von A wartet und dann den Pegel von B
>ausliest umd die Drehrichtung zu bestimmen. So wie du es vorgeschlagen
>hast.

Stimmt, gleichzeitig einlesen ist besser, so wie ich es in meinem 
Beispiel ja auch gemacht habe.

Allerdings dürfte das schnell genug sein, jedenfalls für meinen 
mechanischen Drehimpulsgeber mit 15 Impulsen pro Umdrehung.
Der scheitert eher an meinem 100nF/33k -> 48 Hz Tiefpass...

Nun ja, es gibt aber auch nicht nur so mechanische Spielzeug Encoder.

>>steigende Flanke + Low = Links
>>steigende Flanke + High = Rechts"
>
>Einige Leute halten das für sehr clever, es ist aber schlicht falsch,
>und leicht aus dem Tritt zu kriegen. Wie? Ganz einfach. Stell dir vor,
>der Encoder pendelt zwischen den Zuständen aB und AB. Dann würde diese
>Ausertung immer steigende Flanken detektieren, einen Interrupt auslösen
>und einen Schrit nach links machen. Das wäre falsch!
>
>Eine Abtastung der Signale im festen Zeitraster wie in den Links
>angegeben kann dies gar nichts anhaben, es würde lediglich einen Schrit
>vor und zurück pendeln (so wie es der Encoder ja real macht).

Da ich auf beide Wechsel teste ist es überhaupt kein Problem, wenn nur 
'a' wackelt und 'b' fest bleibt pendelt meine Routine auch.

Also den IRQ auf Zustands-Wechsel einstellen und beide Pins gemeinsam 
lesen.

Dann hätte man allerdings ein Problem wenn während des Interrupts ein 
weiterer Wechsel auftritt.
Das Problem hat man aber auch bei Abtastung mit festem Zeitraster wenn 
man zu langsam abtastet.

von Timo (Gast)


Lesenswert?

Hallo zusammen,

hier brechen ja Diskussionen von der Stange....

Routinen für Drehpulsgeberauswertung gibt es ja, Ablauf ist z.B. hier 
recht gut beschrieben

www.produktinfo.conrad.com/datenblaetter/700000-724999/705514-da-01-ml-D 
rehimpulsgeber_Serie_427_Dil_de-en.pdf

Ohne Eure Grundsatzfrage zu stören: Die ursprüngliche Frage/Bitte war 
nach einen fertigen Code, der Drehpulsgeber auswertet und ide Daten als 
I2C-Slave bereitstellt!?
Gibt es dazu nichts?

Timo

von Falk B. (falk)


Lesenswert?

@ Rudolph (Gast)

>Stimmt, gleichzeitig einlesen ist besser, so wie ich es in meinem
>Beispiel ja auch gemacht habe.

Ja, aber nicht in deinem ersten Posting. Da hast du was anderes 
vorgeschlagen.

>Also den IRQ auf Zustands-Wechsel einstellen und beide Pins gemeinsam
>lesen.

Ist auch schlecht, weil dann bei pendelndem Encoder oder Prellen 
tierisch viele Interrupts erzeugt werden.

>Dann hätte man allerdings ein Problem wenn während des Interrupts ein
>weiterer Wechsel auftritt.

Eben.

>Das Problem hat man aber auch bei Abtastung mit festem Zeitraster wenn
>man zu langsam abtastet.

Aber die Abtastung im festen Zeitraster ist sicher und genau! 
vorhersagbar.

MfG
Falk

von Rudolph (Gast)


Lesenswert?

@Timo:

Wie ich im ersten Posting schon schrieb, I2C habe ich noch nicht 
probiert und dafür auch keine Anwendung, sorry.
Aber der Tiny25, Tiny45 oder Tiny85 wären dafür geeignet,
die haben sechs I/O's und USART.
Und wenn es noch für ein paar LED's oder so reichen soll dann kannst Du 
Dir auch den Tiny44 ansehen.
Was fertiges ist nicht nur langweilig, da muss man schon sehr viel Glück 
haben.

@Falk Brunner

>>Stimmt, gleichzeitig einlesen ist besser, so wie ich es in meinem
>>Beispiel ja auch gemacht habe.
>
>Ja, aber nicht in deinem ersten Posting. Da hast du was anderes
>vorgeschlagen.

Nicht wirklich. Mein Code macht genau das und auch nicht im Interrupt.

Erst im letzten Absatz steht die Vermutung:
"Mit Pin-Interrupt geht das bestimmt eleganter..."

Was ich jetzt nicht mehr behaupten würde. ;-)

>>Also den IRQ auf Zustands-Wechsel einstellen und beide Pins gemeinsam
>>lesen.
>
>Ist auch schlecht, weil dann bei pendelndem Encoder oder Prellen
>tierisch viele Interrupts erzeugt werden.

Guter Punkt.

>>Das Problem hat man aber auch bei Abtastung mit festem Zeitraster wenn
>>man zu langsam abtastet.
>
>Aber die Abtastung im festen Zeitraster ist sicher und genau!
>vorhersagbar.

Hmm, beim festen Zeitraster sehe ich noch keinen Vorteil gegenüber 
meiner Abtastung in der Hauptschleife.
Wobei, ist ja quasi auch ein festes Raster - so schnell es eben geht. 
:-)

von Magnus Müller (Gast)


Lesenswert?

> Erst im letzten Absatz steht die Vermutung:
> "Mit Pin-Interrupt geht das bestimmt eleganter..."
>
> Was ich jetzt nicht mehr behaupten würde. ;-)

Mit Pin-Interrupt gehts definitiv am elegantesten...

>>>Also den IRQ auf Zustands-Wechsel einstellen und beide Pins gemeinsam
>>>lesen.
>>
>>Ist auch schlecht, weil dann bei pendelndem Encoder oder Prellen
>>tierisch viele Interrupts erzeugt werden.

Dabei hat der µC definitiv weniger Interrupts abzuarbeiten, als wenn er 
permanent im Millisekundentakt vom Timer gestört wird!

>>>Das Problem hat man aber auch bei Abtastung mit festem Zeitraster wenn
>>>man zu langsam abtastet.
>>
>>Aber die Abtastung im festen Zeitraster ist sicher und genau!
>>vorhersagbar.

Oh haue haue ha.... Kinder... wo liegt das Problem?!?

Macht die Nummer mittels Pin-Change-Interrupts auf 2 Pins (Leitung A und 
B)!

Argumentation Interruptauslastung:

Die Pin-Change-Interrupt Variante (im Folgenden mit PCIV abgekürzt) 
verursacht pro Schritt nur Einen Interrupt, wogegen die 
Timer-Interrupt Variante (im Folgenden TIV abgekürzt) eine permanente 
Interruptlast darstellt, selbst wenn der Encoder still steht.


Argumentation Geschwindigkeit:

Die PCIV kann problemlos Encodersignale im mehrstelligen kHZ-Bereich 
bewältigen, ohne die CPU bei niedrigfrequenten Signalen unnötig zu 
belasten. Die TIV hingegen belastet die CPU permanent! Will man mit der 
TIV ein hochfrequentes Signal auswerten, muss der Timerinterrupt 
entsprechend oft abgearbeitet werden. Egal ob sich der Encoder dreht 
oder nicht!!!


Gruß,
Magnetus

von Falk B. (falk)


Lesenswert?

@ Magnus Müller (magnetus)

>Mit Pin-Interrupt gehts definitiv am elegantesten...

Deine Meinung. Mehr nicht.

>Dabei hat der µC definitiv weniger Interrupts abzuarbeiten, als wenn er
>permanent im Millisekundentakt vom Timer gestört wird!

Nein. Ausserdem, was soll die unsinnige Formulierung, "vom Timer gestört 
wird" ?

>Oh haue haue ha.... Kinder... wo liegt das Problem?!?

Dass du das reale Verhalten von Drehencodern noch nicht verstanden hast.

>Die Pin-Change-Interrupt Variante (im Folgenden mit PCIV abgekürzt)
>verursacht pro Schritt nur Einen Interrupt, wogegen die
>Timer-Interrupt Variante (im Folgenden TIV abgekürzt) eine permanente
>Interruptlast darstellt, selbst wenn der Encoder still steht.

Ja. Aber nun verabschiede dich mal von deinem idealen Encoder und schau 
dir einen REALEN Encoder an. Der kann (und WIRD!) auch mal zwischen zwei 
Codes hin und her pendeln, und das bisweilen recht fix (kHz und 
schneller). Das kann zwei Ursachen haben

1) Der Encoder pendelt wirklich mechanisch
2) Die Signale prellen, was vor allem bei elektromechanischen Abstastern 
vorkommt. Optische Abtaster prellen selten, da dort schon Elektronik zur 
Signalvorverarbeitung drin ist.

Dann sieht deine Pin-Change Interrupt Auswertung ziemlich alt aus.

>belasten. Die TIV hingegen belastet die CPU permanent! Will man mit der

Richtig, und damit deterministisch.

>TIV ein hochfrequentes Signal auswerten, muss der Timerinterrupt
>entsprechend oft abgearbeitet werden. Egal ob sich der Encoder dreht
>oder nicht!!!

Richtig, aber das ist kaum ein Problem, die Auswertung braucht nur eine 
Handvoll Befehle. Zumal im Grenzfall der maximalen Geschwindigkeit die 
Belastung gleich ist.

MfG
Falk

von Roland K. (rolki)


Angehängte Dateien:

Lesenswert?

Hallo zusammen !

Ich habe mal die verschieden Codes die hier gepostet wurden eingegeben
und gesestet, weil ich eine Lösung suchte. keiner der Codes brachte den 
gewünschten Erfolg. Aber es hat mir schon etwas weiter geholfen.

Jetzt habe ich einen Code entwickelt, mit dem ich bis zu acht Decoder
gemultiplext über ein 74HC138 abfrage. Dieser Code basiert darauf, nicht 
einen Wechsel abzufragen wie in den vorrangestellten Codes, sondern eine
Folge von 4 paar Bitwechsel. So lässt sich jeder Decoder exakt abfragen 
und auch die Mittelstellung zwischen 2 Rasterpunkten wird ignoriert.

Allerdings lässt es sich manchmal nicht vermeiden, das irgendein Decoder
der betätigt wurde, offensichtlich nicht ganz einrastet. Ich habe die 
günstigen Alps Decoder von Conrad verwendet.Damit lassen sich die 
anderen erst wieder richtig abfragen, wenn man diesen Decoder betätigt 
und rasten lässt.

Die Abfrage ist so aufgebaut, das alles was sonst noch gemacht werden 
muß im jeweiligen Programm weiter läuft.

Es versteht sich von selbst denke ich, wenn jemand nur einen Potio 
abfragen will, das er dann halt nur die potinummer fest auf auf NULL 
setzen muß.

Leider habe ich kein Schaltplan programm und so kann ich nur ein 
fertiges
Layout drann hängen.

viel Spaß damit

rolki

von Roland K. (rolki)


Angehängte Dateien:

Lesenswert?

Ups ! Hatte es nicht geschafft den code anzuhängen ....

von Falk B. (falk)


Lesenswert?

@  Roland Klutschewski (rolki)

>Dateianhang: dekoder_multiplex_abfrage.doc (30 KB, 0 Downloads)

>Ups ! Hatte es nicht geschafft den code anzuhängen ....

Und auch nicht geschafft mal 5s klar zu denken. Quelltexte als .doc 
File, Oh Mann!!!!

Und mal was über Bildformate zu lesen würde dir auch gut tun.

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.