Hallo ich bin mich gerade mit der Funktion Millis am beschäftigen. Mein
Plan ist es eine Steuerung mit Touchscreen zu bauen wo ich Zeiten
Temperaturen einstellen kann und dann das Programm eine Heizplatte
steuert. Da ich bis jetzt nur sehr Mini Projekte gemacht habe und vorher
immer Bascom benutzt habe kenne ich mich mit der IDE noch nicht gut aus.
Ich wollte jetzt stück für Stück einzelne Programmteile erstellen und
Testen (Üben) um später alles zu einen großen ganzen zusammenzusetzten.
Ich habe jetzt schon einiges gelesen und hoffe das ich jetzt soweit
alles verstanden habe.
1. Millis startet bei Strom bzw. Reset und läuft knapp 50 Tage
2. Ich speichere die Startzeit in einer unsigned long Variable
3. Im loop lese ich erneut Millis aus Rechne die Startzeit ab und
erhalte die Differenz.
Daraus kann ich jetzt natürlich die Zeit Berechnen. Was ich jetzt aber
noch nicht ganz genau verstehe ist wie ich damit genau 1 Sek immer
erreiche. Weil ich weiß ja nicht wann das Programm die Differenz
berechnet. Jetzt mal total übertrieben wenn meine schleife sagen wir mal
2 Sekunden brauchen würde um durchzulaufen könnte ich ja nie jede
Sekunde meinen Timer runter zählen. Es wäre nett wenn mir das Prinzip
mal jemand erklären könnte. Den Code finde ich schon selbst heraus mir
reicht allein das Prinzip
Nachdem du so viel Text geschrieben hast ohne dass wirklich was dabei
rauskommt, vermute ich, dass du in Cobol programmierst. Rechner ist wohl
eine IBM 700.
Richtig?
Mit welchem Arduino kämpfst Du denn?
"Häufige Fehlerquelle: Da millis() relativ schnell über den Wertebereich
int hinauslaufen, sollte man hier den Variablentyp long bevorzugen.
Der Return ist vom Dateityp unsigned long. Nach ca. 50 Tagen springt
millis() zurück auf 0."
mfg
Einhart P. schrieb:> Wenn du eine schnelle Reaktion brauchst, dann darf die Haupschleife halt> keine 2 s laufen. 2s sind schon eine Ewigkeit.
Und "Ewigkeit" ist hier noch untertrieben. Wenn die mehr als ein paar
Millisekunden braucht, ist das schon heftig viel.
Christian S. schrieb:> sollte man hier den Variablentyp long bevorzugen.
Wer lesen kann ist klar im Vorteil.
Wer verstehen kann, noch mehr.
Sebastian schrieb:> Ich speichere die Startzeit in einer unsigned long Variable
Leute das mit 2 Sekunden war nur ein Beispiel auch wenn die Schleife
sagen wir mal 255ms braucht komme ich ja nach 4 schleifen auf 1020ms
raus und mir würde dann schon 20ms fehlen im meine Variable Sek 1 zu
veringern. Bei 1 Stunde wäre das dann eine große Differenz
Sebastian schrieb:> wie ich damit genau 1 Sek immer> erreiche.
Wer erklärt Ihm das mit den Bienen und Blümchen?!
Was du braucht nennt sich Timer-Interrupt.
Ich glaube Ihr versteht mich nicht richtig ich weiß wie ich mit Millis
2-3 Leutdioden oder was auch immer im Sekundentakt oder auch 2 Sekunden
leuchten lassen kann. Aber je nach dem was im loop abgearbeitet werden
muss dauert der unterschiedlich lang. Wenn ich jetzt die Funktion millis
() benutze und den Interval auf 1000ms setzte und dann daraufhin eine
Variable Sek um 1 hochzähle kann es doch sein das erst Millis bei 1010ms
die If Schleife durchläuft. Dann fehlen mir doch schon 10ms
Keiner schrieb:> ich weiß wie ich mit Millis> 2-3 Leutdioden oder was auch immer im Sekundentakt oder auch 2 Sekunden> leuchten lassen kann. Aber je nach dem was im loop abgearbeitet werden> muss dauert der unterschiedlich lang.
Ich glaube nicht, daß du weißt wie es geht. Das merkt man an deinen
Bemerkungen. Die Intervalle sind NICHT unterschiedlich lang, wenn man es
richtig macht...
Schau dir bitte die Links an.
Dann wirst du merken, daß du nicht weißt wie es geht.
Sebastian schrieb:> wie ich damit genau 1 Sek immer erreiche.
Wie "genau" musst du die 1 Sekunde "erreichen"?
Welchen Jitter beim Sekundenwechsel kannst du dir erlauben.
Keiner schrieb:> Aber je nach dem was im loop abgearbeitet werden muss dauert der> unterschiedlich lang.
Es darf aber eben niemals länger als 1 Sekunde dauern, wenn du jede
Sekunde sicher "erreichen" willst.
Und wenn du jeden Sekundenwechsel auf 0,1s genau "erreichen" willst,
dann darf deine Mainloop niemals länger als 100ms deauern.
BTW: bitte nur 1 Name pro Thread!
So steht es in den Nutzungsbedingungen
Die millis Funktion basiert auf dem CPU Takt, der für derart lange
Zeiträume sicher nicht zufriedenstellend genau ist. Wenn du da in 50
Tagen auf 5 Minuten Abweichung kommst ist das schon gut, 15 Minuten
würde ich auch noch für normal halten.
Verwendet besser eine RTC ( z. Beispiel mit dem DS3231 Chip), die läuft
erheblich genauer und liefert dir praktischerweise auch gleich den
ganzen Kalender mit ohne dass du großartig rechnen musst.
Sebastian schrieb:> 2. Ich speichere die Startzeit in einer unsigned long Variable> 3. Im loop lese ich erneut Millis aus Rechne die Startzeit ab und> erhalte die Differenz.
Ich mache das andersherum: Ich rechne die Zielzeit aus und prüfe, ob
millis() größer als diese ist. Dann kneift mich ein evtl. Überlauf
nicht.
Simples Beispiel:
(Es wird nicht direkt compilieren, den Fehler findest Du selbst)
1
intLEDInfo=10;
2
unsignedlongintFlashLEDTime=0;
3
4
voidloop(){// Hauptschleife
5
if(millis()>FlashLEDTime==HIGH){// LED blinken lassen
6
digitalWrite(LEDInfo,!digitalRead(LEDInfo));
7
FlashLEDTime=(millis()+450);
8
}
Teo D. schrieb:> Was du braucht nennt sich Timer-Interrupt.
Warum? Der Arduino kann in der Hauptschleife rotieren und ein paar
Zeitstempel prüfen. Man muss natürlich aufpassen, das nicht durch
blockierende (delay) Unterroutinen zu versauen.
Keiner schrieb:> Ich glaube Ihr versteht mich nicht richtig
Oder du das Problem bzw. wie millis() wirklich funktioniert.
> ich weiß wie ich mit Millis> 2-3 Leutdioden oder was auch immer im Sekundentakt oder auch 2 Sekunden> leuchten lassen kann. Aber je nach dem was im loop abgearbeitet werden> muss dauert der unterschiedlich lang.
Ja.
> Wenn ich jetzt die Funktion millis> () benutze und den Interval auf 1000ms setzte
Wie machst du dass denn genau?
Millis liefert eine Zahl, die Millisekunden seit dem Reset. Diese Zahl
wird in einem 1kHz [8Interrupt]] vom Arduino-Framework hochgezählt,
unabhängi davon, was deine loop macht, denn der Interrupt hat Priorität
und kann die loop() und sonstige Funktionen oder Methoden in Klassen
IMMER unterbrechen. Damit ist die Zahl immer korrekt.
> und dann daraufhin eine> Variable Sek um 1 hochzähle> kann es doch sein das erst Millis bei 1010ms> die If Schleife durchläuft. Dann fehlen mir doch schon 10ms
Richtig. So macht man es auch nicht. Du liest IMMER über millis() die
altuelle "Zeit" aus und rechnest die IMMER in HH:MM:SS um. Und schon
kann es NIE Abweichungen oder Zählfehler geben. Du brauchst keine extra
Zählung der Sekunden, das ist im Rückgabewert von millis() schon drin.
/1000 ist einfach, der Rest auch.
Hallo,
dem TO geht es um die Abweichung des millis Vergleiches. Der sich im
dümmsten Fall aufaddiert.
Man hat doch immer noch eine zweite Variable lastMillis oder ähnlich
benannt mit der man die verstrichene Zeit vergleicht. Wenn man diese
nach dem Ereignis gewöhnlich mit millis auf den aktuellen Stand bringt,
dann addieren sich die Laufzeitfehler auf. Bedingt durch die Laufzeit
von loop. Wir nehmen einmal an loop benötigt extrem lange.
Setzt man jedoch nach dem Ereignis/Zeitvergleich lastMillis nicht auf
den aktuellen millis Wert, sondern addiert zu lastMillis den gewünschten
Intervallwert (1000ms), dann kann sich kein Abweichungsfehler addieren.
Auch wenn die loop länger als 1ms benötigt, bleibt das Ereignis im
1000ms Fenster. Eine Abweichung kann es dennoch geben, aber wie gesagt,
addiert sich nicht auf.
Im ersten Fall kann lastMillis folgende Werte annehmen.
0, 1001, 2000, 3009, 4023 usw.
Im zweiten Fall sind es immer Vielfache vom Intervall 1000.
0, 1000, 2000, 3000, 4000 usw.
Der Vergleich kann im zweiten Fall dennoch z.Bsp. bei 2003 abgearbeitet
werden, aber das Zeitfenster kann sich nicht verschieben.
Veit D. schrieb:> dem TO geht es um die Abweichung des millis Vergleiches. Der sich im> dümmsten Fall aufaddiert.
Js, sber . . .
>> Man hat doch immer noch eine zweite Variable lastMillis oder ähnlich> benannt mit der man die verstrichene Zeit vergleicht. Wenn man diese> nach dem Ereignis gewöhnlich mit millis auf den aktuellen Stand bringt,> dann addieren sich die Laufzeitfehler auf. Bedingt durch die Laufzeit> von loop.
Nur dann, wenn man es naiv macht.
> den aktuellen millis Wert, sondern addiert zu lastMillis den gewünschten> Intervallwert (1000ms), dann kann sich kein Abweichungsfehler addieren.
Was falsch ist. Wunschdenken war noch nie sonderlich zielführend.
Manfred schrieb:> Teo D. schrieb:>> Was du braucht nennt sich Timer-Interrupt.>> Warum? Der Arduino kann in der Hauptschleife rotieren und ein paar> Zeitstempel prüfen. Man muss natürlich aufpassen, das nicht durch> blockierende (delay) Unterroutinen zu versauen.
Weil er es Punktgenau, ohne Jitter haben will. Unabhängig davon, was den
das Programm grade macht. Warum wie so, ist hierbei auch erst mal schei.
egal.
Veit D. schrieb:> Setzt man jedoch nach dem Ereignis/Zeitvergleich lastMillis nicht auf> den aktuellen millis Wert, sondern addiert zu lastMillis den gewünschten> Intervallwert (1000ms), dann kann sich kein Abweichungsfehler addieren.> Auch wenn die loop länger als 1ms benötigt, bleibt das Ereignis im> 1000ms Fenster. Eine Abweichung kann es dennoch geben, aber wie gesagt,> addiert sich nicht auf.
Das ist schlüssig, merke ich mir für zukünftige Projekte!
Je nach Auslastung / Aktivität der Hauptschleife kann es etwas Jitter
geben, aber die Langzeit wird nicht verschoben.
Falk B. schrieb:> Veit D. schrieb:>> den aktuellen millis Wert, sondern addiert zu lastMillis den gewünschten>> Intervallwert (1000ms), dann kann sich kein Abweichungsfehler addieren.>> Was falsch ist. Wunschdenken war noch nie sonderlich zielführend.
Das ist kein Wunschdenken. Das funktioniert genauso ohne
Aufaddierfehler.
Was soll daran falsch sein? Dein hh:mm:ss Vergleich funktioniert in dem
Fall übrigens genauso, weil grob auf eine Sekunde aufgelöst.
Manfred hat das schon korrekt wiedergegeben.
Sebastian schrieb:> 1. Millis startet bei Strom bzw. Reset und läuft knapp 50 Tage
Gleich die erste Annahme ist falsch. Millis() läuft, bis du dem µC
wieder den Strom abklemmst oder einen Reset auslöst.
Teo D. schrieb:> Was du braucht nennt sich Timer-Interrupt.
Genau das macht millis() und zwar mit Timer0.
Wolfgang schrieb:> Sebastian schrieb:>> 1. Millis startet bei Strom bzw. Reset und läuft knapp 50 Tage> Gleich die erste Annahme ist falsch. Millis() läuft, bis du dem µC> wieder den Strom abklemmst oder einen Reset auslöst.
Könntest du uns dann mal deine Definition von "Anfang" und "Ende"
mitteilen?
Veit D. schrieb:> Das ist kein Wunschdenken. Das funktioniert genauso ohne> Aufaddierfehler.
OK, ich hab da wohl ein Zitat verhauen. Ich meinte den Abschnitt vorher.
Das mit dem Aufaddieren ist korrekt.
Sebastian schrieb:> Daraus kann ich jetzt natürlich die Zeit Berechnen. Was ich> jetzt aber noch nicht ganz genau verstehe ist wie ich damit> genau 1 Sek immer erreiche.
Garnicht. Millis() ist eine Uhr, was du suchst ist ein Wecker. Eine Uhr
ist ein wesentlicher Bestandteil eines Weckers, den Rest musst du selbst
dazubasteln.
Wolfgang schrieb:> Was hat diese Frage mit dem Thema des TO zu tun?
Die Antwort würde helfen deine ansonsten unsinnige Antwort verständlich
zu machen. Also wäre der TO nicht noch zusätzlich verwirrt wenn er dein
Posting liest.
Ausser dir ging es nur darum einfach mal sinnfrei zu widersprechen.
Lothar M. schrieb:> Und wenn du jeden Sekundenwechsel auf 0,1s genau "erreichen" willst,> dann darf deine Mainloop niemals länger als 100ms deauern.
Sag nie "niemals" ;-)
Wenn man sich ungeschickt genug anstellt und mit Polling in loop()
arbeitet, hast du natürlich Recht.
Damit irgendwelche Abläufe in loop() das Auslesen nicht verzögern, ist
es besser, millis() unabhängig von loop() aufzurufen und zwar mit
höherer Priorität.
Der einfachste Weg dazu ist, den sowieso für die Zeitfunktion laufenden
Timer0 zu nutzen und den Aufruf von millis() per Timer Compare Interrupt
zu veranlassen. Damit reduziert sich der Jitter auf wenige µC-Takte.
Nick M. schrieb:> Die Antwort würde helfen deine ansonsten unsinnige Antwort verständlich> zu machen.
Du scheinst millis() nicht verstanden zu haben. Das ist eine Funktion,
die einen 32 Bit Zähler ausliest, der etwa im 1ms-Takt hochgezählt wird,
sobald der µC läuft - und wenn er hundert Jahre läuft. Mit Integer
Arithmetik sollte man allerdings schon klar kommen, um den zu nutzen.
Kannst du dein Unverständnis bitte mal in Form einer klaren Frage
formulieren?
Wolfgang schrieb:> Kannst du dein Unverständnis bitte mal in Form einer klaren Frage> formulieren?
Ich hab keine Frage, ich versteh das schon. Selbst wenn du versuchst mir
was unterzujubeln.
Es ging um den Unsinn:
Wolfgang schrieb:> Sebastian schrieb:>> 1. Millis startet bei Strom bzw. Reset und läuft knapp 50 Tage> Gleich die erste Annahme ist falsch. Millis() läuft, bis du dem µC> wieder den Strom abklemmst oder einen Reset auslöst.
Die Aussage von Sebastian ist richtig. Dein Widerspruch ist unsinnig,
die Begründung dazu um so mehr.
Du hast einen Widerspruch gebastelt, indem du dich auf das Ende
beziehst, Sebastian aber vom Anfang sprach.
Nick M. schrieb:> Die Aussage von Sebastian ist richtig. Dein Widerspruch ist unsinnig,> die Begründung dazu um so mehr.
Wo bitte hört millis() nach 50 Tagen auf zu laufen, mal ganz davon
abgesehen, dass millis() nur eine Funktion ist, um einen Zähler zu
lesen?
Wolfgang schrieb:> Wo bitte hört millis() nach 50 Tagen auf zu laufen,
Der Zähler läuft über und fängt bei 0 an. Je nach Auswertung kann das zu
Problemen führen.
1
#define DELTA_T 1000 //ms
2
unsignedlongnow=millis();
3
4
// Dieser Vergleich schlägt beim Überlauf fehl!!!
5
If((now>(before+DELTA_T)){
6
// DELTA_T Zeitdifferenz erreicht
7
foo();
8
before=now;
9
}
10
11
// Dieser Vergleich funktioniert auch beim Überlauf
Falk B. schrieb:> Der Zähler läuft über und fängt bei 0 an. Je nach Auswertung kann das zu> Problemen führen.
Aach - so ist das nun mal mit einem Zähler mit endlicher Breite -
irgendwann läuft der über. Wenn 32 Bit nicht reichen, muss man den
Überlauf auswerten und entsprechend agieren oder die Rechnung
überlaufsicher formulieren.
Wie gesagt:
Wolfgang schrieb:> Mit Integer Arithmetik sollte man allerdings schon klar kommen, um den> zu nutzen.
Hey Sebastian,
also wenn du in der loop() wirklich sooo ewig brauchen solltest,
dann hast du recht - das macht dann mit millis() keinen Sinn.
Du brauchst einen Timer mit Interrupt, in dem du dir dann die Zeit
basteln kannst wie du magst.
Entweder du initialisierst dir einen eigenen Timer (außer Timer0, der
wird vom Arduino für die millis verwendet).
Oder du manipulierst die Arduino Sourcen, find es eh voll daneben, dass
es da standardmäßig keine Callback gibt die man nutzen könnte.
Da könntest du wie folgt vorgehen:
Pfad ist Arduino Install-Ordner, z.B.:
"C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino"
1)
Die Datei "Arduino.h" um folgende Zeile erweitern:
1
boolsetTimer0Callback(void(*)(void));
2)
Die Datei "wiring.c" um folgendes erweitern:
1
staticvoid(*timer0_callback)(void);
2
3
boolsetTimer0Callback(void(*cb)(void))
4
{
5
if(cb==NULL)
6
{
7
returnfalse;
8
}
9
10
timer0_callback=cb;
11
12
returntrue;
13
}
14
15
/**
16
* Weiterhin musst du die vorhandenen ISR um den Callback erweitern.
17
*/
18
#if defined(TIM0_OVF_vect)
19
ISR(TIM0_OVF_vect)
20
#else
21
ISR(TIMER0_OVF_vect)
22
#endif
23
{
24
// copy these to local variables so they can be stored in registers
25
// (volatile variables must be read from memory on every access)
26
unsignedlongm=timer0_millis;
27
unsignedcharf=timer0_fract;
28
29
m+=MILLIS_INC;
30
f+=FRACT_INC;
31
if(f>=FRACT_MAX){
32
f-=FRACT_MAX;
33
m+=1;
34
}
35
36
timer0_fract=f;
37
timer0_millis=m;
38
timer0_overflow_count++;
39
40
/* Dies ist dein Callback-Aufruf, falls initialisiert. */
41
if(timer0_callback!=NULL)
42
{
43
timer0_callback();
44
}
45
}
3)
Dann kannst es wie folgt nutzen:
1
/* Oder alles schön als struct verpackt, wie du magst */
2
volatileuint16_tms;
3
volatileuint8_tsec;
4
volatileuint8_tmin;
5
6
voidmein_timer_callback(void)
7
{
8
ms=++ms%1000;
9
10
if(!ms)
11
{
12
sec=++sec%60;
13
14
if(!sec)
15
{
16
min=++min%60;
17
}
18
}
19
}
20
21
voidsetup()
22
{
23
setTimer0Callback(mein_timer_callback);
24
}
25
26
voidloop()
27
{
28
}
Hab dir die Dateien mal angehängt.
Oder du erweiterst die "wiring.c" direkt um eine Zeitstruktur die
in der ISR inkrementiert wird und baust zusätzlich eine
getTime() Funktion zu den millis() - dann sparst dir das mit dem
Callback.
Gibt mehrere Möglichkeiten.
Man könnte die Callback auch als "weak" definieren, dann würde man sich
die set-Funktion sparen - aber naja, wie gesagt, 1000 Wege führen zum
Ziel.
Keiner schrieb:> Wenn ich jetzt die Funktion millis> () benutze und den Interval auf 1000ms setzte und dann daraufhin eine> Variable Sek um 1 hochzähle kann es doch sein das erst Millis bei 1010ms> die If Schleife durchläuft. Dann fehlen mir doch schon 10ms
Wenn Du es so machst wie Du schreibst, dann kannst Du nicht einfach die
Sekunden hochzählen. Du mußt aus der Zeitdifferenz die Sekunden
berechnen und einer Variablen zuweisen.
1
longSekunden;
2
longaktmillis=0;
3
longstartzeit=millis();
4
5
for(;;){
6
//irgendwelcher Code
7
aktmillis=millis();
8
Sekunden=(aktmillis-startzeit)/1000;
9
}
Schön ist natürlich anders. Man macht das eigentlich, wie schon mehrfach
beschrieben mit einem Timerinterrupt.
Adam P. schrieb:> Du brauchst einen Timer mit Interrupt, in dem du dir dann die Zeit> basteln kannst wie du magst.>> Entweder du initialisierst dir einen eigenen Timer (außer Timer0, der> wird vom Arduino für die millis verwendet).>> Oder du manipulierst die Arduino Sourcen, find es eh voll daneben, dass> es da standardmäßig keine Callback gibt die man nutzen könnte.
Ist doch gar nicht nötig.
Arduino nutzt den Timer0 Overflow. bei ca 0,98 kHz
Der Timer0 hat 2 weitere Compare Interruptquellen.
Nutzt man diese, hat man mindestens einen Takt in der gleichen Frequenz.
Wen man beide geschickt nutzt kommt man auf die doppelte.
Dafür muss man nicht in den originalen Quellen rumbasteln.
Zudem sind Callbacks an der Stelle recht ineffektiv, führen zu langen
push pop Orgien.
Alles in allem: Du hast recht, es ist ein Weg.
Aber, es ist ein ungeschickter.
Falk B. schrieb:> Wolfgang schrieb:>> Wo bitte hört millis() nach 50 Tagen auf zu laufen,>> Der Zähler läuft über und fängt bei 0 an. Je nach Auswertung kann das zu> Problemen führen.
Und die richtige Auswertung ist (wie Falk schreibt):
>
1
>#defineDELTA_T1000//ms
2
>unsignedlongnow=millis();
3
>
4
>// Dieser Vergleich funktioniert auch beim Überlauf
5
>If((now-before)>DELTA_T){
6
>// DELTA_T Zeitdifferenz erreicht
7
>foo();
8
>before=now;
9
>}
10
>
Denn die Differenz zweier unsigned long hängt (solange sie unter 2^32
bleibt; das sind >49 Tage) nicht von eventuellem Überlauf ab.
Wenn man jetzt noch eine Kleinigkeit verbessert, dann hat man sogar
einen mittleren Abstand von 1000ms (in Rahmen der Taktgenauigkeit).
1
#define DELTA_T 1000UL //ms
2
unsignedlongnow=millis();
3
4
// Dieser Vergleich funktioniert auch beim Überlauf
5
If((now-before)>DELTA_T){
6
// DELTA_T Zeitdifferenz erreicht
7
foo();
8
// wann hätte der aktuelle Lauf sein sollen, auch wenn die
9
// restliche loop() mal wieder länger dauert (<1000ms)
10
bevor+=DELTA_T;// auch hier funktioniert der Überlauf
Generell muss man sagen, daß der Ansatz mit dem millis() und Vergleich
zum alten Wert eher so lala ist. Kann man machen, geht für viele
einfache bis mittlere Ansprüche. Wenn es aber besser, genauer und vor
allem jitterarm sein soll, will man einen direkten Aufruf im EXAKTEN
Zeitraster. Wie das geht, sieht man u.a. hier, das geht auch auf dem
Arduino mit einem Timer1 oder Timer2.
https://www.mikrocontroller.net/articles/Multitasking#Verbesserter_Ansatz_mit_Timer
Das kann man sogar noch sehr leicht um eine Stromsparfunktion mittels
Sleep Mode erweitern, einfach am Anfang der while(1) Schleife den
Sleep Mode aktivieren. Die CPU wacht dann beim Interrupt wieder auf und
rattert alles einmal durch.
https://www.mikrocontroller.net/articles/Sleep_Mode#UART_Terminal
Wolfgang schrieb:> Wo bitte hört millis() nach 50 Tagen auf zu laufen,
Das nennt sich Überlauf. Der TO hat das etwas schlampig beschrieben aber
dennoch verwertbar. Denn nach 50 Tagen ist die Zahl nicht mehr sinnvoll
auswertbar weil sie wieder bei Null beginnt.
Ich mach uptime Zähler (denn das ist die bessere Bezeichnung) immer als
uint_64t in einer Auflösung von 1/100 Sekunden.
Diese Plattform traut sich wohl selbst nur eine uptime von 50 Tagen zu,
was ja auch schon recht bezeichnend ist. Scheinbar gibt es sogar paar,
die dann auch tatsächlich nicht so weit denken können.
> mal ganz davon> abgesehen, dass millis() nur eine Funktion ist, um einen Zähler zu> lesen?
Was soll das billige Ablenkungsmanöver? Bleib mal bei einem Punkt, du
verlierst die Übersicht schon so schnell genug.
Zeno schrieb:> Keiner schrieb:>> Wenn ich jetzt die Funktion millis>> () benutze und den Interval auf 1000ms setzte und dann daraufhin eine>> Variable Sek um 1 hochzähle kann es doch sein das erst Millis bei 1010ms>> die If Schleife durchläuft. Dann fehlen mir doch schon 10ms>> Wenn Du es so machst wie Du schreibst, dann kannst Du nicht einfach die> Sekunden hochzählen. Du mußt aus der Zeitdifferenz die Sekunden> berechnen und einer Variablen zuweisen.>
1
>longSekunden;
2
>longaktmillis=0;
3
>longstartzeit=millis();
4
>
5
>for(;;){
6
>//irgendwelcher Code
7
>aktmillis=millis();
8
>Sekunden=(aktmillis-startzeit)/1000;
9
>}
10
>
>> Schön ist natürlich anders. Man macht das eigentlich, wie schon mehrfach> beschrieben mit einem Timerinterrupt.
Genau so würde ich es auch machen. Millis() nutzt ja schon einen
Timerinterrupt, weshalb braucht man da noch einen weiteren. Und mit der
Differenz 'millis() - startzeit' kann man ja eine Zeitspanne bis zu 50
Tagen abdecken.
Sebastian schrieb:> Hallo ich bin mich gerade mit der Funktion Millis am beschäftigen. Mein> Plan ist es eine Steuerung mit Touchscreen zu bauen wo ich Zeiten> Temperaturen einstellen kann und dann das Programm eine Heizplatte> steuert. Da ich bis jetzt nur sehr Mini Projekte gemacht habe und vorher
Ich denke eine Heizplatte betreibt man maximal einige Stunden (Minuten
oder Sekunden), und dies kann man mit der Millis()differenz problemlos
abdecken. Da die Differenz direkt in Sekunden/Minuten/Stunden
umgerechnet werden kann, ist ein zusätzlicher Sekundentimer unnötig.
Manfred schrieb:> Ich mache das andersherum: Ich rechne die Zielzeit aus und prüfe, ob> millis() größer als diese ist. Dann kneift mich ein evtl. Überlauf> nicht.>
1
intLEDInfo=10;
2
>unsignedlongintFlashLEDTime=0;
3
>
4
>voidloop(){// Hauptschleife
5
>if(millis()>FlashLEDTime==HIGH){// LED blinken lassen
6
>digitalWrite(LEDInfo,!digitalRead(LEDInfo));
7
>FlashLEDTime=(millis()+450);
8
>}
9
>
Und genau so macht man es nicht!!!
Wenn hier der millis() Zähler nach etwa 52 Tagen kurz vor dem Überlauf
steht (2^32 - 449) dann wird 'FlashLEDTime = (millis() + 450)' in einen
Wert von kleiner 450 resultieren, und die Abfrage schlägt 450 msec lang
jede Millisekunde zu. Das ist bei einer LED sicher unkritisch, die
leuchtet hier leuchtet dann eine halbe Sekunde mit halber Helligkeit,
aber für andere Aktionen kann das schon sehr kritisch werden. Und so
einen Fehĺer zu finden, der nur alle 52 Tage auftritt, ist schon sehr
sehr schwierig.
Wolfgang schrieb:> Sebastian schrieb:>> 1. Millis startet bei Strom bzw. Reset und läuft>> knapp 50 Tage>> Gleich die erste Annahme ist falsch. Millis() läuft,> bis du dem µC wieder den Strom abklemmst oder einen> Reset auslöst.
Nun ja, es gibt immer zwei Möglichkeiten.
Die eine ist, eine... ähh... arg grenzwertige (für die
Schweiz: falsche) Aussage SO richtigzustellen, dass
jeder Leser weiss, was gemeint ist. Also etwa in der
Form: "Nein, der Zähler, den millis() abfragt, läuft
ewig und drei Tage, sofern der Controller so lange Saft
hat -- richtig ist aber, dass der Zähler nach 50 Tage
überläuft , also wieder von Null anfängt mit zählen."
Die andere Möglichkeit besteht darin, in bewährter
Mathematiker-Manier "FALSCH!!!" zu brüllen, was ebenso
korrekt wie nutzlos ist.
Aber natürlich, die zweite Möglichkeit eignet sich besser,
einer dahindümpelnden Diskussion endlich mal eine gewisse
Lebhaftigkeit zu verleihen...
Nick M. schrieb:> Das nennt sich Überlauf. Der TO hat das etwas schlampig beschrieben aber> dennoch verwertbar.
"Aufhören zu laufen" und "Überlauf" sind verschiedene Dinge. Wenn du das
im Rahmen von "schlampig beschrieben" als gleichwertig betrachtest, ist
das dein Problem.
Wolfgang schrieb:> Wenn du das> im Rahmen von "schlampig beschrieben" als gleichwertig betrachtest, ist> das dein Problem.
Lies das da:
Beitrag "Re: Sekunden,Minuten zählen mit der Funktion Millis()"
und schau dir bitte nochmal deine Minuspunkte an die du im Laufe deines
Geschwätzes dafür kassiert hast.
Und fang mal an zu denken, dein präpupertäres Fußaufstampfen hilft dir
hier nicht weiter. Das klappt nur bei Mutti.
Nick M. schrieb:> Wolfgang schrieb:>> Wo bitte hört millis() nach 50 Tagen auf zu laufen,>> Das nennt sich Überlauf. Der TO hat das etwas schlampig> beschrieben aber dennoch verwertbar. Denn nach 50 Tagen> ist die Zahl nicht mehr sinnvoll auswertbar weil sie> wieder bei Null beginnt.
... was natürlich Unsinn ist. Das ist jedoch noch lange
kein Grund, es nicht mit kühner Stirne, stozer Brust zu
behaupten.
Merke: Sachkunde ist einer lebhaften Diskussion durchaus
abträglich.
Egon D. schrieb:> ... was natürlich Unsinn ist. Das ist jedoch noch lange> kein Grund, es nicht mit kühner Stirne, stozer Brust zu> behaupten.
Dann schau dir doch mal die Verrenkungen an wenn du dir selbst einen
Zeitpunkt für ein Ereignis in der Zukunft setzen willst. Z.B. Daten an
einen Server melden in 3 Stunden. Und das, wenn der Überlauf dazwischen
liegt.
Eine interne Zeit die überläuft ist ein prinzipieller Designfehler.
Genauso ist es ein prinzipieller Designfehler dafür eine Zeit zu
verwenden die von aussen verstellt werden kann oder die Lokalzeit (die
auch eine Sommerzeit hat) zu verwenden.
Solche üblen Fehler zu erkennen trau ich dir nicht zu, zu erkennen. Da
fehlts dir an Weitblick, 50 Tage scheinen bei dir schon eine komplette
Überforderung zu sein.
> Merke: Sachkunde ist einer lebhaften Diskussion durchaus> abträglich.
Dann halt dich bitte auch dran.
Nick M. schrieb:> Dann schau dir doch mal die Verrenkungen an wenn du dir selbst einen> Zeitpunkt für ein Ereignis in der Zukunft setzen willst. Z.B. Daten an> einen Server melden in 3 Stunden. Und das, wenn der Überlauf dazwischen> liegt.
Die "Verrenkungen" hat Falk bereits vorgeführt. Sorry, wenn dich das
überfordert.
Falk B. schrieb:> If ((now - before) > DELTA_T)> {> ...> }
Nick M. schrieb:> Egon D. schrieb:>> ... was natürlich Unsinn ist. Das ist jedoch noch lange>> kein Grund, es nicht mit kühner Stirne, stozer Brust zu>> behaupten.>> Dann schau dir doch mal die Verrenkungen an [...]
Jaja, schon gut.
Du weisst natürlich alles besser -- nicht nur als ich,
sondern auch als alle anderen. In Ordnung. Nur weiter
so.
Egon D. schrieb:> Jaja, schon gut.>> Du weisst natürlich alles besser -- nicht nur als ich,> sondern auch als alle anderen. In Ordnung. Nur weiter> so.
Dann erklär mal auf die Schnelle was du machst, wenn das nächste
Ereignis in 2 Monaten sein soll.
Kannst du so weit denken? Nein. Aber klug daherreden. Das kannst du und
Wolfgang.
Falk B. schrieb:> Donner schrieb:>> Und so>> einen Fehĺer zu finden, der nur alle 52 Tage auftritt, ist schon sehr>> sehr schwierig.>> Good point!
Das musste auch Microsoft schon feststellen, die in ihre Win32 API
damals den gleichen Fehler eingebaut und in Windoww 95 selbst benutzt
hatten. Wer konnte auch damit rechnen, dass je einer einen Computer 50
Tage am Stück laufen lassen will? ;-)
Ach, diese ganzen "Problemchen" lassen sich mit ein bisschen Logik und
den Grundrechenarten erledigen.
Ich verstehe gar nicht wieso ihr euch dafür so angehen müsst.
Vielen dank für die nette Konversation. Ich denke ich werde einfach wie
früher in Bascom den Timer1 mir einfach so einstellen das er genau bei 1
Sekunde einen Interrupt hat. Die Aussagen hier sind hier sehr
unterschiedlich und bringen mich nicht wirklich weiter. Aber ich denke
persönlich ist die Funktion Millis für die meisten Anwendungen genau
genug wer es aber ganz genau will nimmt den Timer Interrupt.
Trotzdem allen einen großen Dank für die Hilfe
Arduino Fanboy D. schrieb:> Ach, diese ganzen "Problemchen" lassen sich mit ein bisschen Logik und> den Grundrechenarten erledigen.
Dann führ das doch mal vor.
Nimmt man uint64, dann ist plötzlich alles easy und entspannt:
1
if(now>=triggerTime){
2
doIt();
3
triggerTime=0;
4
}
Fertig. Man muss lediglich triggerTime löschen (oder DELTA_T). In dem
von euch so gelobten Beispielen muss man DELTA_T löschen und den Fall
berücksichtigen, dass DELATA_T 0 ist und dann NICHTS zu tun ist. Die
zusätzliche Falle entfällt bei mir.
Na ihr Schlauberger? Hab ihr es jetzt kapiert?
OK, die uptime genügt nur für 584 Jahre mit 1/1000 Sekunden. Aber so
lang wird wohl keine Hardware überleben.
Nick M. schrieb:> Egon D. schrieb:>> Jaja, schon gut.>>>> Du weisst natürlich alles besser -- nicht nur als>> ich, sondern auch als alle anderen. In Ordnung.>> Nur weiter so.>> Dann erklär mal auf die Schnelle was du machst,> wenn das nächste Ereignis in 2 Monaten sein soll.
Wie komme ich denn dazu?
Deine Behauptung war, dass sich der Timer-Wert nach
erfolgtem Überlauf nicht mehr sinnvoll auswerten lässt.
Diese Behauptung ist FALSCH . Diskussion beendet.
Nick M. schrieb:> Fertig. Man muss lediglich triggerTime löschen (oder DELTA_T). In dem> von euch so gelobten Beispielen muss man DELTA_T löschen und den Fall> berücksichtigen, dass DELATA_T 0 ist und dann NICHTS zu tun ist. Die> zusätzliche Falle entfällt bei mir.
MIST!
TriggerTime sollte man auf MAXUINT64 setzen, nicht Null.
Nick M. schrieb:> Dann führ das doch mal vor.> ....> Na ihr Schlauberger? Hab ihr es jetzt kapiert?
Nano, du hast ja richtig Schaum vorm Mund...
Haben deine Einlassungen irgendwas mit dem Problem des TO zu tun?
Arduino Fanboy D. schrieb:> Haben deine Einlassungen irgendwas mit dem Problem des TO zu tun?
Ja. Sie haben direkt was mit Punkt 1) des Ursprungspostings zu tun.
Ist das für dich zu schwer zu erkennen?
Nick M. schrieb:> Ja. Sie haben direkt was mit Punkt 1) des Ursprungspostings zu tun.> Ist das für dich zu schwer zu erkennen?
Ja!
Du siehst da offensichtlich Geister.
Hat Punkt 1 überhaupt mit dem Problem des TO zu tun, oder ist das eher
eine Nebelkerze, mit der er sich selbst täuscht?
Ich sehe nicht, dass er Intervalle größer 50 Tage nutzen möchte.
Bedenke:
Solange die Zeitintervalle kürzer, als die genannten 50 Tage, sind
kompensieren sich die Überläufe. (wenn man es richtig anstellt)
Donner schrieb:> So einen Fehler zu finden, der nur alle 52 Tage auftritt,> ist schon sehr sehr schwierig.Falk B. schrieb:> Good point!
Erinnert mich an meinen Drucker der gerade schon wieder seine
Konfiguration vergessen hat. Das macht er 2x pro Jahr und das nicht nur
bei mir. Vom HP Support bekommt man natürlich alle erdenklichen
Antworten dazu, nur keine hilfreiche.
Nick M. schrieb:> OK, die uptime genügt nur für 584 Jahre mit 1/1000 Sekunden. Aber so> lang wird wohl keine Hardware überleben.
640kB reichen für alle Zeiten ;-)
Falk B. schrieb:> 640kB reichen für alle Zeiten ;-)
Ich glaube, dass hatte jemand damals nur gesagt, um die Konkurrenz in
Sicherheit zu wiegen, die gerade an größeren PC arbeitete.
Ganz ähnlich auch die Aussage von angeblich Intel, dass mehr als 333 MHz
rein physikalisch unmöglich seien. Schon ein halbes Jahr später hatten
alle Intel-Inside Rechner im Handel bereits 500 MHz.
Sebastian schrieb:> früher in Bascom den Timer1 mir einfach so einstellen das er genau bei 1> Sekunde einen Interrupt hat.
Kann man machen, ist aber meistens unpraktisch. Nimm lieber 10ms oder
100ms, damit kann man auch andere Dinge erledigen, z.B. Updates von
Displays, Timerouts etc. 1s ist für einen Mikrocontroller eine EWIGKEIT!
https://www.mikrocontroller.net/articles/Multitasking#Verbesserter_Ansatz
Arduino Fanboy D. schrieb:> Hat Punkt 1 überhaupt mit dem Problem des TO zu tun, oder ist das eher> eine Nebelkerze, mit der er sich selbst täuscht?Das ist ein Punkt des TO Also ist es ein Problem des TO.
> Ich sehe nicht, dass er Intervalle größer 50 Tage nutzen möchte.
Ich sehe nicht, dass er nur Intervalle gleiner 50 Tg nutzen will.
Der Punkt ist aber, dass hier andauernd behauptet wird, wie elegant das
Problem doch gelöst werden kann.
Es geht eben nicht. Siehe dein folgendes Zitat:
> Bedenke:> Solange die Zeitintervalle kürzer, als die genannten 50 Tage, sind> kompensieren sich die Überläufe. (wenn man es richtig anstellt)
Eben, meine Rede. Aber hier gibt es genügend Leuchten denen das nicht
einleuchtet.
Ich hab beschrieben wie man das grundlegend richtig macht.
Arduino Fanboy D. schrieb:> Hat Punkt 1 überhaupt mit dem Problem des TO> zu tun,
Nein.
> oder ist das eher eine Nebelkerze,
"Nebelkerze" suggeriert Absicht; das sicher nicht.
> mit der er sich selbst täuscht?
Mir ist nicht klargeworden, was der TO eigentlich
glaubt:
a) Der Timer bleibt nach 50 Tagen stehen.
b) Der Timer-Wert ist in der Nähe des Überlaufes
nicht auswertbar.
a) ist Unsinn; das wissen wir.
b) ist auch Unsinn; das wissen alle außer Nick Müller.
Lediglich
c) Mit einem Timer, der 50 Tage Zählumfang hat,
lassen sich keine Intervalle erzeugen, die
länger als 50 Tage sind
ist richtig.
(Ich bilde mir zwar ein, dass die Grenze schon beim
halben Zählumfang liegt, bekomme aber die Herleitung
jetzt nicht zusammen. Mag mich also irren.)
> Ich sehe nicht, dass er Intervalle größer 50 Tage> nutzen möchte.
Korrekt; soweit ich mitbekommen habe, war davon keine
Rede.
Falk B. schrieb:> 640kB reichen für alle Zeiten ;-)
Hehe! :-) OK, der Punkt geht an dich, aber ich hab schon damit
gerechnet und daher die Jahre ausgerechnet.
Wenn man den Unsinn mal weiter spinnt, der Arduino hat schon einen 64
Bit Zähler, wenn gleich auf 2 Variablen aufgeteilt. Die kann man atomar
auslesen und auswerten.
wiring.c
1
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
2
// the overflow handler is called every 256 ticks.
Egon D. schrieb:> a) ist Unsinn; das wissen wir.>> b) ist auch Unsinn; das wissen alle außer Nick Müller.>> Lediglich>> c) Mit einem Timer, der 50 Tage Zählumfang hat,> lassen sich keine Intervalle erzeugen, die> länger als 50 Tage sind>> ist richtig.
Na also, damit hast du eben selbst zugegeben dass du nicht mit dem
Überlauf arbeiten kannst. Ausser unter bestimmten Voraussetzungen. Und
das ist halt der Punkt in dem sich Bastler von Profis unterscheiden.
Bastler können nur bis zu maximal 50 Tage weit denken.
Die Bastler sind namentlich:
Egon B., Arduino Fanboy und Wolfgang der sich zusätzlich durch seine
laute Klappe "auszeichnet".
Egon D. schrieb:> c) Mit einem Timer, der 50 Tage Zählumfang hat,> lassen sich keine Intervalle erzeugen, die> länger als 50 Tage sind>> ist richtig.>> (Ich bilde mir zwar ein, dass die Grenze schon beim> halben Zählumfang liegt, bekomme aber die Herleitung> jetzt nicht zusammen. Mag mich also irren.)
Einfach mal ein Beispiel aufschreiben, ggf. mit kleineren Zahlen.
8 Bit Zähler, 0-255.
Könnt ihr großen Meister auch noch die offene Frage beantworten und
nicht wieder elegant ignorieren:
Was macht ihr, wenn ein einmaliges Ereignis nach DELTA_T abgehandelt
wurde. Das ist der code dazu von euch der so jedenfalls nicht
funktioniert:
1
// Dieser Vergleich funktioniert auch beim Überlauf
2
If((now-before)>DELTA_T){
3
// DELTA_T Zeitdifferenz erreicht
4
foo();
5
// wann hätte der aktuelle Lauf sein sollen, auch wenn die
6
// restliche loop() mal wieder länger dauert (<1000ms)
7
bevor+=DELTA_T;// auch hier funktioniert der Überlauf
Falk B. schrieb:> Wenn man den Unsinn mal weiter spinnt, der Arduino hat schon einen 64> Bit Zähler, wenn gleich auf 2 Variablen aufgeteilt. Die kann man atomar> auslesen und auswerten.
Ich vermute das solltest du nochmal überdenken...
Ich sehe da keinen 64 Bit breiten Zähler.
Egal, wie man die die 32 Bit Variablen kombiniert, aber auf einen
"vernünftigen" 64 Bit ms Zähler kommt man da nicht.
Da muss man sich schon etwas mehr Mühe geben.
Nick M. schrieb:> Die Bastler sind namentlich:> Egon B., Arduino Fanboy und Wolfgang der sich zusätzlich durch seine> laute Klappe "auszeichnet".
Du hast ganz offensichtlich nicht die eingangs geschilderten Sorgen des
TO nicht verstanden.
Das macht mich zu einem Bastler, wenn du was nicht verstehst?
Das ist so irrational, dass ich mir ein Grinsen nicht verkneifen kann.
Nick M. schrieb:> Na also, damit hast du eben selbst zugegeben> dass du nicht mit dem Überlauf arbeiten kannst.
Ich glaube, Dir ist da ein kleiner Irrtum unterlaufen.
Ich habe gesagt, dass man mit einem Intervalltimer,
der einen maximalen Umfang von 50 Tagen hat, keine
Intervalle erzeugen kann, die länger als 50 Tage sind.
Von irgend einem Überlauf habe ich kein Sterbenswörtchen
gesagt. DU bist derjenige, der immer davon anfängt.
> Und das ist halt der Punkt in dem sich Bastler von> Profis unterscheiden.
Sicher.
Der Bastler nimmt einen Intervalltimer für kurze
Intervalle und einen Kalender für die langen.
Der Profi behauptet, ein paar Stunden ließen sich
NUR mittels 64 bit abmessen.
Doch, das kommt so hin.
Nick M. schrieb:> Könnt ihr großen Meister auch noch die offene Frage beantworten> und> nicht wieder elegant ignorieren:> Was macht ihr, wenn ein einmaliges Ereignis nach DELTA_T abgehandelt> wurde. Das ist der code dazu von euch der so jedenfalls nicht> funktioniert:> // Dieser Vergleich funktioniert auch beim Überlauf> If ((now - before) > DELTA_T) {> // DELTA_T Zeitdifferenz erreicht> foo();> // wann hätte der aktuelle Lauf sein sollen, auch wenn die> // restliche loop() mal wieder länger dauert (<1000ms)> bevor += DELTA_T; // auch hier funktioniert der Überlauf> }
Du wirst einen Status halten/einführen müssen.
Der klassische einfache endliche Automat.
Nick M. schrieb:> Könnt ihr großen Meister auch noch die offene Frage beantworten und> nicht wieder elegant ignorieren:> Was macht ihr, wenn ein einmaliges Ereignis nach DELTA_T abgehandelt> wurde.
Das war gar nicht die Frage. Aber auch das ist lösbar!
1
#define DATE_TIME 1402
2
uint8_tdate_once_en=1;
3
date_once=DATE_TIME;
4
5
....
6
7
now=millis();
8
9
// Dieser Vergleich funktioniert auch beim Überlauf
10
If(date_once_en&&(now-before)>date_once){
11
// DELTA_T Zeitdifferenz erreicht
12
foo();
13
date_once_en=0;
14
}
Und jetzt jammer bloß nicht rum, daß man dazu eine extra Variable
braucht! Deine 64Bit Zähler sind auch nicht kostenlos, dort steckt die
Variable vier mal drin!
Wer mit minimalen Arduinomitteln eine IT-Revolution starten will, macht
so oder so was falsch!
Arduino Fanboy D. schrieb:>> Wenn man den Unsinn mal weiter spinnt, der Arduino hat schon einen 64>> Bit Zähler, wenn gleich auf 2 Variablen aufgeteilt. Die kann man atomar>> auslesen und auswerten.>> Ich vermute das solltest du nochmal überdenken...> Ich sehe da keinen 64 Bit breiten Zähler.
Ich schon.
1
timer0_millis=m;
2
timer0_overflow_count++;
Das Ganze ist ein klassischer Zähler mit Festkommaarithmetik
basierend auf DDS bzw. Bresenham.
Egon D. schrieb:> Von irgend einem Überlauf habe ich kein Sterbenswörtchen> gesagt. DU bist derjenige, der immer davon anfängt.
Kurz zitiert:
Egon D. schrieb:> Die eine ist, eine... ähh... arg grenzwertige (für die> Schweiz: falsche) Aussage SO richtigzustellen, dass> jeder Leser weiss, was gemeint ist. Also etwa in der> Form: "Nein, der Zähler, den millis() abfragt, läuft> ewig und drei Tage, sofern der Controller so lange Saft> hat -- richtig ist aber, dass der Zähler nach 50 Tage> überläuft , also wieder von Null anfängt mit zählen."
Da hast du auch noch völlig normal argumentiert. Nur irgendwann sind bei
dir die Sicherungen durchgebrannt. Und dann wurde der Unsinn immer
größer.
Egon D. schrieb:> Der Profi behauptet, ein paar Stunden ließen sich> NUR mittels 64 bit abmessen.>> Doch, das kommt so hin.
Wo hast du die paar Stunden bloß her? Bist du nicht in der Lage so zu
programmieren, dass der Code nicht nur unter möglichst vielen
Randbedingungen funktioniert? Oder bist du halt einfach nur ein Bastler
der es gewohnt ist nur irgendwas irgendwie zum Laufen zu bringen?
Und dann versucht durch die fadenscheinigsten Argumente rauszureden.
Schämst du dich dafür nicht?
Falk B. schrieb:> Und jetzt jammer bloß nicht rum, daß man dazu eine extra Variable> braucht! Deine 64Bit Zähler sind auch nicht kostenlos, dort steckt die> Variable vier mal drin!
Keine Angst, ich weiß sogar, dass ein 64 Bit Zähler doppelt so viel
Platz braucht wie ein 32 Bit Zähler!
> Wer mit minimalen Arduinomitteln eine IT-Revolution starten will, macht> so oder so was falsch!
Neinnein, mir ging es darum, aufzuzeigen dass die vermeintlich so
einfache Lösung mit dem Überlauf doch nicht ganz so einfach ist. Denn
jetzt muss man, -wie du selbst aufgezeigt hast- noch ein flag setzen.
Und bitte nicht vergessen.
Meine Lösung ist jedenfalls einfacher und weitsichtiger und kann auch
Intervalle größer 50 Tage lösen.
Das hat nichts mit IT-Revolution zu tun. Das hat damit zu tun, dass
Bastler häuptsächlich Bastlerlösungen liefern und die bis ans blutige
Messer verteidigen. Und sich dabei für nichts zu blöd sind.
Carl D. schrieb:> Wenn man jetzt noch eine Kleinigkeit verbessert, dann hat man sogar> einen mittleren Abstand von 1000ms (in Rahmen der Taktgenauigkeit).> ...
Ich hatte das übrigens genauso gemeint. Ich würde es nur etwas anders
schreiben. Möglichst ohne define und ohne globale Variablen.
Hier sehe ich keinen Vorteil gegenüber der millis Abfrage. "flag_1ms"
ist nur ein Flag was irgendwann abgearbeitet wird. Genauso wie der
millis Vergleich der irgendwann abgearbeitet wird. In beiden Fällen weiß
niemand genau wann der Vergleich stattfindet, wenn die Hauptschleife aus
irgendwelchen Gründen mal kürzer oder länger benötigt. Alles unterliegt
dem gleichen Jitter. Ohne Jitter geht nur, wenn man es direkt im
Timerinterrupt erledigt.
Nick M. schrieb:> Egon D. schrieb:>> Von irgend einem Überlauf habe ich kein Sterbenswörtchen>> gesagt. DU bist derjenige, der immer davon anfängt.>> Kurz zitiert:>> Egon D. schrieb:>> Die eine ist, eine... ähh... arg grenzwertige (für die>> Schweiz: falsche) Aussage SO richtigzustellen, dass>> jeder Leser weiss, was gemeint ist. Also etwa in der>> Form: "Nein, der Zähler, den millis() abfragt, läuft>> ewig und drei Tage, sofern der Controller so lange Saft>> hat -- richtig ist aber, dass der Zähler nach 50 Tage>> überläuft , also wieder von Null anfängt mit zählen.">> Da hast du auch noch völlig normal argumentiert.
Weil ich da versucht habe, einen Gesprächspartner, der
auch normal argumentiert hat, darauf hinzuweisen, dass
seine Antwort zwar sachlich richtig ist, für den
Gesprächsverlauf aber nicht sonderlich förderlich.
> Nur irgendwann sind bei dir die Sicherungen> durchgebrannt. Und dann wurde der Unsinn immer> größer.
Nun ja, dann such' doch mal den ersten Beitrag heraus,
bei dem meine Sicherung (angeblich) durchgebrannt ist,
und ZITIERE diesen hier vollständig . Dann können
wir weiter darüber diskutieren, falls Dir daran liegt.
> Egon D. schrieb:>> Der Profi behauptet, ein paar Stunden ließen sich>> NUR mittels 64 bit abmessen.>>>> Doch, das kommt so hin.>> Wo hast du die paar Stunden bloß her?
Du wirst es kaum glauben: Aus einem Beitrag des TO.
> Bist du nicht in der Lage [...]
Würde es Dir etwas ausmachen, Dich nicht in Spekulationen
über meine Fähigkeiten zu ergehen, sondern auf das zu
antworten, was tatsächlich geschrieben wurde ?
Vielen Dank im Voraus.
Nick M. schrieb:> Meine Lösung ist jedenfalls einfacher und weitsichtiger und kann auch> Intervalle größer 50 Tage lösen.
Ja, kann sie, braucht aber keiner, schon gar nicht der OP. Es muss nicht
immer die ultimative, endlos skalierbare Lösung sein, es darf auch mal
deutlich einfacher sein, der verringerte Aufwand rechtfertigt die
Grenzen.
> Das hat nichts mit IT-Revolution zu tun. Das hat damit zu tun, dass> Bastler häuptsächlich Bastlerlösungen liefern und die bis ans blutige> Messer verteidigen. Und sich dabei für nichts zu blöd sind.
Ich bin einer der Letzten, die aoffensichtlichen MURKS gutheißen würden!
Aber einfache Lösungen sind OK. Und der Vorschlag mit dem RICHTIGEN
Vergleich ist so eine!
Ich finde es nur lustig, wie Nick sich aus den "der Zähler läuft alle 50
Tage über" einen Anwendungsfall wie folgt konstruiert:
"Aber wenn du Ereignisse in 60 Tagen haben willst, na wie machst du das?
Na? Na? Immernoch nicht? Bist du so doof? Schau mal, ich weiß das, das
macht man so. Na? Klingelt's jetzt?"
Nick, ich unterstelle dir ja, dass du mit dem Hammer eine Schraube in
die Gipswand kriegst. Und sogar, dass dir klar ist, dass entweder ein
Schraubenzieher oder ein Nagel dafür die bessere Lösung ist.
Es wäre aber durchaus hilfreich, wenn du anderen nicht unterstellen
würdest, dass sie ausschließlich mit Hammer und Schrauben arbeiten.
Danke.
Veit D. schrieb:> Hier sehe ich keinen Vorteil gegenüber der millis Abfrage.
Ich schon, und nicht nur was den Sleep Mode angeht.
U.a., daß man nicht immer mit dem 32 Bit Zähler hantieren muss. Das
bringt zwar die CPU nicht um, aber auch keine Vorteile.
Die millis() Methode ist nur ein Arduinogewächs.
Außerdem kann man mit dem Flag zur Echtzeit prüfen, ob das Timing noch
stimmt, siehe Artikel Multitasking.
Egon D. schrieb:> Weil ich da versucht habe, einen Gesprächspartner, der> auch normal argumentiert hat, darauf hinzuweisen, dass> seine Antwort zwar sachlich richtig ist, für den> Gesprächsverlauf aber nicht sonderlich förderlich.
Ich hab mehr davon zitiert:
Egon D. schrieb:> Wolfgang schrieb:>>> Sebastian schrieb:>>> 1. Millis startet bei Strom bzw. Reset und läuft>>> knapp 50 Tage>>>> Gleich die erste Annahme ist falsch. Millis() läuft,>> bis du dem µC wieder den Strom abklemmst oder einen>> Reset auslöst.>> Nun ja, es gibt immer zwei Möglichkeiten.
Du wolltest also sagen, dass Wolfgang normal argumentiert hat? Dir ist
doch selbst aufgefallen, dass er blanken Unsinnschreibt. Wie gesagt, das
war alles in Ordnung mit dir.
Hier geht es los:
Egon D. schrieb:>> Das nennt sich Überlauf. Der TO hat das etwas schlampig>> beschrieben aber dennoch verwertbar. Denn nach 50 Tagen>> ist die Zahl nicht mehr sinnvoll auswertbar weil sie>> wieder bei Null beginnt.>> ... was natürlich Unsinn ist. Das ist jedoch noch lange> kein Grund, es nicht mit kühner Stirne, stozer Brust zu> behaupten.> Merke: Sachkunde ist einer lebhaften Diskussion durchaus> abträglich.
Du hast ja inzwischen selbst zugegeben, dass man selbst mit
Berücksichtigung des Überlaufs nicht richtig arbeiten kann. Und wie
sich die Verfechter des einfachen Überlaufs selbst bewiesen haben, es
doch nicht ganz so einfach ist.
Egon D. schrieb:>> Wo hast du die paar Stunden bloß her?>> Du wirst es kaum glauben: Aus einem Beitrag des TO.
Interessant. Hilft aber nichts weiter. Denn ich hab zum wiederholten
Male gesagt, dass das mit dem Überlauf nicht richtig klappt. Der TO hat
erst später gesagt er braucht nur Stunden als Intervall. Das ändert aber
nichts daran, dass die Berücksichtigung des Überlaufs keine
ordentliche Lösung ist. Sondern wieder nur ein Gebastle für den einen
Fall.
Egon D. schrieb:>> Bist du nicht in der Lage [...]>> Würde es Dir etwas ausmachen, Dich nicht in Spekulationen> über meine Fähigkeiten zu ergehen, sondern auf das zu> antworten, was tatsächlich geschrieben wurde ?
Macht mir nichts aus. Du bist es der Bastlerlösungen verteitigt. Also
bist du ein Bastler. Nirgend hast du gesagt, dass meine Lösung richtig
ist und einfach ist. Nein, du hast sie immer wieder angegriffen. ->
Bastler.
Falk B. schrieb:> Ich schon.> timer0_millis = m;> timer0_overflow_count++;>> Das Ganze ist ein klassischer Zähler mit Festkommaarithmetik> basierend auf DDS bzw. Bresenham.
timer0_overflow_count++; zählt die Überläufe, welche mit ca 980Hz
auftreten.
timer0_millis hält einen korrigierten Wert, die ms
Beide zählen recht synchron hoch.
Daraus baust du keinen 64 Bit Zähler.
Muss ich dir den Beweis liefern?
OK, dann hier, auf einem UNO:
Falk B. schrieb:> Veit D. schrieb:>> Hier sehe ich keinen Vorteil gegenüber der millis Abfrage.>> Ich schon, und nicht nur was den Sleep Mode angeht.> U.a., daß man nicht immer mit dem 32 Bit Zähler hantieren muss. Das> bringt zwar die CPU nicht um, aber auch keine Vorteile.> Die millis() Methode ist nur ein Arduinogewächs.> Außerdem kann man mit dem Flag zur Echtzeit prüfen, ob das Timing noch> stimmt, siehe Artikel Multitasking.
Ja gut, wenn es spezialisiert zu geht gibts immer andere Lösungen.
Der Nachteil von den Timer Flags ist, man benötigt für jedes Intervall
ein zusätzliches Flag was man sich basteln muss. Mit millis ändert man
einfach den Wert von "interval".
Ich sage mal so. Jedes Problem bekommt seine eigene Lösung.
Funktionieren muss es. Mehr wird nicht verlangt. :-)
S. R. schrieb:> Ich finde es nur lustig, wie Nick sich aus den "der Zähler läuft alle 50> Tage über" einen Anwendungsfall wie folgt konstruiert:
Ich finde es weitaus witziger, wie man sich auf so starrsinnige Art und
Weise einer ordentlichen, weitsichtigen und allgemein gültigen und
funktionerenden Methode entziehen kann.
Man überlegt sich das einmal richtig, macht es ab dann immer so und
ist vor Überraschungen gefeit.
Die hier so vehement propagierte Methode ist -wie ihr sogar selbst schon
festgestellt habt- gefährlich (selbst Microsoft ist schon drauf
reingefallen).
Mir ist es absolut schleierhaft wie jemand der sich Softwareentwickler
nennt sich so penetrant einer ordentlichen Lösung verweigert.
Für mich sind solche Leute einfach nur Bastler. Bastler und Pfuscher die
ihr Zeug nur hinfummeln und froh sind wenns irgendwie läuft.
Liegt vielleicht auch an der Plattform.
Nick M. schrieb:> Für mich sind solche Leute einfach nur Bastler. Bastler und Pfuscher die> ihr Zeug nur hinfummeln und froh sind wenns irgendwie läuft.> Liegt vielleicht auch an der Plattform.
Der erfolgreiche Bastler kommt mit 32 Bit aus, wenn die Intervalle unter
49,x Tage bleiben.
Der geniale Profi nimmt immer 64 Bit. Egal ob das überflüssig ist. Das
kümmert ihn nicht.
Arduino Fanboy D. schrieb:> Der erfolgreiche Bastler kommt mit 32 Bit aus, wenn die Intervalle unter> 49,x Tage bleiben.
Bis er dann mal aus Versehen ein längeres Intervall braucht und sich
dann wundert. Oder sich wundert, dass das immer wieder kommt.
Und dann kratzt er sich am Kopf, erinnert sich an diesen Thread und sagt
dann: Aber die Experten haben doch alle gesagt, dass das richtig
funktioniert wenn man nur den Überlauf richtig behandelt.
Würd er nur etwas weiter lesen, hätte er schon gemerkt, dass das nur die
halbe Wahrheit ist. Denn er braucht noch ein zusätzliches Flag das er
setzen und löschen muss um überhaupt ein Intervall richtig behandeln
zu können. Wenn er das vergisst, kommt das nämlich spätestens nach 40
Tagen wieder. Obwohl er doch alles richtig gemacht hat.
Ohne es zu wissen, hat er also ein wiederholendes Ereignis gesetzt.
Merkst du es vieleicht jetzt, was das für Hobby-Lösungen sind die ihr
hier propagiert?
Es tut mir leid, aber ich muss mich jetzt aus dem thread ausklinken. Ich
hab es oft genug und ausführlich erklärt.
Ich wünsch euch in eurer Bastler-Blase noch viel Erfolg.
Nick M. schrieb:> Man überlegt sich das einmal richtig, macht es ab> dann immer so und ist vor Überraschungen gefeit.
Das klingt weniger nach ordentlichem Ingeneurswesen, sondern nach
Zwangsstörungen.
Ich mein, du isst ja auch nicht jeden Tag exakt das gleiche, oder etwa
doch? Oder gehörst du zu den Menschen, die jeden Tag pünktlich auf die
Sekunde im Büro erscheinen und dieses pünktlich auf die Sekunde auch
wieder verlassen?
Mir gefallen einigermaßen an das Problem angepasste Lösungen
grundsätzlich besser als Universallösungen, denn letztere haben auch
ihre Schwächen.
Zudem habe ich mal gelernt, dass man diese Schwächen nicht mehr
wahrnimmt, wenn man angefangen hat, eine gute Lösung als "dat ham'wa
imma schon so jemacht" anzusehen. Das wird vor allem dann relevant, wenn
sich die Probleme ändern.
Arduino Fanboy D. schrieb:>> Das Ganze ist ein klassischer Zähler mit Festkommaarithmetik>> basierend auf DDS bzw. Bresenham.>> timer0_overflow_count++; zählt die Überläufe, welche mit ca 980Hz> auftreten.> timer0_millis hält einen korrigierten Wert, die ms
Ja, mein Fehler, da wahr wohl etwas Wunschdenken im Spiel! 8-0
Ich hab die drei Variablen im Überflug als einen Zähler betrachet, es
sind aber nur die ersten beiden verknüpft.
Falk B. schrieb:> Ja, mein Fehler, da wahr wohl etwas Wunschdenken im Spiel! 8-0
Eine positive Bewertung von mir, wegen zugeben eines Irrtums.
Wäre eigentlich nicht erwähnenswert.
.. aber in diesem Forum ist einiges "anders" ...
Ich habe leider nur den immer längerer werdenden Thread überflogen und
es möglich, daß mein Vorschlag Schnee von gestern ist. Ich würde es
eigentlich anders planen. Zuerst einmal eine Rekapitulierung vom Arduino
Default Setup:
Das Arduino Framework konfiguriert ja bekanntlich immer automatisch
TIMER0 als Zeitbasis einschließlich der millis() Funktion. Dieser TIMER0
wird durch die spezifische Vorteilereinstellung im 976Hz Zyklus
getaktet. Millis() wird durch clevere Code-Maßnahmen so genau wie
möglich an 1.000ms angenähert um bei Abfragen als globale Zeitbasis
dienen zu können. Da TIMER0 auch für PWM Zwecke mitverwendet werden
soll, mußte man auf CTC verzichten und den TIMER0 im 976Hz Rhythmus frei
laufen lassen und ist deshalb so nicht direkt im 1.000ms Rhytmus für
andere Zwecke brauchbar. Die millis() Methode hat jedoch viele Nachteile
wesegen sie ich lieber nicht für solche Aufgaben verwenden würde.
Stattdessen könnte nun alternativ aber auf millis() ganz verzichten und
mit TIMER2 eine genau im 1ms Zyklus arbeitende Zeitbasis im CTC Modus
erstellen, die dann bei jeden CTC Interrupt eine FW Uhr im Linux
Datetime Format mit exakter T2 1ms Genauigkeit unterhält. Dadurch wird
die Langzeitgenauigkeit nur von der Quarzgenauigkeit des 16MHz
Oszillators beeinflußt.
In diesem Interrupt macht man auch die Alarmtests und setzt dann globale
Flags die dann im nächsten Loop durchlauf einfach abgearbeitet werden
können und nach Erfüllung der Aufgabe wieder zurückgesetzt werden. Auf
diese Weise hat man eine unabhängige Softwareuhr die zuverlässig im
Hintergrund ihre Aufgabe erfüllt. Die durch die Flag und Loopdurchgänge
auftretenden im us-ms Bereich verursachten Verzögerungen sind für seine
Zwecke vernachlässigbare Jittereffekte die man bei Zeitauflösung im
Sekundentakt meist ignorieren kann. Addierende Zeitfehler gibt es mit
diesem Konzept nicht solange die T2 ISR kurz gehalten ist.
Ich würde es nun so machen:
Eine LONG DATETIME Variable die das LINUX UTC Zeitformat verwendet und
vom T2
CTC Timer im Sekundentakt hochgezählt wird. Das wird wegen des
unvermeidlichen Überlaufs bis 2037 funktionieren und das geht auch Linux
BS so. Helfer-Routinen konvertieren diese Zahl in menschlich praktisches
HHMMSS YYYYMMD Format. Alle Alarmzeitvergleiche werden nativ
abgearbeitet um den Overhead der normalen Zeitformate zu vermeiden. Es
ist ja viel einfacher mit Integerzahlen zu operieren. Umwandlung vom
Linux Datetimefomat werden mit entsprechenden Umwandlungsroutinen
gemacht die nur dann aufgerufen werden wenn es zur Eingabe oder Ausgabe
notwendig ist. Da stört auch deren Komplexität nicht.
Systemzeitberechnungen laufen alle einfach und schnell im Integerformat.
Durch die Flagbefehle kann auch nichts vergessen werden.
Die ganze User Interface Seite kann nun nicht-kritisch in jeder
denkbaren Weise verwirklicht werden. Die Alarmzeiten kann man dann im
SRAM oder EEPROM speichern.
Man kann auch eine DS3231 RTC verwenden um periodisch die Systemzeit zu
synchronisieren. Dadurch könnte auch ein Stromausfall keinen Schaden
anrichten weil beim Wiederanlauf einfach die Linuxzeitvariable nach
Daten vom RTC gesetzt wird.
Die NANO Klonen die mir zur Verfügung stehen haben typisch eine
Laufgenauigkeit unter 1 Minute pro Tag. Deshalb ist eine RTC wie der
DS3231 empfehlenswert.
Alle zeitaufwendigen Aufgaben die die Loopdurchgangszeit vergrößern
könnten, mit State machines verwirklichen um die Loopdurchgänge kurz
gestalten. Durch diese Architektur entkoppelt man zeitkritische Vorgänge
und der uC kann seine Aufgaben im eigenen Zeitmasstab abarbeiten und
wird nicht in eine Zwangsjacke gesteckt. Man muß so etwas natürlich
planen. Am Ende hat man dann aber eine robuste Lösung die durch nichts
gestört werden kann. Auch Stasis des Hauptloopdurchgangs bringt wegen
der T2 ISR die Zeitrechnung nicht ausser Tritt. Nur ein uC Reset kann
das.
Die Programmentscheidungen kann mit so einem Konzept statisch durch
Arithmetik bestimmen und Fehler können bei korrekten Testausdrücken
überhaupt nicht entstehen da die Zustandsmaschine nur von Arithmetik
gesteuert wird und zeitmässig vollkommen entkoppelt ist.
Es hört sich kompliziert an, ist es aber nicht wirklich. Ich mache
langsame Sachen meist so weil ich dem uC so viel Freizügigkeit erlauben
möchte wie möglich und Optimierungen sind auf diese Weise fast nie
notwendig.
Hallo,
es wird sicherlich unendliche Lösungen für unendlich viele Aufgaben
geben. Fakt ist jedoch, dass die millis Genauigkeit in 99% der Fälle für
irgendwelche zyklischen Tasterabfragen und Led Blinkanzeigen völlig
ausreichend ist. Dafür ist millis sehr einfach und praktikabel nutzbar.
Wer höhere Genauigkeit benötigt greift sich einen freien Timer oder
macht sich einen Timer frei. Wie gesagt, alles bekommt seine eigene
Lösung.
Hi
Sorry, aber wenn doch "millis" wie eine Variable beeinflußbar ist, dann
versteh ich das Problem nicht.
If millis > 1000 then
Inc Sek_Count
Millis = millis-1000
end if
Ist jetzt nicht grad eine Sprache, soll ja nur das Prinzip aufzeigen. So
wie nun Sekunden gezählt werden, können Minuten, Stunden und Tage,
Wochen und Jahre folgen. Das Problem, das Millis nicht immer bei 1000
erfaßt werden, erledigt sich, weil ja ein Überlauf wieder auf den
Anfangswert drauf addiert wird. So dauert halt mal eine Sekunde 1060
mSek und die nächste dann vielleicht nur 950. Im Mittel paßt das aber.
Wenn das irgendwo bereits geschrieben war, ok, ich hab nicht alles bis
ins Detail gelesen.
Gruß oldmax
Martin V. schrieb:> Hi> Sorry, aber wenn doch "millis" wie eine Variable beeinflußbar ist,
NEIN! millis() liefert den internen 32 Bit Zähler, welcher die Anzahl
der Millisekunden seit dem Reset zählt. Der normale Arduinoanwender
kennt den Namen der Variablen nicht, soll er auch nicht. Nur der
"Fortgeschrittene"
kennt den und KÖNNTE die Variable auch schreiben. Das ist aber im
Konzept des Arduino-Frameworks nicht vorgesehen. Es kann sein, daß das
auch unerwünschte Nebenwirkungen auf andere Softwareteile hat, welche
auch millis() verwenden.
> versteh ich das Problem nicht.
Das ist dein Problem ;-)
Hi
Falk B. schrieb:> Das ist dein Problem ;-)
Nein, ich verwende den Arduino nicht und auch nicht "C". Aber trotzdem
danke für die Aufklärung.
Wenn das so ist, das ich eine Funktion oder was auch immer habe, die mir
millis liefert, mit denen ich nix anfangen kann, sorry, wozu brauch ich
das dann? Um erst ein kompliziertes Konzept um diese millis-Funktion zu
schreiben? Wahnsinn... Respekt.
Gruß oldmax
Martin V. schrieb:> Wenn das so ist, das ich eine Funktion oder was auch immer habe, die mir> millis liefert, mit denen ich nix anfangen kann,
Wer sagt das?
millis() erfüllt seinen Job.
Wo ist dein Problem damit?
Mache es konkret!
Martin V. schrieb:> Wenn das so ist, das ich eine Funktion oder was auch immer habe, die mir> millis liefert, mit denen ich nix anfangen kann, sorry, wozu brauch ich> das dann?
Keiner zwingt dich dazu, das Arduino Framework zu benutzen. Wenn du
damit nichts anfangen kannst, dann lass es halt bleiben. Alles andere
wäre dumm.
Also wenn man immer genau 1 Sek haben will geht das mit Millis nicht
weil
starttime=0
if (millis()-starttime >=1000) keiner weiß ob diese Überprüfung bei
genau 1000ms geschieht
sek++;
starttime=millis(); startwert wird wieder auf null gesetzt deswegen kann
man so die Gesamtzeit nicht erfassen hier mußte dann vorher
oldstarttime= starttime am anfang stehen so das man später darauf
zurückgreifen kann und die wirkliche Zeit korrigieren kann
Martin V. schrieb:> Nein, ich verwende den Arduino nicht und auch nicht "C". Aber trotzdem> danke für die Aufklärung.> Wenn das so ist, das ich eine Funktion oder was auch immer habe, die mir> millis liefert, mit denen ich nix anfangen kann, sorry, wozu brauch ich> das dann?
Bist du so dumm oder tust du nur so?
> Um erst ein kompliziertes Konzept um diese millis-Funktion zu> schreiben?
Schon wieder nix geblickt? Die Funktion millis() gibt es schon, die muss
keiner programmieren.
> Wahnsinn... Respekt.> Gruß oldmax
Jaja, geh mit deinem BASCOM spielen und sei glücklich.
Denn seelig sind, die da geistig arm sind, denn ihrer ist das
Himmelreich. AMEN!
Hi
Falk B. schrieb:> Jaja, geh mit deinem BASCOM spielen und sei glücklich.
In keinem meiner Beiträge habe ich jemals erwähnt, das ich mit BASCOM
programmiere. Diese Sprache hat aber durchaus eine Daseinsberechtigung.
Ich nutze sie nur nicht.
Falk B. schrieb:> Schon wieder nix geblickt? Die Funktion millis() gibt es schon, die muss> keiner programmieren.
Niemand will eine vorhandene Funktion schreiben, aber wenn ich ein
umfangreiches Programmkonstrukt erstellen muß, um aus dieser Funktion
ein erwünschtes Zeitraster zu erhalten, taugt diese Funktion dafür
nicht, oder der Ansatz ist falsch.
Mag sein, das ich von "C" keine Ahnung hab, aber wenn ich es mal
(wieder) mit einer Pseudo-Sprache (kein BASCOM) verdeutlichen darf:
Liefert mir die Funktion einen Zählerstand, so ist doch die Differenz
leicht auszuwerten.
Anfangs setze ich einen Zaehler_Alt auf das Ergebnis der Funktion
Millis. In meiner Programmschleife frage ich dann wie folgt
If Zaehler_Alt+1000<Millis then
Inc Zeitraster (Sekunden)
Zaehler_Alt= Zaehler_Alt-1000
end if
Die Auswertung bei Überlauf von Millis und weitere Zeitraster wie
Minuten, Stunden etc. überlasse ich euch gern.
Ich glaub, eine gleichwertige "C" Programmierung wird nicht größer sein
und bekommt ihr auch aus diesem Vorschlag gebastelt.
Falk B. schrieb:> Bist du so dumm oder tust du nur so?
Nun, deine unhöfliche Entgleisung schreibe ich mal der Belastung durch
die Pandemie zu. Ich denke schon, das du als Experte einen solchen
Tonfall nicht standartmäßig draufhast, aber wenn ich mich irre und du
auch nur einer der zahlreichen Marktschreier bist, dann tu ich dir den
Gefallen und fühle ich mich halt mal ein wenig beleidigt.
Gruß oldmax
Sebastian schrieb:> starttime=millis(); startwert wird wieder auf null gesetzt deswegen kann> man so die Gesamtzeit nicht erfassen hier mußte dann vorher
Man muss nicht unbedingt den nicht funktionierenden Weg gehen.
Wenn man die Gesamtzeit richtig erfassen möchte, muss man den neuen Wert
für starttime genau um 1000 gegenüber dem alten erhöhen und nicht noch
die (unbekannte) Abfrageverzögerung als Fehler einbauen.
Martin V. schrieb:> If Zaehler_Alt+1000<Millis then
Das funktioniert so nicht, wenn bei Zaehler_Alt+1000 ein Überlauf
auftritt. Die richtige Lösung wurde oben schon lange gepostet.
Martin V. schrieb:> Die Auswertung bei Überlauf von Millis ..... überlasse ich euch gern.
Danke, für nichts.
Das schöne ist, solange man keine Intervalle größer 49,x Tage braucht,
muss man nix "Überlauf auswerten".
Es sei denn, man machst es so wie du:
> If Zaehler_Alt+1000<Millis then
1. Dann fällt man halt mal auf die Fresse, beim Überlauf.
2. Oder man backt ihm eine (unnötige) Extrawurst.
Das darf jeder gerne für sich selber entscheiden.
Sind aber beide recht falsch.
Hi
Arduino Fanboy D. schrieb:> 1. Dann fällt man halt mal auf die Fresse, beim Überlauf.
Noch so ein Corona- Geschädigter. Davor aber noch darauf hinweisen, das
ich sehrwohl mit einem Überlauf rechne. G'scheiter gehts wirklich nicht.
Leute, laßt mal die Kirche im Dorf. Wenn ich solch eine Aufgabe lösen
soll, mach ich das garantiert nicht in "C" und auch nicht auf einem
Arduino. Spielt doch mit was ihr wollt, aber lernt auch mal etwas
Nettikette. Soll manchmal auch im realen Leben etwas hilfreich sein.
Gruß oldmax
Martin V. schrieb:> Davor aber noch darauf hinweisen, das> ich sehrwohl mit einem Überlauf rechne.
Das sieht man aber in deinem Beispiel nicht.
Denn das fällt genau in den Topf.
Und von daher ist es ein ganz schlechtes Beispiel, wenn man millis()
verteufeln will.
Der hinkende Vergleich:
Es ist eher nicht die Schuld des Brotmessers, oder des Herstellers des
Brotmessers, wenn du dich zu dumm anstellst, und dich damit in die
Fingerchen schneidest.