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
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
Gast
#41980
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) ;-)
@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.
Gast
#41982
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.
"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
Gast
#41984
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.
"Ü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
Gast
#41986
> 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.
Gast
#41987
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.
"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
Gast
#41989
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.
Gast
#41990
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.
Gast
#41991
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.
Gast
#41992
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!
Gast
#41993
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.
Gast
#41994
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.
Gast
#41995
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:-).
Gast
#41996
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.
Gast
#41997
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...
"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
Gast
#41999
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
Gast
#42000
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 ...
Gast
#42001
Ja wie denn? Ich check immer noch nicht, wie man an 7 Leitungen 700 Drehschalter oder 1400 Taster dranbekommen soll. Gruß Andi
Gast
#42002
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.
Gast
#42003
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!
Gast
#42004
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.
Gast
#42005
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.
Gast
#42006
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
Gast
#42007
Ich glaube, so müßte es gehen...
Gast
#42008
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
Gast
#42009
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
Gast
#42010
Kann es momentan leider nicht testen, aber ich glaube, ads es geht..
Gast
#42011
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..
Gast
#42012
????? Soll ich dir auch noch einen 2313 schicken?
Gast
#42013
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...
Gast
#42014
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...
Gast
#42015
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
Gast
#42016
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.
Gast
#42017
Hab's geändert, aber es tut sich immernoch nicht mehr :-(
if( PORTD.0 )
i = 1;
Da kannste lange warten.
Du must schon das Input-Register nehmen.
Peter
Gast
#42019
AAAAAAAAARRRRGGGGGHHHH, sowas passiert mir immer wieder... Danke Peter!
Gast
#42020
Funktioniert nun prima, allerdings wird die Variable bei jedem Schritt um 2 verändert, wie kann ich das ändern? Danke, Dominik
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
Gast
#42022
könnte man den ganzen code nun korigiert noch mal posten?
Gast
#42023
Wieso? Im Code waren doch keine Fehler?!?!
Gast
#42024
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 ?!
Gast
#42025
Ich werte das ganz anders aus, lasse auch die Interupts an, da der Rest von meinem Programm sonst streikt.
Gast
#42026
Ü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
Gast
#42027
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?
Gast
#42028
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.
Gast
#42029
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.
Gast
#42030
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.
Gast
#42031
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?
Gast
#42032
Also entweder muß man die Flanken über Interrupts einlesen oder über eine Timer-ISR die Leitungen mit mindestens 10 kHz auslesen.
Gast
#42033
aso jetzt verstehe ich: auswerten am controller (mittels tabelle) aber status nur bei änderung oder nur in bestimmten intervallen
Gast
#42034
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.
Gast
#42035
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)
Gast
#42036
verbindung mit 8051 natürlich!!
Gast
#42037
bei dieser schaltung ist jedoch insgesamt 3x zu demultiplexen und das is nicht was ich mir unter sinnvoll und einfach vorstelle!!!!
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
Gast
#42039
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!!!!
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
Gast
#42041
@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
Gast
#42042
du meinst es ist von grund auf sinnlos?? also ist das projekt abzublasen???
Gast
#42043
"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
Gast
#42044
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.
Gast
#42045
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
Gast
#42046
@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
Gast
#42047
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...
Gast
#42048
@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
Gast
#42049
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
Gast
#42050
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.
Gast
#42051
"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
Gast
#42052
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?
Gast
#42053
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
Gast
#42054
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
Gast
#42055
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.
Gast
#42056
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.
Gast
#42057
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
Gast
#42058
> 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!
Gast
#42059
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:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
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.
Gast
#42060
@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
Gast
#42061
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
Gast
#42062
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.
Gast
#42063
@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
Gast
#42064
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ß.
Gast
#42065
>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
Gast
#42066
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.
Gast
#42067
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?
@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
Gast
#42069
@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
Gast
#42070
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
Gast
#42071
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.
Gast
#42072
"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
Gast
#42073
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.
Gast
#42074
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
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 ---------------
@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
Gast
#42077
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.)
Gast
#42078
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...
Gast
#42079
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.
Gast
#42080
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
@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
Gast
#42082
@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
"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
Gast
#42084
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....
Gast
#42085
"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
Gast
#42086
@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.
Gast
#42087
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.
Gast
#42088
@The Daz die Routine ist entprellend, Du brauchst also keine extra Tiefpässe. Peter
Gast
#42089
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
Gast
#42090
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
Gast
#42091
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.
>Wer sicher gehen will und sich das leisten kann nimmt Interrupts.
Eben nicht!
Gast
#42093
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.
Gast
#42094
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
Gast
#42095
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.
Gast
#42096
Ä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)
Gast
#42097
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.
Gast
#42098
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
Gast
#42099
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.
@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
Gast
#42101
http://www.bourns.com/pdfs/ace.pdf das ist ein absoluter Drehgeber mit total wirrem Graycode, auch Bourns empfiehlt eine Tabelle zu verwenden
Gast
#42102
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.
Gast
#42103
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.
Gast
#42104
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
Gast
#42105
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
Gast
#42106
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.
Gast
#42107
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
Gast
#42108
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; }
}
_____________________
Gast
#42109
n' bisschen einfacher (und leichter zu verstehen...) http://www.mikrocontroller.net/forum/read-4-250095.html#new
Gast
#42110
@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
Gast
#42111
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
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
Gast
#42113
(Dieser Beitrag wurde geloescht)
Gast
#42114
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
Gast
#42115
@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.
Gast
#42116
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
Gast
#42117
"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".
Gast
#42118
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 ;-)
Gast
#42119
"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
Gast
#42120
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
@Peter: Ich habe ein komisches Problem: Wenn ich meinen Zählerstand verändere mache ich das mit
1 | |
Dabei zählt er zwei weiter. Soweit so gut, hatten wir ja oben schon. Nach deinem Lösungsvorschlag müsste das so aussehen:
1 | |
Problem: Der Compiler übersetzt das (nachvollziehbarerweise) so:
1 | |
2 | |
3 | |
4 | |
5 | |
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
1 | |
exakt genauso. Hilfe! :-)
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 ;)
PS: Jetzt übersetzt er es so
1 | |
2 | |
3 | |
4 | |
5 | |
Also alles Klar!
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.
#1
#2
und #3
Gast
#42128
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
Ich danke dir, das sieht ebenfalls sehr interessant aus.
@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:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
Peter
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
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.
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ß
Gast
#422897
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
Gast
#465592
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.
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
Gast
#470000
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)
@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
Gast
#471912
@ 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-;-)
Gast
#476512
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.
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
Gast
#477622
Ja, 400 Hz ist zu langsam, habe nun die 2te Routine auch begriffen, hat ne Weile gedauert. Danke für den Hinweis.
Gast
#516677
DDM427 ROTARY ENCODER DETAILS
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
Gast
#532287
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;
}
Gast
#532344
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
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
@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
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
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.
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
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.
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
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.
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
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.
Gast
#544142
<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>
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
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
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
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
Gast
#546925
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
Gast
#569244
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
Gast
#569248
Was ist ein CCS Code?
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
glaube code composer studio
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.
Gast
#578690
@ 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
Gast
#628028
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
Gast
#784657
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
Gast
#785413
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).
Gast
#785436
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
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
1 | |
2 | |
3 | |
4 | |
5 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
enc_delta lasse ich mir mit 1Hz ausgeben.
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;
}
//
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++
@ 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
@ 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
@ 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
Gast
#799676
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
Bitte melde dich an, um einen Beitrag zu schreiben.

