Hallo, ich würde gerne an meinen Mikrocontroller (ATmega16) einen Drehregler schalten (an den PORTD) und der Mikrocontroller soll dann die Drehung auswerten und dementsprechend einen Wert hoch- bzw. runterzählen (je nach Drehrichtung). Meine Frage ist nun, ob ich das mit einem Drehregler überhaupt lösen kann, denn der macht doch normalerweise nichts anderes, als die Spannung hoch- bzw. runterzudimmen und das kann ich doch schlecht mit nem Mikrocontroller abfragen, oder? Oder benötigt man für dieses Vorhaben besondere Drehregler? Sollte es gehen, könnte mir dann bitte jemand auch den Anschluss, sowie auch die Ansteuerung/Abfrage mittels uC erklären? Vielen Dank für Eure Hilfe Markus
Vielleicht sollte ich noch anmerken, dass ich unter einem Drehregler z.B. die die Regler auf einem Mischpult oder ähnlichem (Lautsprecher, uvm.) meine - keine Ahnung, wie die Dinger wirklich heißen, Drehregler klang mir aber am wahrscheinlichsten.
Wenn dein Drehregler ein Potentiometer ist / ein einstellbarer Widerstand, dann lässt er sich mit einem Mikrocontroller mit ADC auslesen, wenn es sich um einen Drehgeber handelt mit digitalen Eingängen wie z.B. hier: http://www.sprut.de/electronic/pic/programm/rotary/rotary.html
D.h. den Potentiometer schließe ich einfach an eines meiner ADC-Bits an (habe den ATmega16, und laut Datenblatt sind die PORTSA alle ADC0 - ADC7 Poins) - und das wars schon? Was bekommt der Mikrocontroller dann für Werte?
es ist spät in der Nacht, also ADC-Bits sollte ADC-Ports heißen und ADC0 - ADC7 Poins sollte eigentlich ADC0 - ADC7 Pins heißen - sorry.
Da fällt mir gerade ein: Potentiometer haben ja einen Anfang und einen Endregelzustand. Mein Drehregler sollte das aber nicht besitzen, d.h. ich hätte gerne einen Dreher/Drehregler, den man beliebig oft um seine eigene Achse drehen kann - gibt es sowas?
In diesem Fall sollte man einen digitalen Drehsensor benutzen. Man bekommt zwei Phasenverschobene Rechtecksignale. Das gleiche Prinzip ist in einer Maus eingebaut (wenns nicht gerade ne optische ist...). Allerdings sind diese Sensoren nicht gerade billig - es kommt auch auf die gewünschte Auflösung an. Potentiometer ohne Anschlag gibt es zwar, sind aber sehr selten und außerdem hat man zwischen 0° und 359° einen extremen Sprung. Ein digitaler Sensor kann ohne Probleme mehrere Umdrehungen erkennen. Was hast Du denn vor? Evtl. gibts auch eine andere Lösung.
Salut, dann meinst Du einen Drehencoder (rotary encoder). Die geben ein 90° phasenverschobenes Signal an zwei Pins aus. Anhand dessen kannst Du die Richtung bestimmen (warten auf Flanke an Pin 1, bei Eintritt Auswertung des Pegels an Pin 2 -> Richtung). Link zu Code hat Till ja schon gegeben. Ich selbst setze auch einen Drehencoder in meinem Dimmer ein: http://semitone.sf.net Viel Erfolg! Mark
eine weitere anleitung wo der encoder mit interrupt ausgelesen wird ist hier http://www.mcmanis.com/chuck/Robotics/projects/lab-x3/quadratrak.html die encoder gibts für 95cent im surplushandel
Salut, wo denn z.B.? Falls Du die Alps von Pollin meinst, die gibt's schon längere Zeit nicht mehr. ;( Wäre für Tips sehr dankbar. Mark
Such mal im Forum hier. Die Bestell-Adresse wurde des Öfteren gepostet.
Ah, genau, ich glaube so ein Drehencoder dürfte genau das sein, was ich suche. Ich habe unter anderem diesen hier gefunden: http://www.mercateo.com/p/115-743412/Encoder_STEC11B_5V_300V.html. Dort steht "Beschreibung horizontal mit Taster..." bedeutet das, dass dieser Drehencoder auch als Taster funktioniert? Könntet ihr mir vielleicht knapp beschreiben, wie ich diesen Encoder an mein Mikrocontroller anschließe (muss der an die ADC-Pins und an wie viele oder muss ich noch nen AD/DC-Wandler zwischenschalten, etc)? Ich würde mal tippen, das Ding hat 2 Anschlüsse an den uC, einen für Dreher in Rechtsrichtung, einen für Dreher in Linksrichtung, oder so. Und bei nem Tastendruck könnte evtl. auf beiden Kanälen eine 1 kommen? Und außerdem, wie steuere ich das Teil an (vor allem, wenn der auch als Taster funktionieren kann), so ähnlich wie im Folgenden (Code aus dem Forum hier)? ADMUX=(1<<6)|(1<<7); ADCSRA=(1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); ADCSRA|=(1<<ADIE); ADCSRA|= (1<<ADEN) | (1<<ADSC); SIGNAL(SIG_ADC) { char cOutText[100]; int nADCValue; nADCValue = ADCL; nADCValue |= (ADCH<<8); sprintf(cOutText,"measured%d : %d\r\n",(ADMUX&7),nADCValue); SendZTString0(cOutText); ADCSRA|=(1<<ADSC); if ((ADMUX&7)==7) ADMUX^=7; else ADMUX++; } Vielen Dank für Eure Antworten, die waren schon einmal ein mehr als große Hilfe. Gruß Markus
Die Encoder liefern einen Gray-Code. Man schließt sie einfach an 2 beliebige Pins an und wertet sie im Timerinterrupt aus, ob sich der Zustand geändert hat. Je nach Änderung zählt man dann hoch oder runter: hoch: 0->1 1->3 3->2 2->0 runter: 0->2 2->3 3->1 1->0 Peter
Ne... beim Drehimpulsgeber bekommst du doch schon digitale Signale, was willst du danoch mit einem ADC :-). Aber ich hatte vor 3 Wochen die selben Fragen wie du. Deshalb lies einfach mal hier nach. http://www.mikrocontroller.net/forum/read-1-81560.html#81585 Im Anhang ist meine Quellecode zum einlesen. Funktioniert auch! Hat da jemand Verbesserungsvorschläge? Meine Fragen: Ich hab für das einlesen des Gebers auch 2 HW IR geopfert. Geht das nicht auch anders. Ich will aber natürlich auch zu jeder Zeit des Programmablauf mein Gerät bedienen können. Da werde ich wohl bei den HW IR`s bleiben müssen oder? Ausserdem hab ich als TYP für die Variable, die der Geber steuert einen ENUM genommen. Ich war eigetlich der Meinung, dass wenn ich den letzten Wert in der Reihe erreicht habe und nochmal inkremmentiere --> ich dann wieder beim Anfange der Wertereihe ankomme. Dem ist aber nicht so wie kann ich das ändern?
"Könntet ihr mir vielleicht knapp beschreiben, wie ich diesen Encoder an mein Mikrocontroller anschließe" Nein. a) ist das hier schon des öfteren beschrieben b) sind oben mindestens zwei links zu seiten mit detailierter beschreibung inclusive funktionierendem code. zur verfügbarkeit - also ich habe einen ganzen stapel im regal.
> zur verfügbarkeit - also ich habe einen ganzen stapel im regal.
Verkaufst du die Dinger (und wenn ja für wie viel denn)? Was sind das
dann für Drehencoder, mit Rasterung (und wie viel) und mit Taster oder
ohne?
Den Anschluss habe ich mittlerweile auch rausgekriegt, danke ;-)
@Stephan, wenn ich Deinen Code richtig verstehe, wertest Du nur 2 von 4 Phasenwechsel aus, d.h. Du nutzt den Encoder nur zur Hälfte aus. "Ich hab für das einlesen des Gebers auch 2 HW IR geopfert. Geht das nicht auch anders." Ja, siehe Anhang. "Ich war eigetlich der Meinung, dass wenn ich den letzten Wert in der Reihe erreicht habe und nochmal inkremmentiere --> ich dann wieder beim Anfange der Wertereihe ankomme. Dem ist aber nicht so" Das wäre ja schlimm, der Compiler darf nicht einfach die Zahlenformate willkürlich ändern. Ein Byte zählt immer von 0...255 bzw. -128...127. Wenn Du was anderes willst, dann mußt Du das selber tun, z.B.: char i; if( i == 6 ) i = 0; if( i == -1 ) i = 5; Peter
@peter Danke für die Lehrstunde :-) Das gibt mal wieder ein VB ( virtuelles Bier ) Hab deinen Code zwar noch nicht ganz verstanden, aber den werde ich nun mal auseinander nehmen. @ markus mein Code ----------> Anfängerbeispiel peter`s Code -----------> wohl deutlich mehr profimässig
lach he Stephan, ich zücke den Hut vor jedem, der sich mit dem uC ein bisschen auskennt. Dass man am eigenen Code fast immer was zum verbessern finden würde, geht wohl den meisten so. Wäre ja auch schlimm, wenn alles schon perfekt wäre. Ich muss jetzt nur noch nen (billigen) Drehencoder ergattern und dann wirst du schon sehen (Stephan) was ein Anfängerbeispiel ist, keine Sorge ;-). Grüßle und vielen Dank
In dem andern posting, das ich schon angegeben habe, hat jemand geschrieben, das es Bei Bürklin welche für 2 Euro gibt. da steht auch ne Artikelnummer. Ich selber hab eine bei Bürklin bestellt für 7 €. Mir egal, ich muss ihn ja nicht bezahlen. ABer das eigentlich teuere ist doch eh immer der Versand, wenn ich nur ein geringe Menge bestelle. Wenn du es billig haben willst, das würde ich dir empfehlen. In einem Coanrad Shop oder bei Kürklin oder ähnlichen selber Vorbeizuschauen. Aber bei einer gerigne Stückzahl ( 2-3) zum experimentiren ist der Preis doch eh nicht so entscheidend. Oder brauchst du grössere Mengen.? Ich bin auf der Suche nach einem sehr leichtgängigem Teil. Ich will damit ein Jog Shuttle bauen, das aber auch einen zusätzlichen Taster hat.
Ähnliches schwebt mir auch vor, darum wäre ich einem leichtgängigen Teil nicht gerade abgeneigt ;-).
extrem leichtgängig sind die optischen encoderscheiben die sich zuweilen hinten an motoren finden welche man aus alten druckern ausschlachtet
Hallo! Mit Interesse habe ich diesen Thread verfolgt, da ich auch einen Drehencoder verwenden möchte. Vor ein paar Jahren habe ich einen bei Apotheken-Conrad erworben (Damals sollte eine Schaltung mit einem PIC enstehen (bähbäh!)). Dieser Drehencoder hat 5 Anschlüsse: 2 für die Bewegung in axialer Richtung (drücken des Tasters) und 3 für die Rotation. Die Rotation liefert die phaseverschobenen Signale an den beiden Ausgängen. Der dritte Anschluss in dieser Gruppe ist der gemeinsame Kontakt. Da der AVR einen Interrupt-Eingang besitzt, der auf Flankenwechsel in beide Richtung reagieren kann, müsste es doch möglich sein, auf einen entsprechenden Interrupt zu warten, dann den anderen Eingang einzulesen und entsprechend auszuwerten. Notfalls müsste man die Detektionsrichtung des Interrupts umkehren, was bei entgegengesetzter Drehung den Verlust eines Schrittes zur Folge hätte. Könnte das so gehen? So wie ich das Programm von Peter verstehe, wird regelmässig der Port eingelesen, mit dem vorherigen Zustand verglichen und dann entsprechend gehandelt. Dient die Abfrage per Timer-Interrupt einem Entprellen (wie bei dem ASM-Code in der Codesammlung)? Leider habe ich momentan keinen Zugang zu einem Oszilloskop und kann mir somit nicht das Schalt(Prell-)verhalten des Encoders ansehen. Soweit erst mal, Gruß Rahul
Die Pin-Change-Interrupts sind für Drehencoder ungeeignet, am einfachsten geht es mit dem folgenden Code in einem Timer-Interrupt: http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29
Ich hatte kürzlich versucht, Drehencoder bei Oppermann-Electronic zu bestellen (ALPS mit Schalter, 0.95 Euro), aber leider sind die nicht mehr lieferbar. Da ich den Schalter nicht wirklich benötige, kämen für mich auch die für 2 Euro von Bürklin in Frage. Da kann ich aber leider als Privatperson ja nicht bestellen, oder? Und dann hab ich auch nicht gefunden, wie hoch denn da die Versandkosten sind.
Ich glaub ich nehm den von Conrad (http://www1.conrad.de/scripts/wgate/zcop_b2c/~flN0YXRlPTg4MjgzNjQyNQ==?~template=PCAT_AREA_S_BROWSE&glb_user_js=Y&shop=B2C&p_init_ipc=X&~cookies=1). Die sind zwar megaschweineteuer, aber in meinem Umkreis gibts keinen anderen Laden als den Conrad und wenn ich bei den anderen noch die Versandkosten dazurechne, bin ich auch bei 7 Euro :-(. Übrigens Stephan: Hier gibts sogenannte Codie-Räder, vielleicht ist das ja auch was für dich (sind aber relativ teuer, unter D->Drehgeber->Codie-Rad): http://de.farnell.com/jsp/home/homepage.jsp
Man kann übrigens Conrad-Artikel nicht so ohne weiteres verlinken, besser die Artikelnummer hier reinschreiben, damit kommt man einfacher zum Ziel.
" Ich hatte kürzlich versucht, Drehencoder bei Oppermann-Electronic zu bestellen (ALPS mit Schalter, 0.95 Euro), aber leider sind die nicht mehr lieferbar. " mächte sein das ich die letzten 50Stück gekauft habe, werden jetzt wohl nach und nach an PICs angelötet...
Hmmmm, was ist los? Deine Aussage kann ich überhaupt nicht deuten :-) "mächte sein..." == "könnte sein" ?
Ahso, das bringt etwas Klarheit in das Dunkel der Drehgeberbestellungen. Interessant find ich bei Bürklin auch das Teil mit den 31 LEDs rundrum (75 E 680), sieht bestimmt cool aus, wenn man da den aktuellen Wert anzeigt oder so. Leider kostet da einer aber schlappe 24 Euro (naja ok, ab 10 Stk. nur noch 18,70 :-)
@Rahul, "Dient die Abfrage per Timer-Interrupt einem Entprellen (wie bei dem ASM-Code in der Codesammlung)?" in der Tat ergibt sich neben den anderen Vorteilen (beliebige Pins, mehrere Encoder möglich) auch ein Entprelleffekt. Gerade Billigteile prellen gerne mal und auch jegliche Störimpulse (elektrostatische Aufladung) können beim Flankeninterrupt Fehlzählungen bewirken. Ich hatte auch Stephans Beispiel so verstanden, daß die 3ms Wartezeit im Interrupt zur Entprellung nötig sind. Aber bezüglich Warten im Interrupt hab ich ja schon öfter meine Meinung kund getan. Peter
also meiner erfahrung nach reicht 1ms für die alpsteile aus um zu entprellen
Entprellen ist bei Drehencodern mit Gray-Code überhaupt nicht nötig.
Ja, hab ich auch festgestellt :-) Meine 10 Zeilen Assemblercode haben überraschenderweise auf Anhieb funktioniert.
"Entprellen ist bei Drehencodern mit Gray-Code überhaupt nicht nötig." mit dem code von sprut habe ich gelegentliche fehler bekommen wenn zu schnell abgefragt. ich hab mit dem encoder gezählt und den wert auf display ausgegeben.
Soweit ich diesen PIC-Code (http://www.sprut.de/electronic/pic/programm/rotary/rotary.html) entziffern kann wird die Dekodierung dort falsch gemacht. Wenn die Eingangswerte geändert sind kennt das Programm nur 2 Fälle: entweder wurde nach rechts gedreht, oder es wurde nach links gedreht. Der 3. Fall, dass überhaupt nicht gedreht wurde sondern einfach nur eines der beiden Signale prellt, wird überhaupt nicht behandelt.
ich dachte die struktur dort ist wenn nicht links, und nicht rechts, dann geh zum ende und mach nix jedenfalls funktioniert es wenn man halt nur alle 1ms schaut.
> ich dachte die struktur dort ist > wenn nicht links, und nicht rechts, dann geh zum ende und mach nix ;ist neu = alt? ; ja: nicht verdreht, also nichts tun ; nein: encoder verdreht, aber in welche Richtung? Danach wird nur noch zu "rechts" oder "links" verzweigt. > jedenfalls funktioniert es wenn man halt nur alle 1ms schaut. Das ist bei diesem Code kein Wunder, bei richtiger Dekodierung darf die Abtastfrequenz beliebig hoch sein.
Also ich hab jetzt den Drehimpulsgeber von Conrad (705586), nur dieser "bescheidene" Laden liefert ein Datenblatt mit, dass meines Erachtens mehr einer Erörterung denn einem Schaltplan gleicht. Gut, die einen drei Anschlüsse werden wohl A, C, B sein. Davon muss ich wohl C an Ground und A und B jeweils (mit 5V versehen?) an den Mikrocontroller (sagen wir mal PINA0 und PINA1), oder? Doch für was sind die zwei weiteren Anschlüsse da? Für Ground und 5 Volt? Sinnvoll wäre das, wenn einer davon den Tastendruck abfrägt, also vermute ich mal, einer von beiden muss auch an Ground und der andere an einen dritten Pin am Mikrocontroller (und an 5V?) (sagen wir PINA2). Ist das nun richtig angeschlossen und welcher Anschluss stimmt? Die Auswertung des Tastendrucks würde dann folgendermaßen gehen (für die Drehung habe ich vor Peter's Code zu benutzen): Ich schaue einfach, ob dan PINA2 eine 1 kommt. Ist dies der Fall, setze ich meine Variable pressed auf true, wenn nicht wird pressed auf false gesetzt. Funktioniert das so? Der Code würde dann wie folgt aussehen: SIGNAL (SIG_OVERFLOW0) { static char enc_last = 0xFE; char i, j; i = 0; // jetzt kommt die hinzugefügte Zeile pressed = PHASE_C; // PHASE_C bedeutet PORTA -> A2 // Ende der Änderung if( PHASE_A ) i = 1; j = 3; if( PHASE_B ) i ^= j; // convert gray to binary j = enc_last - i; // difference last - new if( (char)(j & 1) ){ // bit 0 = value (1) enc_last = i; // store new as next last i = enc_delta; if( (char)(j & 2) ) // bit 1 = direction (+/-) i -= 2; enc_delta = ++i; } }
Wie ist das: Muss jeder Impuls (A, B und für den Taster auch einer der anderen) an 5 Volt mitangeschlossen werden? Und geht das mit dem Tastendruck abfangen so wie in meinem obigen Code gedacht oder nicht?
Sorry, wenn ich mich nochmal melde, aber es wäre cool, wenn mir jemand sagen könnte, ob alle Ausgänge des Impulsgebers, die an den uC führen, mit 5Volt in Reihe geschaltet werden müssen und wie ich den Impuls für den Taster anschließe und auslese. Vielen Dank für Eure Hilfe Markus
Morgen markus, also ich denke es gibt da verschieden Arten der Beschaltung. Die Pullups extern benutze ich garnciht, da ich die Internen des µC benutze. Anscheinend gibt es auch unterschiedliche Aren von Encodern. Einige brauchen anscheiend eine Richtige Betriebsspannung also +5V und GND. Meinen Encoder benutze ich eher wie einen Schalter. z.B. legen ich halt einen der beiden Kontakte für den axialen Druckschalter auf GND und den anderen Natürlich an den µC. D.H. der Schalter ist dann low_aktiv im Zusammenspiel mit dem internen Pullup. Die Kontakte von Drehgeber sind für mich auch nichts anderes als 2 gekoppelte, zeitlich versetzte, Schalter. Als lege ich auch hier den gemeinsamen Pin auf GND und Taste die anderen beiden mit dem µC ab. Ich denke du hast ein ähnliches Modell wie ich. Wie die andern (mit Betriebsstapnnung) arbeiten hab ich auch noch nicht ganz geblickt. Wenn ich mir die Schaltung unter Sprut.de anschaue.´dann denke ich mir doch anhand der Pullup`s, das auch diese Schaltung lowaktiv ist. Aber wofür brache ich denn dann noch +5V an Encoder. Aber wahrscheinlich arbeiten die einfach mit einer schlaueren Technik.
@Markus Ich hab mir auch die Dinger von Conrad bestellt, allerdings 705514 bzw. 705538, die sind wohl faktisch baugleich mit Deinem. Das Datenblatt dazu ist aber deutlich besser, ab Seite 6 steht eigentlich alles, was Du wissen mußt. Zumindest hab ich die Teile problemlos in Betrieb nehmen können. Gruß Ingo
Der Code von Sprut.de entspricht dem Ablaufdiagramm im Datenblatt (#705514 von Conrad). Die Abtastrate von 1ms hängt wohl mit dem RC-Glied am Eingang zusammen: wenn man den Encoder schneller dreht bzw. abfragt, ergibt sich nur eine Analogspannung am Eingang (meine Vermutung). Die Eingangsbeschaltung mit dem RC-Glied dient dem Entprellen, was man mit Peters Methode ja auch bewerkstelligen kann (weniger externe Bauteile). Gruß Rahul
Ich bin gerade dabei den Code von Peter mal zu zerlegen. Mit dem Timer, das hab ich schonmal geschnallt. Aber der Ablauf in der ISR ist mir noch nicht ganz klar. wie kann ich denn folgende Zeile deuten? #define Phase_A (PINC & 1<<PINC0) ich hab da eine Problem mit dem <<, die Verwendung in der Art ist mir nicht klar, obwohl ich das nun schon oft gesehen habe. Kann mir das bitte mal einer erklären. PINC ist der Inhalt des 8Bit Registers, das den Zustand von PORTC anzeigt. Diese 8 Bit werden mit (1<<PINC0) logisch bitweise verundet. aber was stell der Ausdruck (1<<PINC0 dar)?
Pinc0 müsste eine Zahl mit dem Wert 0 sein. Es wird also eine 1 auf Stelle 2^0=1 nach links verschoben. Phase_a ist also die bitweise Verundung des Inhalts des PortC mit 0x01. Es wird geprüft, ob das LSBit 1 ist. Beim 8051 gibt es dafür spezielle Bitoperationen, die aber auch nur bei bestimmten Registern funktionieren.
Die Zeile ist aus dem Codebeispiel von Peter. (siehe etwas weiter oben / ENCODE.C) Dort ist aber PINCO aber nicht als Variable deklariert. Also was ist PINCO dann?? Ich habe auch ähnliche Verständnisprobleme mit z.B. TCCRO = 1<<CS01; oder TIMSK = 1<<TOIEO; woher weis der µC denn dort, wohin oder wieweit, er die 1 schieben soll? Ist CS01 und TOIEO irgendwo hinterlegt? Aber wenn das stimmt, was du sagst Rahul, dann könnte ich anstatt 1<<PINCO auch einfach 0x01 schreiben.
ja, kann man. PINC0 ist aber übersichtlicher, sobald man mit der Nomenklatur von C etwas vertrauter ist. PINC0, CS01, T0IE0 sind Definitionen in Header-Dateien. Einfach mal eine .h-Datei im Editor öffnen. Da wirst du die Definitionen finden. Gruß Rahul
Schau dir doch einfach mal den Code von http://dse-faq.e-online.de an, das ist eine einfache Zustandsmaschine bei der die Uebergaenge ganz simpel in einer Tabelle abgelegt sind; das benoetigt sicher auch nicht mehr Platz im Speicher als Peters Programm und ist meiner Meinung nach einfacher zu durchschauen. Entprellen ist nicht noetig. Das Sprut-Programm entspricht dem kleinen Ablaufdiagramm im Conrad-Datenblatt und kann kein Prellen erkennen, im grossen Ablaufdiagramm wird die Dekodierung richtig gemacht. Aber warum soll man die Vorteile des Gray-Code verschenken nur um ein paar Programmzeilen zu sparen?
@Ingo und andere Also schließe ich den Encoder praktisch folgendermaßen an? A und B kommen an jeweils zwei Pins am Mikrocontroller. C kommt an GND. E kommt an einen Pin am Mikrocontroller und F kommt wieder an GND? Gruß Markus
Ja genau, ich hab aber noch externe Pullup-Widerstände vom A und B (den Druck-Taster verwende ich nicht) nach +5V angeschlossen, ist aber wohl nicht unbedingt erforderlich. Die im Conrad-Datenblatt angegebenen Kondensatoren nach Masse hab ich weggelassen. So funktioniert es bei mir sehr gut, ich frage nicht flankengesteuert sondern die Zustände in einem Timer-Interrupt alle 4 ms ab (wurde weiter oben beschrieben). Gruß Ingo
so hab mir das unter http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29 mal geauer angeshen, da ich ja nun meinenCode auch mal optimieren will. Peter kann ich leidernicht nachvollziehen. Unter diesen Link wird ja beschrieben, das es genau 4 Zustände gibt, die von einander zu unterscheiden sind. Dabei sind dann die Flanken an sich garnicht so wichtig, sondern es geht um den Vorher - Nachher Vergleich. Nun hab ich mir meien Encoder mal auf dem OSZI mal genau angschaut und sehe da ein ganz anderes verhalten. Ich kann da nur 3 Zustände ausmach. Das sieht da so aus. Rechtsdrehung _________ __________ _______ Sig 1 |______| |_______| |_______ ______ _______ _____ Sig 2 |_________| |__________| |_______ Linksdrehung ______ __________ _______ Sig 1 |______| |_______| |_______ ______ _______ _____ Sig 2 |_________| |__________| |_______ OK OK vergesst es ich könnte mich selber in **piep*** ** piepen**. So eine verdammte ***piep***. Mir ist gerade was eingefallen. Mein Decoder war falsch angeschlossen. Ich hab einfach mit einem Summer versucht rauszufinden wo welcher Kontakt liegt, aber das geht natürlich nicht. Und dadurch kammen so seltsame Signale raus. Die man auch nicht vernünftig auswerte kann. Ich hatte Ihn einfach falsch angeschlossen. So ich fang jetzt nochmal an -------> jetzt sollte es wohl leichter gehen.
Also ich habe jetzt den Dreher angeschlossen (ohne Widerstand und Kondensator), und benutze folgenden Code: SIGNAL (SIG_OUTPUT_COMPARE2) { static uint16_t lc=0; static char enc_last = 0xFE; char i, j; lc++; if (lc % 6 == 0) { i = 0; if( PHASE_A ) i = 1; j = 3; if( PHASE_B ) i ^= j; // convert gray to binary j = enc_last - i; // difference last - new if( (char)(j & 1) ){ // bit 0 = value (1) enc_last = i; // store new as next last i = enc_delta; if( (char)(j & 2) ) // bit 1 = direction (+/-) i -= 2; enc_delta = ++i; } } if (lc >= 1000) { //sekundenzähler hier hochzählen seconds++; if (seconds == 60) { minutes++; seconds = 0; if (minutes == 1440) { state1++; eeprom_write_block(&state1, &eeprom_var1, sizeof(state1)); minutes = 0; } } lc = 0; } } Anschließend in der main-procedure folgendes: lcd_gotoxy(12, 0); lcd_puts (enc_delta); Genialerweise passiert nun folgendes, wenn ich den Dreher bewege: Das Display schaltet sich an und aus - leider ist das nicht unbedingt der Effekt, den ich erzielen wollte ;-) - wo liegt mein Fehler?
Ich hab echt keine Ahnung, warum plötzlich der Impulsgeber mit dem Display "verbunden" ist, das ergibt für mich überhaupt keinen Sinn.?
wie sieht denn deine Schaltung aus? An welchen Pins hängt dein Impulsgeber und an welchen dein Display? Aus dem Programm kann man das sehr schlecht erkennen. (
Also der Impulsgeber hängt an A0, A1 und A2 (Taster, der aber noch nicht angeschlossen ist) und das Display an PORTB (4bit). Dementsprechend sehen meine Definitionen so aus: #define PHASE_A (PINA & 1<<PINA0) // PINA.0 #define PHASE_B (PINA & 1<<PINA1) // PINA.1
Hm, was mir außerdem noch aufgefallen ist: Der Impulsgeber (Conrad, die Art.-Nr. 705514) hat neben 5 kleineren Anschlüssen (würde sagen, dass sind A, B, C, D und E) auch "von den Seiten her kommende" zwei Metallstecker oder was das sind. Die hab ich mal gar nicht angeschlossen, aber für was sind sie dann eigentlich nütze (dachte erst, man müsste sie mit GND verbinden, aber steht ja nix in der Doku)? Vielleicht liegt auch hier mein Fehler? Allerdings wird mir dann trotzdem noch nicht klar, warum das Display an den Taster gebunden ist.
sicher, dass nur das Display Probleme macht? Nicht, dass Du mit Hilfe des Tasters noch einen nette Kurzschluss erzeugst... Die beiden Kontakte die Du meinst sind vermutlich für die mechanische Befestigung vorgesehen, damit die Kraft nicht direkt auf Funktionskontakte geht. Gruß Rahul
lcd_puts (enc_delta); Ich kenne ja Dein lcd_puts() nicht, aber eine Zahlenausgabe scheint mir das nicht zu sein. Versuchs mal mit itoa() und gib dann den String auf das LCD aus. Peter
Also, ich habs gerade getestet: am Code liegt es definitiv nicht. Dann habe ich den Dreher nochmal neu gelötet, mit Widerstand (10k) und ich hatte das gleiche Ergebnis. Wenn ich aber den Ausgang C des Impulsgebers nicht auf GND sondern weg gelötet habe, dann kam dieses An- und Ausschalten des Displays nicht mehr - sonst kam es immer, egal ob ich Spannung angeschlossen hatte oder nicht. Irgendwas stimmt mit dem Ausgang C oder meinem GND nicht mehr. Ein Kurzschluss von C nach GND ist keinesfalls zu erkennen. Das ist echt merkwürdig...
Wow, das liegt absolut außerhalb meiner physikalischen Kenntnisse! Anscheinend kommt es (aus welchen Gründen auch immer) zu einem Kurzschluss, sobald ich an den Schalter Spannung anlege (egal, ob mit oder ohne Widerstand), bzw. wenn ich den Widerstand mit der 5V-Spannungsquelle verbinde. Das Messgerät misst nämlich dann an den Widerständen 0 Ohm (bei 10 kOhm-Widerständen). Noch entschließt sich diese physikalische Eigenschaft meines Verstandes, da ich nirgends einen Fehler entdecken kann, darum meine Frage: Wenn ich den Drehimpulsschalter ohne Spannung anschließen könnte, wäre das perfekt, allerdings weiß ich nicht ob das geht (als ich es versucht habe, hat mein LCD zufällig (also auch wenn ich nicht am Schalter gedreht habe) Werte zwischen 600 und 0 angezeigt - mit dem obigen Code). Grüßle der physikalisch etwas verwirrte Markus
So, um das Problem mit der Spannung zu umgehen, hab ich einfach geschaut, wo am uC noch 5 Volt Spannung an zwei Pins rauskommen und einfach dort diese beiden Ports mit dem Dreher verbunden. Das sind beim ATmega16 in meinem Fall (die B-Ports werden schon verwendet) die Pins PC2 und PC3. Ich habe die Pins umgeschrieben #define PHASE_A (PINC & 1<<PINC2) #define PHASE_B (PINC & 1<<PINC3) aber das LCD zeigt immer 0 an! Mit einem Messgerät habe ich jedoch nachgemessen, dass an PINC2 und PINC3 entweder 5 Volt oder 0 Volt hängen, also der Schalter scheint zu funktionieren. Wo liegt nun das Problem? Erkennt jemand meinen Fehler? Kann ich den Drehimpulsgeber an den PORTC überhaupt anschließen? Vielen Dank für Eure Hilfe Markus
Ähm, sorry, so gut kenn ich mich nicht aus. Aber wahrscheinlich heißt das ich muss JTAGEN auf 1 setzen oder so? Ich schau mal hier im Forum nach, ob ich was dazu finde.
Also ich hab JTAGEN auf false gesetzt, du hattest Recht es war auch true gesetzt! Aber das Programm funktioniert trotzdem noch nicht :-(. (PORTC&0x02) scheint immer wahr zu sein :-(.
Hab mal mein Programm mitgeschickt. Auf dem LCD wird die ganze Zeit 0 angezeigt!
if (PORTC&0x03) //T1 gedrückt wird So kanns ja nicht gehen. Du mußt die der Pinnummer entsprechenden Bitmasken nehmen, d.h. es darf nur ein einziges Bit in der Maske gesetzt sein. Warum nimmst Du nicht meine Schreibweise für die richtige Bitmaske ? Peter
... weil leider auch net gegangen ist :-( Hält mich noch jemand anderes außer ich selbst für nen Trottel. Das Ding will einfach nicht den Port auslesen, dabei kann ich sogar mit dem Messgerät messen, dass einmal 0 und das andere Mal 5 Volt anliegen!
Der LCD zeigt meiner Meinung nach keine sinnvollen Zahlen an, manchmal 055, 455, 355, 0. Die Zahl wechselt aber nicht bei jedem Dreh, sondern willkürlich.
wie wäre es denn, wenn Du erst mal den Inhalt der Eingangspins auf LEDs ausgibst? Scheinbar mangelt es dir daran, Peters Code zu verstehen, und dann die erzeugten Daten auf dem Display richtig darzustellen. Notfalls könntest du den Drehencoder auch durch 2 Tasten simulieren, und so dein Programm testen. Übrigens ist (1<<PINC3) nicht 0x03, sondern 0x08, also 2 hoch 3. Dein Ausdruck muß demnach (PORTC & 0x80) heissen, wobei einlesen von Ports besser mit PINC gemacht werden (zumindest habe ich das irgendwo in der AVR-LIBC mal gelesen...; gilt halt für den AVR-GCC). Ich weiss ja nicht, welche Vorkenntnisse Du hast, aber mir scheint, dass dir irgendwo noch so einiges fehlt. Teilweise benutzt du in deinem Program _BV(...) und dann kennst du Ausdrücke wie "1<<PINC0" nicht. Dabei bedeutet _BV(PINC0) nichts anderes.
Ne, das mit den Pins kapier ich schon, nur habe ich halt n paar Sachen ausprobiert und es funktioniert noch immer nicht (aber im Allgemeinen mangelt es mir schon an Kenntnis). Ich kann schon vorhersagen, was pasiert, wenn ich den Inhalt des Eingangspins auf LED's ausgebe. Sie leuchten und wenn ich den Drehimpulsgeber in irgendeine Richtung drehe, leuchten sie nicht. Bei der nächsten Drehung leuchten sie wieder. Wie gesagt, dass kann ich ja schon mit nem Messgerät messen, dass manchmal 5Volt und manchmal 0 Volt anliegen. Das Problem ist aber, dass mein Programm nicht erkennt, dass an PC2 oder PC3 eine 1 oder eine 0 liegt - komischerweise. Bei der Fehleranalyse tendiere ich eher dahin, dass ich vielleicht irgendwo einstellen muss, dass ich die PC2 und PC3 als Eingabe verwenden möchte? Muss ich evtl. irgendwo PORTC mit 0b00110000 initialisieren oder so?
Na das ist doch schon mal was. Bei Drehung leuchten beide LEDs oder gar keine, so muß es auch sein. In der eingerasteten Stellung des Drehgebers sind immer gleichzeitig A und B mit C verbunden, bzw. beide nicht. Die Richtung kann man nur während des Übergangs von einer Raststellung zu nächsten ermitteln, hier schalten dann A oder B entsprechend früher oder später in den jeweils anderen Zustand. Ok, zumindest ist das so bei meinem Drehgeber von Conrad, ich kann allerdings nicht ausschließen, das es auch andere gibt, die anders funktionieren :-) Wichtig erscheint mir der Hinweis mit PINC_ anstelle _PORTC, einlesen geht doch nur über die PINx-Ports denke ich! Gruß Ingo
@ Markus "Muss ich evtl. irgendwo PORTC mit 0b00110000 initialisieren oder so?" jo , jetzt hab ich auch mal in deinen Quellecode geschaut, Du benutzt also die ISR von Peter. Hast du die wirklich nachvollziehen können? na egal, also ich arbeite nur mit Code, denn ich auch lesen kann. Klar musst du die Datenflussrichtung am PORT bzw. PIN bestimmen, dafür gibts ja die DDRX. Kannst ja nochmal in dem Code nachschauen, denn ich mal gepostet habe. Aber wenn du dir bei einer bestimmten stelle in Programm nicht sicher bist, wie es sich verhält. Dann würde ich dir dazu raten das Programm bis auf eine Minimum der Funktionen zu reduzieren. So hab ich bisher schon einige Fehler bei mir selber ausmärzem können. In deinem Fall. musst du doch erstmal prüfen, ob deine Eingänge überhaupt etwas im MC bewirken, also einfach alles rausschmeissen an überflüssigem Code. Die PINS als Eingang setzen, eine Schalter dranklemmen und in der TIMER ISR einfach mal eine LED je nach Status der Taster ein oder auschalten. Dann weisst du ob deine Eingänge funktionieren und ob die ISR ausgeführt wird. Damit wärst du schon einen riesen Schritt weiter und es dauert nur 10 min. Wenn es nicht klappt, würde ich mich erstaml mit den einfachen Sachen beschäftigen. Z.B. LED über Schalter ein / aus schalten........... usw.
Sehr gute Neuigkeiten, bald seid ihr wahrscheinlich von mir erlöst. Ich benutze nun Peter's Code und das Hochschalten funktioniert schon fast ;-) Leider verstehe ich den Code nicht so richtig, da habt ihr allerdings richtig Recht. Folgendes passiert nun: Zu Beginn steht der Counter auf 0; Dann geht er bei der nächsten Umdrehung nach oben auf 055, dann auf 255, 455, 655, 855, 1055, 1255, etc. Wenn ich runterdrehe geht er von 0 auf 0 und dann auf 254, 252, 250, etc. Er geht also in Zweierschritten runter. Wenn ich nun im Intervall von 0-254 wieder hochdrehe geht er (fast korrekt) in Zweierschritten nach oben (fast korrekt, weil er ja in Einerschritten hochzählen soll). Kann mir jemand vielleicht ein allerletztes Mal helfen und sagen, wo der Fehler liegt? Ich verstehe nämlich nicht, warum er das macht und hab schon alles mögliche probiert. Anbei mein Code. Vielen vielen Dank Markus
Was ich vergessen habe: Eigentlich soll mein Zähler die Minuten in Einserschritten hoch- oder runterzählen und das im Bereich von 0-1440.
"int32_t minutes = 0;" Du solltest Dich schon mal mit den Zahlenformaten beschäftigen, d.h. wenn du "int32_t" benutzt auch wissen, was das bedeutet. 2^32 Minuten sind nämlich 8000 Jahre ! Warum willst Du so weit zählen ? Wenn Du ein long nach char abschneidest und dann wieder nach long, das muß ja schief gehen ! Bei Zuweisungen in ein anderes Zahlenformat, muß man immer prüfen, ob das Ergebnis auch richtig ist. Nimm doch zum Test erstmal "char" Werte, dann sind nur Zahlen von -128...127 möglich. Du änderst ziemlich planlos und an vielen Stellen gleichzeitig rum und wunderst Dich dann, warum nichts mehr geht. Mich wundert das nicht. Versuchs mal mit der Baby-step Methode: Mache nur eine Sache, teste sie und mache dann den nächste Schritt, teste wieder usw. Peter
ganz mein Reden Peter! Bezüglich der Babysteps und irgendwann verstehen wir ( Markus & Ich ) dann auch deinen Code :-)
Fremden Code verstehen, gut und schön. Und man muß das Fahrrad ja auch nicht immer wieder neu erfinden. Aber für mich war es in vielen Fällen sehr hilfreich, daß ich mich erstmal selber hingesetzt und überlagt hab, wie funktioniert das ganze (die Harware, z.B. der Drehencoder) und wie kann ich das nun programmtechnisch erfassen. Und da hab ich mir einfach mal Papier und Bleistift genommen (wie altmodisch :-) und mir das ganze aufgezeichnet/aufgeschrieben, z.B. die möglichen Schalterzustände des Encoders mit 0 und 1. Ja und dann hat es auch schnell "Klick" gemacht, sowohl beim Encoder als auch bei mir selbst. Gruß Ingo
So, ich bin endlich durch Peters Code durchgestiegen. Kann es sein, dass Du Else-Zweige vermeidest? Das macht den Code etwas unübersichtlich. Prinzipiell müsste Markus nur die letzte IF-Abfrage in deinem Code umändern, und zwar für den Fall, dass Bit 1 gesetzt ist, die Minuten in die eine Richtung verändern und falls es gelöscht ist, in die andere Richtung. Die Richtung hängt ja nicht nur von der Software, sondern auch von der Hardware ab. Sehe ich das richtig? Sie ist zumindest wahlfrei (also auch Linkshänder geeignet). Und du gehst davon aus, dass enc_delta zu Beginn des Programms =0 ist? Erklärung für Leute, die da noch nicht durchgestiegen sind: Die Encoder liefern in der Raststellung eine zweitellige Binärzahl mit zwei gleichen Elementen (00 oder 11). Wird der Encoder bewegt, so wird nur eins der beiden Elemente verändert. (Gray-Code / Phase_A und Phase_B) Je nach dem, welcher Eingang sich verändert hat, wird der Variablen i eine ungerade Zahl zugeordnet. Dadurch wird ein Schritt erkannt. In welche Richtung sich bewegt wird, entscheidet das Bit 1. Zu Ingo: Ich hätte es wahrscheinlich so wie Stephan mit 2 Hardware-Interrupts gemacht. Gray-Code kannte ich zwar, aber irgendwie fehlte mir die Verbindung zu Drehencodern mit nur zwei Ausgängen. Wir hatten das in Digitaltechnik nur als Absolut-Drehencoder, sprich 4 Stellen für 16 Werte... Oder so, ist schon wieder etwas her... Die Impulsfolge erinnert auch an die Ansteuerung von Schrittmotoren... Rahul
n'Abend Ich hab einfach mal meinen Encoder angelötet und Peters Code ausprobiert. Abgesehen davon, daß ich noch die internen PullUps angeschaltet und andere Pins genommen habe funktioniert das tadellos. Hardware ist ein Mega32 mit 16MHz, Encoder an PIND6 und PIND7. Ein weiteres riesen Dankeschön an den Meister ! Gruß Eddi
Ich habe hier mal versucht, die Wirkungsweise meines Codebeispiels ausführlich zu erklären: http://www.mikrocontroller.net/forum/read-4-37992.html Die letzte Anweisung habe ich etwas umgeschrieben, ist einfacher zu lesen, aber funktional identisch. Da keine Zwischenvariable verwendet wird, muß man auch nicht mehr aufpassen, ob char, int oder long gezählt werden soll. Peter
Also es tut mir ja wirklich leid, aber ich habe nun noch einmal Peter's Code benutzt und das Ding funktioniert noch immer so wie ich oben beschrieben habe (nämlich im Zweierschritt und wenn ich bei 255 hochdrehen will, dann geht er auf 155, 255, 355, 455, ...). Ich lasse mir die Werte nun dezimal auf den Bildschirm schreiben, die an PHASE_A und PHASE_B liegen und komischerweise bekomme ich entweder 0 0 oder 4 8 angezeigt! Das hat aus meiner Sicht überhaupt nichts mit 00, 01, 11, 10 zu tun! Stimmt da was nicht?
Hi Markus Stimmt, daß mit den Zweierschritt habe ich bei dem Conrad-Drehgeber auch. Die Anzeige der Zahlen ist schon so "richtig". Nach 255 kommt 1 und wenn du keine führenden Nullen bzw. Leerstellen ausfilterst ´bleibt halt die 2. und 3. Stelle als 55 stehen. Ist also ein reines Anzeigeproblem (ich benutze itoa() und wandle in 3stelligen char um). Gruß Eddi
Jo, ich habs gerade eben auch gemerkt, ich Dackel ;-). Wie hast du denn das Problem mit den Zweierschritten bei dir geregelt? Bei mir funktioniert jetzt alles, nur eben wird in Zweierschritten hoch- und runtergezählt, was bei mir aber leider nicht der Fall sein darf :-(.
Momentan teil ich einfach durch 2 :) Sollte aber nicht die endgültige Lösung sein. Ich habs scon mit Änderung der Abfragerate durch Änderung des Vorteilers probiert. Half auch nicht. Ich werde mir wohl nochmal das Datenblatt des Drehgebers angucken, vielleicht findet man da ja eine Lösung.
Was teilst du denn durch 2? Ich habs auch versucht, aber kein gescheites Ergebnis rausbekommen (vielleicht teile ich auch was falsches). Könntest du evtl. deinen Code posten? Vielen Dank, Eddi Grüßle Markus
Mit der Abfragerate hat das nichts zu tun. Hab mir Peters Code nicht genau angeschaut, aber allgemein möchte ich folgendes sagen: Man sollte nur den Übergang der Zustände in einer Richtung auswerten. Also z.B. von 11 -> 01 bzw. 11 -> 10 (je nach Drehrichtung) aber nicht dann auch noch von 01 -> 00 bzw. 10 -> 00 Das wär so, als würde man bei der PC-Tastatur sowohl beim Drücken als auch beim Loslassen ein Tastencode erzeugen :-)
"Das wär so, als würde man bei der PC-Tastatur sowohl beim Drücken als auch beim Loslassen ein Tastencode erzeugen :-)" Aber genau so ist es: Es gibt bei Tastatur und Maus ein Press und ein Release event.
Jaja, das ist schon klar. Nur wenn ich hier bei mir auf der Tastatur, sagen wir mal auf die Taste "A" drücke (und schnell genug loslasse, sonst passieren da noch ganz andere Dinge:-), erscheint da nur ein A. Beim Drehendcoder will ich ja nur einen Tick haben, von einer Raststellung zur nächsten (sofern er Raststellungen hat), und da reicht es dann auch, nur einen Übergang auszuwerten.
Ich glaube, Ingo hatte wirklich Recht. Wenn ich mich recht entsinne frägt Peter's Code 8 Zustände ab. Ich habe mir - auch aufgrund Ingo's Antwort gedacht, einfach mal alle Übergange anzeigen zu lassen und bin auf folgende gekommen (fragt mich bitte nicht, warum meine Zahlen so komisch sind und nicht aus 00, 01, 10 oder 11 besteht, aber ihr werdet sehen, dass das identisch ist): Zwei Übergänge (Peter's Code rechnet 4) bei Linksdrehung: 40 -> 00 08 -> 48 Und zwei Übergänge (Peter's Code rechnet wieder 4) bei Rechtsdrehung: 40 -> 48 08 -> 00 Daraus habe ich dann folgenden Code entwickelt (naja, ich hab nicht viel überlegt, sondern einfach mal eingetragen zum Testen. Das lässt sich natürlich noch optimieren ;-)): // Der Drehimpulsgeber benutzt die Pins C2 und C3 #define PHASE_A (PINC & 1<<PINC2) #define PHASE_B (PINC & 1<<PINC3) volatile int enc_delta = 0; int old_a = 0; int old_b = 0; int new_a = 0; int new_b = 0; void init_timer (void) { TCCR2 = _BV (CS22) | _BV (WGM21); OCR2 = 124; TIMSK = _BV (OCIE2); DDRC = 0xf3; // PortC als Ausgang, 1111 0011, bis auf PC2,PC3 PORTC = 0x0c; // 0000 1100 sei (); } SIGNAL (SIG_OUTPUT_COMPARE2) { static uint16_t lc=0; // interner Counter char i = 0; // Peter's Code lc++; // erhoehe Counter // wenn Counter durch sieben teilbar, also alle 7ms, tue if (lc % 7 == 0) { if( PHASE_A ) i = 1; if( PHASE_B ) i ^= 3; i -= enc_last; // Differenz if( i & 1) { // Diese vier Zeilen sind neu old_a = new_a; old_b = new_b; new_a = PHASE_A; new_b = PHASE_B; enc_last += i; // Peter's Code // Berechne Links- oder Rechtsdrehung if ((old_a == 4) & (old_b == 0) & (new_a == 0) & (new_b == 0)) { enc_delta++; } else if ((old_a == 0) & (old_b == 8) & (new_a == 4) & (new_b == 8)) { enc_delta++; } else if ((old_a == 4) & (old_b == 0) & (new_a == 4) & (new_b == 8)) { enc_delta--; } else if ((old_a == 0) & (old_b == 8) & (new_a == 0) & (new_b == 0)) { enc_delta--; } } } // Jede Sekunde, mache... if (lc >= 1000) { //sekundenzähler hier hochzählen seconds++; lc = 0; // Counter zuruecksetzen } } Bei mir funktioniert der Drehimpulsgeber nun perfekt ;-)
Die Erklärung ist einfach: Jeder Drehgeber macht 4 Phasen, aber nicht jeder rastet auch auf jeder Phase ein. Sehr empfindliche Drehgeber (z.B. 100 Schritte je Umdrehung) rasten auf jeder Phase, da zählt der Code +/-1. Unempfindliche Drehgeber (z.B. nur 10 Rastschritte) rasten nur jede 4. Phase ein (+/-4), d.h. man teilt das Ergebnis /4 (= 2* rechtsschieben). Dazwischen gibt es eben auch welche, die jede 2.Phase einrasten (+/-2), also Ergebnis /2 teilen (= 1* rechtsschieben). Wenn Du Deinen Drehgeber also langsam drehst und nicht einrasten läßt (festhälst), merkst Du deutlich, daß mein Code korrekt immer einen Schritt weiterzählt, aber nur jeden 2.Zählwert eine Rastung erfolgt. > Zwei Übergänge (Peter's Code rechnet 4) bei Linksdrehung: > > 40 -> 00 > 08 -> 48 Nein, das macht er eben nicht !!! Du nimmst nicht das Ergebnis meines Codes, sondern liest die Pins nochmal vollkommen neu ein: > new_a = PHASE_A; > new_b = PHASE_B; Und dann gilt eben: PINC2 = 4 PINC3 = 8 Frische bitte nochmal Deine Kenntnisse bezüglich Rechnen mit Binärzahlen auf, dann weißt Du auch warum. Dadurch ist Dein Code auch nicht mehr Pin unabhängig. Mein Code liefert dagegen immer 0,1,2 oder 3. Peter
Hallo nochmal Bei mir ruhte das Thema etwas, aber nun läuft das Ding endlich. Nachdem ich dann auch begriffen habe, dass es nicht um die Übergänge der "Schalterstellungen" beim Encoder geht, sondern einfach nur ein schneller Vergeich der Zustände ( alt und neu ) nötig ist. Die Abfrage über den Timer ist dabei doch deutlich schneller als, die Schaltgeschwindigkeit des Encoders. Selbst bei sehr schneller Umdrehung mit der Hand, hat man immer noch min. 2 ms zum auswerten. Bei einer Taktfrequenz von 3,6846 MHZ und einem Vorteiler von 64 fragt der µC immer noch alle 17µS den Encoder ab. Also muss man sich dahin keine Sorgen machen. Der Vorteiler kann sogar noch höher ausgelegt werden. Ich hab das Thema noch mal aufgegriffen, weil ich als Einsteiger leider mit Peter`s Code nicht zurechtkam und mir auch selber was basteln wollte. Ich denke mein Code ist was einfacher zulesen, und hilft evtl. Leuten die sich später mal mit dem gleichen Thema rumärgern. Kann gtu sein, das der Code deutlich verbesseet werden könnte, aber es funktioniert sehr gut und ist eben auch schön verständlich. (hoffe Ich) bis dann mal Stephan
Vielleicht hilft das weiter?: http://320027039581.bei.t-online.de/elektronik/controller_drehimp/controller_drehimp.htm cya McMurkser
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.