Guten Morgen Bevor ich mich dumm und dusselig suche ;-) Ich programmiere einen ATmega64 und brauche relativ zuverlässige 3 Stunden, die ich über millis() abfrage. Nun habe ich aber einen Bewegungsmelder am Interrupt3 hängen. Mein Problem: Der Interrupt sorgt dafür, dass millis nicht weiterzählt, während ich in der Interruptroutine bin (und da möchte ich bleiben, bis keine Bewegung mehr festgestellt wird). Kann mir jemand sagen, wie ich das clever lösen kann? Danke :-)
Jerry B. schrieb: > Kann mir jemand sagen, wie ich das clever lösen kann? Danke :-) Ja selbstverständlich. > während ich in der Interruptroutine bin (und da möchte ich bleiben, bis > keine Bewegung mehr festgestellt wird). Einfach mal das ganze Konzept über Bord werfen, alles von Grund auf neu denken und dann richtig machen.
Was meinst Du damit? Das hilft mir wenig, wenn jemand sagt : "Einfach mal das ganze Konzept über Bord werfen" Sorry, aber so ein Kommentar ist doch für uns beide vertane Zeit, oder?
Jerry B. schrieb: > Guten Morgen > Bevor ich mich dumm und dusselig suche ;-) > Ich programmiere einen ATmega64 und brauche relativ zuverlässige 3 > Stunden, die ich über millis() abfrage. Die berühmt, berüchtigte Arduino-Funktion. Gibt es überhaupt einen offiziellen Arduino mit ATmega64? > Nun habe ich aber einen > Bewegungsmelder am Interrupt3 hängen. > Mein Problem: Der Interrupt sorgt dafür, dass millis nicht weiterzählt, > während ich in der Interruptroutine bin (und da möchte ich bleiben, bis > keine Bewegung mehr festgestellt wird). Ganz dumme Idee. Lies mal was über Interrupt und Multitasking. > Kann mir jemand sagen, wie ich das clever lösen kann? Danke :-) Einfach so, wie der Rest der Welt, der gescheit programmieren gelernt hat.
Also eigentlich wollte ich nur wissen, ob es einen Timer gibt, der unabhängig von Interruptroutinen weiterläuft? Ich könnte sonnst zur Not auch meinen DS3231 abfragen...
:
Bearbeitet durch User
Jerry B. schrieb: > Also eigentlich wollte ich nur wissen, ob es einen Timer gibt, der > unabhängig von Interruptroutinen weiterläuft? Die TIMER laufen so oder so parallel zur CPU, denn es sind unabhängige Hardwareblöcke. Aber die Zeitverwaltung braucht auch den dazugehörigen Interrupt. > Ich könnte sonnst zur Not auch meinen DS3231 abfragen... Unfug^3.
Hallo, Wenn dein Konzept besteht in einer ISR auf etwas zu warten, ist das schon "falsch". ISR sollte man in der Regel so kurz wie möglich halten, zudem auf delay(), Serial.println() also allgemein blockierende funktionen verzichten. Besserer Ansatz: Setz in der ISR nur ein Flag und werte es in der main loop aus. Wenn du genauere drei Stunden brauchst empfehle ich dir ein DS3231.
Jerry B. schrieb: > Bewegungsmelder am Interrupt3 hängen. Das ist unklug. Erzeuge dir per Hand einen 1ms Interrupt und frage dort deinen Bewegungsmelder ab (ohne Interrupt, nur pollen) und zähle deine Millisekunden dort bei bis 3*60*60*1000 und gut is.
Danke, aber ich lege den AT in den sleep-Modus (idle) und er wird vom Interrupt geweckt
Jerry B. schrieb: > Danke, aber ich lege den AT in den sleep-Modus (idle) und er wird vom > Interrupt geweckt Ja und? Bei idle laufen auch die Timer weiter und dein AVR wird bei jedem Timer-Interrupt geweckt. Du brauchst eines sinnvolle Statemachine.
:
Bearbeitet durch User
Jerry B. schrieb: > Der Interrupt sorgt dafür, dass millis nicht weiterzählt, > während ich in der Interruptroutine bin (und da möchte ich bleiben, bis > keine Bewegung mehr festgestellt wird). Sowas macht man einfach nicht. Warten im Interrupt auf ein Ereignis ist Pfui-Bäh. Interrupthandler sind nur wenige CPU-Zyklen lang, so daß der 1ms Interrupt genügend Zeit hat, die ms zu zählen. Löse daher 2 Interrupts aus, einmal für die low-Flanke und einmal für die High-Flanke. Dazwischen sind dann andere Interrupts wieder erlaubt.
Peter D. schrieb: > Jerry B. schrieb: >> Der Interrupt sorgt dafür, dass millis nicht weiterzählt, >> während ich in der Interruptroutine bin (und da möchte ich bleiben, bis >> keine Bewegung mehr festgestellt wird). > > Sowas macht man einfach nicht. Warten im Interrupt auf ein Ereignis ist > Pfui-Bäh. > Interrupthandler sind nur wenige CPU-Zyklen lang, so daß der 1ms > Interrupt genügend Zeit hat, die ms zu zählen. > > Löse daher 2 Interrupts aus, einmal für die low-Flanke und einmal für > die High-Flanke. Dazwischen sind dann andere Interrupts wieder erlaubt. Ja danke - schon kapiert und umgebaut -läuft jetzt :-)
Jerry B. schrieb: > Der Interrupt sorgt dafür, dass millis nicht weiterzählt Ein Interrupt dauert ein paar us, sonst ist es kein Interrupt, sondern ein Programmfehler. Jerry B. schrieb: > ich lege den AT in den sleep-Modus (idle) Und dann machst du dir keine Sorgen um die millis()? Die laufen im Schlaf ja auch nicht mehr... Ist es jetzt Mode, solche schnarchlangsamen Dinger wie PIR-Sensoren per Interrupt auszuwerten? Der hier wills auch so machen: Beitrag "Re: ESP32 resettet" Ich würde da einfach einen Timer laufen lassen und den uC alle 300ms oder so aus dem Schlaf aufwecken, tun, was zu tun ist und wieder schlafen gehen. Das ist deterministisch und funktioniert auf Anhieb.
:
Bearbeitet durch Moderator
Jerry B. schrieb: > Danke, aber ich lege den AT in den sleep-Modus (idle) und er wird vom > Interrupt geweckt Ich bringe erstmal nur die Applikation zum Laufen und lassen alle Sparoptionen außen vor. Erst wenn alles perfekt läuft, kann man den Sleep-Modus hinzufügen. Dieses nacheinander Entwickeln macht das Programmieren und die Fehlersuche deutlich einfacher.
Lothar M. schrieb: > Jerry B. schrieb: >> Der Interrupt sorgt dafür, dass millis nicht weiterzählt > Ein Interrupt dauert ein paar us, sonst ist es kein Interrupt, sondern > ein Programmfehler. Verstanden :-) und umgesetzt > > Jerry B. schrieb: >> ich lege den AT in den sleep-Modus (idle) > Und dann machst du dir keine Sorgen um die millis()? Die laufen im > Schlaf ja auch nicht mehr... Das ist mir neu...: SLEEP_IDLE: makes the MCU enter Idle mode, stopping the CPU but allowing the SPI, Serial, Analog Comparator, ADC, Wire, Timer/Counters and the interrupt system to continue operating. This mode enables the microcontroller to wake up from external triggered interrupts as well as internal ones like the Timer Overflow and Serial Transmit Complete interrupts. SLEEP_ADC: makes the microcontroller enter ADC Noise Reduction mode, stopping the CPU but allowing the ADC, the external interrupts, Wire Serial Interface address match and Timer/Counter2. This improves the noise environment for the ADC, enabling higher resolution measurements. If the ADC is enabled, a conversion starts automatically when this mode is entered. Only an External Reset, a Wire serial interface interrupt, a Timer/Counter2 interrupt, an SPM/EEPROM ready interrupt, an external level interrupt on INT7:4 or a pin change interrupt can wakeup the microcontroller from ADC Noise Reduction mode. > > Ist es jetzt Mode, solche schnarchlangsamen Dinger wie PIR-Sensoren per > Interrupt auszuwerten? Der hier wills auch so machen: > Beitrag "Re: ESP32 resettet" > Wo siehst Du ein Problem dabei? > Ich würde da einfach einen Timer laufen lassen und den uC alle 300ms > oder so aus dem Schlaf aufwecken, tun, was zu tun ist und wieder > schlafen gehen. Das ist deterministisch und funktioniert auf Anhieb. Geht wahrscheinlich genausogut...
Jerry B. schrieb: > Danke, aber ich lege den AT in den sleep-Modus (idle) und er wird vom > Interrupt geweckt Na und? Das kannst du mit Pollen auch haben. Nur daß du dazu zeitbasiert aufwachst. Bei einem Bewegungsmelder muß das sicher nicht mit 1ms Abstand sein. Da reichen 10ms oder auch 100ms wohl aus. Aber dein Hauptproblem ist, daß du glaubst millis() wäre ein Timer. Das ist es nicht. Aber dein ATMega64 hat mehrere richtige (d.h. von der CPU unabhängige) Timer. Benutze sie. Nur weil die Arduino-Leute ihre Anwender für zu blöd halten, die Timer direkt zu verwenden und deswegen mit Krücken a'la millis() angehumpelt kommen, muß man das nicht nachmachen. Schau z.B. in das AVR-Tutorial: Timer
Axel S. schrieb: > Nur weil die Arduino-Leute ihre Anwender für zu blöd halten Nö. Die Idee dahinter ist eher, ein einheitliches API zur Verfügung zu stellen, was unabhängig vom konkreten MC-Typ ist. Nur an einer sauberen Dokumentation krankt es. Die Doku zu allen Arduino-MCs ist nur sehr oberflächlich und geht auf die Internas nicht ein. Abseits der Anfängerbeispiele ist das API nur wenig hilfreich und man muß dann doch nach Datenblatt programmieren.
Jerry B. schrieb: > Ich könnte sonnst zur Not auch meinen DS3231 abfragen... Die Wire Lib, also die Library, welche in der Arduino Welt für I2C zuständig ist, benötigt selber Interrupts. Funktioniert somit erstmal nicht in einer ISR. Natürlich kann man auch in einer ISR die Interrupts wieder aktivieren. Aber dass dürfte dann die zweit oder dritt dümmste Variante sein. Vor allen Dingen, wie hier, so ganz ohne jede rationale Not.
EAF schrieb: > Jerry B. schrieb: >> Ich könnte sonnst zur Not auch meinen DS3231 abfragen... > > Die Wire Lib, also die Library, welche in der Arduino Welt für I2C > zuständig ist, benötigt selber Interrupts. Funktioniert somit erstmal > nicht in einer ISR. > > Natürlich kann man auch in einer ISR die Interrupts wieder aktivieren. > Aber dass dürfte dann die zweit oder dritt dümmste Variante sein. > Vor allen Dingen, wie hier, so ganz ohne jede rationale Not. Nein, ich will die 3 Stunden ja im Hauptprogramm messen. Aber dadurch, dass ich nun in der Interruptroutine nur ein flag setze, bin ich "sogar" mit millis() ziemlich nah dran an den 3 Stunden.
EAF schrieb: > Die Wire Lib, also die Library, welche in der Arduino Welt für I2C > zuständig ist, benötigt selber Interrupts. Funktioniert somit erstmal > nicht in einer ISR. muss neu sein! Ich habe hier Programme wo nach PeDa Timerinterrupts 10ms laufen zur Entprellung und in der IRQ I2C Uhr und/oder PCF8574 Ports mit Tasten abgefragt werden, ich habe die I2C Zugriffe vermessen die schwanken so um 1-2µs sind also schnell genug um in die 10ms Entprellung Timerzugriffe zu passen. Ich erweiterte es sogar mit ukw IR Empfang 15000/s IRQ zähle bis 150 und hüpfe in die Entprellroutine Man muss nur darauf achten das sich das Teil nicht selber blockiert! Aber das kann man ja messen, IRQ -> Port setzen -> Gewünschtes im IRQ ausführen (so kurz wie möglich bis vor dem nächsten IRQ) -> Port rücksetzen Dauer mit dem Oszi messen oder Clocks der Befehle zählen Das läuft nun bei mir schon seit 2015 in meiner wordclock12 mit mega328p
Joachim B. schrieb: > muss neu sein! Nein, ist es nicht. Du vergleichst Äpfel mit Birnen! Der TO wollte in einer Pin ISR die RTC abfragen. Das versuch du mal, dann kannst du deine Argumentation stumpf in die Tonne kloppen.
Nachtrag: Ich habe die I2C ISR mal für dich rausgesucht: https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/Wire/src/utility/twi.c#L503
EAF schrieb: > Der TO wollte in einer Pin ISR die RTC abfragen. wo kann ich das mit der Pin ISR lesen? ich habe alle seine 9 Beiträge durchsucht und "Pin" nicht gefunden. OK gefunden Interrupt3 und dann noch Jerry B. schrieb: > ATmega64 klar ist unpassend³ zu Arduino Ich muss raus hier, ein doofes Konzept wird ja durch Diskussion nicht besser.
Jerry B. schrieb: > Also eigentlich wollte ich nur wissen, ob es einen Timer gibt, der > unabhängig von Interruptroutinen weiterläuft? Den Timer interessiert die Interrupt Routine überhaupt nicht. Der läuft unabhängig davon. Das ist deine Software, die Mist baut. Die Interrupt Routine soll durch dein Ereignis nur kurz angestoßen werden und möglichst schnell wieder verlassen werden. Wenigstens könntest du deine Timer Interrupts frei bei geben, damit deine Software auf den Timer reagieren kann und die Uhr weiter läuft.
>> Und dann machst du dir keine Sorgen um die millis()? Die laufen im >> Schlaf ja auch nicht mehr... > Das ist mir neu...: > SLEEP_IDLE: makes the MCU enter Idle mode, stopping the CPU but allowing > the.... Timer/Counters and the > interrupt system to continue operating. Stimmt alles, aber da steht eben nichts vom millis-Zähler. Nur mal angenommen, der nächste für millis nötige Interrupt würde den uC aufwecken und dann die millis hochzählen (millis ist ein von Software verwalteter Zähler!), wer versetzt dann nach dieser ISR den Controller wieder in den Schlafzustand?
Lothar M. schrieb: > Nur mal angenommen, der nächste für millis nötige Interrupt würde den uC > aufwecken und dann die millis hochzählen (millis ist ein von Software > verwalteter Zähler!), wer versetzt dann nach dieser ISR den Controller > wieder in den Schlafzustand? Noch nie etwas von Arduinomagie gehört? Sich echt enttäuscht zurücklehnend…
Lothar M. schrieb: > wer versetzt dann nach dieser ISR den Controller > wieder in den Schlafzustand? Die Hauptschleife natürlich.
Michael M. schrieb: > Besserer Ansatz: Setz in der ISR nur ein Flag und werte es in der main > loop aus. Völlig bekloppter Ansatz: Denn für das Flag braucht man keine Software in einem Interrupt, es wird schon -und zwar wesentlich schneller- durch die Hardware gesetzt. Zu jedem Interrupt wird ein Interruptflag gesetzt. Das kann man dann in der main direkt abfragen. Nennt sich polling und ist das Gegenteil von einem Interrupt. Flags für polling in einer ISR zu setzen führt Interrupts ad absurdum. Gruß Jobst
SO, es ist Zeit dieser Diskussion ein Ende zu setzen! Ich hatte eine doffen Ansatz - gebe ich zu. Bin aber lernfähig und hatte ca. 10 Minuten später dnak ein paar gute Tipps meine Anforderung umgesetzt und seit heutevormittag schnurrt die Software. Dank also an alle, die sich die Mühe gemacht haben, eine kompentente Antwort zu geben bzw. mir zu helfen. Die anderen sollten sich mal fragen, warum sie so auf dicke Hose machen müssen? Das hilft keinem und ist meistens nicht mal fundiert...etwas einfach nur als schlecht abtun, ist lediglich für euer Ego gut. Es gibt eben nicht immer nur euren Weg bei der Programmiererei...free your mind!
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.