Hallo, Ich habe ein Problem beim Entprellen von Drehgebern (Bourns Rotary Encoder mit graycode). Ich bastel gerade an 2 Projekten damit. Bei dem einen will ich das eine Taktsignal an den Interrupt1 und das andere Taktsignal an PD4 eines Atmega8 hängen. Der Bascom-Quelltext, den ich bisher habe ist im Anhang. Das ist bisher nur zum Testen. Leider zählt die Variable c völlig wahllos. Wenn ich in eine Richtung drehe, zählt er mal rauf und mal runter, ausserdem sind die Sprünge zwischen den Werten auch bei einem einzelnen Klick unterschiedlich gross. Die Drehgeschwindigkeit ist da auch völlig egal. Ich brauche allerdings die Abfrage per Interrupt, da das Hauptprogramm sehr zeitintensiv wird. Es wird daher auch per Assembler geschrieben sein. Ich habe auch schon versucht, den Interrupt einfach abzuschalten, damit er nicht mehrfach aufgerufen wird. Nur irgendwie scheint der AVR die zwischenzeitlichen Interrupt-Aufrufe zu speichern, um sie später nachzuholen. Ich hoffe ihr könnt mir helfen, da ich mich jetzt schon ein paar Stunden damit herumgequält habe und nun nicht mehr weiter weiss. Danke! Maik
Du mußt den Zustand eines Drehgeber-Pins in einer Variablen "merken" und vor der Auswertung auf Veränderung prüfen, z. B. Kanal A. Erst wenn sich Kanal A verändert hat hat der Nutzer den Drehgeber betätigt und darauf hin dann die Auswertung "IF PinD.3=0 then" etc. Noch mal der Ablauf: If Gemerkt <> PinD.3 dann If PinD.3 = PinD.4 dann ..... else ..... EndIf Gemerkt = PinD.3 EndIf MfG Andi
Für eine zuverlässige Auswertung muss sich das Programm die Zustände beider Ausgänge merken, dann kann man sich das Entprellen auch i.d.R. sparen. http://www.mikrocontroller.net/forum/read-4-37992.html#87902
Naja... wenn ich das so machen würde, könnte ich mein Projekt gleich abhaken. Bei der ersten Lösung würde ich 10-20 Zyklen alleine im Hauptprogramm mehr haben, und bei der 2. wären diese 10-20 Zyklen regelmässig beim Timeraufruf. Bei mechanischen Drehgebern muss man nicht alle 4 Stadien der Ausgänge auswerten. Da der Regler ja selbst rastet, würde man so eh pro Klick um 2 werte nach oben zählen. @Andi: Die Lösung funktioniert wenn überhaupt, nur mit einem bereits hardwaremässig-entprellten Drehgeber.
Bei mir ging es ganz einfach: Pullups des uC aktivieren, 10nF nach Masse zur Entprellung und ein Ausgang des Inkrementgebers an einen Interrupt. In der Interruptroutine wird der Zustand des zweiten Pins abgefragt: Ist der High wurde vorwärts gedreht, ist es Low wurde rückwärts gedreht. Fragt micht nicht wiso das so ist, ich weiß nur dass es einwandfrei bei mir läuft.
@MyCo "Naja... wenn ich das so machen würde, könnte ich mein Projekt gleich abhaken. Bei der ersten Lösung würde ich 10-20 Zyklen alleine im Hauptprogramm mehr haben, und bei der 2. wären diese 10-20 Zyklen regelmässig beim Timeraufruf." Das must Du aber schon näher erläutern ! 20 Zyklen in einem Timer z.B. alle 200µs (5kHz) sind bei 8MHz 20/1600=1,25% CPU-Last. Du must also die Quarzfrequenz nur um 1,25% erhöhen und Du hast genau die gleiche Leistung wie ohne Drehgeber auslesen. Ich kenne jedenfalls keine Anwendung, die bei 1,25% CPU-Last schon in die Knie geht. Peter
Ich will den Atmega als "stellbaren" Taktgeber einsetzen, mit Frequenzen zwischen 2MHz und 50Hz, wobei Low- und High-Zeit getrennt geregellt werden kann. Das wichtige dabei ist, dass wenn die Frequenz einmal gestellt ist, der Taktgeber 100% genau laufen soll. Ein Timer-Interrupt der immer mal das Hauptprogramm unterbricht würde so zB. das ganze Prinzip kaputt machen. Der µC läuft schon mit einem 16MHz Quarz, ein Erhöhung der Taktrate bringt dann nur noch mehr Fehler.
2MHz?? Hut ab, das ist ein hohes Ziel! Und denn noch 100% genau... Da wird ein AVR arg zu knabbern haben, selbst bei Verwendung der Hardware-PWM. ...
"Ich will den Atmega als "stellbaren" Taktgeber einsetzen, mit Frequenzen zwischen 2MHz und 50Hz, wobei Low- und High-Zeit getrennt geregellt werden kann." Und warum nimmst Du nicht die PWM (Mode 14 oder 15) ? Die macht das doch voll in Hardware, da stört ein Interrupt überhaupt nicht. Und unter 245Hz nimmst Du eben die Pin-Set und Clear-Funktion des Timers. Peter
Es zwingt dich doch niemand dazu die Auswertung im Timerinterrupt zu machen, das geht genau so gut in der Hauptschleife.
Ich habe bisher pwm noch nicht dazu bekommen, das zu tun was ich will... die Dokumentation in Bascom bringt einem nicht weiter, und mit ASM bin ich auch noch nicht so weit... Software-mässig bekomme ich mit meinem ASM-Code bisher etwa 1,5MHz konstant Aber es geht mir auch darum, einen Drehgeber abzufragen, ohne dafür die Pins abzufragen. Es soll also nur der Drehgeber abgefragt werden, wenn bereits feststeht, dass er bewegt wurde.
"Ich habe bisher pwm noch nicht dazu bekommen, das zu tun was ich will... die Dokumentation in Bascom bringt einem nicht weiter" Die Doku im Datenblatt aber schon. Es schad nix, wenn man sich mal mit den internen Registern und Funktionen der CPU beschäftigt und sich nicht blindlings auf die vorgefertigten Black-Boxes in Bascom verläßt. Ich finds sogar interessanter, wenn man weiß, wie etwas funktioniert. "Software-mässig bekomme ich mit meinem ASM-Code bisher etwa 1,5MHz konstant" Wie machst Du denn da die Einstellung des Tastverhältnisses ? "Es soll also nur der Drehgeber abgefragt werden, wenn bereits feststeht, dass er bewegt wurde." Ginge im Prinzip auch (beide Pins auf beide Interrupts und dann bei beiden Flanken auslösen). Beide Interrupthandler rufen dann die Routine auf. Trotzdem wirst Du dann aber ohne die PWM Signalstörungen haben, auch wenns nur beim Drehen ist. Peter
Der Hauptteil des Taktgebers ist: mainloop: cbi $15,0 movw Temp,LTimeH dlya: sbiw Temp,1 brne dlya sbi $15,0 movw Temp,HTimeH dlyb: sbiw Temp,1 brne dlyb rjmp mainloop Im Interrupt soll dann per Drehgeber LTimeH, LTimeL, HTimeH und HTimeL gesetzt, und der Hauptteil macht dann automatisch den Rest. Wie gesagt, die PWM-Beschreibung ist mir im Moment zu schwer zu verstehen, da ich ASM noch nicht so gut kann. Den Hauptteil habe ich gerade so zusammenbekommen. Vielleicht kann mir jemand eine PWM-Version geben, die ähnliches erzielt, wie mein Hauptteil. Aus Quelltext kann ich besser lernen, als aus trockenen Dokumentationen.
Hi! Also sowas sollten unbedingt der/die Timer selber machen. Beschäftige dich mal mit Output Compare A+B. Du wirst sehen dein Zeitproblem löst sich in Luft auf. Mal so als Tip OC1A macht Low-Teil, OC1B macht High-Teil deiner Freq. Aber um's Datenblatt kommst du nicht herum. MFG Uwe
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.