www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Pollin-Drehencoder


Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
ich hab mir bei Pollin diesen Drehencoder bestellt:
http://www.pollin.de/shop/shop.php?cf=detail.php&p...
(Artikelnummer 240 313, falls der Link nicht geht)

Ich kriegs aber nicht hin den vernünftig auszuwerten.
Hat den zufälligerweise noch jemand und hat den schon verbaut.

Datenblatt.
http://www.pollin.de/shop/downloads/D240313D.PDF

Edit:
ich habs mit meiner eigenen und der Bibliothek von Peter Dannegger 
probiert

Autor: sergey (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, er macht Doppelschritte. Geht einwandfrei mit dem Sprut-Beispielcode 
auf PICs.

http://sprut.de/electronic/pic/programm/rotary2/rotary2.html

Autor: Sinusgeek (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die eine Spur dieser Drehgeber ist etwas unpräzise. Wertet man die 
Flanke der anderen Spur aus, funktioniert es sehr gut. Hier ein 
funktionierendes Beispiel in AVR-Assembler:
http://www.mikrocontroller.net/attachment/43903/sinus.zip

MfG,
der mit den Sinüssen

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sergey schrieb:
> Ja, er macht Doppelschritte. Geht einwandfrei mit dem Sprut-Beispielcode
> auf PICs.
>
> http://sprut.de/electronic/pic/programm/rotary2/rotary2.html

Das der Doppelschritte macht, weiß ich.
das kann ja Dannegers Code auch handlen.
Das Mausrad, was ich vorher provisorisch genutzt hatte, hatte auch 
Doppelschritte.

Sinusgeek schrieb:
> Die eine Spur dieser Drehgeber ist etwas unpräzise. Wertet man die
> Flanke der anderen Spur aus, funktioniert es sehr gut. Hier ein
> funktionierendes Beispiel in AVR-Assembler:
> http://www.mikrocontroller.net/attachment/43903/sinus.zip
>
> MfG,
> der mit den Sinüssen

Ich werds heut mal mit euren Codes probieren, danke.
Ich werd aus den Datenblatt aber auch nicht so richtig schlau.
Laut dem Timing-Diagramm, liegen die Rast-Postionen ja genau auf der 
Flanke.
das ist doch dämlich

Autor: Andy H. (vinculum) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es liegen hier beide Phasen auf der Flanke. Das ist noch dämlicher als 
manche Typen von Alps, wo nur ein Signal auf der Flanke liegt. Man kann 
es aber den Dingern von Alps auch vorher nicht ansehen, ob es so ist. 
Ich nehme nur welche von Hopt schuler DDM 427 zB, die nerven mit sowas 
nicht rum. Gibt es bei C und R,kosten aber mehr als aus der 
Grabbelkiste.

Autor: Doktor Gnadenlos (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Von Xilinx gibt es eine exakte Handlungsanweisung zur Auswertung eines 
Drehencoders. So geht's und nicht anders.
Wer das Prinzip verstanden hat, kann damit den VHDL-Code genauso 
erstellen wie C oder Assembler.

Autor: Sinusgeek (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also dass die Rastungen auf der Flanke liegen, kann ich nicht 
bestätigen. Mir kommt es vor, als ob eine Spur (immer dieselbe) einen 
Wackelkontakt hat, also zusätzliche Flanken erzeugt.

Wenn man dafür sorgt, dass die wacklige Spur nicht auf Flanke, sondern 
nur auf Zustand geprüft wird, dann arbeitet der Drehgeber sehr sauber. 
Ich habe ihn in mehreren verschiedenen Projekten eingesetzt und bin sehr 
zufrieden damit.

MfG

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Die eine Spur dieser Drehgeber ist etwas unpräzise.
Konkret sieht das so aus:
A   --------_________---------_________--------________
B   _--------_________---------_________--------________
Raste   #        #        #        #        #        #       
Es sind also pro Rastung zwei Schritte.

Richtig schön wäre so was:
A   --------___________---------__________--------
B   ____----------_________----------_________----
Raste    #     #    #    #    #    #    #   # 


> Von Xilinx gibt es eine exakte Handlungsanweisung zur Auswertung eines
> Drehencoders. So geht's und nicht anders.
Doch, anders gehts auch  ;-)

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Von Xilinx gibt es eine exakte Handlungsanweisung zur Auswertung eines
>Drehencoders.
der Xylinx-ansatz basiert ja quasi auf intertupts, die würd ich gern 
vermeiden.
>So geht's und nicht anders.
Schon klar, die die es bisher anders gemacht haben, haben gezaubert.

Lothar Miller schrieb:
>> Die eine Spur dieser Drehgeber ist etwas unpräzise.
> Konkret sieht das so aus:
>
> A   --------_________---------_________--------________
> B   _--------_________---------_________--------________
> Raste   #        #        #        #        #        #
> 
> Es sind also pro Rastung zwei Schritte.

Laut datenblatt sieht es aber anders aus
A   ---|_________|---------|_________|-------
B   --------|_________|---------|_________|--
            #          #        #
der 1. ist auf der Flanke, der 2. leicht dahinter


Ich hab das Problem, dass er in die eine Richtung immer eins vor und 
direkt wieder zurück springt und in die andere Richtung gar nichts 
macht.
(verwendeter Code 
http://www.mikrocontroller.net/articles/Drehgeber#...)

> Richtig schön wäre so was:
>
> A   --------___________---------__________--------
> B   ____----------_________----------_________----
> Raste    #     #    #    #    #    #    #   #
>
Das wärd as optimum, da könnte man die Abtastfrequenz auch ordentlich 
runterschrauben, da man keine kurzen Zwischenschritte erfassen müsste.
Mir ist sowiso unklar, warum man das mit den 2 schritten macht.





>
>
>> Von Xilinx gibt es eine exakte Handlungsanweisung zur Auswertung eines
>> Drehencoders. So geht's und nicht anders.
> Doch, anders gehts auch  ;-)

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
> Laut datenblatt sieht es aber anders aus
>
> A   ---|_________|---------|_________|-------
> B   --------|_________|---------|_________|--
>             #          #        #
> 
der 1. ist auf der Flanke, der 2. leicht dahinter

Das Datenblatt passt nicht ganz zu dem verkauften Drehgeben, alleine 
schon die Anzahl an Rastpunkten ist unterschiedlich. Vermutlich handelt 
es sich da um irgendwas leicht kundenspezifisches.
Das Hauptproblem an dem Drehgeber ist, dass es wirklich so aussieht wie 
Lothar es gezeichnet hat: Die Phasenverschiebung zwischen den beiden 
Signalen ist deutlich kleiner als 90°, daher muss die Samplerate mit der 
man das ganze abtastet recht hoch sein, sonst kommt es zu obigem 
Ergebnis, dass das ganze nur in einer Richtung funktioniert.

Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wertet man die Flanke der anderen Spur aus

Bitte bitte nicht so doof sein und versuchen, Flanken auszuwerten.

> verwendeter Code http://www.mikrocontroller.net/articles/Drehgeber

Der ist in Ordnung, aber recht uneffektiv geschrieben, vielleicht führst 
du ihn zu langsam aus. Effektiver wäre es so:

  int table[4][4]={{0,1,-1,0},{-1,0,0,1},{1,0,0,-1},{0,-1,1,0}};
  int position=0; // zaehlen wir mal die absolute Position
  volatile int quadrature_input; // bit 0 und bit 1 sind 
Quadratureingaenge
  int new_quadrature_value, last_quadrature_value=quadrature_input;

Folgenden Code ausreichend oft wiederholen (in der Programm Hauptscheife 
oder einer Zeitgeber gesteuerten Interrupt Routine):

  new_quadrature_value=quadrature_input;
  position+=table[last_quadrature_value][new_quadrature_value];
  last_quadrature_value=new_quadrature_value;

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
>>Von Xilinx gibt es eine Anweisung zur Auswertung eines Drehencoders.
> der Xylinx-ansatz basiert ja quasi auf intertupts
Nein, das ist eine State-Machine. Die hat nichts mit Interrupts zu tun.
Der Drehgeber-Code von Peter Dannegger ist auch eine State-Machine.

Die beiden Lösungen gehen also in die selbe Richtung.

> Effektiver wäre es so: ...
Das kommt darauf an, was der Compiler daraus macht. Hast du dir den 
eigentlichen Timer-Interrupt aus 
http://www.mikrocontroller.net/articles/Drehgeber mal angeschaut? Die 
Tabellenberechungen in deinem Code dürften länger dauern als die 
logischen Verknüpfungen...

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Vlad Tepesch schrieb:
>>>Von Xilinx gibt es eine Anweisung zur Auswertung eines Drehencoders.
>> der Xylinx-ansatz basiert ja quasi auf intertupts
> Nein, das ist eine State-Machine. Die hat nichts mit Interrupts zu tun.
> Der Drehgeber-Code von Peter Dannegger ist auch eine State-Machine.
>
> Die beiden Lösungen gehen also in die selbe Richtung.

soweit ich das verstanden habe, soll doch die erste Flanke ein FF 
triggern, das erst duch die Flanke auf dem anderen zurückgestzt werden 
kann.
die umsezzung wär demzufolge auf nem µC ein Interupt.

>
>> Effektiver wäre es so: ...
> Das kommt darauf an, was der Compiler daraus macht. Hast du dir den
> eigentlichen Timer-Interrupt aus
> http://www.mikrocontroller.net/articles/Drehgeber mal angeschaut? Die
> Tabellenberechungen in deinem Code dürften länger dauern als die
> logischen Verknüpfungen...

Ich fand auch nciht, dass der Ineffzient geschrieben wäre.
Meine eigene Lösung vorher war zwar etwas kleiner, aber auch direkter in 
meinen Code eingebettet und speiziell darauf ausgelegt nur mitzubekommen 
in welche richtung gedreht wurde, ohne mitzuzählen.

Da meine Lösung mit diesem Drehgeber aber nich funktioniert hat (wie 
gesagt, bei meinem Mausrad gings), hab ichs mit Peters Code ausprobiert.

wenn mein Kleiner Mittagschlaf macht, schau probier ichs erst mal mit 
ner höheren Abtastrate und dann mit Sinusgeeks Code.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MaWin schrieb:
>> verwendeter Code http://www.mikrocontroller.net/articles/Drehgeber
>
> Der ist in Ordnung, aber recht uneffektiv geschrieben,

Das träumst Du aber.

Wenn Du "int" nimmst, wo "unsigned char" ausreicht, ist Dein Code 
schonmal extrem größer.
Und für einen Feldzugriff muß der Interrupt ja erstmal ein 
Pointerregister freischaufeln und laden, das ist auch teuer.
Schau mal ins Assemblerlisting, Dein Code dürfte mindestens 4-mal größer 
als meiner sein.


> vielleicht führst
> du ihn zu langsam aus.

Daran dürfte es liegen. Probier mal 100µs statt der 1ms.

Was natürlich pures Gift ist, wenn man an den Eingängen noch 
Kondensatoren hat, die hebeln das Entprellen der Software komplett aus 
und dann gehts auf keinen Fall.
Wenn die Flanken zu dicht hintereinander kommen, könnten auch die 
internen Pullups zu hochohmig sein, probier mal externe 4,7k.


Peter

Autor: Matthias Larisch (matze88)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe ebenfalls die Pollin Drehencoder in größerer Stückzahl verbaut, 
es stimmt, die machen mit vielen Codes einige Probleme. Aber PeDa's Code 
funktioniert einwandfrei (wobei ich auch mit dem erst einige Probleme 
hatte)

Wie folgt setze ich ihn erfolgreich ein, aufgerufen jede ms:
/* rotary encoder on PB 0 1 2 6 low nibble */
  KEY_PORT = 0xFF;     /* KEY PORT is always input; enable pullups */
  SW_PORT = 0x00;


  uint8_t new_state;
  uint8_t index_full;

  for(temp = 0; temp <=3; temp++)   // 4 "ports"
  {

   SW_DDR = (1 << (temp));      /* SW_PORT is always zero; make one output */

    for(temp2 = 0; temp2 <= 3; temp2++)
    {
      index_full = 4 * temp;
      index_full += temp2;
      temp3 = ((1 << (2*temp2)) | (1 << (2*temp2+1)));
      new_state = KEY_PIN & temp3;
      if((new_state ^ last_cnt[index_full]) == temp3)    /* difference in bits */
      {
        if((new_state ^ last_state[index_full]) == (2 << (2*temp2)))    /* check rotation */
          enc_delta[index_full]++;
        else
          enc_delta[index_full]--;

        last_cnt[index_full] = new_state;
      }
      last_state[index_full] = new_state;
    }

  }

Der Code ist eigentlich noch nicht so alt aber nicht wirklich durchdacht 
(viel zu langer Interrupt). Das Prinzip funktioniert allerdings, man 
kann mit der Hand so schnell drehen wie man möchte (Hab das ausprobiert 
indem ich den Encoder so schnell wie's geht etwa 180° rumgerissen hab, 
dabei ist kein Schritt verloren gegangen). Kann auch sein, dass der Code 
jetzt ne leichte Abwandlung von PeDa's ist, aber den hab ich so in etwa 
auch irgendwo hier ausm Board.

Matthias

Autor: screwdriver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Encoder-Routine von peda aus 
http://www.mikrocontroller.net/articles/Drehgeber ist hocheffizient, 
wenn man mittels Drehencoder lediglich den Encoderwert (Drehwinkel) 
bestimmen möchte. Ein Fehler bspw. durch Drehung um erst eine halbe 
Rastung vorwärts und anschließend wieder rückwärts, wird sofort 
korrigiert durch die Addition und anschließende Subraktion des 
Inkrementalwertes.

Der TS möchte jedoch auch die Zählflanken auswerten, sprich, ob sich der 
Encoderwert erhöht oder vermindert hat. Genau hier ist die Routine von 
peda nicht geeignet, da der verwendete Encoder mehr Zustandswechsel als 
Rastungen hat. Dann müssen nämlich drei Pin-Status berücksichtigt 
werden, peda wertet nur den aktuellen und den vorherigen aus.

Beispiel:
Eine Drehung am Encoder nur bis kurz vor Einrasten der nächsten Stellung 
und Zurückdrehen in die Ausgangsrastung würde zunächst zu einem 
positiven Zählimpuls und anschließend zu einem negativen Zählimpuls 
führen, da ja auch die Encodervariable inkrementiert und anschließend 
dekrementiert wurde.
Tatsächlich wurde aber überhaupt keine gültige Weiterrastung ausgeführt, 
da ja bereits vor Einrasten des Drehgebers zurückgedreht wurde. Es darf 
also weder der Encoderwert verändert werden noch dürfen Zählimpulse 
generiert werden. Und dazu bedarf es der Berücksichtigung von drei 
Encoderzuständen.

MFG
screwdriver

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Häh, wo hast du denn das rausgelesen?

Ich möchte nur wissen, ob seit der letzten Abfrage nach rechts oder 
links gedreht wurde, wie weit ist Bonus, den ich nicht unbedingt 
bräuchte.

was in solchen extremfällen passiert, wie kurz vor rastung drehen und 
dann zurückfallen lassen, ist mir egal.

Ich hab aber grad ein anderes Problem, weswegen ich es doch noch nicht 
testen konnte.

Autor: screwdriver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vlad_tepesch schrieb:
>Häh, wo hast du denn das rausgelesen?

Weibliche Intuition! - Außerdem hast du weiter oben gepostet:
>Meine eigene Lösung vorher war zwar etwas kleiner, aber auch direkter in
>meinen Code eingebettet und speiziell darauf ausgelegt nur mitzubekommen
>in welche richtung gedreht wurde, ohne mitzuzählen.

Die Aussagen...
screwdriver schrieb:
>Der TS möchte jedoch auch die Zählflanken auswerten, sprich, ob sich der
>Encoderwert erhöht oder vermindert hat.
...und ...
vlad_tepesch schrieb:
>Ich möchte nur wissen, ob seit der letzten Abfrage nach rechts oder
>links gedreht wurde, wie weit ist Bonus, den ich nicht unbedingt
>bräuchte.
...hören sich für mich einigermaßen gleich an.


vald_tepesch schrieb:
>was in solchen extremfällen passiert, wie kurz vor rastung drehen und
>dann zurückfallen lassen, ist mir egal.
Gerade bei einem Drehencoder, der mechanisch unsymmetrisch ist, ist das 
alles andere als ein Extremfall sondern Alltag und meiner Meinung auch 
eine Ursache deiner Schwierigkeit den Encoder vernünftig auszuwerten.

screwdriver

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
screwdriver schrieb:
> Genau hier ist die Routine von
> peda nicht geeignet, da der verwendete Encoder mehr Zustandswechsel als
> Rastungen hat.

Nö, das klappt schon.
Deshalb gibt es ja 3 Ausgaberoutinen, je nachdem, ob der Encoder ohne 
Rastung oder mit Rastung alle 2 Schritte oder alle 4 Schritte ist.
Ich hab es auch mit allen 3 Typen getestet.

Den Interrupt interessiert das aber nicht, der ist immer gleich.


Peter

Autor: screwdriver (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@peda
Ich programmiere meine Hobbyanwendungen in einer Programmmiersprache, 
deren Namen ich in diesem Forum lieber nicht aussprechen möchte.
Deshalb habe ich anderenorts meine Lösung, speziell zu dem o.g. 
Drehencoder von Pollin, vorgestellt: 
http://www.roboternetz.de/phpBB2/viewtopic.php?t=4...

Desweiteren habe ich mir inzwischen die im Anhang befindlichen Dateien 
im Netz zusammengeklaubt und mir aus deiner Encoderroutine das 
Testprogramm encoder.c zusammengezimmert und auf meine Hardware 
programmiert.

Beide Versionen laufen sehr gut. Der Unterschied zwischen meiner und 
deiner Version ist jedoch wie ich bereits sagte, das bei dir 
Zwischenschritte beim Drehen bis vor eine Rastung und wieder zurück 
mitgezählt werden und bei mir nicht. Ob das eine Rolle spielt, ist wohl 
von der Anwendung abhängig. Da ich jedoch die Zählimpulse zur 
Menusteuerung verwende, dürfen halbe Schritte nicht registriert werden.

MFG
screwdriver

Autor: screwdriver (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Verzeihung, aber im letzten Anhang war eine unbrauchbare encoder.c. Hier 
ist eine Version, die sich auch kompilieren lässt und mit der ich meinen 
im Roboternetz dargestellten Code verglichen habe.

Ich möchte noch was zu dem Vergleich sagen:

Den Encoder-Pins habe ich jeweils so angeschlossen, weil nur noch mein 
TWI-Port frei ist.

      Vcc
       |
       -
  10K | |
       -     100R
       |      __
 PC0 --------|__|-- Ph_A
 bzw. PC1           bzw. Ph_B


Ich habe eben noch mal mit dem C-Code von peda an dem o.g. 
Billigst-Encoder von Pollin rumgespielt. Selbst dieser "schwierige" 
Encoder läuft absolut fehlerfrei. Ich muß mich schon sehr, sehr 
anstrengen um Schrittverluste zu erzielen.

Fazit:
An diesem Code kommt kein C-Programmierer vorbei. Alles Rumgebastle 
macht den Code nur kaputt. Wenn eure Encoderauswertung nicht läuft, 
sucht woanders nach Fehlern oder Verbesserungsmöglichkeiten, aber lasst 
diesen Code in Ruhe - er ist perfekt!

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
screwdriver schrieb:
> aber lasst diesen Code in Ruhe - er ist perfekt!

Nö, da ist keine dynamische Beschleunigung drin.
Wenn die noch drin wäre, dann wäre er perfekt...

Autor: Vlad Tepesch (vlad_tepesch)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
lol,
noch besser wär, wenn er auf gedanken reagieren würde.

back to topic:
ich hab jetzt die Abtastfrequenz erhöht und noch mal außerhalb meines 
Boards auf dem Steckbrett getestet. Dort funktionierts.
folgender Plot ergibt sich (anhang).
Die Flanken sind sehr nah beieinander (die zeiten sind millisek).
Abtastrate 0,5-1ms sollte aber trotzdem noch reichen.

Ein recorden in meiner Schaltung hat ergeben, dass eine Phase immer auf 
GND steht. da scheint der Encoder defekt zu sein. - hmpff

hab ihn ausgelötet und getauscht, um sicher zu gehen, dass es nicht an 
der Verkabelung liegt und siehe da, jetzt gehts.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  internen Pullups zu hochohmig sein, probier mal externe 4,7k.

genau dises problem hatte ich mit den encodern von POLLIN.
immer gerätzelt warum sich die Pullups nicht aktivierten.   rrrrr

mit 3k3, gings dann.  ;-)))

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.