Forum: Mikrocontroller und Digitale Elektronik Timer Atmega während Interrupts


von Jerry B. (jerry_b)


Lesenswert?

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 :-)

von Norbert (Gast)


Lesenswert?

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.

von Jerry B. (jerry_b)


Lesenswert?

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?

von Falk B. (falk)


Lesenswert?

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.

von Jerry B. (jerry_b)


Lesenswert?

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
von Falk B. (falk)


Lesenswert?

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.

von Michael M. (Gast)


Lesenswert?

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.

von Jerry B. (jerry_b)


Lesenswert?

Danke @Michael

von Ingo Less (Gast)


Lesenswert?

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.

von Jerry B. (jerry_b)


Lesenswert?

Danke, aber ich lege den AT in den sleep-Modus (idle) und er wird vom 
Interrupt geweckt

von Falk B. (falk)


Lesenswert?

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
von Peter D. (peda)


Lesenswert?

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.

von Jerry B. (jerry_b)


Lesenswert?

@Falk

Ich bezog mich auf Ingo mit dem sleep-Mode

von Jerry B. (jerry_b)


Lesenswert?

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 :-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
von Peter D. (peda)


Lesenswert?

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.

von Jerry B. (jerry_b)


Lesenswert?

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...

von Axel S. (a-za-z0-9)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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.

von EAF (Gast)


Lesenswert?

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.

von Jerry B. (jerry_b)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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

von EAF (Gast)


Lesenswert?

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.

von EAF (Gast)


Lesenswert?


von Joachim B. (jar)


Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

>> 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?

von Norbert (Gast)


Lesenswert?

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…

von MaWin (Gast)


Lesenswert?

Lothar M. schrieb:
> wer versetzt dann nach dieser ISR den Controller
> wieder in den Schlafzustand?

Die Hauptschleife natürlich.

von Jobst M. (jobstens-de)


Lesenswert?

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

von Jerry B. (jerry_b)


Lesenswert?

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
Noch kein Account? Hier anmelden.