Εrnst B. schrieb:
> Überleg dir, was passiert sobald millis() seinen 32-bit-Rollover hat.
Es passiert viel öfter Seltsames. Nämlich schon, wenn "geschickt"
zwischen
*if(millis()/1000 > crontimer + 3){* und *crontimer = millis()/1000;*
der millis-Zähler einen der allsekündlichen Tausender-Überläufe hat.
Dann wird nämlich eine "Schaltsekunde" eingelegt, wenn z.B. zum
Zeitpunkt der if-Abfrage millis() noch 12999 hatte, beim Berechnen des
neuen crontimer Werts aber schon auf 13000 weitergezählt hat.
Εrnst B. schrieb:
> Schöner:
> if ((millis() - crontimer)>3000) {
> crontimer=millis();
Und noch viel viel schöner ist es, wenn man am Anfang der Mainloop ein
einziges Mal den millis()-Zeitstempel abholt und den Rest im Zyklus mit
derselben Zeit rechnet:
1 | unsigned long jetzt, crontimer = 0, t5s = 0;
|
2 |
|
3 | void loop() {
|
4 | jetzt = millis(); // einmalig Zeitstempel für diesen Schleifendurchlauf abholen
|
5 |
|
6 | if (jetzt - crontimer > 3000) { // alle 3s ...
|
7 | crontimer = jetzt;
|
8 | Serial.println(pulse_total);
|
9 | }
|
10 |
|
11 | if (jetzt - t5s > 5000) { // alle 5 s
|
12 | t5s = jetzt;
|
13 | :
|
14 | }
|
15 | }
|
Und so richtig schön wäre es dann, wenn man am Anfang der Schleife die
Eingänge ebenfalls auf ein Prozessabbild einlesen und alle berechneten
Änderungen erst am Schluss der Schleife auf die Ausgänge schreiben
würde. Dann hat man nämlich die vielmillionenfach erprobte
Vorgehensweise einer SPS. Da kann zwar die Zykluszeit der SPS insgesamt
zu langsam sein, es gibt aber kein seltsames Timingverhalten wegen einer
zum Programmablauf hinzugefügten Funktion.