Forum: Projekte & Code Drehgeber auslesen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Peter D. (peda)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Die Encoder liefern einen Gray-Code.
Anbei ein C-Programm.

Für mittlere Geschwindigkeiten oder manuelle Bedienung ist das Abtasten
im Timerinterrupt das Optimale. Damit umgeht man sämtliche Probleme mit
der Flankenumschaltung beim externen Interrupt. Außerdem kann man auch
mehrere Encoder anschließen. Der Rechenzeitaufwand ist
vernachlässigbar.


Die Funktion get_gray_delta() liefert die Anzahl der Impulse seit dem
letzten Aufruf zurück.
In Zeile 8 und 9 kann man auswählen, ob bis zu 127 oder 32767 Impulse
seit der letzen Auswertung gespeichert werden sollen.

Die Decodierroutine arbeitet mit einer Tabelle aus den 16 möglichen
Kombinationen der 2 aktuellen und der 2 vorherigen Bits.
Bei den Übergängen:
0->1->3->2->1 steht eine "+1" in der Tabelle und bei:
0->2->3->1->0 eine "-1".
D.h. der Counter graycount wird dadurch um 1 erhöht oder erniedrigt.


Diese Routine habe ich z.B. auch für die hochgenaue X-Y-Positionierung
bei einer Steppermotorsteuerung verwendet (+/-50µm). Dabei wurden
optische Encoder verwendet.


Peter

von Peter D. (peda)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Anbei eine 2. Variante ohne Tabelle, die noch schneller und kleiner
ist.

Das Codebeispiel ist diesmal für den AVR geschrieben, die Änderungen
für den 8051 sind aber nur minimal (Definition der Portpins,
Timerinitialisierung).


Funktionsweise:

Das Einlesen der beiden Signale erfolgt mit:
  if( PHASE_A )
    ...
  if( PHASE_B )
    ...
Dadurch kann man beliebige Pins von beliebigen Ports nehmen.

Wenn man die beiden Encoder-Signale als Binärzahl darstellt, ergeben
sich folgende Zustände:
00 - 01 - 11 - 10 -10
Dieser Code wird auch Gray-Code genannt. Das besondere Merkmal des
Gray-Code ist, daß sich zwischen aufeinanderfolgende Werten immer nur
ein Bit ändert. Dadurch können keine Fehldekodierungen auftreten.

Würde man nun die Differenz zwischen zwei Codes bilden, käme nur Müll
heraus, da die CPU ja im Binärcode rechnet.
Eine Lösung ist die obige, wobei mittels einer Wertetabelle eine
Gray-Code Subtraktion realisiert wird.

Einfacher ist jedoch eine Umwandlung des Gray-Code nach Binär, wie sie
in diesem 2.Programmbeispiel erfolgt:

Gray-Code   Binär-Code
00          00 (0)     o.k.
01          01 (1)     o.k.
11          10 (2)     ändern
10          11 (3)     ändern

Wie man sieht, muß man also nur das niederwertige Bit umdrehen, sobald
das höherwertige Bit gesetzt ist.

Diese Anweisung:
  if( PHASE_B )
    i ^= 3;
setzt das höherwertige Bit und invertiert das niederwertige, fertig ist
die Codeumwandlung.

Danach kann man nun die Differenz zwischen 2 aufeinanderfolgenden
Auslesungen bilden:
  i -= enc_last;

Erfolgt keine Änderung, ist die Differenz 0.

Erfolgt eine Änderung über 2 Schritte, ist die Differenz 2. Das kann
aber nur bei Störungen passieren oder wenn die Abtastgeschwindigkeit zu
langsam ist. Die Drehrichtung läßt sich dabei nicht bestimmen. Deshalb
wird auch eine solche Änderung ignoriert:
  if( i & 1 ){
    enc_last += i;

Bei einer Änderung über einen Schritt, ergeben sich je nach
Drehrichtung folgende Werte (in Klammern der 2-Bit Wert als
Dezimalzahl):

Vorwärts:
00 - 11 = 01 (1)
01 - 00 = 01 (1)
10 - 01 = 01 (1)
11 - 10 = 01 (1)

Rückwärts:
00 - 01 = 11 (3)
01 - 10 = 11 (3)
10 - 11 = 11 (3)
11 - 00 = 11 (3)

Maskiert man nun das höherwertige Bit (2) heraus und zieht 1 ab,
ergeben sich die Byte-Werte +1 bzw. -1, die man zu dem Zählerwert
addiert, um ihn rauf bzw. runter zählen zu lassen:
    enc_delta += (i & 2) - 1;



Peter

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Naja, da fehlt noch Fehlerkorrektur, wie man merkt, wenn man einen
Treiber für einen mechanischen Drehgeber macht.
Die beiden Zähler für eine Flanke, die einer halben Raster-Drehung nach
rechts/links  entsprechen, resete ich deshalb wenn eine stationäre
Position (d. h. input_l == input_r) erreicht ist.
Damit kann man auch stark prellende Drehgeber gut entprellen, denn
dadurch werden durch Prellen entstehende halbe Raster-Drehungen
ignoriert (fehlerkorrigiert) ;-)

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
@nobody0,

also ich verstehe nur Bahnhof.
Welche "beiden Zähler" meinst Du denn, da ist doch nur einer ?

Prellungen werden nämlich durch den Gray-Code automatisch kompensiert.
Wenn Du aber Zweifel an der Funktion hast, dann probiere es doch bitte
erstmal aus, anstatt nur irgendwas zu vermuten.

Bzw. erkläre bitte etwas genauer, was Du eigentlich meinst.


Es ist natürlich möglich, daß man Schritte verliert, wenn man sehr
schnell dreht. Dann muß man aber nur die Abtastzeit verkürzen und schon
gehts wieder.
Der Wert in meinem Beispiel (11,0592MHz  256  8 = 5,4kHz) sollte in
der Regel ausreichend sein.


Peter


P.S.:
Wenn man aber Drehgeber nimmt, die nur alle 2 oder 4 Phasen einrasten,
muß man den Zählwert nach dem Auslesen /2 bzw. /4 teilen.

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich meine einfach einen Zähler für die halben Linksdrehungen und einen
für die halben Rechtsdrehungen. Von einem zum anderen Rasterpunkt hat
man ja zwei halbe Drehungen und am Rasterpunkt einen stationären
Zustand (beide Adern 0 oder 1).
Deshalb setze ich an einem Rasterpunkt beide Zähler auf 0 und logge die
Fehler. Dadurch kann man diagnostizieren wie zuverlässig der Drehgeber
ist und ihn austauchen bevor das Prellen so stark wird, dass es nicht
mehr zu 99,9 % korrigierbar ist.
Ich habe das in einer ISR gemacht und es funktioniert gut, wobei aber
aus Kostengründen auf das Austauschen u. loggen verzichtet wird.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
"auf das Austauschen u. loggen verzichtet wird"

Wenn Du sie nicht auswertest, dann streich sie gleich ganz aus Deinem
Programm. Ist so doch nur toter Code.


Wie gesagt, das Prellen stört bei meinem Code nicht.
Wenn durch eine Störung mal zu weit gezählt wird, wird sofort in der
nächsten Abtastung, wo die Störung vorbei ist, zurück gezählt und alles
stimmt wieder. Deshalb nimmt man ja den Gray-Code.


Peter

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Den toten Code sollte der Compiler wegoptimieren und wenn es eng wird,
kann ich den betreffenden Code mit defines kapseln.

Dass das Prellen bei mechanischen Drehgebern sehr wohl stören kann,
merkt man wenn einige tausend Geräte produziert werden und einige
reklamierte ein starkes Prellen des Drehgebers zeigen. Da zeigt sich
dann der Unterschied zwischen Theorie und Praxis. Mit Fehlerkorrektur
kann man da noch einiges machen.

Übrigens hat der Gray-Code allein nichts mit Fehlertoleranz zu tun; der
Gray-Code minimiert nur die Hamming-Distanz benachbarter Codeworte,
aber beim Prellen hilft das nicht, weil der Gray-Code allein keine
Fehlerkorrektur macht; er ist kein ECC-Code.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
"Übrigens hat der Gray-Code allein nichts mit Fehlertoleranz zu tun"

Das ist falsch.

Der Trick beim Gray-Code ist nämlich, daß sich immer nur ein Bit
gleichzeitig ändert.
D.h. es kann immer nur ein Signal prellen und das bewirkt nur das Hin-
und Herzählen zwischen 2 aufeinanderfolgenden Zählwerten.
Sobald das Prellen vorbei ist, liegt also immer der richtige Zählwert
vor.


Übrigends ist die Polling-Methode im Timerinterrupt automatisch viel
sicherer, als die Flankeninterrupt-Methode.
Beim Timerinterrupt muß nämlich die Störung zufällig auch noch
gleichzeitig mit dem Abtastzeitpunkt zusammenfallen.

Der Flankeninterrupt wartet dagegen geradezu sehnsüchtig auf jede
Störung und kann dadurch auch auf jeden noch so kurzen Störimpuls (z.B.
elektrostatisch aufgeladene Kleidung) fehlreagieren.


Peter

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> Der Trick beim Gray-Code ist nämlich, daß sich immer nur ein Bit
> gleichzeitig ändert.

Ja, aber durch Prellen ändern sich kurz hintereinander mehrere Bits und
wenn man die nicht fehhlerkorrigiert, hat man ein (unnötig) starkes
Prellen.
Praktisch sieht das so aus, dass eine Drehung des Drehgebers um ein
Raster meist +/-=2 (statt +/-=1) bewirkt und machmal auch +/-0 (statt
(+/-=1) bewirkt. Mit der Fehlerkorrektur bekommt man diese Fehler fast
immer beseitigt.


> D.h. es kann immer nur ein Signal prellen ...

Falsch; es könen sehr wohl beide Adern gleichzeitig ein Prellen zeigen.
Die Annahme, das zu einem Zeitpunkt nur ein Fehler auftreten kann, ist
einfach falsch. Deshalb sind. z. B. in Kernkraftwerkten die wichtigen
Teile mindestens doppelt redundant, damit zwei gleichzeitig auftretende
Fehler nicht zum GAU führen.
Aus Kosten- oder anderen Gründen wird aber meist mehr als ein Fehler
außerhalb der Vorstellungskraft verlagert ...


> Beim Timerinterrupt muß nämlich die Störung zufällig auch noch
> gleichzeitig mit dem Abtastzeitpunkt zusammenfallen.

Ich nehme natürlich keinen Timer-Interrupt; davon habe ich nix
geschrieben. Ich verwende einen Port-Interrupt.


> Der Flankeninterrupt wartet dagegen geradezu sehnsüchtig auf jede
> Störung und kann dadurch auch auf jeden noch so kurzen Störimpuls
> (z.B.
> elektrostatisch aufgeladene Kleidung) fehlreagieren.

Logischerweise ist vor jedem Eingang mit enabletem Interrupt ein
Tiefpass, der sowas wie Elektrostatische Entladungen rausfiltert.
Bei MCs ohne ausgeprägte Hysterese, wie dem Samsung S3C2410, verwende
ich zwischen dem Tiefpass u. dem MC Schmitt-Trigger.

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Nachtrag: Hosted (z. B. unter embedded Linux) Polling zu betreiben wäre
keine gut Idee; das benötigt einiges an CPU-Leistung und unterbricht
andere wichitge Tasks.
Mit einem eigenen Tastatur-Contoller ist Polling natürlich immer
optimal, aber aus Kostengründen ist sowas ja selten und sowas wie einen
Tiefpass zum Rausfiltern von elektrostatischen Entladungen kann man
damit nicht komplett ersetzen.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
"das benötigt einiges an CPU-Leistung"

In meinem Beispiel sind das maximal 5%, wobei die Abtastfrequenz sehr
hoch angesetzt ist und bei Bedarf noch reichlich verringert werden
kann.

Ich habe allerdings kein embedded Linux laufen sondern nur nen schnöden
AVR und dem machen die 5% nicht das geringste aus.
Insbesondere, da dieser Timerinterrupt noch ne Menge anderer Aufgaben
mit erledigt, relativiert sich das reine Abtasten auf etwa 2%
CPU-Last.
Bei Mikrokontrollern ist die Verarbeitungsgeschwindigkeit ja noch
linear zur Taktfrequenz. Also ein 16MHz AVR mit 5% CPU-Grundlast ist
exakt gleichschnell wie ein 15,2MHz AVR ohne Grundlast.


Dagegen reagiert der Flankeninterrupt schon auf sehr kurze Impulse
(AVR: wenige ns). Da reichts manchmal, daß man beide Signalleitungen
wenige cm ungeschirmt nebeneinander führt und schon koppelt sich die
Schaltflanke kapazitiv von einem zum anderen Signal über, d.h. beide
Interrupts können auslösen.


Du hast natürlich recht, daß bei absolut schrottigen Drehgebern, z.B.
durch Verschmutzung, lockere Kontaktnieten usw. auch auch auf dem
anderen gerade nicht betätigten Kontakt ein Impuls entstehen kann.
Dagegen ist aber auch jede noch so komplizierte Fehlererkennung
machtlos.
Jede Kette ist nur so stark, wie ihr schwächstes Glied.
Deshalb wird keiner auf die Idee kommen in einem KKW Schrott
einzusetzen und dann an anderer Stelle das mit Software auszugleichen
versuchen, d.h. dieses Beispiel ist einfach hirnrissig.


In Low-Cost Konsumgütern aber zählt kein Mensch die Rastungen mit,
sondern schaut aufs Display was dort angezeigt wird. Und wenn da nach
einer kompletten Umdrehung nur 99 statt 100 angezeigt wird, wen störts,
einfach einen Schritt weiter drehen.


Ich benutze aber auch das gleiche Programm zur Positionsbestimmung, wo
es auf absolute Genauigkeit ankommt. Allerdings werden dort
grundsätzlich optische Positionsgeber verwendet, d.h. die prellen
nicht.
Auch habe ich den Code einfach 3* hintereinander geschrieben, da alle 3
Koordinaten ausgelesen werden müssen. Ich wüßte jetzt gerade keinen µC,
der 6 Flankeninterrupts hat.


Ich denke mal, weitere rein theoretische Vermutungen, daß mein Code
fehleranfälliger sein müßte, nur weil er kürzer ist, sind überflüssig,
solange Du ihn noch nicht einmal ausprobiert hast.
Die Praxis ist doch immer noch der beste Test.

Ich weiß, er ist nicht gerade einfach zu verstehen, aber dann sieht
man, daß er sehr fehlertolerant ist.


Peter

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Also die Kunden zählen schon mit und wenn die z. B. genau 200 einstellen
wollen aber die Anzeige (mit Einheit 5) mal auf 210 springt oder auf
195 stehen bleibt dann nervt das schon; da kann man schon verstehen,
dass deshalb ausgetauscht wird.

Das mit den 6 Flanken-Interrupts verstehe ich nicht, denn z. B. ein
MSP430F149 hat 16 Eingänge die flankengetriggert sind und der S3C2410
noch einige mehr.

Und Koppeln von Eingängen habe ich noch nie gesehen; ich habe nur mal
Leitungsreflektionen auf einem IIS-Bus gefunden, die aber mit
Tiefpässen problemlos weggefiltert werden konnten.

von Ingo Henze (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich würde mal sagen, das hängt wie immer vom speziellen Anwendungsfall
ab :-)

Für mich hat die Timerinterrupt-Abfragemethode den großen Vorteil, das
ich mehrere Drehgeber multiplexen kann.
So benötige ich z.B. für die Auswertung von 8 Drehgebern nur 5
I/O-Leitungen (und etwas Zusatzelektronik: 1aus8-Decoder, Dioden), mit
einer weiteren Leitung (und einem weiteren 1aus8-Decoder) komme ich
dann auf 16 Drehgeber.

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Für 8 Drehgeber und 5 Leitungen braucht man doch keine
Zusatz-Elektronik, außer eine Diode pro Schalter.
Mit 5 Leitungen kann man doch ganz einfach 4 + 3 + 2 + 1 = 9 Schalter
einzeln abfragen.

von Ingo Henze (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hmmmm, dat versteh ich nicht ganz !?
Andererseits haben 8 Drehgeber ja zusammen schon 16 Schalter, zumindest
die, die ich verwende (den Drucktaster zähle ich da mal nicht mit, den
brauch ich eh nicht, sonst wären es sogar drei :-).
Kannst Du das bitte mal etwas näher erläutern.
Danke!

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Achso; bei 16 statt 8 Schaltern ist es etwas anders.

Also bei einer einfachen Matrix-Schaltung braucht man 4+4 Leitungen,
aber es geht effizienter: Man kann ja einfach von der Leitung n zu den
Leitungen n-1 ... 0 je einen Schalter (m. serieller Diode) anschließen,
also insgesammt 0 + 1 + 2 + 3 ... + n-1.
Bei 7 Leitungen kommt man so auf schon 6+5+4+3+2+1=21 Schalter; bei 8
zweiadrigen Drehgebern kann man also bei 7 Leitungen noch 5 Taster
verwenden.
Das ist natürlich nur für den einfachen Fall, dass die Dioden nur den
Strom in eine globale Richtung durchlassen, also von Leitung k nach l >
k oder umgekehrt; allgemein kann man natürlich (n-1)! Schalter
abfragen, also bei n=7 kann man 6*5*4*3*2=720 Schalter abfragen.
Natürlich kann man das auch noch ausbauen, indem man Schalter (mit
Diode) nicht nur zwischen den Daten-Leitungen sondern auch noch +UB und
GND sowie NC verwendet.

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Korrektur: Mit NC geht's bei Schaltern natürlich nicht ;-)
Mit +UB und GND (über ausreichend hochohmige Widerstände), und weil man
pro Verbindung 2 Schalter (mit antiparallelen Dioden) verwenden kann,
kann man insges. 2*(n-1)! + 2*n Schalter abfragen, also mit 7 Leitungen
1454 Schalter. Zum Dekodieren brauch man aber mehr Rechenzeit als bei
einer einfachen Matrix-Schaltung.

von Ingo Henze (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich würde mal sagen, das hängt wie immer vom speziellen Anwendungsfall
ab :-)

Für mich hat die Zusatzelektronik-Methode den großen Vorteil, das
ich die Teile bereits habe, die Schaltung nebst Software erprobt,
übersichtlich und kompakt ist, und der Rechenleistungsbedarf in einem
vertrebaren Rahmen bleibt.
Mit einer weiteren Leitung (und einem weiteren 1aus8-Decoder) kann ich
das ganze bei Bedarf mit nur kleinsten Änderungen der Abfrageroutine
auf 16 Drehgeber erweitern (sofern ich mal eine wirklich günstige
Quelle für die Teile finde sollte:-).

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja, eine Auswertung für 1454 Schalter (an 7 Leitungen (+UB u. +GND) habe
ich bisher auch nur theoretisch gemacht und in der Firma wird bisher
praktisch nur ein Schalter pro Eingang verwendet, obwohl es kaum
ausgenutzt wird; Shortcuts gibt's bisher noch nicht.

Nachtrag zur Grey-Dekodierung: Die einfachen Routinen, vom Anfang des
Threads, habe ich so in vorhandener Software gefunden und durch meine
Variante mit Fehlerkorrektur ersetzt; die ist also praxis-erprobt und
wirksam.

von Ingo Henze (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Andererseits hat das was, 1454 Schalter, das wären ja dann mehr als 700
Drehgeber (wenn ich jeweils zwei Kontakte pro Geber annehme). Ein
unbestimmte Gefühl sagt mir aber auch, das es bestenfalls, wenn
überhaupt, theoretisch funktionieren würde.

Aus meiner Sicht kommt man mit 16 Drehgebern ganz gut hin, denkbar wäre
noch eine Erweiterung auf 24 oder höchstens 32 (ja, dann bin ich schon
bei 7 Leitungen + zwei weiteren 1aus8-Decodern).

Es gibt zwar auch Geräte mit mehr Drehreglern (z.B. Drehbank mit 64),
aber da wird das schon leicht unübersichtlich.
Ich würde dann eher noch 8 Schieberegler und ein oder zwei
Mini-Joysticks dazunehmen.

Falls ich meine Gerät jemals fertig bekomme, kann ich es ja dann mal
kurz hier vorstellen...

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
"Die einfachen Routinen, vom Anfang des Threads"

Ich muß gestehen, daß es zwischen beiden Varianten einen kleinen aber
feinen Unterschied gibt:

Die Tabellenversion (1.Beispiel) zählt nicht weiter, wenn ein Übergang
über 2 Stufen erkannt wird, speichert ihn jedoch trotzdem ab. Dadurch
kann es passieren, wenn es sich um ein Prellen beider Kontakte während
eines Übergangs gehandelt hat, daß dann die nächste Abtastung einen
Zähler in die falsche Richtung macht.

Die Differenzmethode (2.Beispiel) ignoriert einen Übergang über 2
Schritte auch, aber speichert ihn nicht ab. Sie zählt also erst weiter,
wenn nur ein einstufiger Übergang erkannt wurde, also die Prellung
vorbei ist.

Die obigen Aussagen bezüglich der Fehlerfestigkeit beziehen sich daher
ausschließlich auf das 2.Programmbeispiel.

Es liegt ja in der Natur der Sache, daß eine spätere Codevariante in
der Regel weiter entwickelt und daher besser ist.

Es würde auch keinen Sinn machen eine gleichartige Funktion zu
veröffentlichen, wenn sie keinerlei Vorteile hätte.


Es gibt im Prinzip folgende Drehgeberaufbauten:

Billige Drehgeber arbeiten mit einer Scheibe mit metallisierten
Segmenten, auf der 3 Schleifkontakte aufliegen. Dann ist es in der Tat
möglich, daß durch Verschmutzungen auch der 2. Kontakt unterbrochen
wird, während er auf der metallisierten Fläche gleitet.

Etwas bessere Drehgeber arbeiten mit einer Art Nockenscheibe, die 2
Mikrotaster abwechselnd betätigt. Damit ist eine gleichzeitige
Umschaltung beider Kontakte ausgeschlossen. Beide können zwar prellen
aber eben nicht gleichzeitig.

Das beste sind aber optische Drehgeber (Mausprinzip). Sie schalten
nicht gleichzeitig und prellen auch nicht.


Und wenn die Portpins nicht ausreichen, kann man an je einen 74HC165 je
4 Drehgeber anschließen und davon beliebig viele per SPI über insgesamt
nur 3 Leitungen einlesen.


Peter

von Andi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe festgestellt, das die "billigen", aber bei Conrad sehr teuren
;-), Drehgeber sehr stark prellen können, wie der ddm427, auch wenn man
nicht all zu schnell dreht.
Da gibs entweder nur die passenden Kondensatoren oder, wie Nobody0
meint, Hochpassfilter einzusetzen, oder per Software entprellen.
Habe leider keine passenden Kondensatoren da gehabt (zu klein oder zu
groß) und den Drehgeber per Pin Change IRQ ausgelesen und per Software
entprellt.
Hier der Ausschnitt aus dem Prog für nen Tiny12 mit Pin Change IRQ:

PinIRQ:
.....
rjmp Dreher
.....
PinIRQ1:
  reti

Dreher:
  in r16,pinb         Neuen Wert von A und B auslesen
  andi r16,0b11000    A und B an PB5 und PB4 ausmaskieren
  cp r16,KeyAlt       Hat sich was verändert?
  breq DrExit         Wenn nicht, dann raus

  ldi r16,250         Ca. 1 ms warten, bis evtl. prellen weg ist
Dreher1:
  nop
  dec r16
  brne Dreher1

  in r16,pinb         Neuen Wert erneut einlesen
  andi r16,0b11000    und maskieren
  cp r16,KeyAlt       Vielleicht doch nur ein prellen?
  breq DrExit         Dann raus

  mov r17,r16         Neuen Wert kopieren
  lsr r17             2 mal nach rechts schieben
  lsr r17
  or r17,KeyAlt       und mit dem alten Wert verknüpfen
  mov KeyAlt,r16      Neuen AB-Wert sichern
  ldi r20,0b11110     XOR-Maske für ABAB
  sbrs r17,4          Ist Bit 4 bzw 3 gesetzt?
  eor r17,r20         Wenn nicht, letzen und vorigen AB-Wert
invertieren
  cpi r17,0b10000     War die letzte Bit-Folge von ABAB 1000?
  breq DrLinks        Dann wurde 1 Raster nach links gedreht
  cpi r17,0b10110     War es 1011?
  brne DrExit         Wenn nicht, ein falscher Wert (prellen?)

DrRechts:                   Ansonsten war es eine Rasterstelle nach
rechts
  cpi VZeit,VZeitMax  Abhandlung zur Rechts-Drehung
  breq DrExit
  ldi r16,VZeitStep
  add VZeit,r16
DrExit:
  rjmp PinIRQ1

DrLinks:
  cpi VZeit,VZeitMin  Abhandlung zur Linksdrehung
  breq DrExit
  subi VZeit,VZeitStep
  rjmp PinIRQ1

Bin damit am besten zurecht gekommen und habe es in eine Pin Change
Interruptroutine geschmissen.
Da muß man schon sehr schnell drehen, ca. in 0,3 Sekunden einmal um die
Achse, damit das Prog den Faden bzw. die Impulse oder Prellungen
empfängt verliert.
Und das trotz der Wartezeit von ca. 1 ms die ja als Entprellung dienen
soll.
Und wenn keiner am Geber dreht wird das Sub-Prog nicht ausgeführt.

Gruß
Andi

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Das Problem bei 700 drehgebern an 7 Leitungen wäre das Abfragen - es muß
mit Pin-Wackeln (ein Pin high, alle anderen, bis auf den einen auf low
usw.) geprüft werden ob der Schalter zwischen Leitung 0 u. 1 und der in
umgekehrte Richtung geschlossen ist usw. - also 1400 einzelne Abfragen.
Damit wäre ein Tastatur-Controller wohl voll ausgelastet.
Aber man kann so viel Hardware sparen ...

von Andi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja wie denn?
Ich check immer noch nicht, wie man an 7 Leitungen 700 Drehschalter
oder 1400 Taster dranbekommen soll.

Gruß
Andi

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ganz einfach: Ein Schalter mit eine Diode, so dass Strom nur von Leitung
0 nach 1 fließen kann, einer in entgegengesetzter Richtung usw..
Dann muß beim Abfragen ein Pin auf low gelegt werden und alle anderen,
bis auf einen (Eingang mit pullup) auf high. Wenn der eine Eingang low
ist, dann ist der Schalter von der Leitung auf low zu dem einen Eingang
geschlossen.

So komme ich nun je Eingang auf 2*(n-1) Schalter und insgesammt auf
2*n*(n-1) also 2n^2-2n; bei 7 also 35.
Da ist mir wohl ein Flüchtigkeitsfehler unterlaufen ...

Jedenfalls bekommt man so deutlich mehr als mit einer Matrix-Schaltung;
bei 7 Leitungen wären mit einer Matrix-Schaltung nur maximal 3*4=12
Schalter anschließbar.

Das fakultative Ansteigen, das ja stärker als ein exponentielles
Ansteigen ist, bekommt man hin, wenn man n Leitungen mit n Leitungen
verbindet, denn das entspricht einer Permuation von n Elementen und von
denen gibt es bekanntlich n!. Das hatte ich mit Schaltern verwechselt,
weil es verwandte Sachen sind.

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Naja, um diese Zeit stimmt das Beispiel nicht ganz; 2*n(n-1) ist mit n=7
natürlich 84. Gegenüber der einfachen Matrix-Schaltung hat man damit 7
mal mehr Schalter!

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Nachtrag: Je nach verwendeten Pegeln muß man die Dioden ggf. geeignet
auswählen (höhere Schwellspannung), damit nicht Strom über mehrere
Schalter (u. den seriellen Dioden) fließt. Bei sowas wie 1N4148 braucht
man sonst einen MC mit einer Versorgungsspannung um 2 V, aber viele MCs
sind ja bis 1,8 V spezifiziert.

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Also das Abfragen habe ich mir nochmal mit einem MC mit Pullups
überlegt: Es muß Leitung m auf GND geschaltet werden, während alle als
Eingänge mit Pullups geschaltet sind. Dann sind alle diejenigen
Eingänge auf 0, bei denen der Schalter zw. m u. der Leitung geschlossen
ist. So testet man insgesamt n mal durch. Bei einem 16-Bit-Port kann
man so mit 16 Port-Abfragen 240 Schalter abfragen.

Da fällt mir auch auf, dass es natürlich nur n*(n-1) Schalter sind (d.
h. ohne Faktor 2), die man so abfragen kann ...

Jedenfalls hat man so n^2-n gegenüber (maximal) (n/2)^2 gegenüber der
Matrix-Schaltung, also bei n=7 schon 3,5 mal mehr Schalter.

von philip (Gast)


Bewertung
0 lesenswert
nicht lesenswert
hmms

könnte bitte einer mal das programm für nen 2313 umportieren ?
und wenn an dreht das ein kurzer impuls für jede richtung an einem
pin ausgegeben wird?

währ ich echt dankbar für!!!! ich komme einfach nicht weiter

von avusgalaxy (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube, so müßte es gehen...

von Philip (Gast)


Bewertung
0 lesenswert
nicht lesenswert
schon mal danke, kannst du mir auch die pins duch sagen ?
b1 zb oder b2 ... d etc.. das ich die pins weiss werd da net so ganz
schlau raus

von avusgalaxy (Gast)


Bewertung
0 lesenswert
nicht lesenswert
An PORT D,0 und PORT D, eins kommt jeweils eine Led.

Ab PORT D... 4 und 3 den Drehgeber.. Ah ja, so solls ausehen:


.include "2313def.inc"

.set DIPGPin=PinB    ;Port mit Drehimpulsgeber
.set DIPGChA=4       ;Pin mit Channel A
.set DIPGChB=3       ;Pin mit Channel B
.set DIPGBT=2        ;Pin mit Button
.def DIPGAlt=r4      ;Vorriger Zustand von Channel A
.def DIPG=r5         ;Drehimpulsgeber-Aktion. Nach Abfrage löschen
.def ButtonAlt=r6    ;Vorriger Zustand des Buttons

 ldi r16, RAMEND  ;Stackpointer initialisieren
 out SPL, r16

 ldi r24, 0xff
 out DDRD, r24

 ldi r24, 0xff
 out PORTD, r24

 ldi r24, 0xff
 out DDRb, r24

main:

 in r17,DIPGPin      ;1   Drehimpulsgeber lesen
 mov r18,r17         ;1   und in die Working-Register
 mov r19,r17         ;1   kopieren

 andi r18,1<<DIPGChA ;1   Channel A des Drehgebers ausmaskieren.
 cp r18,DIPGAlt      ;1   Hat es sich verändert?
 breq DrButton       ;1/2 Wenn nicht, dann Button prüfen.
 mov DIPGAlt,r18     ;1   Aktuellen Zustand von Channel A sichern
 lsl r19             ;1   Aus der Kopie des Drehgeberports
 andi r19,1<<DIPGChA ;1   Channel B ausmaskieren.
 cp r18,r19          ;1   Ist Channel A = Channel B?
 breq DrLinks        ;1/2 Wenn ja, dann wurde nach links gedreht
DrRechts:
 rcall rechts
 rjmp DrButton
DrLinks:
 rcall links
 rjmp DrButton
DrButton:

 tst DIPG           ;Wurde vorher abgeholt?
 brne main        ;Wenn nicht, dann Ende
 mov DIPG,r16
 rjmp main

links:
 cbi PORTD,0
 rcall pause
 sbi PORTD,0
 ret

rechts:
 cbi PORTD,1
 rcall pause
 sbi PORTD,1
 ret

pause:


          ldi  R21, 0x72
schleife1:ldi  R22, 0xF2
schleife2:dec  R22
          brne schleife2
          dec  R21
          brne schleife1

      ret

von avusgalaxy (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Kann es momentan leider nicht testen, aber ich glaube, ads es geht..

von Philip (Gast)


Bewertung
0 lesenswert
nicht lesenswert
ich werde mal schnell die schlatung aufbauen und das ganze auf den avr
laden, könntest du mir eventuell noch schnell die hex machen ?
dann gehts schnell weiss net wo mein compiller is..

von avusgalaxy (Gast)


Bewertung
0 lesenswert
nicht lesenswert
????? Soll ich dir auch noch einen 2313 schicken?

von Philip (Gast)


Bewertung
0 lesenswert
nicht lesenswert
ne danke hab 4 stück hier liegen, ne scho okay trozdem hab den compiler
gefunden^^ werds gleich mal auf spielen such gerade noch widerstände...

von Philip (Gast)


Bewertung
0 lesenswert
nicht lesenswert
habs mal aufgebaut, aber so richtig funz es net...
hmms auf wie viel mhz hast du es laufen ? ich hab derzeit nen 10mhz
quarz dran...

von Dominik (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe versucht den zweiten Code von Peter zum laufen zu kriegen. Ich
verwende einen AT90S2313 und den Drehgeber dessen Datenblatt im Anhang
ist.
Ich habe den gemeinsamen C - Anschluss auf 5V gelegt und A und B über
10k Widerstände gegen Masse. Dazwischen gehts jeweils zu einem Port-Pin
(PD.0 und PD.1) vom µC.

Habe am PortB LED's angeschlossen um zu schauen was die Variable
enc_delta macht, aber es leuchtet dauernd nur die LED an PB.0 (auch
keine Frequenz). Ich kann den Drehgeber drehen wie ich will, es tut
sich nichts.

Kann mir jemand weiterhelfen? Programmiere in CodevisionAVR.

Hier mein Code:


#include <90s2313.h>


volatile char  enc_delta;    // -128 ... 127




interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
 static char enc_last = 0x01;
  char i = 0;

  if( PORTD.0 )
    i = 1;

  if( PORTD.1 )
    i ^= 3;        // convert gray to binary

  i -= enc_last;      // difference new - last

  if( i & 1 ){        // bit 0 = value (1)
    enc_last += i;      // store new as next last

    enc_delta += (i & 2) - 1;    // bit 1 = direction (+/-)
  }
}


void main(void)
{

State7=0
PORTB=0x00;
DDRB=0xFF;

PORTD=0x00;
DDRD=0x00;

TCCR0=0x04;
TCNT0=0x00;


TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1H=0x00;
OCR1L=0x00;


GIMSK=0x00;
MCUCR=0x03;
GIFR=0x40;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02;


ACSR=0x80;

// Global enable interrupts
#asm("sei")
while (1)
      {
      // Place your code here
      PORTB = enc_delta;
      };
}



Gruß, Dominik

von Wolle (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wenn ich nicht irre, ist der Code so ausgelegt, dass "C" an 0V liegt.
Demzufolge werden die Pins dann wechselweise (Gray-Code) nach 0V
gezogen.
Probiers halt mal.

von Dominik (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hab's geändert, aber es tut sich immernoch nicht mehr :-(

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
if( PORTD.0 )
    i = 1;

Da kannste lange warten.

Du must schon das Input-Register nehmen.


Peter

von Dominik (Gast)


Bewertung
0 lesenswert
nicht lesenswert
AAAAAAAAARRRRGGGGGHHHH, sowas passiert mir immer wieder...


Danke Peter!

von Dominik (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Funktioniert nun prima, allerdings wird die Variable bei jedem Schritt
um 2 verändert, wie kann ich das ändern?

Danke, Dominik

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Drehgeber für manuelle Bedienung machen oft 2 oder 4 Pegelwechsel je
Rastung.

Einfach dann den Wert vor der Auswertung 1* nach rechts schieben:

int count;

cli();
count += enc_delta >> 1;
enc_delta = 0;
sei();


Peter

von philip (Gast)


Bewertung
0 lesenswert
nicht lesenswert
könnte man den ganzen code nun korigiert noch mal posten?

von Dominik (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wieso? Im Code waren doch keine Fehler?!?!

von Philip (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Drehgeber für manuelle Bedienung machen oft 2 oder 4 Pegelwechsel je
Rastung.

Einfach dann den Wert vor der Auswertung 1* nach rechts schieben:

int count;

cli();
count += enc_delta >> 1;
enc_delta = 0;
sei();


Peter



angeblich schon?
und ich hatte auch probleme mit dem programm
die led ging nimma aus ?!

von Dominik (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich werte das ganz anders aus, lasse auch die Interupts an, da der Rest
von meinem Programm sonst streikt.

von peter dannegger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Üblicher Weise will man ja mit einem Drehgeber mehrere Parameter
einstellen, je nach Menüpunkt.

Und count ist hier nur stellvertretend für irgend einen Parameter in
irgend einem Menü.

Die Beispielroutine betrifft das nicht, sondern eben nur die
Weiterverarbeitung.
Ist ja nur ein Beispiel und keine komplette Anwendung.


@Dominik

Eine Interruptsperre ist immer notwendig, wenn man Variablen
bearbeitet, die auch ein Interrupt in den Fingern hat.
Im Beispiel ist das eine Sperre von etwa 1µs, kann also gar keinen
Einfluß auf andere Programmteile haben.



Peter

von Philip (Gast)


Bewertung
0 lesenswert
nicht lesenswert
kann einer das eventuell so umbauen, das ich bei ner endsprechenenden
drehbewegung zb nach rechts nen kurzen impuls bekomme und nach links
wieder einen auf nen bestimmten port´?

so dasich von auß0en weiss das das teil gedreht wird endweder nach
links oder nach rechts....

währ einer so nett?

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Geht nicht; so einen Drehgeber für Dummys gibt's nicht.
Du mußt die aktuelle Flanke (steigentd/fallend) und dabei den Zustand
der anderen Ader (high/low) auswerten.
Wenn man alle Flanken auswertet, kommt man auf halbe Schritte, durch
die man die meisten Fehler rausfiltern kann.

von Hermann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
ich habe eure unerhaltung -hoffentlich ganz - gelesen. sie wure mir von
peter danegger empfohlen. Doch glaube ich nicht, sie in meinem fall
anwnden zu können.
Ich weiss zwar noch nicht welchen controller ich schussendlich
verwenden werde, doch besteht meine aufgabe ... mein ziel... darin
dieses signal über den controler mittels profi bus an eiene sps
weiterzuschicken!!
ich habe scho einmal ein reines empfang und anzeigeprogramm
geschreiben, doch hier werden mehrere takte benötigt!
so denke ich, dass ich zu langsam für einen impulsgeber werde. sollte
das nicht stimmen bitte ich um antwort.

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Du solltest den Gray-Encoder in den Controller packen und den Status des
Gray-Encoders über den Bus schicken, wenn sich der Status geändert hat.
Je nach Anwendung sollte das limitiert sein, also z. B. nach jedem
Datenpaket vom Controller eine Sendepause von mindestens 100 ms.

von Hermann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
soweit ich das mitbekommen habe, ist der grey code nichts anderes als
die beiden signale, die ich vom impulsgeber bekomme, und aus denen ich
die information über vor - rück und "stand" holen kann.
was mache ich wenn ich ein signal übersehe, also wie ich meine zu
langsam bin???
oder ist das direkt schicken abhilfe genug?

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Also entweder muß man die Flanken über Interrupts einlesen oder über
eine Timer-ISR die Leitungen mit mindestens 10 kHz auslesen.

von Hermann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
aso jetzt verstehe ich:

auswerten am controller (mittels tabelle) aber status nur bei änderung
oder nur in bestimmten intervallen

von nobody0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja, die Information, daß sich nichts geändert hat, braucht man ja
normalerweise nicht übertragen. Sofern im System keine Daten verloren
gehen, ist sowas komplett überflüssig.

von Hermann (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
noch eine frage:
ich habe eine schalturg empfhlen bekommen, die extern decoded und einen
insgesamt 32 bit zähler enthält??
was soll ich davon halten?
die schaltung (im .doc format ist von der hctl 2020 verbindung mit 051)

von Hermann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
verbindung mit 8051 natürlich!!

von Hermann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
bei dieser schaltung ist jedoch insgesamt 3x zu demultiplexen
und das is nicht was ich mir unter sinnvoll und einfach vorstelle!!!!

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Nimm doch einfach einen AT89C2051 der den Drehgeber einliest und dann in
den Profibus umsetzt.

Dürfte wesentlich billiger sein als der HCTL2020.

Ob Du dann 32 oder 64 Bit zählst ist auch egal.

Ist der HCTL2020 nicht außerdem abgekündigt (last order 06/2005) ?


Peter

von Hermann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
du meinst einen anderen controller???
ich hatte zuerst vor die 90er serie zu verwenden, da ich da das 200stk
besitze!
der externe zähler wäre wahrscheinlich wegen der geschwindigkeit!

ich habe eben bedenken wegen der geschwindigkeit, wenn extern ein 32
bit zähler vorgeschlagen ist!!!!

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Das war nur ein Beispiel, ein ATTiny26 oder ähnliches geht natürlich
auch.

Für die Abtastgeschwindigkeit ist nur die maximale Drehgeschwindigkeit
entscheidend, also wieviele Phasenwechsel pro Sekunde.
Der Timerinterrupt sollte mindestens doppelt so oft kommen.

Die Zählbreite ist uninteressant.


Peter

von Jörg (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Peter
>Nimm doch einfach einen AT89C2051 der den Drehgeber einliest und >dann
in
>den Profibus umsetzt.

auch wenn es etwas am Thema vorbei ist, aber was machst Du denn mit
einem AT89C2051 am Profibus? Ich dachte bisher, dass da nur etwas vom
Schlage eines SPC3 o.ä. zu finden ist. Die eigentliche Übertragung ist
zwar nur RS485 und UART, aber das ganze Protokoll...? Sollte das
wirklich in einen 2k-8051er passen?

Jörg

von Hermann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
du meinst es ist von grund auf sinnlos??
also ist das projekt abzublasen???

von peter dannegger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
"du meinst es ist von grund auf sinnlos??
also ist das projekt abzublasen???"


Aber wer wird denn gleich aufgeben.

Die maximale Datenrate von 12MBaud schafft der zwar nicht, aber
93,75kBaud geht.
Bzw. mit nem ATMega8 oder AT89LP4052 bis zu 500kBaud.

Das Protokoll zu implementieren dürfte eher eine Frage Deiner
Programmierkünste sein oder du kriegst irgendwo was fertiges.


Oder Du nimmst irgendein fertiges Profibus-IO-Modul und der ATTiny26
(oder was auch immer) übergibt nur die Zählwerte (seriell oder
parallel).


Peter

von Hermann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke für deine weiteren Bemühungen. ich habe jetzt eine Lösung
gefunden:
             Ich lese das Signal mittels HCTL2032 aus und lese dann
alle x ms ein. Denn mit dem Profi BUS übertragen wird der Controller
genug zu tun haben.

von holm (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Scahue Dir mal den LS7366 von LSI/CSI an, hat einen Quadraturdecoder
und
wird über eine SPI angehängt.  Distributor ist die Scantec GmbH in
Germering.
Der hat auch einen internen 32 Bit Counter sowie Carry/Borrow Ausgänge
zur externen Kaskadierung.

Ich habe hier auch so was vor, allerdings arbeite ich mit optischen
Encodern mit
2500 Impulsen/Umdrehung und bis zu 80Khz Impulsfrequenz im 4x Mode.
Ich muß mir dazu noch eine Regelung einer PWM mit AVR einfallen
lassen.

Momentan weiß ich da noch gar nicht recht wie ich da anfangen soll...
2 LS7366 habe ich als Samples bekommen.

Gruß,

Holm

von peter dannegger (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@Holm,

das Problem dürfte aber sein, den LS7366 zu beschaffen und billig
dürfte so ein Exot auch nicht gerade sein.

Aber die 80kHz sind auch ohne weiteres auch mit einem µC zu schaffen.
Wenn man mit 160kHz abtastet, hat der ATTiny bei 16MHz internem Clock
immer noch massige 100 Zyklen Zeit.

Und wenn man in Assembler optimiert, braucht man nur max 26 Zyklen im
Interrupt.
D.h. man kann ohne weiteres alle 32 Zyklen abtasten, also noch Signale
bis 250kHz fehlerfrei einlesen.

Anbei die Encoder-Routine in Assembler.
Nur Timer Initialisierung und SPI fehlt noch.


Auch 80kHz sind also noch lange kein Grund, teure und schwer
beschaffbare Exoten zu nehmen.


Peter

von keksohr (Gast)


Bewertung
0 lesenswert
nicht lesenswert
währ einer bereit für die conrad drehimpuls potis be routint zu coden ?
für einen S2313 ?avr

?

das bit muster der 2 pins kann ich gerne raus geben..

was ich brauche ist ne ganz einfache schaltung die 2 bins jeweils auf
high setzt und dann wieder auf low, so das ich nen kurzen impuls nur
habe, für jede dreh richtung einen pin, sprich dreht man nach links ->
pin 1 auf high, dreht man nach rechts -> pin 2 auf high,....

schalt plan kann ich gerne mit geben, wo die pins stehen und das bit
muster was den avr vom dreh impuls geber erwartet... sind 2 leitungen
vom impulsgeber...

währ echt sehr sehr danbakar hab das teil seid 2 monaten und komme
einfach nicht mit der software im avr klar, hab das www ach schon wie
blöde durchsucht...

von holm (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@peter:

Ja.
Ich habe auch schon daran gedacht einen 2313, von denen hier einige
herumliegen, für sowas zu mißbrauchen. Irgendwo gibt es auch eine
Implementation mit einem 90S1200 in Assembler.
Momentan habe ich den Decoder in ein GAL(16V8) gebrannt und da kommt
ein Richtungssignal und ein Clock heraus. Die Mimik wird mit 1,8432
Mhz
getaktet und der Ausgangsimpuls ist nur eine halbe Periode breit.
Diese Mimik habe ich an einen AtMega16 gehängt und befeuere damit  den
externen Int0. Die ISR hat nicht mehr zu tun, als nach am Port nach der
Richtung zu fragen und den 32 Bit Counter zu incrementieren oder zu
decrementieren.
In der Hauptschleife zeige ich auf einem LCD Drehzahl und sowas an. Das
Ganze in C (gcc). Der mit 16Mhz getaktete AtMega16 verliert dabei aber
Interrupts. (Die sind Flankengetriggert!)
Ich habe die Clockimpulse mit einem 74LS74 aufgefangen und bestätige
diese
mit einer Art INTACK Signal um das FF wieder zurückzusetzten.
Das geht besser, Allerdings gefiel es mir halt selber nicht.

Dazu käme eigentlich noch ein digitales Filter für die A und B
Phasensignale
aus einem weiteren GAL und 2 74LS72. (oder halt CMOS, aber die GALs
sind
ja auch schon heftig mit der Stromaufnahme). An der Stelle habe ich
mich umgesehen, was es sonst noch so gibt. Ich habe irgendwo mal 2
HCTL2016
ausgeschlachtet, aber deren Interner Zähler ist zu klein (16 Bit) und
es gibt außen kein Signal das irgendwie Bescheid gibt, daß sich am
Geber was getan hat. Man muß das Ding also pollen.... find ich doof.
Ein HCTL2020 war mir zu teuer, ist aber dem LS7366 ähnlich und enthält
wie dieser schon die digitalen Filter.

In AVR Assembler bin ich überhaupt nicht firm, habe ich noch nicht
gebraucht.
Ich kann das Zeug zwar lesen, aber nicht schreiben :-) Ich kenne aber
Assembler diverser anderer Micros, Z80 Maschine teilweise noch aus dem
Kopf, auch Ekeldinger wie 8048 hatte ich schon mit teilweise
selbst(um)gebauten Assemblern zwischen den Fingern aber auch 51er
68000er und 6809/11.

Bei dieser speziellen Sache hier geht es mir um Nichts weiter, als die
Steuerung
meiner im Bau befindlichen 2. Trafowickelmaschine. (Ich mache auch noch
mit Röhren rum und brauche ab und an Ausgangstrafos).

Ich bräuchte da vielleicht mal ein paar Hinweise oder mal ein Beispiel
in irgend einer Form, welche Algorithmen es gibt um einen
Gleichstrommotor mittels Drehgeber und PWM  bestimmte Positionen
anfahren zu lassen.
Ich habe aber keine PWM Brücke gebaut, sondern habe da ein Relais für
die Drehrichtungsumkehr, einen 100W Getriebemotor und eine PWM Stufe
mit einem IGBT, das Zeug klappt soweit ganz gut.
Ich habe aber natürlich, weil das ein Bastelobjekt ist, keinerlei Daten
über Massenträgheiten oder ähnlichen Kram, des noch nicht fertigen
mechanischen Systems. Irgendwie soll das Ding mal "weich" die
Drehzahl regeln, gegen Ende einer Wicklungslage langsamer werden und
stehen bleiben damit man Lagenisolation einfügen kann usw. usf. Die
Drahtverlegung soll ein Schrittmotor mit einer Spindelmimik machen, der
mittels programmierbarem Teilerverhältnis von den Drehgeberimpulsen
angesteuert wird, natürlich soll das Ding auch noch selber ausrechnen
wie das Teilerverhältnis bei unterschiedlichen Drahtstärken auszusehen
hat.
Den Schrittmotor werde ich mit einem TA8345H Ansteuern, der ist
programmierbar von Voll- bis Achtelschritt, sowas liegt hier gerade
herum (fertige kleine Endstufen).
Die Drahtspannung, und damit natürlich auch die Last des Motors soll
natürlich auch variabel sein, also wo und wie fange ich an ....?

Suggestions?

Danke,

Holm

von Hermann (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Holm

Ich habe die 20xx (keinen!!!) bekommen.
doch habe ich jetz eine Seite gefunden, wo ich 7366 kaufen(scantec
schickt nicht nach Ö) kann.

Was hast du mit deinen IC gemacht?
Wie funktioniert deine Steuerung bzw Regelung?
Könnte ich vielleicht die SPI Kommunikations Source haben?


danke hermann

von Birger* (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wo bekommt man denn diese Drehgeber? Hab in der Vergangenheit den DDM427
von Conrad verwendet, doch nun soll er angeblich nicht mehr lieferbar
sein. Bei RS hab ich auch noch keinen gesichtet und bei Reichelt erst
recht nicht.

Noch ne Anmerkung zur Programmierung. Die DDM427 sind eigentlich nur im
Interruptbetrieb einsetzbar, weil dieser Drehgeber im Vergleich zu
anderen nicht statisch abfragbar ist.
Nimmt man das im Datenblatt vorgeschlagene RC-Glied zum Entprellen, so
geht das ganz wunderbar.

von Andi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
"Die DDM427 sind eigentlich nur im
Interruptbetrieb einsetzbar, weil dieser Drehgeber im Vergleich zu
anderen nicht statisch abfragbar ist."
So ein schmarrn!
Ich setze den DDM427 sowohl im PKW im Pin Change Interrupt an einem
Tiny26 mit RC-Glied und zu Hause im Polling-Modus ohne RC-Glied, wo der
Geber aus dem Timer-Interrupt mit 10KHz abgefragt wird, ein.
Beides geht wunderbar.

MfG
Andi

von Birger* (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Na, jetzt mal nicht so deftig dahergeplappert. Die Treffsicherheit im
Pollingmodus ist deutlich geringer als wenn man Interrupts verwendet.
Ich hab's ausprobiert. Wenn mann wenig Rechenzeit verbraten möchte,
ist der Pollingbetrieb jedenfalls nicht optimal.

Und wo krieg ich jetzt neue Drehgeber her?

von Andi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
War das so heftig?
Tschuldigung!
Mal im Ernst.
Im Polling-Modus, und vor allem ohne RC-Glied, sollte man natürlich
eine Soft-Entprellung mit einbauen, welche man für den Button gleich
mit verwenden kann, oder das Verfahren von Peter, hier ganz oben,
verwenden.
Auf jeden Fall, gehn tut das, habe ja beides erfolgreich ausprobiert.
Und wenn man sowieso einen 10KHz-Timer wegen viele anderer Dinge im
Einsatz hat ist das auch nicht mehr die Welt, zumindest in ASM.

Das Conrad die nicht mehr hat verstehe ich nicht, immer hin haben die
bei deren Preis wohl recht gut daran verdient.
Wahrschinlich zu geringe Mengen davon verkauft und dann ausgemustert.
Weis auch nicht, wo man den selben Typ her bekommt und Reichelt hat
leider immer noch keine Geber.

MfG
Andi

von Elektrikser (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

warum sollte der DDM427 bei Conrad nicht mehr lieferbar sein? Im
Online-Katalog sind die als sofort verfügbar gekennzeichnet.
(Bestellnr.: 705514-07; 705526-07; 705538-07)
Hast du nähere Infos?

Gruß Elektrikser

von Birger* (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Für meine Diplomarbeit brauch ich noch dringend 'nen neuen Drehgeber.
War deswegen bei Conrad in der Filiale Dortmund. Dort waren keine
vorrätig und auch nicht lieferbar (Best.-Nr. 705514) - laut Aussage des
"Fachmanns" hinterm Tresen.

von JojoS (Gast)


Bewertung
0 lesenswert
nicht lesenswert
bei Neuhold Elektronik gibts einen guten und günstigen (5 Euro):
http://www.neuhold-elektronik.at/catshop/default.php?cPath=41_56_153
der liefert hier auch ohne Entprellung gute Ergebnisse.

von Ampel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Tach zusammen,

ich hab grad auch eine Anwendung, wo ich ein Dreh-Encoder (auch Jog-Rad
genannt) einsetze. Damit will ich in einem Menue rumdrehen und mit der
Taste am Dreh-Encoder meine Auswahl treffen (Eigentlich wird nur ein
Zähler auf- oder abwärts gezählt).
Die Spur A ist auf einem Interrupt gelegt, Spur B liegt auf einem Port
ohne Interrupt. Erfolgt eine Drehung, springt der Interrupt mit der
Spur A an. Dann kommt eine Auswertung wie Spur A steht, gleichzeitig
wie Spur B steht. Der Wert wird mit dem letzten Wert verglichen. Ist es
unterschiedlich, wird entschieden, ob ein Zähler auf- oder abwärts
zählt.
Aber irgendwie ist das nicht das wahre: drehe ich langsam, kommt
manchmal Mist raus, drehe ich zu schnell ebenso.
Wie habt Ihr die Abfrage des Dreh-Encoders realisiert? Sollte ich
anstatt des Interrupts einen Timer nutzen (wenn ja, wie)?

Gruss,
Ampel

von Thorsten (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> Wie habt Ihr die Abfrage des Dreh-Encoders realisiert? Sollte ich
> anstatt des Interrupts einen Timer nutzen (wenn ja, wie)?

Schau dir mal den ersten Beitrag an. Funktioniert einwandfrei!

von Rolf F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe es mal auf MSP430 und ARM9 mit Fehlerkorrektur gemacht, da ja
von einer Position zur nächsten zwei Interrupts kommen, und folglich
jeder als ein halber Schritt gezählt werden sollte. Zählt man jeden
Interrupt als halben Schritt, dann sind auch prellende Drehgeber kein
Problem, wie auch Praxis-Tests zeigten. Das langsame Drehen bekommen
man mit der Hand hin; das schnelle mit einer Bohrmaschine.
Hier der Code für MSP430:
// Macro for setting the IES flags for the gray encoder consitent.
// E. g. BIT6 set -> set the associated IES (for IRQ on falling edge).
// Has to be called e. g. at the start of main.
#define mc_CONSISTENT_J \
{ \
if (P2IN & BIT6) \
 P2IES |= BIT6; \
else \
P2IES &= ~BIT6; \
if (P2IN & BIT7) \
  P2IES |= BIT7; \
else \
  P2IES &= ~BIT7; \
}

signed char c_gc_c = 0;         // grey code (interrupt) counter with
sign for direction: + means right
unsigned char uc_l = 0;         // counter for the irqs from left
output (port2, Bit6) of grey encoder
unsigned char uc_r = 0;         //                           right     
 (port2, Bit7)
uint32_t uli_errors = 0;

// macro for resetting the grey encoder variables (above)
// Has to be called e. g. at the start of main.
#define mc_RESET_J \
{ \
P2IFG &= ~(BIT6 | BIT7); \
c_gc_c = 0; \
uc_l = 0; \
uc_r = 0; \
}

#define mc_c_gc_cP {if (c_gc_c < 100) ++c_gc_c;}   // one step with
direction, increment with saturation
#define mc_c_gc_cM {if (c_gc_c > -100) --c_gc_c;}  // decrement

#define mc_uc_lP {if (c_gc_c < 100) ++uc_l;} // one step left;
increment with saturation
#define mc_uc_rP {if (c_gc_c < 100) ++uc_r;} // one step right


In der ISR:
    switch (P2_IRQs & (BIT6 | BIT7))     // Mask for BIT6 and BIT7.
    {
      case 0:                  // no irq; should never happen
        uli_errors++;
        break;

      case (BIT6 | BIT7):      // 2 irqs; should never happen
        mc_uc_lP;
        mc_uc_rP;
        uli_errors++;          // error
        break;

      case BIT6:
        mc_uc_lP;
        switch (P2IES & (BIT6 | BIT7))
        {
          case 0:              // 00 -> 01 (P2IN, bit6 = 0  and bit7 =
1), right
            mc_c_gc_cP;
            break;

          case (BIT6):         // 01 -> 00, left
            mc_c_gc_cM;
            break;

          case (BIT7):         // 10 -> 11
            mc_c_gc_cM;
            break;

          case (BIT6 | BIT7):  // 11 -> 10
            mc_c_gc_cP;
            break;

          default: // can never happen
            uli_errors++;
            break;
        }
        break;

      case BIT7:
        mc_uc_rP;
        switch (P2IES & (BIT6 | BIT7))
        {
          case 0:              // 00 -> 10
            mc_c_gc_cM;
            break;

          case (BIT6):         // 01 -> 11
            mc_c_gc_cP;
            break;

          case (BIT7):         // 10 -> 00
            mc_c_gc_cP;
            break;

          case (BIT6 | BIT7):  // 11 -> 01
            mc_c_gc_cM;
            break;

          default: // can never happen
            uli_errors++;
            break;
        }
        break;

      default: // can never happen because only PIN6 and PIN7 are
interrupt enaled
        uli_errors++;
        break;
    }
    mc_CONSISTENT_J;

    if (((P2IN & BIT6) >> 6 == (P2IN & BIT7) >> 7)      // equal
inputs
        && (uc_l)               // left irq
        && (uc_r)               // right irq
      )                         // stationary position
    {
      if (c_gc_c <= -2)
      {
        if (c_gc_c < -2)
          uli_errors++;          
        KEYBOARD.key[KEYBOARD.start] = KEY_JOG1PLUS; // one step right
        KEYBOARD.start++;       // new input
        mc_RESET_J;
      }
      else
      {
        if (c_gc_c >= 2)
        {
          if (c_gc_c > 2)
            uli_errors++;
          KEYBOARD.key[KEYBOARD.start] = KEY_JOG1MINUS; // one step
left
          KEYBOARD.start++;     // new input
          mc_RESET_J;
        }
      }
    }

Man kann es natürlich auch umschreiben auf einen Timer-Interrupt, der
die
Eingänge ausliest.

Bei einem Prozessor, bei dem man die Eingänge zweifach
flankengetriggert
einstellen kann, ist der Code kleiner.

Hierbei hat left u. right irq nichts mit der Drehrichtung zu tun; die
beiden
sind für die beiden Adern des Drehgebers; die Information der
Drehrichtung ist
zeitlich codiert (durch Phasenverschiebung).

Bei einem 4-er-Drehgeber ist es etwas komplizierter, aber es können
auch noch
3-Flanken-Fehler korrigiert werden.

Durch den Fehler-Zähler kann man angeben wie zuverlässig der Drehgeber
ist,
indem man den Fehler-Zähler durch die Anzahl der Steps (Rechts-
u. Links-Schritte) zählt.

von Peter Dannegger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Rolf,

wirklich ein imposantes Codemonster, wenn ich doch bloß erkennen
könnte, was daran besser sein soll.


Warum probierst Du nicht mal mein kleines schnuckeliges Progrämmchen
(Encode.c) aus ?

Du wirst verblüfft sein, wie zuverlässig es entprellt und dekodiert.


Für Ängstliche, die denken, ein Timer ist zu aufwendig, es muß auch
nicht im Timerinterrupt aufgerufen werden.

Man kann genausogut einen Pin-Change-Interrupt nehmen, Hauptsache der
Interrupt reagiert auf alle 4 Flanken.


Peter

von Andi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo rote Ampel :-)

Im ersten Beitrag von mir hier habe ich meinen ersten Versuch mit einem
Drehgeber über IRQ von Kanal A (Pin Change IRQ) abgebildet.
Ist zwar am Ende etwas anders geworden aber im Prinzip geht das über
Pin Change IRQ wie folgt:

 Drehgeber ändert Kanal A -> IRQ wird ausgelöst.
 Kanal A und B auslesen.
 Kanal A und B mit zuvor gemerkten Kanal A und B vergleichen.
 Ist der aktuelle Wert von Kanal A und B anders als der vorige dann:
  Aktuellen AB-Wert merken (Variable).
  Ist Kanal A = Kanal B dann wurde nach links gedreht.
  Ist Kanal A <> Kanal B dann wurde nach rechts gedreht.

Das ist alles.
Entweder mit 10K und 10nF jeden Kanal und den Button entprellen oder
per Timer-Software.

MfG
Andi

von Rolf F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Der Code von mir wird in einigen Geräten eingesetzt und der funktioniert
sehr zuverlässig. Bei Drehgebern, bei denen es mit nur einfacher
Flanken-Zählung (nur fallende oder steigende Flanken) deutliches
Prellen gibt, funktioniert mein Code ohne Prellen.
Die Fehlerzählung habe ich drinn für Features wie den extrapolierten
Zeitpunkt des Totalausfalls oder Ferndiagnose, aber bisher ist es
ungenutzt.

von Andi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Rolf F:
Es ist einfach nur irsinnig so viel Code zur Drehgeberauswertung zu
machen.
Ich habe Peters Code in ASM umgesetzt was ein paar Befehle sind und es
funtzt ohne Probleme genauso wie die Version A = B ist links und A <> B
ist rechts mit Soft-Entprellung per Timer (0,3ms).

MfG
Andi

von Rolf F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ok, mit
  Ist Kanal A = Kanal B dann wurde nach links gedreht.
  Ist Kanal A <> Kanal B dann wurde nach rechts gedreht.
kann man meinen Code noch optimieren.
Beim MSP430 hat man etwas mehr Code als z. B. beim ARM9 dadurch, daß
die Eingänge nicht doppelt flankengetriggert eingestellt werden können,
so daß man das emulieren muß.

von Andi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
>daß die Eingänge nicht doppelt flankengetriggert eingestellt werden
>können
Dann wäre ja gerade beim MSP430 ein Polling im Timer der beiden Kanäle
sinnvoller.

>Ok, mit
>  Ist Kanal A = Kanal B dann wurde nach links gedreht.
>  Ist Kanal A <> Kanal B dann wurde nach rechts gedreht.
>kann man meinen Code noch optimieren.
Du meinst wohl ersetzen.
Oder mit Peters Methode welche komplett ohne Hard- oder
Soft-Entprellung auskommt.

MfG
Andi

von JojoS (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ich hatte bevor ich hier die C-Variante gefunden habe auch mal eine asm
Version mit Tabelle gebaut, d.h. die Schritte müssen wenn die zwei Bits
binär codiert in der Reihenfolge 1,3,0,2 oder andersrum kommen. Wenn man
prüft ob der neue Zustand genau einen davor oder dahinterliegt wird es
auch einfacher als die bitweise Prüfung. In meinem Beispiel wird + oder
- je nach Step ausgegeben. Zusätzlich gibt es noch ein paar Tasten die
dann Ziffernausgaben machen (allerdings noch nicht ordentlich
entprellt, nur über das delay durch serielle Ausgabe zwischen zwei
Abtastungen). Das soll mal mein Drehgeber für einen CarPC werden.

von Thomas (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe gerade den Code von Peter mit einem Drehgeber von Conrad
getestet (427), funktioniert auch sehr gut (besser als mein eigener mit
Flankenwechsel im Interrupt).
Jedoch ändert sich der Wert bei jeder Rasterstellung um zwei anstatt um
eins.
Peters Tip mit:

> Einfach dann den Wert vor der Auswertung 1* nach rechts schieben:
> int count;
> cli();
> count += enc_delta >> 1;
> enc_delta = 0;
> sei();

funktioniert bei mir nicht.
Was meiner Meinung nach daran liegt, dass wenn enc_delta negativ ist,
und ich dieses Zweiekomplement nach rechts schiebe, mein Wert nicht
mehr negativ ist.
Beispiel: enc_delta = -2
0b 1111 1110 // -2
und um eine Stelle nach rechts verschoben:
0b 0111 1111 // +127

Oder habe ich irgendwo einen Denkfehler?

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
@Thomas

Stimmt, ganz so einfach geht es nicht. Die Halbschritte gehen
verloren.


So sollte es gehen:

cli();
if( !(enc_delta & 1)){
  count += enc_delta >> 1;
  enc_delta = 0;
}
sei();

Das Schieben selber funktioniert auch mit negativen Zahlen, nennt sich
arithmetisches Shift (Befehl ASR).


Peter

von Ralf (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Peter Dannegger:

Du hast in einem Beitrag vom 17.03.2005 den AT89LP4052 erwähnt. Das
Teil interessiert mich brennend. Hast du schon mit dem gearbeitet? Wenn
ja, woher hast du ihn bekommen?

Gruß Ralf

von Gerd (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Das Problem bei allen Softwarelösungen ist dass sie nicht alle Flanken
auswerten und damit an Auflösung einbüßen. Die "Drehgeber" sind
Quadraturencoder und liefern 4 Zustände von denen nur 2 zu
Richtungsermittlung und 2 für den Weg benutzt werden können. Entweder
werden nur 0 oder 1 ausgewertet. Steigende- und Fallende Flanken sind
mit den üblichen Kontrollern nicht auswertbar zum anderen ist der
Kontroller mächtig beschäftigt.
Die eine arbeitet sehr zuverlässig und arbeitet mit 4 CMOS Gatter und
ein paar R und C's. Sie wertet alle 4 Flanken aus und liefert Takt für
den Weg und ein Bit für Rechts/Links-Lauf. ich benutze den Counter der
8051 Derivate zur Wegermittlung (Zählerstand) und ein Portbit für die
Richtung. Von Hand habe ich es mit einem Incrementalgeber mit
200Ticks/-1 nicht geschafft Schrittverlusste zu erzeugen.
Eine andere Lösung ist weniger Aufwändig jedoch muss man CPLD's von
Xilinx Programmieren können. Etwas teuerer ist sie liefert aber sofort
6 Auswerter. Dazu wird ein XC9536 mit einem TTL-Takt Generator
eingesetzt. Die Ausgangssignale sind ebenfalls Takt und Richtung. Evtl.
will ich auch mal einen Zähler implementieren. Man könnte das Ding dann
direkt an einen Bus koppeln und die Zähler via Register auslesen. Mal
sehen.
Wenn interesse kann ich das Zeug mal Posten
Gruß Gerd

von JojoS (Gast)


Bewertung
0 lesenswert
nicht lesenswert
das kommt eben darauf an wofür der Encoder eingesetzt wird:
die meisten hier vorgeschlagenen Routinen sind für die digitalen
Drehknöpfe wie sie z.B. an Audiogeräten zu finden sind und die werden
nicht so schnell gedreht. Wenn der Encoder an einer drehenden Welle
sitzt dann muss man rechnen ob man da noch schnell genug abtastet.

von Peter Dannegger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
"Das Problem bei allen Softwarelösungen ist dass sie nicht alle Flanken
auswerten und damit an Auflösung einbüßen."


Häää ???

Wenn man etwas zu einem Thread zu sagen zu haben meint, dann sollte man
ihn doch auch bitteschön erst einmal lesen.

Bzw. wenn man etwas nicht verstanden hat, dann kann man ja erst einmal
fragen.


"ich benutze den Counter der 8051 Derivate zur Wegermittlung
(Zählerstand) und ein Portbit für die Richtung."

Seit wann kann denn der internen Zähler vorwärts und rückwärts zählen
?


Peter

von Rolf F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja, sehe ich auch so.
Meinen obigen Code habe ich zwar nur für einen Drehschalter für Menüs
gemacht, aber testweise auch mit einer Bohrmaschine angetrieben.
Übrigens gibt's auch Drehgeber die von einer Raster-Position zur
nächsten nicht zwei sondern vier Flanken liefern.

Bei sehr hohen Drehzahlen muß man einen MC nehmen, der nichts weiter
macht als nur den Drehgeber auswerten und das Ergebnis ohne IRQ, z. B.
als Gray-Code parallel ausgibt. Damit kann man bis ca. eine Million
Flanken pro Sekunde zählen.

von Uli Huber (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Gerd,

das mit

'Steigende- und Fallende Flanken sind
mit den üblichen Kontrollern nicht auswertbar zum anderen ist der
Kontroller mächtig beschäftigt.'

ist eher eine historische Betrachtung, oder ?

Bei den ATTinys jedenfalls hast Du mit den PCINT natürlich die
Möglichkeit  auf alle Flanken zu triggern.

Gruß
Uli

von Christian K. (christiank)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

nach diesem ewig langen Thread blickt ja keiner mehr durch, daher poste
ich hier nocheinmal Peter's Code, angepasst für Drehgeber wie den von
Contrad Elektronik, d.h. die Rast-Stellung ist entweder bei 00 oder 11.

Dafür habe ich eine winzige Erweiterung eingebaut (variable tmp), so
dass der Zählerstand pro Raststellung nur um eins, nicht um zwei
weiterzählt.

Den ganzen quatsch mit cli() und shiften und murksen und sei() kann man
sich dann nämlich sparen.

Ich musste allerdings auch feststellen, dass Peters Code bzgl.
Entprellung nicht optimal ist. Es passiert leider häufiger, dass
Drehimpulse verloren gehen, besonders wenn man etwas vorsichtig dreht.
Das werde ich mir später mal genauer ansehen. Vielleicht hilf ja eine
externe Filterung.

Hier der Code: (Drehimpulsgeber ist angeschlossen an PE4 und PE3)


---- globaler Speicher des Drehwertes

volatile int8_t  enc_delta=0;    // -128 ... 127

---- innerhalb der Timer Routinte ----

  static int8_t enc_last = 0x01;
  int8_t i;
  uint8_t tmp;

  i=0;
  // digiswitch polling
  tmp=PINE;
  if( (tmp & _BV(PINE4)) )
    i = 1;

  if( (tmp & _BV(PINE3)) )
    i ^= 3;      // convert gray to binary 00->11, 01->10

  tmp=i;         // save value in binary code for test of increment

  i -= enc_last;       // difference new - last

  if( i & 1 )         // bit 0 = value (1)
  {
    enc_last += i;     // store new as next last
    if (!(tmp & 1))    // change only for 00/10 in binary code
      enc_delta += (i & 2) - 1;   // bit 1 = direction (+/-)
  }

------------ end ---------------

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
@Christian

"Den ganzen quatsch mit cli() und shiften und murksen und sei() kann
man sich dann nämlich sparen.
...
Es passiert leider häufiger, dass Drehimpulse verloren gehen"


Ja das kommt davon.
Ich hab mir nämlich bei dem "ganzen Quatsch" schon was gedacht.

Und das cli/sei kann man erst recht nicht sparen, da man ja die
Variable gleichzeitig lesen und löschen muß (atomar).


Peter

von ChristianK (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

ich verändere/lösche die Variable enc_delta nicht. Warum sollte ich
auch, ich brauche sie absolut.

Trotzdem gehen Impulse verloren, im ungüstigsten Fall zählt er sogar
mal in die falsche Richtung. Die Conrad Drehgeber scheinen wahre
Prell-Wunder zu sein.

Im Moment fehlt mir die Zeit, aber bei Gelegenzeit werde ich mir die
Signale mal mit dem Speicher-Osci. anschauen was da so los ist und ob
eine SW Entprellung Sinn macht.

Grüße
  Christian

P.S:
(Wenn man enc_delta ausserhalb des Interrupts verändert, muss man
natürlich die Interrupts blockieren, ich denke das ist klar.)

von ChristianK (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Das Prellen des Conrad rotary switch bekommt man übrigens recht gut in
den Griff, wenn man den Timer Tick stark reduziert. Ich habe den jetzt
auf 100Hz eingestellt (waren bisher 1000Hz). Damit ist das Prellen
ziemlich stark reduziert. (laut Datenblatt ist die Prellzeit 2ms und
die Pulsezeit 6ms bei 60rpm! (d.h. 30pulse/sec))

Natürlich gehen - wenn man schnell dreht - Impulse verloren, aber bei
meiner Anwendung stört das nicht, Genauigkeit beim langsamen drehen ist
mir wichtiger.

Grüße
  Christian

Wenn man Lust hat, könnte man natürlich die Pulsedichte (Pulse/sec)
auswerten und die Sample-Zeit dynamisch anpassen...

von Rolf (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Bei dem Drehgeber von Conrad kommt von einer Raster-Position zur
nächsten nur einen Puls; besser ist einer der zwei Flanken (statt
einer) ausgibt, bei dem man also halbe Schritte zählen kann.

von Andi K. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Seltsam.
Wenn Du den ddm427 meinst, den habe ich mit Peters Code, in ASM
umgeschrieben, und auch mit eigenem Code bei 10KHz Timer erfolgreich
betrieben.
Bei dem eigenen Code brauchte ich zum Entprellen für alle 3 Signale, A,
B und Button, nur 1 Filterung von 2 Timer-Ticks.

MfG
Andi

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
@Christian,

daß eine geringere Abtastung helfen soll, klingt äußerst merkwürdig.

Hast Du denn die Variante mit dem Schieben überhaupt probiert ?

Ich hab jetzt Deine Code nicht in allen Einzelheiten überprüft, würde
aber sagen, daß er die Entprellfunktion aushebelt.

Auch ist ein ASR wesentlich weniger Code, als ein zusätzliches Register
im Interrupt (+PUSH/POP).



Peter

von ChristianK (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Andi,
ja laut Conrad Datenblatt heisst er ddm421. Ich betreibe ihn auch
erfolgreich mit Peters Code, nur halt nicht 100% ohne Prellen, ich
benutze aber auch keinerlei zusätzlicher Entprellung so wie du. Und er
ist nagelneu. Das Prellen ist übrigens nur bei wenigen der
30-Raststellungen festzustellen. Ist vielleicht auch ein
Montagsgerät...

@Peter,
der Code ist 99.5% identisch mit deinem.
Änderungen:
- Samplen des Inputregisters nur einmal (vmtl. irrelevant)
- Berechnen des Ausgangswertes nur wenn Zustand 00/11 vorliegt, Das
sind die Raststellungen des Drehgebers (bei dir wurde er immer
berechnet d.h. bei 00/01/11/10 - darum zählt er doppelt)

Die Graycode Entprellung wird dadurch aber nicht beeinflusst. Das
Prellverhalten war mit 100% Peter genauso wie mit 99.5% Peter.

Performance:
Eine tmp Variable habe ich sowieso in meiner Timer Tick Routine, aber
darauf kam es mir ja auch nicht an, ich möchte mir das Rechnen im
Hauptprogram sparen.

Warum bei langsamen Timer-Tick weniger prellen?
Die Wahrscheinlichkeit, dass man die 2ms Prellzeit trifft, nimmt
natürlich ab je weniger schnell man sampled. Mit 1kHz (1ms) treffe ich
zwei mal den undefinierten Zustand während der Prellzeit, mit 10ms nur
noch mit Wahrscheinlichkeit 1:5. (Die Prellzeit sollte dabei natürlich
nicht stark von der Drehgeschwindigkeit abhängen...)

Grüße
  Christian

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
"Die Graycode Entprellung wird dadurch aber nicht beeinflusst. Das
Prellverhalten war mit 100% Peter genauso wie mit 99.5% Peter."


Gibs doch zu, Du hast es garnicht erst probiert.
Deine 0,5% setzen nämlich die Entprellung außer Kraft:

Du zählst bei 00->10 rauf aber bei 11->10 runter.
D.h. ein Preller 00->10->00 zählt nur rauf und damit falsch.


Prinzipbedingt kann mein Code erst dann ein Prellen nicht mehr
korrigieren, wenn beide Signale gleichzeitig prellen, d.h. kein
Graycode mehr rauskommt (nur ein Signal ändert sich).
Eventuell gibt es ja ein Übersprechen, probier doch mal kleinere Pullup
Widerstände.


Peter

von ChristianK (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Asche auf mein Haupt, ich ziehe alle vorherigen Postings zurück und
behaupte das Gegenteil....

Der Conrad Drehgeber scheint sehr wenig zu Prellen, ansonsten hätte ich
wohl doppelte Zählungen sehen müssen. Komischerweise habe ich nur
fehlende Pulse beobachtet...

> Gibs doch zu, Du hast es garnicht erst probiert.
Doch und das ist genau das Problem, einfach mal eben in der Hardware
geändert... läuft und gut ist. Solche Dinge sollte man u.U. doch besser
erst am PC simulieren....

von Peter Dannegger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
"Der Conrad Drehgeber scheint sehr wenig zu Prellen, ansonsten hätte
ich
wohl doppelte Zählungen sehen müssen. Komischerweise habe ich nur
fehlende Pulse beobachtet..."


Ob der Geber prellt, kann man mit meinem Code nicht feststellen, da er
ja entprellt.

Fehlende Pulse deuten auf eine zu langsame Abtastung hin. Eventuell
sind ja andere Interrupts zu lange beschäftigt.


Peter

von The Daz (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Peter
Ich plane auch gerade mal diese Drehgeber zu verbauen. Ist bei deiner
Routine die Benutzung externer RC-Glieder ueberfluessig oder hilfreich
(bei manueller Geber-Betaetigung) ? Koente mir moeglicherweise ne Menge
Bauteile und Platinenflaeche sparen.

von Rolf (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Also die Drehgeber, die ich programmiert habe, liefen beim MSP430 ohne
Tiefpass, aber beim ARM9 mussten Tiefpässe genommen werden (und es
wurden freiliegende Schmitt-Trigger verwendet); das hängt vom Prozessor
und Drehgeber ab.

von Peter Dannegger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@The Daz

die Routine ist entprellend, Du brauchst also keine extra Tiefpässe.


Peter

von Michael Demuth (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
wir stellen alle Arten von Drehgebern her (auch die vom Conrad).
Das Problem mit der Entprellung ist vor allem dann ein echtes wenn man
1/2 Schritt vor und dann wieder zurück dreht. Für einen echten Schritt
müssen 2 (4) Zustandswechsel (gepollt oder per IRQ) ausgewertet werden.
Dann klappt's auch.
Dazu ein bissl Source Code:

void lesen()
    {
    const signed int table[16] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  // 16 erlaubte Bit-codes

    old=old<<2;      // die alten Daten 2 nach links schieben

    if (input(PIN_B4))     // Spur /A abfragen (A0)//B4
      bit_set(new,0);
  else
          bit_clear(new,0);

    if (input(PIN_B5))     // Spur /B abfragen (A2)//B5
      bit_set(new,1);
  else
            bit_clear(new,1);
    old |=(new & 0x3);          // alte und neue bits verodern
    angle_1 += table [(old & 0xf)];   // aktion aus dem Feld auswählen
  }

Dann etweder durch 2 oder durch 4 teilen:

void teiler_4()
  {
  if (angle_1>7)    // unterlauf?
    {
    angle++;
    if (angle > 99) angle = 0;  // Überlauf abfangen
    angle_1=4;
    }
    if (angle_1<1)
    {
    angle--;
    if (angle > 250) angle = 99;    // Unterlauf abfangen
    angle_1=4;
    }
   }
/****************************************************************/
void teiler_2()
  {
  if (angle_1>5)    // unterlauf?
    {
    angle++;
    if (angle > 99) angle = 0;  // Überlauf abfangen
    angle_1=4;
    }
    if (angle_1<3)
    {
    angle--;
    if (angle > 250) angle = 99;    // Unterlauf abfangen
    angle_1=4;
    }
   }
Alle anderen Methoden funktionieren eigentlich nicht wirklich.
Zur Umwandlung von Qudratursignalen in Impuls-Richtungssignale gibt es
ICs oder GALs. Viel Erfolg!

www.ebe-gmbh.de

von mgiaco (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wie schnell sollte man so ein Drehgeber einlesen wenn man ihn für die
Bedienung eines Gerätes verwenden will? Ich habe die vom Conrad.

Ich meine die Funktion lesen() ==> die muss man ja Zeitgesteurert
ausführen oder?

mfg mathias

von SuperUser (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Für Drehgeber zur Geräte-Bedienung (z.B. der von Conrad) welche in den
Stellungen AB=00, AB=11 einrasten funktioniert auch dieser Code

http://www.mikrocontroller.net/forum/read-4-250095.html#new

einwandfrei - auch beim Zurückdrehen aus halben Stellungen. Er zählt
aber - was normalerweise auch so gewünscht ist - nur die
Raststellungen.

Die Pollgeschwindigkeit hängt von der Applikation ab. Wenn man viele
Feineinstellungen braucht (+/- ein paar Stellungen) reicht z.B. 500 mal
pro Sek. pollen aus. Muss viel gekurbelt werden (d.h. grosse Schritte),
muss man schneller samplen da sonst je schneller man dreht weniger
Pulse gezählt werden.

Wer sicher gehen will und sich das leisten kann nimmt Interrupts.

von Patrick D. (oldbug) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
>Wer sicher gehen will und sich das leisten kann nimmt Interrupts.

Eben nicht!

von Rolf (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Interrupts sind am besten, wenn die CPU hauptsächlich anderes machen
soll, aber zum Entprellen per Software ist Polling etwas besser.
In der Regel ist der Unterschied aber nur marginal; es ist also
hauptsächlich Geschmackssache.

von Christoph Kessler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo
ich benutze am Atmel 8515 die beiden Interrupt-Eingänge:

ExtInt0:
  push  Temp1    ; save Temp1
  in  Temp1,SREG  ; save flag register
  push  Temp1
  in  Temp1,MCUCR  ; Int0  _/~ or ~\_ ?
  sbrc  Temp1,0    ; skip next line if  ~\_
  rjmp  UpA    ; was _/~ so jump to UpA
  ori  Temp1,$01  ; MCUCR-bit0 = 1
  out  MCUCR,Temp1  ; Int0 next change will be _/~
  sbic  PinD,3    ; skip next line if channel B=0
  rjmp  DecRot    ; if B=1 and A=~\_ -> decrement
  rjmp  IncRot    ; if B=0 and A=~\_ -> increment
UpA:
  andi  Temp1,$FE  ; MCUCR-bit0 = 0
  out  MCUCR,Temp1  ; Int0 next change will be ~\_
  sbic  PinD,3    ; skip next line if channel B=0
  rjmp  IncRot    ; if B=1 and A=_/~ -> increment
  rjmp  DecRot    ; if B=0 and A=_/~ -> decrement

ExtInt1:
  push  Temp1    ; save Temp1
  in  Temp1,SREG  ; save flag register
  push  Temp1
  in  Temp1,MCUCR  ; Int1  _/~ or ~\_ ?
  sbrc  Temp1,2    ; skip next line when ~\_
  rjmp  UpB    ; was _/~ so jump to UpB
  ori  Temp1,$04  ; MCUCR-bit2 = 1
  out  MCUCR,Temp1  ; Int1 next change will be _/~
  sbic  PinD,2    ; skip next line if channel A=0
  rjmp  IncRot    ; if A=1 and B=~\_ -> increment
  rjmp  DecRot    ; if A=0 and B=~\_ -> decrement
UpB:
  andi  Temp1,$FB  ; MCUCR-bit2 = 0
  out  MCUCR,Temp1  ; Int1 next change will be ~\_
  sbic  PinD,2    ; skip next line if channel A=0
  rjmp  DecRot    ; if A=1 and B=_/~ -> decrement
  rjmp  IncRot    ; if A=0 and B=_/~ -> increment

IncRot:
  mov  Temp1,RotVal  ; max limit = +127 reached ?
  cpi  Temp1,$7F  ;
  breq  Exit    ; yes, so don't increment
  inc  RotVal    ; no, increment
  rjmp  Exit    ;
DecRot:
  mov  Temp1,RotVal  ; min limit = -128 reached ?
  cpi  Temp1,$80  ;
  breq  Exit    ; yes, so don't decrement
  dec  RotVal    ; no, decrement
Exit:
  pop  Temp1    ; restore Flag register
  out  SREG,Temp1  ;
  pop  Temp1    ; restore Temp1
  reti

das ganze muß natürlich noch gestartet werden
Das Hauptprogramm fragt gelegentlich die Variable RotVal auf Werte
ungleich Null ab
Durch die schnelle Antwortzeit des Interrupt habe ich keine Problem mit
Prellen, vermutlich zählt die Interruptroutine auch alle Preller vor und
zurück mit.
Ich benutze auch die Conrad-Drehgeber DDM427 von hopt-schuler.com ,der
leider nur auf jeder zweiten Flanke rastet

73
Christoph

von Rolf (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja, bei dem Auswerten der Interrupts sollten natürlich auch die Preller
komplett ausgewertet werden; ansonsten hat man ja wieder das Prellen
drinn. Durch die Preller wird der Wert aber nur für ein paar
Mikrosekunden geändert.
Wenn das unerwünscht ist, kommt man um Polling nicht herum, braucht
dafür aber mehr CPU-Zeit und kann schnelles Drehen des Drehgebers nicht
mehr auswerten.
Optimal wäre natürlich ein Drehgeber mit mehr als zwei Adern,
beispielsweise mit 8-Bit-Gray-Code-Ausgabe (256 Schritte/Vollkreis) und
einem Inkrementieren/Dekrementieren alle N>2 Schritte, denn dann werden
alle Preller automatisch exakt eleminiert und man braucht weder
Interrupts noch Polling. Nur bei mehr als 360 Grad bräuchte man einen
Timer-IRQ um die Nulldurchgänge zu zählen. Der Nachteil ist natürlich
die teurere Hardware.

von SuperUser (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ähm...

Eine Interrupt Auswertung sollte sich eigentlich grundlegend von der
Polling Implementierung unterscheiden. Ich halte es für risikoreich
darauf zu hoffen, dass der Interrupt schon alle Preller mitbekommt...

Z.B. so (noch nicht getestet mit Drehgeber):
a) wir reagieren auf die erste Änderung mit b)
b) wir stellen uns blind für die erwartete Prellzeit
c) nach deren Ablauf lesen wir den derzeitigen Zustand und entscheiden
was zu tun ist
d) wir warten auf die nächste Änderung

(Prellzeit für DDM427 z.B. 3ms nach Datasheet)

von Rolf (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Das ist aber empfindlich auf Preller.
Ich mache es beim Polling so, dass der aktuelle Wert derjenige ist, der
zuletzt 30x in Folge (konstant) eingelesen wurde.

von Christoph Kessler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo
Ich habe auch so einen Drehgeber mit 8Bit-Absolutcodierung von Bourns.
Leider gibt es nicht nur DEN Graycode, sondern viele verschiedene. Den
von Bourns kann man soweit ich sehe nur mit einer Tabelle in Dualzahlen
umcodieren. Es gibt eine speziellen Graycode beliebiger Breite, der
systematisch mit EXOR-Gattern hin- und zurück codiert werden kann (
wenn man mal von der Laufzeit in den hintereinandergeschalteten Gattern
absieht, die den Vorteil des Gray-Codes zunichte macht, dass sich nur
ein Bit pro Stufe ändert - die Glitches müssen wieder berücksichtigt
werden)
73
Christoph

von Rolf (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja, man kann den Gray-Code natürlich auch genau anders rum verwenden,
also z. B. in der ersten Stufe so kodieren:
0 -> 0
1 -> 0xff
2 -> 0xfe
...
ohne die grundsätzlichen Eigenschaften zu ändern, aber die Variante mit
den Gattern ist das zu 99,9 % verwendete auch in den Lehrbüchern.
Die Glitches kann man mit einem Mikrocontroller vermeiden.
Man kann dafür auch den Parallelport am PC nehmen.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
@Christoph

"Leider gibt es nicht nur DEN Graycode"

Kannst Du mir denn einen anderen zeigen ?

Ich habe noch nirgends einen anderen Gray-Code gefunden.

Die Bedingung ist ja, daß sich nur ein Bit ändern darf und das geht
eben nur mit der bekannten Bildungsregel, jedes nächste Bit spiegelt
alle darunter liegende Bits (EXOR).

Und der Gray-Code muß natürlich vollständig sein, d.h. 256 Werte bei 8
Bit.


Peter

von Christoph Kessler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
http://www.bourns.com/pdfs/ace.pdf
das ist ein absoluter Drehgeber mit total wirrem Graycode, auch Bourns
empfiehlt eine Tabelle zu verwenden

von Rolf F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Naja, da hat man einiges Abzutippen.
Ungewöhnlich ist ja schon die Bezeichnung p1..p8 bei den Adern, denn
normalerweise wird statt p1 stattdessen p0 (etspr. für n*2^0)
verwendet.

Aber man findet ja schon im Datenblatt vom Conrad einen Algorithmus,
der nur eine Sorte Flanken auswertet und entsprechend viele Preller
gibt.

von Christoph Kessler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Abtippen bei PDF kann man ja sparen, besser kopieren und in
openoffice-calc einlesen und umformen
aber der Graycode ist hier auch unvollständig, 128 Stufen mit 8 Bit ist
eines zuviel, scheint aber kein Korrekturbit zu sein, das wenigstens
nützlich wäre
So einen Schalter hat mir mal ein Vertreter auf einer Spoerle-
Regionalausstellung geschenkt, ich habe dann irgendwann an ein Eprom
angeschlossen, um ihn als Kanalwähler für eine PLL zu benutzen, da
spielen Glitches keine Rolle.

von Rolf F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Tatsächlich, 8 Adern für nur 127 Positionen; das ist ja richtig
pervers!
Dabei ist der übliche Gray-Code ganz einfach:

http://www.peg.si/electro/angle.html

von Christoph Kessler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
ja genau das meinte ich mit den hintereinadergeschalteten EXORs, das ist
wie beim ripple-counter, die Bits ändern sich alle nacheinander um je
eine Gatterlaufzeit verzögert, also genau was man mit dem Graycode
vermeiden wollte, glitches von einigen Nanosekunden

von Rolf F. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja, stimmt; eigentlich muss man dafür einen Mikrocontroller-Port nehmen
und per Software dekodieren, also mittels

  x ^= (x >> 4);
  x ^= (x >> 2);
  x ^= (x >> 1);

Weil unter dem Link nur eine LED-Anzeige ist, sind die Glitcher aber
egal, weil nicht sichtbar.

von Der T. (_techniker_)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter!

Damit ich vom Conrad-Drehgeber nur bei jeder vollen Rasterstellung den
Wert aktualisiere, habe ich deinen Code ein bischen erweitert!

_______________________
// 3. Drehimpulsgeber auswerten
 static int DIG_enc_last = 0x01;
  char DIG_i = 0;
  if( PHASE_A ) { DIG_i = 1; }
  if( PHASE_B ) { DIG_i ^= 3; } // convert gray to binary
  DIG_i -= DIG_enc_last; // difference new - last
  if( DIG_i & 1 ) // bit 0 = value (1)
  {
   DIG_enc_last += DIG_i; // store new as next last
   DIG_enc_delta += (DIG_i & 2) - 1; //Halbschrittzähler
   if ((DIG_enc_delta - DIG_enc_delta2) > 1) { DIG_value++;
DIG_enc_delta2 = 0; DIG_enc_delta = 0; }
   if ((DIG_enc_delta2 - DIG_enc_delta) > 1) { DIG_value--;
DIG_enc_delta2 = 0; DIG_enc_delta = 0; }
  }
_______________________

Im Prinzip wird der Zähler aus deinem Code mit einem 2. Zählerwert
verglichen (Startwert von DIG_enc_delta2 = 1). Weicht der
Halbschrittzähler mehr als 1 ab, so wird der aktelle Vollschritt
übernommen (DIG_value) und beide delta-Zähler wieder zurückgesetzt.

Der Code funktioniert, bin aber für Verbesserungsvorschläge -wie immer-
dankbar! (z.B. Code minimieren..)

Gruß,
Techniker

von Der T. (_techniker_)


Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Hab gerade festgestellt, dass ich oben einen alten Code eingefügt
hatte! ;)

Hier der richtige:

_____________________
// 3. Drehimpulsgeber auswerten
 static signed int DIG_enc_last = 0x01;
 static signed char DIG_enc_delta = 0, DIG_enc_delta2 = 1;
  char DIG_i = 0;
  if( PHASE_A ) { DIG_i = 1; }
  if( PHASE_B ) { DIG_i ^= 3; } // convert gray to binary
  DIG_i -= DIG_enc_last; // difference new - last
  if( DIG_i & 1 ) // bit 0 = value (1)
  {
   DIG_enc_last += DIG_i; // store new as next last
   DIG_enc_delta += (DIG_i & 2) - 1; //Halbschrittzähler
   if ((DIG_enc_delta - DIG_enc_delta2) > 1) { DIG_value++;
DIG_enc_delta -= 2; DIG_enc_delta2 = DIG_enc_delta; }
   if ((DIG_enc_delta2 - DIG_enc_delta) > 1) { DIG_value--;
DIG_enc_delta += 2; DIG_enc_delta2 = DIG_enc_delta; }

  }
_____________________

von SuperUser (Gast)


Bewertung
0 lesenswert
nicht lesenswert
n' bisschen einfacher (und leichter zu verstehen...)

http://www.mikrocontroller.net/forum/read-4-250095.html#new

von Der T. (_techniker_)


Bewertung
0 lesenswert
nicht lesenswert
@SuperUser:
Den hatte ich schnomal probiert, hatte aber nicht funktioniert...

Nun habe ich es nochmal ausprobiert und er funktioniert auf anhieb
einwandfrei. :) Keine Ahnung, was damals schiefgelaufen ist.

Gebe mich damit geschlagen... ;)

(muß mir jetzt mal den Code vom Christian genau vornehmen, weil ich
noch nicht ganz über den Funktionsablauf dahintergekommen bin..)

Gruß,
Techniker

von Philipp Kälin (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Kann mir jemand sagen, wie ich einen Drehgeber mit der C-Control von
Conrad in Basic auslesen kann. Die Idee von peter dannegger (oberster
Beitrag dieser Seite) klingt für mich eigentlich logisch, nur kann ich
mit C nichts anfangen. Kann das Jemand für mich in Worte oder
Flussdiagramm übersetzen, damit ich es verstehe und dann in Basic++
programmieren kann?

MfG

Philipp

von Kersten D. (unbenannt-editor)


Bewertung
0 lesenswert
nicht lesenswert
Hi!
Ich probiere gerade den 2. Code von Peter Dannegger. Drehgeber ist ein
Poti-ähnliches Ding von Alps aus einer alten Maus.

Die Erkennung funktioniert soweit, allerdings muss man sehr langsam
drehen. Der Drehgeber ist aber auch sehr fein und ohne Rasterung. Wie
kann ich den Code ändern, dass nur z.B. alle 10 oder alle 100 Impulse
ausgewertet wird?
Danke!
Kersten

von (geloescht) (Gast)


Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

von Thomas Lamparter (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jetzt dachte ich in meinem jugendlichen Leichtsinn, hier in dem Forum
etwas über: "wie lese ich einen Absolutwertgeber aus" zu erfahren.
Das es mit Clock, und Data und n Bits geht, ist klar, ... nur suche in
nach einem Sourcecode....

Wer ne Idee hat, melden. Danke

von peter dannegger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Thomas

"Jetzt dachte ich in meinem jugendlichen Leichtsinn ..."

... es gibt weltweit nur einen einzigen Absolutwertgeber.


Nein, es gibt natürlich viele verschiedene.

Und keiner kann hellsehen, welchen Du gerade meinst.

Du mußt also schon nach Deinem bestimmten Typ suchen bzw. ein Blick ins
Datenblatt könnte auch nicht schaden. Manchmal enthalten Datenblätter
sogar Beispielcode.


Peter


P.S.:
In der sozialistischen Staatengemeinschaft gab es von einigen Geräten
wirklich nur einen einzigen Typ, aber das ist doch schon über 15 Jahre
her.

von Thomas Lamparter (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo peter dannegger,

Es mag sein, dass in der Planwirtschaft, so was möglich war....

Scherz beiseite, die Drehgeber mit Synchron Seriellem Interface oder
kurz SSI. haben eine relativ klare Vorschrift, was die Datenblätter
angeht ;-) die habe ich schon durch, sei es von dem Maxe Stegmann, oder
von T&R um hier nur 2 stellvertretend zu nennen, da ist kein
Beispielcode daargestellt.

Den C-Quelltext könntest Du , wenn Du gewillt bist ihn mir zu
schreiben, auch variabel halten, (12 Bit... 31 Bit) Denke aber ich
kriege das selber hin, dachte ich geh nur den Weg des kleinsten
Wiederstandes, (Elektrokermentalität eben)


Also, lass es gut sein, lg, Tommy

von peter dannegger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
"Also, lass es gut sein"

Wird mir wohl nichts anderes übrig bleiben, wenn Du keine Lust hast,
eine genaue Typenbezeichnung und einen Link aufs Datenblatt zu geben.

Als Elektroniker sollte man eigentlich in der Lage sein, seine Fragen
präzise zu stellen.

Keiner kann in Deinen Kopf schauen. Es ist ja Dein Bier, wenn Du kein
Interesse an Hilfe hast.


Peter

P.S.:
Was ist ein "Elektroker" ?
Ein Elektroniker kennt jedenfalls keine "Wiederstände".

von Thomas Lamparter (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Es handelt sich um einen Siemens Geber :6FX2001-5FS12

oder um ein optisches Absolutwertmesssystem, der Firma Leuze
electronic, welches sich BPS37 nennt. Hier ist die Anzahl der
auszutaktenden Bits, sehr variabel, kann frei konfiguriert werden (ab
12 Bit, bis 31 Bits, je nach Auflösung).  Die Taktrate kann zwischen
90kHz und 1 MHz liegen.
Die Totzeit nach dem LSB (least signifcant bit = letztes oder
niederwertigstes, auszutaktendede Bit)

Und Du hast recht, eine Elektroniker kennt keine Wiederstände, nur
Widerstände. (Wuste nicht, dass wir hier ein Genie in Sachen deutsche
orthographie haben - danke für die Belehrung, hab wohl wirklich 1 Bier
zu viel gehabt).

Aber ich denke Du kannst mir nicht helfen, nicht weil das ein Ding der
Unmöglichkeit wäre, sondern, weil Du nicht willst, oder nict in der
Lage bist. (Sorry für meine offenen Worte)

Ich habe mir eien Ansatz zusammengereimt, wie ich den Geber austakte:

Port 1.2 udn Port 1.3 aös Daten udn Taktleitungen (Optokoppler und
RS485-Transceiver nachgeschaltet)

Akku löschen, Clockbit setzen, Timer freigeben, nach abgelaufener Zeit
Portpin für die Daten abfragen und in Ziel schieben, Zähler um 1
dekrementieren, wenn Zähler 0, dann die Zahl von Gray in Binaer
wandeln, danach in Hexzahl wandeln, und via UART an PC senden.

Also Danke nochmals. (Und entschuldige, über eventuelle
Rechtschreibfehler die Dir im AUge wehtun ;-)

von peter dannegger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
"Aber ich denke Du kannst mir nicht helfen, nicht weil das ein Ding
der
Unmöglichkeit wäre, sondern, weil Du nicht willst, oder nict in der
Lage bist. (Sorry für meine offenen Worte)"


Da bist Du völlig auf dem Holzweg.
Das einzige Hindernis bist Du selber, der einen blöde anmacht, wenn man
ihm versucht mehr Informationen aus der Nase zu ziehen.


Google findet jedenfalls einen Treffer, ist zwar 8051-Code, aber als
Anregung bestimmt gut zu gebrauchen.
Der Autor gibt nämlich den Typ an, weil er nicht denkt, daß es nur
einen Typ gibt und jeder gleich Bescheid wissen muß.


In der Regel läßt man ungenaue Fragen einfach links liegen und ich
werde es das nächste mal besser auch so machen.


Peter

von thomas lamparter (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hilfe, es läuft.

werde morgen (jetzt ist es eh zu spät, mal nen Absolutgeber mit 24 Bit
anschliesen, und wenn es läuft, dann nur noch die Fehlerauswertung)

warst ne echte Hilfe, also nochmals vielen Dank....

Thomas

von Simon K. (simon) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
@Peter:

Ich habe ein komisches Problem:

Wenn ich meinen Zählerstand verändere mache ich das mit
rot_pos += tmp;

Dabei zählt er zwei weiter. Soweit so gut, hatten wir ja oben schon.
Nach deinem Lösungsvorschlag müsste das so aussehen:
rot_pos += tmp>>1;

Problem: Der Compiler übersetzt das (nachvollziehbarerweise) so:
        rot_pos += tmp>>1;
  c8:  86 95         lsr  r24
  ca:  90 91 6a 00   lds  r25, 0x006A
  ce:  89 0f         add  r24, r25
  d0:  80 93 6a 00   sts  0x006A, r24

Der Knackpunkt ist aber, dass tmp eine char (signed!) Variable ist. Das
Vorzeichen-bit geht somit flöten. Und dementsprechend gibt das Drehen in
die Eine Richtung Stuss, und in die andere Richtung garnichts.
Was hast du dir dabei gedacht? Oder habe ich einen Denkfehler?
Komischerweise übersetzt er bei signed aber
rot_pos += tmp/2;
exakt genauso.

Hilfe! :-)

von Simon K. (simon) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Hm, kaum eine Minute geschrieben, schon habe ich die Lösung:

char ist komischerweise (Wahrscheinlich mit den vielen Parametern
hinter dem gcc.exe) ein unsigned char.

Blöderweise widern mich die Parameter an, weil das so viele sind.
Deswegen beschäftige ich mich damit nur ungern ;)

von Simon K. (simon) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
PS: Jetzt übersetzt er es so
      rot_pos += tmp>>1;
  c8:  85 95         asr  r24
  ca:  90 91 6a 00   lds  r25, 0x006A
  ce:  89 0f         add  r24, r25
  d0:  80 93 6a 00   sts  0x006A, r24

Also alles Klar!

von Simon K. (simon) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Hm, zu früh gefreut. Verhält sich genau gleich der Mikrocontroller.

@Peter oder jemand anders :-): Kannst du mal kurz über meinen Code
sehen? Ich hänge dir mal die relevanten Dateien an.

von Simon K. (simon) Benutzerseite


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
#1

von Simon K. (simon) Benutzerseite


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
#2

von Simon K. (simon) Benutzerseite


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
und #3

von SuperUser (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sorry, habe mir deinen Code nicht angesehen, aber wenn dich das doppelt
zählen stört kannst du auch mal dort nachsehen:

http://www.mikrocontroller.net/forum/read-4-250095.html#new

von Simon K. (simon) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Ich danke dir, das sieht ebenfalls sehr interessant aus.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
@simon,

nein, so kann es nicht gehen.

Wenn Du das Bit 0 nicht auswertest, darf es auch nicht gelöscht werden,
sonst funktioniert das Entprellen nicht.

Du mußt also die Auslesefunktion so ändern:
signed char rot_getdelta(void)
{
  signed char tmp;

  cli();
  tmp = rot_delta;
  rot_delta = tmp & 1;  // bit 0 needed for debounce !
  sei();

  return tmp >> 1;      // pulse / 2
}


Peter

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Simon,

Schweigen im Walde ?

Wäre schon interessant, ob es nun funktioniert.
Theoretisch müßte es.
Ich habe leider keinen solchen Drehgeber, um es zu testen.


Peter

von Simon K. (simon) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Hi Peter, ich hab direkt den Code von SuperUser genommen.

Schlimm dass ich dein Codeschnipsel nicht mehr ausprobieren konnte? Das
von SuperUser klappt jedenfalls mit meinem Encoder von Pollin sehr gut.

von Thorsten F. (thorsten)


Bewertung
0 lesenswert
nicht lesenswert
Sorry fürs ausbuddeln.

@Peter

Wollte nur mal melden, dass die Anpassung auf den Drehgeber der nur
alle 2 Schritte einrastet (Pollin-teil) funktioniert.

gruß

von Holger G. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo P E T E R  D A N N E G G E R ?

ich benutze:

- deinen Codeschnipsel mit der Differenzmethode aus "encoder.c"
- optischen Drehencoder Grayhill-62A (1 Flanke pro Rastung)
- Auswertung durch Polling per Timer-Interrupt auf MSP430

Problem:

Beim Drehen funktioniert die Auswertung tadellos. Allerdings macht mir 
der Anfangszustand der Zählvariable "enc_delta" zu schaffen. Je nach 
Position des Drehencoders wird "enc_delta" um 1 inkrementiert / 
dekrementiert wenn die Funktion das erste mal gestartet wird und zwar 
bevor ich überhaupt gedreht habe.

Wenn ich mir den Code anschaue, sehe ich, dass nach der Differenzbildung 
"i-=enc_last" eine Zahl zwischen 0 und 3 entsteht und diese im Schritt 
"if (i & 1)" auf jeden Fall ausgewertet wird (i=1, i=3), also auch wenn 
die Funktion das erste mal gestartet wird und "enc_last=1" ist.

Wie löse ich dieses Problem? Eventuell A und B schon vorher einlesen und 
dann "enc_last" auf diesen Wert und nicht auf 1 setzen? Oder gibt es 
einen anderen Weg?


Bitte, bitte helft mir!

hg

von the_absolute_trough_blicker ;-) (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Autsch Peter Danegger scheint heir einem Denkfehler auferlegen zu sein.

wenn ich nun einen Sin/cos-geber habe, wie werde ich damit glücklich.

Ich kann zwar einen Quadraturencoderchip verwenden um damit klare 
rechecksignale auzubereiten und diese damit dem µcontroller zur 
Verfügung stellen, aber das ist nur die halbe Miete. Wenn ich schon ne 
fast unendlich hohe Auflösung habe sollte ich die doch auch verwenden 
und mich nicht mit schlappen 1024 oder 2048-Inkrementen zufrieden geben, 
oder was meint Ihr dazu ? Natürlichist die Auflösung beschrenkt, durch 
die Reckenleistung des µC´s.

Also Fakt ist, dass hier nicht ein Billigheimergeber eingesetzt werden 
soll sondern ein hochwertiger, der dann bei einem Motor mit hoher 
Achslast nicht zu Microtorsion neigt udn damit bei eienm sagen wir mal 
500 Inc. Geber zum Nachregeln und aufschwingen neigt. Ja ich weis... 
jeder Regler bedarf einer Regelabweichung... aber sollte diese nicht so 
klein wie möglich sein ?

Also. P.Danekker, wie ist die Erfahrung mit Präzisionsgebern.

Einsatzgebiet. Switched Reluktanzmotor, Achlast nach Getriebe 240/12/2 
Umsetzung, udn einem Supergenialen Sin/Cos-Geber, wie er auf dem Markt 
erhältlich ist auf die Lastabgewandte Seite (also nicht auf der 
Getriebeseite und nicht nach dem Getriebe)

Den Assemblercode für den Geber (Absolutwertgeber) habe ich, die 
Grobauswertung kann ich a la den Beispielen hier super gestalten, nur 
die 65535-wertige Feinauflösung bekomme ich nicht gebacken.

Wenn jemand was weis, bitte kurz Datenblatt oder Sourcecode anhängen ..

nun gut für das erste mal, eine Super Newsgroup (was für ein grässliches 
neudeutsches Wort) und richtig schöne Beiträge hier.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
the_absolute_trough_blicker ;-) wrote:
> Autsch Peter Danegger scheint heir einem Denkfehler auferlegen zu sein.

> Verfügung stellen, aber das ist nur die halbe Miete. Wenn ich schon ne
> fast unendlich hohe Auflösung habe sollte ich die doch auch verwenden
> und mich nicht mit schlappen 1024 oder 2048-Inkrementen zufrieden geben,
> oder was meint Ihr dazu ? Natürlichist die Auflösung beschrenkt, durch
> die Reckenleistung des µC´s.


Der Denkfehler liegt eindeutig bei Dir

Die Rechenleistung ist völlig schnurz.

Analogsignale kann man nicht unendlich gut auflösen. Außerdem machen Dir 
Nichlineritäten, Störspannungen, Vibrationen, Rauschen usw. einen Strich 
durch die Rechnung.

Es stimmt schon, es gibt auch Drehgeber mit Analogausgang. Allerdings 
macht man dann möglichst nahe eine Umwandlung in Gray-Code, weil sich 
das viel leichter weiterleiten und verarbeiten läßt.
Wir haben sie auf eine Auflösung von 16 Teilschritten gesetzt, weil es 
darüber instabil wird.


Peter

von the_absolute_trough_blicker ;-) (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter Danegger,

meine etwas scharfe Provokation hat genutzt. Ich habe Deine vollste 
Aufmerksamkeit erregt.

Ja, ich gebe Dir vollkommen Recht, einen Positionsgeber auf mehr als 16 
Bit aufzulösen ist für die meisten Anwendungen mumpitz ;-)

aber die Feinauflösung (Sin/Cos-Geber welche mit Arg-Tan vermostet 
werden) ist dennoch von Berechtigung. So ist es in der Lageregelung von 
Bedeutung, dass heir eine möglich hohe Auflösung erreicht wird. In der 
Drehzahlregelung ist das eher von geringerer Bedeutung, und somit 
reichen bei der Regelung gar die Spuren A und B aus.

Anwenungsfall Aufzug hast Du vollkommen Recht
Anwendungfall µ-Positionierung bin ich im Recht.

Aber um hier zu schlichten wird denke ich kein Schlichter oder Anwalt 
benötigt ;-)

Deine Forumsbeiträge sind eien Bereicherung.

Absolutwertgeber mit Serial-Synchon-Interface oder gar BISS werden von 
mir eher wenniger eingesetzt, da die vonDir erwähnten EMV-Probleme bei 
dieser differentiellen Schnittstelle ein großes Problem darstellen.
Wir verwenden eher die für Feldbus aufbereiten Systeme (hier ist es egal 
ob  Lichtlaufzeit (linear) Barcodepositioniersysteme von Leuze oder 
Drehgeber von Stegmann für die rotatorische Auswertung zum Einsatz 
kommen.

Gray-Code o.k. hat den Vorteil, dass der Wechsel von 2 Zuständen immer 
nur 1 Bitsprung bewirkt, aber wenn das diff-Signal madig ist (zu viele 
Störungen) dann kann es zu Bitdrehern kommen und so der Positionsistwert 
frei nach dem Motto "Cat down the River" oder schwäbisch "d´Katz da Bach 
na" bedeutet. Hier habe ich inder Vergangenheit immer (für mich 
aufwendig erscheinende) Plausibilitätsprüfungen durchführen müssen. Das 
hat dann in Abhängigkeit von Geschwindigkeit zu geschehen.

grüßle und ich hab es total verschwitzt. ein gutes Neues Jahr.


(wer Rechtschreibfehler findet darf sie behalten)

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
@nur sich selbst dafür haltenden "the_absolute_trough_blicker"


Also wir benutzen gekaufte Lineargeber mit Analogausgang und dazu 
gehörige Wandler in Gray-Code, womit wir dann Piezomotoren <=50µm 
positionieren.

Die Graycodeauswertung erfolgt mit dem obigen Programm einwandfrei.

Die Analogleitungen sind höllisch empfindlich und so kurz wie möglich zu 
halten. Mit 16 Stufen meinte ich, sie interpolieren noch weitere 4 Bits 
je Viertelwelle.

Aber 16 Bits halte ich für völlig unmöglich, da ist ja das Husten von 
Flöhen viel leichter zu zählen.


Mit Aufzügen habe ich absolut nichts zu tun.
Ich hab nur mal gesagt, daß die Aufzugsfirma in unserem Gebäude unfähig 
ist, die Ruftasten zu entprellen (Es gehen immer beide Lampen an, wenn 
man über den Teppich geht). Ich verlasse auch immer schnell die Tür, 
wenn sie sich bewegt, denn ob die Lichtschranke richtig entstört ist, 
weiß man dann ja auch nicht.


Peter

von the_absolute_trough_blicker ;-) (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@ Peter

ich kenn mich nicht mehr so ultragut mit den Aufzugssteuerungen aus, 
aber sei versichert, dass der Sicherheitskreis in europäischen Aufzügen 
funktioniert.
Ob es eine KOllmorgen oder eine LISA oder eine Schindlersteuerung oder 
eine von Liftequip... egal sie tun.

Wenn man(n) und frau bedenkt dass die LISA noch in Pascal programmiert 
wurde (igit) entweder Assembler oder ne ordentzliche Hochsprache ich 
mochte Pascal noch nie (ist denek ich was persönliches) (Ebensowennig 
Cobol) und schon weitaus mehr als 15 Jahre auf dem Buckel hat ist sie 
für den Anwender "easy 2  use".

die Feinauflösung bei den Sin/Cos-Gebern finde ich immer noch brillant, 
aber da scheiden sich unsere Geister ein wennig.

Für Analoge "Geschichten" in der Nähe von Servomotoren oder anderen 
Motoren, welche mit Umrichtern gefahren werden ist es höchst Brisant, 
wie Du schon geschrieben hast. Da ist nicht die kleinen Störspitzen der 
Verursacher sondern das irre hohe dU/dt (mehrere KV/µs werden hier bei 
sogenannten IGBT´s geschaltet - auch wenn der Zwischenkreis bei den 
Reglern sprich FU´s lediglich schlappe 680V- hat.  ooops das ist falsch, 
wenn der Motor in den Generatorischen Zustand geht und Energie 
zurückgibt ist es ein wennig mehr). Also hier helfen nur Motordrosselön 
um die Oberwellen zu fixen und dann noch um das Geberkabel Wunderkerne. 
Die sind im allgemeinen als Ferritkerne erhältlich und lassen sich auf 
das Kabel aufklipsen. Ich bin immer noch verwundert, wie die wirken. 
wenn mann bedenkt, dass solche Ferrite lediglich aus gesintertem 
gekraktem und wieder gepresstem Material besteht.

Also ich wünsch noch was, und freu mich auf weitere rege Beiträge.

liebe Grüße t_a_t_b-;-)


von Joe (Gast)


Bewertung
0 lesenswert
nicht lesenswert
So, habe mir beide Varianten mal angesehen.

Variante 1 habe ich um einen Pulscount mit Vorteiler erweitert. Die 
Abtastrate beträgt ~ 400 Hz und die Routine funktioniert einwandfrei. 
Durch die Vorteilung ist auch noch der genannte Fehler ausgemerzt.

Variante 2 ist zwar schön kurz führt aber bei mir zu Fehlern.

enc_delta sollte ja +/- 1 liefern, zeitweise bekomme ich allerdings auch 
andere Werte zurück z.B. 3/4 etc, so als ob sich der Nullpunkt 
verschiebt. Bin mir nicht sicher ob es mein Fehler ist oder ob der 
Algorithmus einen Fehler erzeugen kann.

@ Peter, hast du ne Idee hierzu.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Joe wrote:

> enc_delta sollte ja +/- 1 liefern, zeitweise bekomme ich allerdings auch
> andere Werte zurück z.B. 3/4 etc

Nö, der Wert kann -128 ... +127 betragen, je nachdem, wieviel Pulse seit 
dem letzten Lesen gezählt wurden.
Wichtig ist, daß das Lesen und Löschen atomar erfolgen muß.


Was bedeutet denn Vorteilung ?
Wenn Du die Pulse auf 2 Teiler gibst, sind sie doch nicht mehr um 90° 
phasenverschoben.

400Hz scheint mir etwas langsam.


Peter

von Joe (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja, 400 Hz ist zu langsam, habe nun die 2te Routine auch begriffen, hat 
ne Weile gedauert.

Danke für den Hinweis.

von D.ESWAR (Gast)


Bewertung
0 lesenswert
nicht lesenswert
DDM427 ROTARY ENCODER DETAILS

von Dirk F. (dirk-frerichs)


Bewertung
0 lesenswert
nicht lesenswert
hallo
ich habe ein kleines problem...

ich habe einen ATmega8 mit dem pollin Encoder
PANASONIC EVEQDBRL416B
datenblatt:
http://www.pollin.de/shop/downloads/D240313D.PDF

er hat also in den rastungen entweder 00 oder 11
01 und 10 sind nur während der drehung  dynamisch vorhanden

habe nun mittlerweile verschiedene codes getestet
einer funktioniert recht gut ..
ABER er bleibt manchmal einfach hängen
auch wenn er fast alleine läuft


kann mir jemand dabei helfen ?

das mit dem graycode ist gut , nur bn ich noch nicht SO in C bewandert 
das ich das komplett durchblick ...
oder etwas genauer erklären ...

vielen Dank
grüße
Dirk

von ich (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Dirk Frerichs

Teste mal das hier:

// ---- include Dateien ----
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>


// 
************************************************************************ 
**************
// ---- function prototypes ----

void wait_until_key_pressed(void);


// 
************************************************************************ 
**************
// ---- constant definitions ----

#define Schalter_A PIND1 // Schalter A im Drehgeber
#define Schalter_B PIND0 // Schalter B im Drehgeber
#define Taster_P   PIND2 // Taster im Drehgeber
#define Geber      PIND  // Drehgeber Port

#define Ausgabe    PORTB // Ausgabe Port zum Testen

volatile unsigned char richtung = 0;  // 0 ... 255


// 
************************************************************************ 
**************
ISR(TIMER0_OVF_vect)
{
  static unsigned char alter_status = 0,step = 0;
  unsigned char        neuer_status;

      neuer_status = Geber & (_BV(Schalter_A) | _BV(Schalter_B)); // 
Änderung einlesen
  if ((neuer_status ^ step)==(_BV(Schalter_A) | _BV(Schalter_B)))
  {
    if ((neuer_status ^ alter_status)==_BV(Schalter_A))
      richtung +=1;                  // Es war eins nach rechts
    else
      richtung -=1;                  // Es war eins nach links
    step = neuer_status;
  }
  alter_status = neuer_status;
}

von dirk-frerichs (Gast)


Bewertung
0 lesenswert
nicht lesenswert
hi
hab dank aber ich habe es mit der ursprünglichen routine  hinbekommen
es läuft auch sehr gut...

da der regler aber entweder in 00 oder 11 rastet
habe ich den delta-wert nochmal geteilt



grüße

werd es mal heute abend reinstellen

von Philipp P. (putzer_philipp)


Bewertung
0 lesenswert
nicht lesenswert
Hallo!!

Ich hätte eine Frage zur Routine und deren Anwendung:
Ich möchte eine Wetterfahne (Windrichtung) mit einem Drehgeber 
auswerten. Ich habe hierfür die Routine von Peter Dannegger verwendet 
und durchaus gute Ergebnisse erzielt.

Nun habe ich aber ein kleines Problem: die Messung soll längere Zeit 
unbeaufsichtigt betrieben werden, das heißt das Teil wird einmal zu 
Beginn der Messung genau nach Norden ausgerichtet. Der MC soll nun aus 
den erhalteten Pulsen über einen Umrechungsfaktor die Abweichung von 
Norden bestimmen. Also eine Pulsändereung nach rechts -> +3,6° usw. 
(Überlauf wird berücksichtigt)

Ist das oben beschriebene Vorgehen für eine Langzeitmessung sinnvoll? 
Wenn ich nun einen Puls pro Woche oder Tag, keine Ahnung, verliere (der 
Encoder gibt 100Pulse/Um) wären das ja 3,6° Fehler!!

Gibt es für solche speziellen Anwendungen eine besondere Art von 
Encodern?
Oder brauche ich mir um den Verlust von Pulsen keine Gedanken machen?


Vielen Dank und schöne Grüße

Philipp

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
@Phillip

solange die Wetterfahne sich nicht im Zentrum eines Tornados befindet, 
dürfte die Windrichtung sich nicht so schnell ändern, daß Schritte 
verloren gehen.

50kHz Abtastrate und 100 Schritte bedeuten max 15000 Upm.



Peter

von Philipp P. (putzer_philipp)


Bewertung
0 lesenswert
nicht lesenswert
Super, so was habe ich gehofft!!

UNd wenn es zu einem Tornado kommt, ist der Verlust von ein paar 
Schritten garantiert mein kleinstes Problem!!

Danke und schöne Grüße

Philipp

von Andreas S. (andreas) (Admin) Benutzerseite Flattr this


Bewertung
0 lesenswert
nicht lesenswert
Relative Drehgeber sind dafür nicht gut geeignet; dass aus irgend einem 
Grund (Schwingung, ruckartige Bewegung, mechanische/optische Probleme im 
Drehgeber)  alle paar Tage/Wochen mal ein Schritt verloren geht kann man 
nicht ausschließen. Ein Encoder der einen Absolutwert ausgibt wäre 
sinnvoller. Alternativ dazu könnte man den Drehgeber regelmäßig 
automatisch kalibrieren, z.B. durch eine Lichtschranke oder einen 
Mikroschalter an einer bestimmten Position.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Andreas Schwarz wrote:
> Relative Drehgeber sind dafür nicht gut geeignet; dass aus irgend einem
> Grund (Schwingung, ruckartige Bewegung, mechanische/optische Probleme im
> Drehgeber)  alle paar Tage/Wochen mal ein Schritt verloren geht kann man
> nicht ausschließen.

Nein, man kann es ausschließen !

Das ist ja gerade der Witz am Graycode, daß sich immer nur ein Bit 
ändern kann.

Wenn also mal ein kurzer Störimpuls gezählt wird, ist er ja bei der 
nächsten Abtastung vorbei und wird wieder abgezogen.

Es kann also nur temporär ein Fehler von +-1 Impuls auftreten, aber nie 
akkumulierend.


Das trifft allerdings nur für entprellende Algorithmen wie dem obigen 
zu, die im Timerinterrupt abtasten.

Algorithmen mit Flankeninterrupt können dagegen Pulse verlieren, wenn 
die Störungen zu schnell kommen.
Und auch alle Algorithmen, die im Interrupt mehrmals den selben Pin 
einlesen, lassen sich durch Störungen leicht aus dem Tritt bringen.


Peter

von Andreas S. (andreas) (Admin) Benutzerseite Flattr this


Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger wrote:
> Andreas Schwarz wrote:
>> Relative Drehgeber sind dafür nicht gut geeignet; dass aus irgend einem
>> Grund (Schwingung, ruckartige Bewegung, mechanische/optische Probleme im
>> Drehgeber)  alle paar Tage/Wochen mal ein Schritt verloren geht kann man
>> nicht ausschließen.
>
> Nein, man kann es ausschließen !

Du würdest also guten Gewissens ein Signal von einem relativen Drehgeber 
mit 4 Zuständen über mehrere Wochen hinweg aufintegrieren? Das ist sehr 
mutig.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Andreas Schwarz wrote:

> Du würdest also guten Gewissens ein Signal von einem relativen Drehgeber
> mit 4 Zuständen über mehrere Wochen hinweg aufintegrieren? Das ist sehr
> mutig.

Daran ist überhaupt nichts mutig, wenn der Drehgeber mechanisch und 
elektrisch in Ordnung ist und die Software auch in Ordnng ist.

Und ob 4 Sekunden, 4 Wochen oder 4 Jahre spielt überhaupt keine Rolle.

Relative Drehgeber werden sehr häufig eingesetzt und ich habe noch nie 
gehört, daß sie schlechter als absolute Drehgeber sein sollen.

Natürlich braucht man noch einen Referenzkontakt, um die Software nach 
einem Reset zu nullen.


Peter

von Dirk H. (arm-dran)


Bewertung
0 lesenswert
nicht lesenswert
Also bei sowas wäre ich sehr vorsichtig.

Synchronisationsverluste jedweder Art können immer vorkommen.
Man kan jedoch einen Kompromiss eingehen.

Indem man für einen evtl. Referenzlauf an irgendeiner Stelle einen
sozusagen Nullungskontakt einbaut (optisch, mechanich etc).

Gibt diesem Rad (oder was auch immer es ist) einen Schwung um die eigene
Achse. Spätestens am Nullungkontakt baut er eine Referenzposition auf.

Zum einlernen dreht er das Rad bis es z.B. auf Norden zeigt, drückt ne 
Taste
und speichert intern die Anzahl der Steps bis zur 0 Referenz.

Es ist anzunehmen, daß dieser Kontakt aller Zeitperiode X dort mal 
vorbeikommt
und sich referenziert. Anhand der Steps von Norden bis 0 Punkt weiss er 
wo er steht.
Wenn die Elektronik mal ausfallen sollte oder ein kurzer Reset das 
System
lahm legt, erkennt er, das noch keine Nullung durch den Kontakt 
stattgefunden
hat und wartet zumindest, bis der Wind sein nötigstes getan hat.

Sollte natürlich ein Erdbeben auftreten und die Erdplatten verschieben
oder Nord und Südpol plötzlich umswappen, hat man halt Pech.


von Philipp P. (putzer_philipp)


Bewertung
0 lesenswert
nicht lesenswert
Hallo!!

Danke erstmal für die Lösungsvorschläge!


@Dirk
Dein Vorschlag kling ziemlich gut, nur verstehe ich den im Moment nicht 
so ganz.

Ich stelle also meine Windfahne irgenwie auf. Wohin der Pfeil zeigt ist 
Wurscht? Unter der Fahne habe ich irgendwo einen Kontakt

Um die Fahne zu refenzieren drücke ich am MC eine Taste um dem MC zu 
sagen, jetzt kommt der Refernezwert

Nun drehe ich die Fahne bis auf Norden hin, lasse die Taste zb. los 
(oder drücke sie nochmals, je nach dem wie ichs programmiere)

Die bisher gezählten Schritte vom Puls des 0-Pkt's bis zum Nordpol 
speichere ich im EEp.

Liege ich bisher richtig??

Nur wie komme ich von diesem refenezwert auf meine Richtung? Das 
verstehe ich noch nicht ganz!
Kannst Du mir das vielleicht ein wenig genauer erklären?

Vielen Danke und schöne Grüße

Philipp

von Dirk H. (arm-dran)


Bewertung
0 lesenswert
nicht lesenswert
Philipp Putzer wrote:
> Hallo!!
>
> Danke erstmal für die Lösungsvorschläge!
>
>
> @Dirk
> Dein Vorschlag kling ziemlich gut, nur verstehe ich den im Moment nicht
> so ganz.
>

@Philipp

OK.

Du hast eine Wetterfahne oder nen Wetterhahn.

Das ganze hängt an einer drehbaren Welle bzw. Stange.

Unten an der Stange ist ein Drehimpulsgeber montiert. Sagen wir mal mit
100 Schritten und damit einer Auflösung von 3.6°.

Nun gibt es mehrere Möglichkeiten:
(Drehimpulsgeber mit eingebauter Referenzspur lassen wir mal weg)
Ich erkläre es nur mal als Beispiel zum Verständniss. Du kannst es dann
auch anders lösen.

Du montierst auf die Welle, auf der auch der Drehgeber sitzt eine (z.B) 
Kunststoffscheibe oder Metallscheibe mit angemessenem Durchmesser.
Bohrst in diese Scheibe ziemlich weit aussen 1 (!!!) kleines (!!!) Loch.
Dann nimmst Du ne Gabellichtschranke und montierst Sie so, das Sie nen
Impuls abgibt, wenn Sie am Loch vorbei kommt. Der Reaktionsbereich 
sollte ziemlich eng sein.
Die Scheibe dreht sich natürlich mit der Welle.

Soweit so gut. Du kannst diese einmalige Position natürlich auch anders
detektieren.

Beim Einlernen drehst Du die Fahne oder den Hahn (;-)) mind. ein mal von 
Hand um die eigene Achse.

Die Software erkennt jetzt anhand des Impulses von der Lichtschranke
einen Referenzpunkt, der hat aber noch garnichts mit der Himmelsrichtung
zu tun.
Du musst hier auch keine Taste drücken, da der Referenzpunkt durch das
Drehen der Scheibe automatisch gefunden wurde.
Die Software setzt den internen Zählwert auf null und zählt ab jetzt
die Steps vom Drehgeber in beide Richtungen.

Jetzt nimmst Du Deine Fahne oder Deinen Wetterhahn noch mal in die Hand
und richtest Ihn nach Norden aus (nehme an mit Kompass) und drückst kurz 
eine Taste. Den Wert musst Du dann intern abspeichern.
Jetzt weiss Dein µC, wieviele Schritte es vom 0 Punkt bis Norden sind.
Aufgrund dieser Werte kann er alles andere berechnen.

Du könntest Dir zum Beispiel noch 2 LEDs hinbauen.
Die eine zeigt an, wenn das System nach dem Einschalten zum ersten mal
den Referenzpunkt gefunden hat und die andere ob der NORD-Wert 
eingelernt
wurde. Wenn beide LEDs an sind, arbeitet das System einwandfrei, es sei
denn, Du hast beim einlernen Norden mit Süden verwechselt.

Die Referenzierung findet dann immer wieder automatisch statt, weil 
anzunehmen ist, daß der Wind die Fahne oder den Hahn irgendwann mal
um die eigene Achse bewegt.

Die Software synchronisiert sich sozusagen immer neu, wenn Sie an dieser
Lichtschranke (nur Beispiel) vorbeikommt.




Und jetzt noch eine Möglichkeit, die alles obige unnötig macht.

Schau mal auf die Website von www.austriamicrosystems.com

AS5040
AS5043
AS5045
AS5140

So gehts auch.





von Werner B. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
<Offtopic>
Beim lesen bin ich auf ein anderes Problem gestoßen.

Wie wird die Windrichtung an den Polen bestimmt?

Am Nordpol herrscht immer Südwind?
Am Südpol immer Nordwind?
Von der puren Logik her stimmt das doch.
</Offtopic>

von Dirk H. (arm-dran)


Bewertung
0 lesenswert
nicht lesenswert
Werner B. wrote:
> <Offtopic>
> Beim lesen bin ich auf ein anderes Problem gestoßen.
>
> Wie wird die Windrichtung an den Polen bestimmt?
>
> Am Nordpol herrscht immer Südwind?
> Am Südpol immer Nordwind?
> Von der puren Logik her stimmt das doch.
> </Offtopic>

Da wo die Fahne oder der Hahn hinzeigt, kommt aus der Gegenrichtung der 
Wind.
Ist ja nur eine Softwaredefinition wie man das dann auswertet.

Dirk

von Philipp P. (putzer_philipp)


Bewertung
0 lesenswert
nicht lesenswert
Super, werde das mal testen.

Ich habe gesehen, dass mein Enecoder einen Z-Ausgang besitzt, könnte das 
so ein Refenzpunkt sein, der beretis im encoder drin eingebaut ist??

wenn ja, würde ich natürlich den nehmen



grüße

philipp

von Dirk H. (arm-dran)


Bewertung
0 lesenswert
nicht lesenswert
Philipp Putzer wrote:
> Super, werde das mal testen.
>
> Ich habe gesehen, dass mein Enecoder einen Z-Ausgang besitzt, könnte das
> so ein Refenzpunkt sein, der beretis im encoder drin eingebaut ist??
>
> wenn ja, würde ich natürlich den nehmen
>
>
>
> grüße
>
> philipp

Z ist leider keine Referenzposition sondern nur eine UND Verknüpfung
von Signal A & B
Daher, wenn A=1 + B=1 so ist Z auch =1

Dirk

von Philipp P. (putzer_philipp)


Bewertung
0 lesenswert
nicht lesenswert
Hi!

Habe gerade den Encoder ausgemessen, dieser liefert am Z-Ausgang an 
EINER einzigen Position einen High-Pegel.

Deshalb denke ich, der Z-Ausgang wird dann auch als refenzierungspunkt 
gedacht sein.


werde das mal in absehbarer zeit testen!

vielen dank für die Hilfe und schöne grüße

philipp

von Knut (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Als Nullimpuls oder Referenzimpuls wird ein einzelner Impuls je 
Umdrehung der Geberwelle bezeichnet. Er dient insbesondere zur exakten 
Feststellung einer Null- oder Referenzposition. Um den Nullimpuls 
drehrichtungsunabhängig exakt auswerten zu können, wird er als Standard 
mit dem High-Pegel der beiden Kanäle A und B verknüpft. Durch den 
Phasenversatz der Kanäle ist der Nullimpuls nur halb so lang wie ein 
Impuls A oder B. Die Auswerte-Elektronik muß für den Nullimpuls in der 
Lage sein, die doppelte Eingangsfrequenz zu verarbeiten. Für den Fall, 
daß dies nicht möglich ist, oder wenn aus anderen Gründen ein längerer 
Nullimpuls benötigt wird, kann er für viele Typen auch unverknüpft und 
mit nahezu beliebiger Länge geliefert werden.

Quelle:
http://www.wachendorff.de/Drehgeber/Signalverarbeitung.php

von Gast (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

kann jemand das Beispiel von Hr. Dannegger mal in CCS Code darstellen. 
Ich kriege den Encoder einfach nicht abgefragt,bzw. den Code portiert...

Danke

von sepp (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Was ist ein CCS Code?

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
sepp wrote:
> Was ist ein CCS Code?

Wüßte ich auch gern.

Muß jedenfalls etwas total anderes als C sein, wenn selbst 8 Zeilen 
C-Code zuviel sind :-)


Peter

von Dirk F. (dirk-frerichs)


Bewertung
0 lesenswert
nicht lesenswert
glaube code composer studio

von Dirk H. (arm-dran)


Bewertung
0 lesenswert
nicht lesenswert
Dirk Frerichs wrote:
> glaube code composer studio

Code Composer Studio ist eine Software und keine Programmiersprache.
Für die ARM Controller TMS470 von TI aber hauptsächlich für alle DSP 
Familien TMS320--------
24xx
28xx
5000
6000
etc.

von gast (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@ Peter Man kann genausogut einen Pin-Change-Interrupt nehmen, 
Hauptsache der
Interrupt reagiert auf alle 4 Flanken.

Hallo Peter

Wie ist das gemeint? Der gleiche Code geht auch mit PinChange Interrupt? 
Natürlich auf beide Pins (A und B) oder. Zudem muss man aber auch auf 
alle Flanken reagieren also steigende und fallende oder?.

danke

von Andi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ja, geht auch mit Pin-Change Interrupt.
Hatte es mit einem ATTiny26 gemacht und sicherheitshalber doch kleine 
Kondensatoren (10µF glaube ich) drangehängt.
Ob jetzt beide Pins oder nur einer für die Kanäle auf Pinchange gesetzt 
werden müssen weis ich nicht mehr genau, schon lange her. Aber im 
Prinzip wird primär erst nur ein Pin auf Veränderung abgefragt, also 
müsste einer reichen. Bei Veränderung kommt dann die weitere Auswertung.
Der Pinchange muss auf "toggle" gesetzt werden, also steigend UND 
fallend.
Aber auf was Peter eigentlich hinaus wollte ist, das man sich mit seiner 
Art der Timer-Abfrage und Auswertung die Kondensatoren sparen kann da 
gewisses "flimmer" ausgefiltert wird.
Hatte mir das für nen anderes Projekt in AVR-ASM umgesetzt und es geht 
wunderbar.
Natürlich, je schneller der Timer je weniger bzw. keine Fehler gibt es.
Der Timer sollte, denke ich, mind. 5 mal so hoch sein wie es 
Raststellungen je Umdrehung gibt um auch schnell drehen zu können.

MfG
Andi

von neuhier (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen, ich bin noch recht neu hier, und versuche schon eine 
Weile den 2ten Code von Peter für die Einstellung der Uhrzeit zu 
verwenden.

Jedoch ist mir leider noch immer nicht klar geworden wie ich den 
Drehgeber richtig auswerte.
Im Moment gebe ich nur enc_delta auf einem LCD aus. Der Wert läuft auch 
wenn ich am Drehgeber Drehe von -128 bis +127.

Ich bekomm es leider nicht hin das mir nur die Änderung seit dem letzten 
Interrupt angezeigt wird.

Gruß Michael

von falscher Hase (Gast)


Bewertung
0 lesenswert
nicht lesenswert
In ca. 2 Beiträgen oben steht die Lösung auf Dein Problem mit 
zusätzlicher Info: enc_delta bei der auswertung auf null setzen. Evtl. 
auch noch durch 2 teilen (besser um ein Bit verschieben).

von falscher Hase (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe aber auch eine Frage:

Ein Komparator macht aus den durch Drehen entstehenden 
Wechselspannungsimpulsen eines Schrittmotors ein 5-V Rechtecksignal 
(Beitrag "bürstenloser motor als quadraturencoder, störungen beheben"). Leider ist aber der 
Normalzustand 11, daher gibt es beim Drehen immer erst ein low-Impuls 
auf einer der Leitungen, bevor dann schöner Gray-Code kommt.

Ich benutze den Algorithmus von Peter in einem Pin-Change Interrupt, der 
auf beide Leitungen anspricht.
Ich hatte gehofft, dass der Algorithmus den Anfangsimpuls ignoriert, 
bekomme aber keine entsprechendes Ergebnis (enc_delta chaotisch auf 2 
oder 3).

Schöner wäre es sowieso, wenn gleich der erste Impuls (ein 
(Halb-?)Schritt des Motors) ausgewertet werden könnte, aber ich sehe 
nicht, wie das mit P.D.s Logik vereinbar ist.

Hier noch Codeausschnitte für einen tiny2313 @ 8MHz, 'Encoder' ist an 
PB1 u. PB0
// ENCODER

#define PHASE_A (PINB & 1<<PB0)
#define PHASE_B (PINB & 1<<PB1)


volatile int8_t enc_delta;    // -128 ... 127
  // pin change interrupts
  GIMSK =  1<<PCIE;
  PCMSK = 1<<PCINT0 | 1<<PCINT1;

  sei();
ISR(PCINT_vect)
{

  static int8_t enc_last = 0x01;
  int8_t i = 0;

  if( PHASE_A )
    i = 1;

  if( PHASE_B )
    i ^= 3;        // convert gray to binary

  i -= enc_last;      // difference new - last

  if( i & 1 ){        // bit 0 = value (1)
    enc_last += i;      // store new as next last

    enc_delta += (i & 2) - 1;    // bit 1 = direction (+/-)
  }
  
}

enc_delta lasse ich mir mit 1Hz ausgeben.

von Thomas S. (thomas55)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo und guten Morgen,

gestern Abend brauchte ich eine Routine für einen Rotgeber und bin dann 
bei der Suche hier gelandet. Dann habe ich auch einiges hier 
heruntergeladen um den Rotgeber zum Leben zu erwecken. Lief alles nicht 
wirklich und mit AT´s und mit C (HILFE) kenne ich mich noch ganz 
schlecht aus.
So. Es läuft. Und ich weiss auch warum. Und weil ich da vielleicht was 
anderes habe möchte ich es Euch zeigen.
Die Überlegung: A ist der Takt bei dem mich nur die steigende Flanke 
interessiert und Bist das Datum, das mir sagt ob rechts oder links 
gedreht wurde.
Damit und mit der Info aus meiner Krikelei (Anlage) ist dann die kleine 
Interruptroutine entstanden die wunderbar läuft.

Euch allen hier danke ich für die Vorarbeit. Mit Eurer Hilfe weiss ich 
jetzt wie diese kleinen Dinger funktionieren.
So, jetzt kommt das Programm. Interessant ist ja nur die 
Interruptroutine.
Hoffenlich kann es jemand gebrauchen.

#include <avr/io.h>
#include <avr/interrupt.h>
// #MCU ATmega16
#define Schalter_A PINA1 // Schalter A im Drehgeber
#define Schalter_B PINA0 // Schalter B im Drehgeber
#define Taster_P   PINA2 // Taster im Drehgeber
#define Geber      PORTA  // Drehgeber Port
#define Ausgabe    PORTC // Ausgabe Port zum Testen

volatile unsigned char richtung = 0;  // 0 ... 255
unsigned char        neuer_status;
#define PHASE_A  (PINA & 1<<PINA0)  // RotaryEncoder
#define PHASE_B (PINA & 1<<PINA1)  // RotaryEncoder
volatile uint8_t  enc_delta;      // RotaryEncoder

// 
************************************************************************ 
**************
// WICHTIG: Die Frequenz der Interrupts muss möglichst hoch sein.
// Sonst gibt es so mekwürdigkeiten dass man denken könnte die Tasten
// prellen wie doll und verrückt. Wie hoch die Frequenz hier ist
// weiss ich nicht. Wie könnte man das herausbekommen?
SIGNAL (SIG_OVERFLOW2)
{
//Interrupt, wenn T2 überläuft wird der RotaryEncoder abgefragt
// PHASE_A und PHASE_B sind die Spuren A und B
// A ist jetzt die Taktspur und B die Datenspur.
  static char A_alt;

  if (PHASE_A != A_alt) // es gab zumindest einen Flankenwechsel
    {if (PHASE_A)    // wenn das auch noch WAHR ist war die Flanke 
steigend
    {if (PHASE_B)    // wenn jetzt B HIGH ist
        enc_delta++;  // dann ist das eine Rechtsdrehung
     else      // wenn nicht,
      enc_delta--;  // dann ist es eben eine Linksdrehung
       }        // fertig
     }          // aaaaaH, fast vergessen:
  A_alt = PHASE_A;  // jetzt aber: Fertig.
}
// 
************************************************************************ 
**************
int main(void)
{
  // Drehgeber Anschluß
  DDRA  &= ~(_BV(PA1) | _BV(PA0)); // Pin's als Eingang
//  PORTA  =  (_BV(PA1) | _BV(PA0)); // PullUp's ein
  DDRC   = 0xFF;                   // Port  als Ausgang

  // Timer2 einstellen
    TCCR2 |=  (1<<CS22)| (0<<CS21)  | (1<<CS20);
    TIMSK  = 1<<TOIE2;      //enable timer2 interrupt OVERFLOW
  sei();

  for(;;)                       // Hauptschleife
  Ausgabe  = enc_delta;
}

// 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
++++++++++++++

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@ Thomas Salewsky (thomas55)

>Dateianhang: gekrikel.jpg (210,2 KB, 11 Downloads)

Nomen est Omen.

>Die Überlegung: A ist der Takt bei dem mich nur die steigende Flanke
>interessiert und Bist das Datum, das mir sagt ob rechts oder links
>gedreht wurde.

Die "Idee" ist nicht neu, aber leider schlecht. Siehe Drehgeber.

MFG
Falk

von Thomas S. (thomas55)


Bewertung
0 lesenswert
nicht lesenswert
@  Falk Brunner (falk)

Hallo Falk,
Deinem Rat bin ich gefolgt und habe den Artikel Drehgeber gelesen.

In dem Artikel wird genau meine Lösung empfohlen "Absatz 
Signalauswertung".

Leider steht dort auch im ersten Absatz richtiger Unsinn über Entprellen 
und den Vorteil der Gray-Codierung. Aber der Autor wiederspricht sich ja 
dann noch bei seinem Gemecker über die Auswirkungen des Prellens.

Jedenfalls sollte meine Lösung für jeden Rastpunkt nur eie Stelle zählen 
und klein sein. Das ist keine Auswertung von Motordrehgebersignalen - 
ausser wenn Motoren Seeeehr langsam laufen (ab Drehzahl > 600 wird es 
kritisch).

Vielleicht bin ich aber auch zu sehr Anfänger.

Deine Kritik kann ich jedenfalls nicht nachvollziehen.


Gruss Thomas

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@  Thomas Salewsky (thomas55)

>In dem Artikel wird genau meine Lösung empfohlen "Absatz
>Signalauswertung".

???
Das Verstehen von Sachtexten müssen wir wohl noch ein wenig üben . . .

>Leider steht dort auch im ersten Absatz richtiger Unsinn über Entprellen
>und den Vorteil der Gray-Codierung. Aber der Autor wiederspricht sich ja
>dann noch bei seinem Gemecker über die Auswirkungen des Prellens.

Ach ja?

>Vielleicht bin ich aber auch zu sehr Anfänger.

Sieht wohl so aus.

>Deine Kritik kann ich jedenfalls nicht nachvollziehen.

Siehe oben.

MFG
Falk

von friedrich (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hier kurzer Erfahrungsbericht:

Habe einen STEC12E06 :: ALPS STEC12E Drehimpulsg., 24/24, horiz., MT

an zwei pins mit internem pull-up liefert das Ding gerastet 11. Peters 
Code erkennt auch die Schritte zwischen den Rastungen einwandfrei (pin 
change interrupt).

Man muss daher aufpassen, dass man den Schrittzähler erst vierteilt, 
wenn das auch Sinn macht. Sonst wundert man sich.

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.