Hallo, Im moment setze ich in einer Simulation einen Atmega128 ein der ein Rotary Encoder in einer Schleife abfragt um dann einen Counter hoch bzw runterzuzählen, je nach Drehrichtung versteht sich. Doch der Atmega128 scheint jetzt schon überfordert zu sein ... Statt dass alles zackzack geht braucht er 1 Sekunde für das Abfragens der PINS (wo der Encoder dranhängt) Eigentlich kaum zu fassen, aber ich möchte einen Flüssigen Drehregler haben und keinen der nur einmal pro Sekunde hochzählt. Ich überlege mir daher direkt zu einem ARM7 (LPC2138) zu wechseln ... Kann ich damit eventuell ein "Flüssiges" am Drehregler-Drehen implementieren? Danke im Voraus und liebe Grüße
Der Simulator arbeitet natürlich nicht in Echtzeit. Schau doch mal Links auf den Cycle Counter!!! Jeder Takt dauert Counter/XTAL. Da stehen auch die us, allerdings stehen die glaub ich bei reiner Software Simulation auf 4MHz. Abfragen eines Pins sollte glaub ich nur 1-2 Takte dauern
Naja also die Takte werden schon schnell simuliert. Wenn ich ne Whileschleife mache die einfach nur den Counter hochzählt und auf dem LCD ausgibt schiesst der so schnell hoch, da kann ich nicht gucken! Frage ich aber PortB ab und vergleiche mit der temporären Maske ab um rauszufinden ob der Drehregler links oder rechts gedreht wurde dauert das Ewig ... An die 5 Sekunden habe ich gerade gestoppt.
Wie kommst du darauf, dass die Zeit, die die Simlation benötig, irgendetwas mit der Laufzeit zu tun hat? Du gehst doch nicht etwa davon aus, dass die Simulation in Echtzeit stattfindet, oder? Im Simulator (wlcher überhaupt?) findest du sicher auch eine Anzeige der Laufzeit oder der Taktzyklen. Die ist relevant, und nicht die Zeit, die während der Simulation auf deiner Uhr vergeht.
Poste doch mal den Quellcode, den du simulierst.
>geht braucht er 1 Sekunde für das Abfragens der PINS
Das ist nämlich unsinn. Die reine Abfrage dauert 2Prozessortakte. Oder
steht dieser auf 1Hz?
Der ISIS Simulator der bei Proteus dabei ist. Ja Simulatorzeit wird angezeigt und hinkt nur Minimal der Realen-Laufzeit hinterher. Ich würde sagen der Simulator ist nur 5-10% langsamer als Echtzeit!
Cagara wrote:
> Ich würde sagen der Simulator ist nur 5-10% langsamer als Echtzeit!
Immer? Hast du das ganz konkret mit der Laufzeit/Zyklen-Anzeige
verglichen?
Nein, der ARM7 kann das auch nur in 0.58 Sekunden erledigen. IMHO würde ich gleich auf die neue ATOM Plattform setzen. SCNR!
Also hier schonmal der simple Code: Zwar funktionieren die Messungen rein garnicht, aber ich habe einen kleinen "Zykluscounter" und der steigt nur 1 mal die Sekunde ... Nehme ich die Port abfrage raus gehts super super flott. Und zum Letzten Beitrag ... Ein Billig-China-Radio mit Drehtuner kriegt das doch auch hin, dass man flüssig die Frequenz Zurechtdrehen kann ... OHNE Atom Platform :) #define ENCODER PINB #define CHANNEL_A 2 // Encoder 'A' channel input #define CHANNEL_B 3 // Encoder 'B' channel input #define CHANNEL_MASK ((1<<CHANNEL_A) | (1<<CHANNEL_B)) #define DIR_LED 7 // Encoder direction bit unsigned char EncoderCurrent; unsigned char EncoderLast = 0; unsigned char EncoderIndex = 0; char EncoderCount = 0; const char ENCODER_STATE[] = {0x04, 0x0C, 0x08, 0x00}; unsigned char I_O_Debounce(unsigned char Port, unsigned char Bit) { static unsigned char LastKey; unsigned int DebounceCount = 0; do { if ( LastKey != (Port & Bit) ) DebounceCount = 0; LastKey = Port & Bit; } while (DebounceCount-- != 100); return (~LastKey & Bit); // Negated for use with the STK500/STK600 } int main(){ // Initialize Display glcd_setup(); glcd_init(); glcd_clear_text(); int Counter=0; int zyk=0; do { // Assuming the encoder is connected to PORTD EncoderCurrent = I_O_Debounce(ENCODER, CHANNEL_MASK); if (EncoderLast != EncoderCurrent) { if ((EncoderCurrent & CHANNEL_MASK) == ENCODER_STATE[EncoderIndex]) { // Encoder forward direction EncoderIndex = ++EncoderIndex & 0x03; Counter--; } else { // Encoder reverse direction EncoderIndex = --EncoderIndex & 0x03; Counter++; } EncoderLast = EncoderCurrent; } zyk++; PrintFrequency(Counter,zyk); } while(1); }
Der korrektheit halber muss ich sagen dass ich den Code von http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=62118&start=20 zurechtgecopy-pasted hab!
Hallo, einen Drehencoder sauber auszuwerten, ist mit einem AVR mühelos möglich, auch während in Echtzeit richtig aufwändige andere Sachen drauf laufen. Ich gehe davon aus, dass es sich nur um einen Drehknopf handelt, nicht etwa um einen hochdrehenden Spindelencoder von einer Fräsmaschine mit 2048 Counts pro Umdrehung. Vergiss einfach den Simulator, programmier es interruptgesteuert und es funktioniert. Pin1 löst Interrupt aus und dort wird geprüft, ob Pin2 gesetzt ist. Fertig. Schalterentprellung am besten in Hardware. Viele Grüße, Peter
Schalterentprellung? Wäre lieb wenn du mir kurz zeigen oder sagen könntest wie man einen solchen Intterupt / Callback auf einen Pin setzt! Und ja: Ist ein ganz simpler Drehschalter, da ich aber gerade erste Versuche in sachen AVR mache und ein bisschen Experimentiere fehlt mir natürlich jetzt die Info mit dem Interrupt!
Cagara wrote: > Hallo, > > Im moment setze ich in einer Simulation einen Atmega128 ein der ein > Rotary Encoder in einer Schleife abfragt um dann einen Counter hoch bzw > runterzuzählen, je nach Drehrichtung versteht sich. > > Doch der Atmega128 scheint jetzt schon überfordert zu sein ... Mit Sicherheit nicht. Wenn Du die Sache dann noch richtig programmierst funktioniert das auch und kostet fast garnichts an Rechenzeit.
Hallo, du setzt so wie es im Datenbatt des Controllers gezeigt ist, die Special function Register. Damit aktivierst du einen Interrupt auf einem der Pins an denen der Drehknopf hängt und stellst die Flanke entsprechend deiner Schaltung ein. Fallend oder steigend, je nachdem ob die Schalter nach Vcc oder Gnd ziehen. Dann gibst du den Pin Interrupt drei und gibst den global interrupt enable frei. Jetzt brauchst du eine Interruptroutine, die aufgerufen werden kann, wenn der Interrupt auftritt. Wie das geht, steht im libc manual des gcc compilers. Vergiss nicht, das Interruptflag am Ende der Interruptroutine zurückzusetzten, sonst kommt er von alleine immer wieder. In der Interruptroutine kannst du dann den Status des anderen Pin auswerten. Je nach dem, ob high oder low ist ein rechts oder links Tick aufgetreten. Du musst jede Variable, die sowohl im Interrupt als auch im Hauptprogramm verwendet wird als volatile deklarieren. Natürlich muss einer der Schalter auch an einem Interruptfähigen Pin angeschlossen sein. Viele Grüße, Peter
Streiche mal folgende Zeile aus dem Quellcode und simuliere nochmal:
1 | PrintFrequency(Counter,zyk); |
>Wie das geht, steht im libc manual des gcc compilers. Vergiss nicht, das >Interruptflag am Ende der Interruptroutine zurückzusetzten, sonst kommt er >von alleine immer wieder. Das liegt nicht am µC, sondern an der fehlenden Entprellung ! Eine solche Abfrage macht man nicht mit Interrupts! Besagtes Bit wird vom µC automatisch beim Anspringen der ISR gelöscht! >Pin1 löst Interrupt aus und dort wird geprüft, ob Pin2 gesetzt ist. >Fertig. Schalterentprellung am besten in Hardware. Ich erwarte demnächst eine ganz bestimmte Antwort eines ganz bestimmten Mitredners ;-)
Hallo, meine Antwort bezog sich nicht auf das Programm von oben, sondern auf ein neues. Das Rücksetzen des Interruptflags habe ich mit einem anderen Prozessor verwechselt. Es würde aber auch nicht schaden, es zu clearen. Aber du hast an dieser Stelle natürlich Recht. Und eine Abfrage von einem Drehencoder macht man immer mit einem Interrupt, es sei denn, man möchte seine Rechenleistung vergeuden. Eine Lösung ohne Interrupt funktioniert mit Programmzykluszeiten von 500µs und abwärts vernünfig. Dann macht der Controller aber wirklich nichts anderes mehr. Das kann man mal machen, wenn man nur seinen Encoder testen will, aber wenn der Prozessor noch andere Sachen erlegigen soll, ist das extrem kontraproduktiv, gerade beim ATMEGA128 mit 8 (?) Hardwareinterrupts. Dass er eine Entprellung braucht, habe ich doch erwähnt. Diese in Software zu lösen, ist jedoch bei Auslösen von Interrupts kontraproduktiv. Natürlich trotzdem möglich. Ich verstehe nicht, warum ihr unbedingt den obigen Code umbauen wollt, das geht neu programmiert 10 mal schneller. Peter
>Und eine Abfrage von einem Drehencoder macht man immer mit einem Interrupt >>Ich erwarte demnächst eine ganz bestimmte Antwort eines ganz bestimmten >>Mitredners ;-)
Hallo, was soll der Unsinn? Ich hab sowas schon programmiert, du auch? Probier doch mal eine Version ohne Interrupts, wenn nebenher ein Phasenanschnitt für einen Drehstromthyristorsteller, ein Grafik-LCD mit Touchpanel, eine Temperaturregelung auf 1mK genau und dafür 3 PID Regler in Floatingpoitarithmetik laufen! Dein Kunde wird dir dein Gerät um die Ohren hauen, weil es bescheiden auf den Drehknopf reagiert, wenn er was verstellen will. Natürlich kannst du damit die immer gewünschte Stellbeschleunigung bei schnellem Drehen auch nicht. Und jetzt erwarte ich eine Antwort. Und eine funktionsfähigen Code.
Cagara wrote: > Wenn ich ne Whileschleife mache die einfach nur den Counter hochzählt > und auf dem LCD ausgibt schiesst der so schnell hoch, da kann ich nicht > gucken! Soso und das soll also am Drehgeber liegen? 1. Wie lange braucht denn das LCD alleine? 2. Muß ein LCD überhaupt schnell sein, weil ja jeder Mensch eine Million Werte pro Sekunde ablesen kann? Hint: Ergonomisch sind 2..5 Werte, dann ist der Mensch am Anschlag. Bezüglich Drehgeber: Beitrag "Drehgeber/Encoder 1-, 2- oder 4-schrittig" Peter
>Ich hab sowas schon programmiert, du auch? Ja. Da wir ja nur von Hand-Encodern reden. Diese haben ja bekanntlich relativ geringe Auflösungen und geringe Drehzahlen, gegenüber Drehgebern der Industrie. Also : Jede (µC) Applikation benötigt eine (konstante) Zeitbasis, resp. einen Timer. Somit gibt es immer einen freilaufenden TImer (meist Null), der zB im ein oder zehn Millisekunden Takt überläuft und somit einen INT auslöst. Innerhalb dieses INTs, werden die beiden Spuren eingelesen, und zB nach 4Q-Manier ausgewertet. Es wird geprüft, ob der Encoder einen korrekten Sprung (nach Gray-Code) ausgeführt hat, wenn ja, Wert erhöhen, verkleinern. /Somit entsteht, unabhängig vom Encoder eine konstante niedrige µC-Last./ Was passiert denn bei INT-gesteuerter Abfrage, wenn der Encoder prellt oder um eine Position pendelt? Da bläst du den µC mit INTs zu. >Natürlich kannst du damit die immer gewünschte Stellbeschleunigung bei >schnellem Drehen auch nicht. Die habe ich noch nicht reingebracht, aber warum sollte die hier nicht gehen? >Ich erwarte demnächst eine ganz bestimmte Antwort eines ganz bestimmten >Mitredners ;-) Gut, dann mach ich das mal. klick mal drauf, und lies das durch Drehgeber
Hallo, diese Lösung ist auch ellegant, wenn man sich die Zeit im Timerinterrupt leisten kann. Peter
Peter Diener wrote: > diese Lösung ist auch ellegant, wenn man sich die Zeit im Timerinterrupt > leisten kann. Ich wüßte jetz keine Anwendung, die an ~30 Zyklen (2µs) scheitert. Man kann Timerinterrupts aber auch mit SEI am Anfang unterbrechbar machen, falls der unwarscheinliche Fall eintritt, daß schon 30 Zyklen stören. Peter
>Und jetzt erwarte ich eine Antwort. Und eine funktionsfähigen Code. >diese Lösung ist auch ellegant, wenn man sich die Zeit im Timerinterrupt >leisten kann. Interessante Tonlagenänderung....
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.