Hallo , ich habe meine Code fast fertig, mit delay geht auch alles. nun will ich aber in bestimmten fällen 2 sachen gleichzeitig schalten und nicht im delay hängen. mit if ((hilfausloesen == 1) && (currentMillis - previousMillis) <= magzeit) komme ich im loop in meine schleife, aber das ist ja nicht was ich will. in dem fall oben komme ich ja nur alle (magnetzeit) in die schleife Ich möchte dass im loop die Bedingung immer wahr ist solange wie die magnetzeit ist . Also angenommen die magnetzeit ost 100ms dann soll die bedinung 100ms wahr sein. . while will ich nicht verwenden weil ich dann ja wieder festhänge. hat da jemand einen lösungsvorschlag? Nach 3 stunden googlen dachte ich frag hier mal.
:
Gesperrt durch Moderator
Code-Übermittlung in Prosa ist scheisse. Zeige dein Programm und versuche nochmal genauer zu beschreiben was du wann erreichen willst. Beachte: längere Code (als eine Bildschirmseite) als Anhang posten.
ich möchte mit millis eine funktion eine zeit ausführen, mehr eigentlich nicht. z.b. führe 1000ms ein befehl aus. Eigentlich das selbe wie delay macht nur ohne festhängen.
pascal schrieb: > Eigentlich das selbe wie delay macht nur ohne festhängen. Dann setze beim Start eine Variable auf den Startzeitpunkt und frage in deiner Hauptschleife immer ab, ob die aktuelle Zeit minus der Startzeit größer als die Dauer ist. Wenn das der Fall ist, ist dein "Delay" abgelaufen.
pascal schrieb: > z.b. führe 1000ms ein befehl aus. Willst du, dass der Befehl 1s "dauert" oder dass während der 1s "andauernd" der selbe Befehl wiederholt wird? > Eigentlich das selbe wie delay macht nur ohne festhängen. Im Ernst: du musst einfach nochmal ein wenig über die Möglichkeiten der Abfrage von millis() nachdenken. "Ein wenig" kann schon mal 1-2 Tage dauern. Aber millis() wird dein Problem lösen. Wenn ich eine Schleife hätte und während 1s irgendwas ausführen wollte, dann würde ich mir die Startzeit merken:
1 | if (startknopf_gedrueckt()) |
2 | startzeit = millis(); |
und dann prüfen, ob die aktuelle Zeit schon 1s weiter ist. Ist die aktuelle Zeit kleiner als startzeit+1000ms, dann tue ich das, was für eine Sekunde zu tun ist:
1 | if (millis() < startzeit+1000) |
2 | tu_das_was_eine_sekunde_lang_zu_tun_ist(); |
Und weil bei dieser Abfrage das übliche Überlaufproblem passieren kann, stelle ich die Rechung um, dass das nicht mehr passiert:
1 | void loop() { |
2 | if (startknopf_gedrueckt()) |
3 | startzeit = millis(); |
4 | |
5 | if (millis()-startzeit < 1000) |
6 | tu_das_was_eine_sekunde_lang_zu_tun_ist(); |
7 | }
|
Wenn du konkrete Hilfe willst, dann poste genau den Code, der dir
Probleme bereitet. Nicht nur Ausschnitte, wo nichts nirgends passt:
> magzeit .... magnetzeit
Was jetzt?
Und wie gesagt: ruhig mal 1-2 Tage über die Verwendung von millis()
nachdenken. Sonst hast du laufend solch simple Probleme damit.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > if (millis() < startzeit+1000) So geht's nicht ... Spätestens nach einem Überlauf des millis()-Zählers geht dies Art der Abfrage gnadenlos schief und man sucht sich einen Wolf. Beitrag "Re: Arduino frage zu Serial.print"
pascal schrieb: > nun will ich aber in bestimmten fällen 2 sachen gleichzeitig schalten > und nicht im delay hängen. Schonmal Richtung RTOS geschaut? Ein Scheduler hilft dir hier und entzerrt dein Programm. In der Zeit des Delay kannst schonmal andere Sachen machen. Wenn es sehr präzise sein muss, dann wäre ein Timer Interrupt von Vorteil, welcher natürlich unabhängig läuft. > mit > if ((hilfausloesen == 1) && (currentMillis - previousMillis) <= magzeit) Bei diesem Denglisch-Konstrukt bekomme ich aber auch Denkprobleme ;-)
Wolfgang schrieb: > Lothar M. schrieb: >> if (millis() < startzeit+1000) > > So geht's nicht ... > > Spätestens nach einem Überlauf des millis()-Zählers geht dies Art der > Abfrage gnadenlos schief und man sucht sich einen Wolf. Aber als uint32 geht zB ((millis() - Start) < 1000)
Wolfgang schrieb: > So geht's nicht ... Genaus das habe ich zum Glück sofort gleich im Satz danach geschrieben. Und einen Hinweis zum Nachdenken über das "übliche Überlaufproblem" geliefert. > So geht's nicht ... Lustigerweise "geht's" so doch. Aber es "spinnt" halt mal alle paar Tage. Vielen ist das "gut genug".
Lothar M. schrieb: >> So geht's nicht ... > Lustigerweise "geht's" so doch. Aber es "spinnt" halt mal alle paar > Tage. Vielen ist das "gut genug". Ohje ... Ich will daran glauben können, dass für einen Aufzug oder PKW alle Kriterien der Sicherheit eingehalten wurden und solche Konstrukte dort nicht existieren ... :-)
Lothar M. schrieb: > Genaus das habe ich zum Glück sofort gleich im Satz danach > geschrieben. Dann schreib solchen Unfug gar nicht erst als Programmzeile hin. Das Konstrukt funktioniert nämlich genau nicht. Grund ist, dass du in C nicht die Menge der ganzen Zahlen zur Verfügung hast. > Aber es "spinnt" halt mal alle paar Tage. Genau solche Software braucht die Welt nicht. Das meinte ich mit "man sucht sich einen Wolf". Mth schrieb: > Aber als uint32 geht zB ((millis() - Start) < 1000) Genau das steht im verlinkten Post, danke.
Wolfgang schrieb: > Dann schreib solchen Unfug gar nicht erst als Programmzeile hin. Ich vertraue darauf, dass einer nicht völlig verblödet die erstbeste Codezeile kopiert, die er im Internet findet, sondern wenigstens den Text drumrum anschaut. Und wenn er sowas trotzdem ohne Verständnis und unkontrolliert tut, dann darf er sich von mir aus ruhig den Wolf suchen. Vielleicht lernt er es auf diese Art. Und wenn nicht, dann liegt das eigentliche Problem nicht daran, dass diese Zeile dort steht. Das war die Ansage zum Freitag. > Das Konstrukt funktioniert nämlich genau nicht. Grund ist, dass du in C > nicht die Menge der ganzen Zahlen zur Verfügung hast. Und deshalb ein unsigned long verwendet wird und damit der millis() Timer nach 2**32 ms = 49 Tagen überläuft. Und genau dann gibt es ein Problem, denn nach millis() == 4294967296 kommt eine Millisekunde später millis() == 0. Die Suche zu den Stichworten "millis" und "49 Tage" bringt dann auch ein Füllhorn an Informationen: https://www.google.com/search?q=millis+49+tage
Zwei statemachines die hintereinander laufen (in einer Mainloop) wäre die Lösung die dem ursprünglichen Ansatz am nächsten kommen. Edit: Kann man natürlich in zwei Tasks zerlegen, jede eine state machine und die zwei tasks werden in der mainloop aufgerufen.
Dann mach es halt so:
1 | // constants won't change. Used here to set a pin number:
|
2 | const int ledPin = LED_BUILTIN;// the number of the LED pin |
3 | |
4 | // Variables will change:
|
5 | int ledState = LOW; // ledState used to set the LED |
6 | |
7 | // Generally, you should use "unsigned long" for variables that hold time
|
8 | // The value will quickly become too large for an int to store
|
9 | unsigned long previousMillis = 0; // will store last time LED was updated |
10 | |
11 | // constants won't change:
|
12 | const long interval = 1000; // interval at which to blink (milliseconds) |
13 | |
14 | void setup() { |
15 | // set the digital pin as output:
|
16 | pinMode(ledPin, OUTPUT); |
17 | }
|
18 | |
19 | void loop() { |
20 | // here is where you'd put code that needs to be running all the time.
|
21 | |
22 | // check to see if it's time to blink the LED; that is, if the difference
|
23 | // between the current time and last time you blinked the LED is bigger than
|
24 | // the interval at which you want to blink the LED.
|
25 | unsigned long currentMillis = millis(); |
26 | |
27 | if (currentMillis - previousMillis >= interval) { |
28 | // save the last time you blinked the LED
|
29 | previousMillis = currentMillis; |
30 | |
31 | // if the LED is off turn it on and vice-versa:
|
32 | if (ledState == LOW) { |
33 | ledState = HIGH; |
34 | } else { |
35 | ledState = LOW; |
36 | }
|
37 | |
38 | // set the LED with the ledState of the variable:
|
39 | digitalWrite(ledPin, ledState); |
40 | }
|
41 | }
|
:
Bearbeitet durch User
Philipp G. schrieb: > Dann mach es halt so: Wie soll dieser kommentarlos dahinkopierte Code dem TO helfen? Dieses Beispiel findet man zigfach an jeder Ecke des Internets. Wenigstens die Quelle hättest du noch nennen können: https://learn.adafruit.com/multi-tasking-the-arduino-part-1/using-millis-for-timing
:
Bearbeitet durch Moderator
Philipp G. schrieb: > // if the LED is off turn it on and vice-versa: > if (ledState == LOW) { > ledState = HIGH; > } else { > ledState = LOW; > } Sowas finde ich immer irgendwie unfassbar, unfasslich... ledState = not ledState;
https://learn.adafruit.com/multi-tasking-the-arduino-part-1/using-millis-for-timing und Folgende: scheduler with millis() oder Beitrag "Wartezeiten effektiv (Scheduler)" https://www.mikrocontroller.net/articles/AVR_Softwarepool
:
Bearbeitet durch User
Arduino Fanboy D. schrieb: > Sowas finde ich immer irgendwie unfassbar, unfasslich... > > ledState = not ledState; Wobei sicher schon viele die Erfahrung gemacht haben, dass man nach einigen Jahren denkt: Was ist das, was hast Du da gemacht?* Wenn man da den notwendigen Kommentar anhaengt, kann man es auch gleich so schreiben: > if (ledState == LOW) { ... Das erschliesst sich ohne Kommentar. wendelsberg *mich selbst ausdruecklich eingeschlossen
Lothar M. schrieb: > Und genau dann gibt es ein Problem, denn nach millis() == 4294967296 > kommt eine Millisekunde später millis() == 0. Wenn man es richtig formuliert, gibt es eben kein Problem, solange die Zeitdifferenz nicht zu groß wird - auch nicht beim Überlauf des millis()-Zählers.
Arduino Fanboy D. schrieb: > Philipp G. schrieb: >> // if the LED is off turn it on and vice-versa: >> if (ledState == LOW) { >> ledState = HIGH; >> } else { >> ledState = LOW; >> } > Sowas finde ich immer irgendwie unfassbar, unfasslich... > > ledState = not ledState; Was du vorschlägst kann man bei einer Boolschen Variablen machen, aber nicht bei einer Definition, die du nicht unter deiner Kontrolle hast. In Arduino.h ist LOW und HIGH wie folgt definiert: #define HIGH 0x1 #define LOW 0x0 Mit 'int ledState' ergibt dein Vorschlag beim Wechsel LOW->HIGH ein ledState = 0xFFFF, und damit würde eine möglicherweise im Code nachfolgende Abfrage auf 'if (ledState == HIGH') nicht mehr funktionieren. So ein Fehler ist auch nicht mehr auf den ersten Blick erkennbar.
Kollege schrieb: > Was du vorschlägst kann man bei einer Boolschen Variablen machen, aber > nicht bei einer Definition, die du nicht unter deiner Kontrolle hast. Ja so ist er, der Fanboy. Bringt die wildesten C++ Ausdrücke daher (ich meine jetzt nicht unbedingt diesen not Operanden) und wirft sie den Arduino-Anfängern vor die noch keine einzige Zeile C-Code erfolgreich geschrieben haben. Beispiele dafür hab ich gesehen sonst würde ich nicht so daher reden. Sehr einfühlsam und didaktisch wertvoll. Aber Hauptsache: besser Wissen, protzen, ich bin ich ....
ich würde so oft man Zeit brauch diesen abschnitt immer in eine beschreibende Funktion kopieren.. das macht die Sache übersichtlicher. z.B.: https://pastebin.com/2RU4GKyS
wendelsberg schrieb: > kann man es auch gleich so schreiben: Interessant! Du bist der Erste, welcher mir sagen möchte, dass Verzweigungsblöcke leichter zu lesen sind, als Zuweisungen. In meiner kleinen Welt, gehören "Verschachtelungstiefen" zu den bösen Dingen. Je tiefer, und je komplizierter die Bedingung, desto böser. Sogar exponentiell zunehmend böse.
Kollege schrieb: > Mit 'int ledState' ergibt dein Vorschlag beim Wechsel LOW->HIGH ein > ledState = 0xFFFF, und damit würde eine möglicherweise im Code > nachfolgende Abfrage auf 'if (ledState == HIGH') nicht mehr > funktionieren. So ein Fehler ist auch nicht mehr auf den ersten Blick > erkennbar. Iss klar. Da hasste aber einen schönen Traum. Vielleicht mal nachschauen, was der not Operator so tut. Und was die impliziten Casts so machen. Beides sollte man schon wissen, wenn man andere kritisiert, denke ich mal. Kollege schrieb: > Was du vorschlägst kann man bei einer Boolschen Variablen machen, aber > nicht bei einer Definition, die du nicht unter deiner Kontrolle hast. In einem hast du recht! Wenn man eine Variabel hat, welche nur 2 Zustände kennt, sollte man sie zu einem bool machen. Das wäre konsequent, aber nicht unbedingt nötig, in C hat das ja schließlich auch ca 30 Jahre so geklappt.
Ich hatte ein ähnliches Problem. Hab das über ein Timer gelöst. In deinen Fall : Beim Start der Schleife = Timer.on Einziger Befehl des Timers = Timer.off (bei mir noch eine Varible umschalten da ich den Status den Timers nicht abfragen konnte). Mag vielleicht ein wenig ungenau sein. Aber diese Ungenauigkeit kann man wenn man muss logisch berechnen und angleichen. Mich haben 3-4 millis mehr oder weniger nicht gejuckt.
Wolfgang schrieb: > Wenn man es richtig formuliert, gibt es eben kein Problem, solange die > Zeitdifferenz nicht zu groß wird Welche "nicht zu große" Zeit würde dir da so vorschweben? Ich biete 49kommaeinpaarzerquetschte Tage. Mehr kann man mit dieser "millis()-startzeit > dauer" Methode nicht erreichen, weil dann ja die "dauer" nicht mehr in einem unsigned long Platz hat. Allerdings ist das auch ein arg fraglicher Ansatz, wenn jemand mit einem Millisekundentimer etwas verwaltet, das länger als einen Monat braucht...
Lothar M. schrieb: > Allerdings ist das auch ein arg fraglicher Ansatz, wenn jemand mit einem > Millisekundentimer etwas verwaltet, das länger als einen Monat > braucht... na und. Dann muss man nur an der richtigen Stelle die "Rücksetzung" berücksichtigen. Auch nicht so weltbewegend.
Nachtrag : Solange man keine Operationen hat die länger als die genannten 49 Tage dauert macht man das ganz einfach. Man legt sich eine public-Variable Zeit an. Nun einfach die Variable mit den akt. millis-wert füllen. Bei der nächsten Abfrage einfach vorher fragen ob millis kleiner sind als der aktuelle Wert. Einzige Fehlerquelle. Wenn die nächste Abfrage > 49 Tage ist. Falls das eintritt sollte man vielleicht 3 Euro opfern und sich ein Uhr-Modul kaufen. ;)
Schlaumaier schrieb: > Dann muss man nur an der richtigen Stelle die "Rücksetzung" > berücksichtigen. Welche "Rücksetzung" denn? Und an welcher Stelle? Zeig das mal mit einer LED, die per millis() im 100-Tage-Takt "blinkt", also 50 Tage on und 50 Tage off. 50 Tage = 50*24*60*60*1000 ms = 4320000000 ms = 0x1017DF800 ms Schlaumaier schrieb: > Man legt sich eine public-Variable Zeit an. Nun einfach die Variable mit > den akt. millis-wert füllen. Bei der nächsten Abfrage einfach vorher > fragen ob millis kleiner sind als der aktuelle Wert. Welcher "aktuelle Wert" ist hier gemeint?
:
Bearbeitet durch Moderator
If millis > alt_millis then ' hier ist die Rücksetzung ' Wenn Millis "überlaufen fangen sie wieder bei 0 an". end if alt_millis = millis Fertig. Muss halt nur in jede Abfrage rein oder durch einen sehr großzügig dimensionierten Timer erfolgen. Wo ist das Problem ???
Hier wurde der Käse mit dem uint32 doch schon durchgekaut. Beitrag "Sekunden,Minuten zählen mit der Funktion Millis()" Das ist broken by design, egal wie oft man es ignorieren will. Arduino halt. Mit uint64 ist das erledigt für die nächsten 584 Jahre. Einmal ordentlich drüber nachgedacht und danach muss man nie wieder irgendwelche Fallstricke beachten. OK, ausser man plant ausserplanetarische Reisen.
Schlaumaier schrieb: > If millis > alt_millis then > ' hier ist die Rücksetzung > ' Wenn Millis "überlaufen fangen sie wieder bei 0 an". > end if > alt_millis = millis Fehler im code. Zu spät gesehen es muss heissen. If millis < alt_millis then KLEINER. Weil der Wert ja bei 0 neu startet nach den 49 Tagen.
Nick M. schrieb: > Mit uint64 ist das erledigt für die nächsten 584 Jahre. Da hast du 1. noch einen argen Rechenfehler drin. Ich komme auf annähernd 590 Millionen Jahre. Und 2. kann man mit solchen völlig unpassenden und von Hilflosigkeit zeugenden Datentypen einen 8-Bit-Rechner ganz schön in die Knie zwingen. Schlaumaier schrieb: > Wo ist das Problem ??? Das Problem ist, dass man es einfach mal kapieren muss, dass diese ganze "Verwaltung" schon die Vergleichsrechnung "millis-startzeit" so nebenher mitmacht:
1 | if (millis() - startzeit > dauer) { |
2 | zeitdauer_abgelaufen(); |
3 | }
|
Das geht gut solange dauer maximal 0xffffffff = 49,7 Tage ist. Da braucht man keine zusätzlichen Vergleich auf einen millis()-Überlauf samt Sonderbehandlung. Und es ist auch schnurzegal, ob millis() bei der Zuweisung der an die startzeit 0xffffffff oder 0x00000000 war.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Da hast du 1. noch einen argen Rechenfehler drin. Ich komme auf > annähernd 590 Millionen Jahre. Oh, mit Brille: Ich auch. > Und 2. kann man mit solchen völlig unpassenden und von Hilflosigkeit > zeugenden Datentypen einen 8-Bit-Rechner ganz schön in die Knie zwingen. Passend ist er wohl schon, weil das Problem dann weg ist. Hilflos ist eher die Diskussion hier und im verlinkten Thread. Und der Rechenaufwand ist verglichen mit uint32 nicht so immens größer, da Überläufe in die oberen 32 Bit nur alle 50 Tage auftreten. Es geht hier nur um ein +1. Ein bisschen weiter zu denken hilft also auch hier. if (millis() - startzeit > dauer) { zeitdauer_abgelaufen(); } Der Ansatz ist halt auch nicht wirklich schlau. Rechne die Zeit aus, wenn sie abgelaufen ist und mach dann: if (uin64ticker <= targetTime) ... Aber diskutiert ruhig weiter ... :-)
Lothar M. schrieb: > if (millis() - startzeit > dauer) { > zeitdauer_abgelaufen(); > } Millis = 10.000 Startzeit = 1000 Dauer = 500 > if (millis() - startzeit > dauer) { if 10.000 - 1000 > 500 then 'Gut - solange millis nicht überläuft end if '************************* Millis = 100 ' gerade übergelaufen Startzeit = 1000 Dauer = 500 if 100 - 1000 > 500 then ' Startzeit NICHT Abgelaufen ' grund : Millis ist viel zu klein gegenüber Startzeit, ergo gibt es fast immer ein - Wert und da Dauer im + ist ....... end if Das würde im Endeffekt bedeutet dein Prg. spinnt nach den 49 Tagen.
Schlaumaier schrieb: > Das würde im Endeffekt bedeutet dein Prg. spinnt nach den 49 Tagen. Nein! Solange die interval Zeit kleiner als 49 Tage ist, läuft das sauber durch. Alle Überläufe werden zur genau der richtigen Zeit durch Unterläufe kompensiert. Es ist ok, wenn du und auch von Nick M. (muellernick) das nicht verstehen wollen. Und wenn man wirklich Intervalzeiten größer als 49 Tage benötigt, muss man eben eine Extrawurst backen. Aber meist, reichen die 32 Bit völlig aus.
1 | uint64_t wideMillis() |
2 | {
|
3 | union
|
4 | {
|
5 | struct
|
6 | {
|
7 | uint32_t lo; |
8 | uint32_t hi; |
9 | };
|
10 | uint64_t zeit; |
11 | } static daten; |
12 | uint32_t jetzt = millis(); |
13 | if(jetzt < daten.lo) daten.hi++; |
14 | daten.lo = jetzt; |
15 | return daten.zeit; |
16 | }
|
Die Funktion geht von einem stetig wachsenden millis() Wert aus. Den dürfte man in der Praxis immer so haben.
Schlaumaier schrieb: > Das würde im Endeffekt bedeutet dein Prg. spinnt nach den 49 Tagen. Denk nochmal drüber nach. du Schlaumaier schrieb: > ' grund : Millis ist viel zu klein gegenüber Startzeit Nein, der Grund ist der, dass die Zeitdauer, die du abfragen wolltest ja schon ewig vorbei ist und die Reaktion darauf schon lange stattgefunden hat und somit eigentlich in der Vergangenheit und vergessen ist. Das ist so, wie wenn du dieses Jahr einen Zettel schreibst: "am 22.01. Brot kaufen!" und du findest den Zettel nächstes Jahr wieder. Dann kaufst du am 23.01. Brot, obwohl du eigentlich keines brauchst. Du musst den Zettel nach dem Einkaufen also vernichten. Oder die Jahreszahl dazuschreiben. Und genau das selbe musst du mit der Bearbeitung von solchen Aktionen natürlich auch machen. Wenn du die Startzeit einfach unverändert lässt, dann klappert es natürlich nach 49 Tagen. Muss ja.
:
Bearbeitet durch Moderator
Arduino Fanboy D. schrieb: > Es ist ok, wenn du und auch von Nick M. (muellernick) das nicht > verstehen wollen. Da haut einer arg aufs Blech ... > Und wenn man wirklich Intervalzeiten größer als 49 Tage benötigt, muss > man eben eine Extrawurst backen. und führt dann uint64 ein. Und denkt, er ist schlau wie Harry! Wisch dir doch die Kagge aus dem Gesicht!
Lothar M. schrieb: > Zeig das mal mit einer LED, die per millis() im 100-Tage-Takt "blinkt", > also 50 Tage on und 50 Tage off. > 50 Tage = 50*24*60*60*1000 ms = 4320000000 ms = 0x1017DF800 ms
1 | //#include "INTERVAL.h"
|
2 | |
3 | const byte LED = LED_BUILTIN; |
4 | |
5 | |
6 | uint64_t wideMillis() |
7 | {
|
8 | union
|
9 | {
|
10 | struct
|
11 | {
|
12 | uint32_t hi; |
13 | uint32_t merker; |
14 | };
|
15 | uint64_t zeit; |
16 | } static daten; |
17 | uint32_t jetzt {millis()}; |
18 | if(jetzt < daten.merker) |
19 | {
|
20 | daten.hi++; |
21 | }
|
22 | daten.merker = jetzt; |
23 | return daten.zeit; |
24 | }
|
25 | |
26 | //// ----------------------------------
|
27 | uint64_t zeitmerker; |
28 | const uint64_t interval = 4320000000ULL; |
29 | |
30 | void setup() |
31 | {
|
32 | pinMode(LED,OUTPUT); |
33 | }
|
34 | |
35 | void loop() |
36 | {
|
37 | if(wideMillis()-zeitmerker > interval) |
38 | {
|
39 | digitalWrite(LED,!digitalRead(LED)); |
40 | zeitmerker += interval; |
41 | }
|
42 | }
|
Nick M. schrieb: > und führt dann uint64 ein. Richtig! Und zwar genau dann, wenn es nötig ist! Keine Sekunde vorher.
Arduino Fanboy D. schrieb: > if(wideMillis()-zeitmerker > interval) Und hier auch wieder: Eine unnötige Rechenoperation, aber jammern wie langsam uint64 sei. Rechne einmal aus zu welchen Zeitpunkt das nächste Ereignis ist (nextEvent = now + interval) und überprüf mit: if (wideMilli() >= nextEvent) Jämmerlich.
Arduino Fanboy D. schrieb: > Und zwar genau dann, wenn es nötig ist! > Keine Sekunde vorher. Genau das gleiche macht die Addition schon für dich (hab ih oben schon geschrieben). Wenn es keinen Überlauf gibt, ist die Addition beendet. Schön dass du genau das nachstellst. Fans sind schon reichlich verblendet!
pascal schrieb: > komme ich im loop in meine schleife, ... > ... > Also angenommen die magnetzeit ost 100ms dann soll die bedinung 100ms > wahr sein. > > Nach 3 stunden googlen dachte ich frag hier mal. Du schreibst derart wirr, daß unsereiner nicht versteht, was du denn eigentlich machen willst. Ich mache mal ein paar Annahmen: 1. du willst deinen Programmablauf nicht mit elend langen Warteschleifen konstruieren. OK, das ist löblich, denn dann kann dein µC in der Zwischenzeit etwas anderes machen. 2. Du hast irgend einen Magneten, der offenbar so um die 100 ms angesteuert werden sollte und dann wieder auszuschalten ist. 3. aus irgend einem sonstigen Grunde ergibt sich gelegentlich, daß dieser Magnet einzuschalten ist, danach soll er dann nach Ablauf der o.g. Zeit wieder ausgeschaltet werden. 4. in der Zwischenzeit willst du tatsächlich mit deinem µC noch etwas anderes tun. Ist das so korrekt dargestellt? Wenn ja, dann empfehle ich dir, deine Firmware ereignisgesteuert aufzubauen. 1. Dazu richtest du dir erst mal eine Systemuhr ein. So alle 1ms oder 10 ms sollten ausreichen, ist aber nach deinem Gusto. 2. Als zweites richtest du dir eine Liste ein, die zu erledigende Arbeiten und deren Zeitpunkt speichern kann. Der Zeitpunkt kann als unsigned long gemacht werden, der die Millisekunden des Tages zählt und die zu erledigende Arbeit kann durch irgend etwas (irgend ein Kenner, ein Byte, ein Word oder so) gemacht werden. Diese Liste braucht nicht lang zu sein, nur soviele Einträge, wie du an Vorhaben brauchst. 3. Du schreibst dir eine kleine Routine zum Eintragen eines Vorhabens in diese Liste. Die kriegt dann 2 Argumente: was zu tun ist und um wieviel Millisekunden in der Zukunft es zu tun ist. Daraus macht sie einen Eintrag in obiger Liste mit dem Kenner was zu tun ist und aktuelle Uhrzeit plus zu wartende Millisekunden. 4. Deine ISR der Systemuhr sieht die obige Liste durch und guckt, ob da etwas dabei ist, wo die Zeit grad abgelaufen ist. Wenn sie etwas findet, dann schreibt sie die Aktion was zu tun ist in eine Ereigniswarteschlange (ein simpler Ringpuffer) und löscht den EIntrag in obiger Liste. 5. deine Grundschleife in main testet immer wieder, ob in der Ereigniswarteschlange etwas drinsteht - und wenn ja, dann holt sie es heraus und startet die betreffende Aktion gemäß dem Kenner. So. Sowas ist ein Konzept, mit dem man Aktionen in seiner Firmware zeitlich planbar realisieren kann UND zugleich keinerlei Warteschleifen oder anderes blockierendes Zeugs benötigt. Das Ganze ist auch viel einfacher und übersichtlicher als ein echtes RTOS. W.S.
Lothar M. schrieb: > Und genau das selbe musst du mit der Bearbeitung von solchen Aktionen > natürlich auch machen. Wenn du die Startzeit einfach unverändert lässt, > dann klappert es natürlich nach 49 Tagen. Muss ja. Ja im Prinzip schon. Nur nicht wenn zwischen der Startzeit und der Abfrageroutine ein Überlauf von Millis vorkommt und dadurch mills genullt werden. ;) Je kleiner die Laufzeit desso geringer die Gefahr. Aber frei nach "Murphys Gesetz" .... es passiert. Und man wundert sich warum. Um das Problem zu lösen musst du nur einfach eine Abfrage extra machen. Ich persönlich würde das über eine Funktion lösen. If millis <= Startzeit then dort einfach die Startzeit neu berechnen und dann normal durch das Prg. end if
Nick M. schrieb: > Fans sind schon reichlich verblendet! Nick M. schrieb: > Jämmerlich. Nick M. schrieb: > Wisch dir > doch die Kagge aus dem Gesicht! Der arme muellernick .... Da argumentiert er hier rum, für seine 64 Bit, die man sowieso nie nicht braucht. Keiner interessiert sich für den Quatsch, bzw. stimmt ihm zu.... Dann kann er nicht anders, dann muss er persönlich werden, bis zu Beleidigungen. Naja.. Eigentlich ist es ja schön wenn er für sich eine Lösung gefunden hat. Aber dieses dogmatische dulle und verblendete Priestertum, das nervt etwas. Erinnert mich irgendwie an die Erlebniswelt des Don Quichotte. ------------- Und jetzt zu den fachlichen Dingen. millis umbauen oder einen 64Bit Zähler einzubauen, in den Arduino Core, dauert ca 5 Minuten! Das ist also keine Hürde. Die Hürde ist: Man wird zum restlichen Arduino Universum inkompatibel. Wieder etwas persönlicher: Es kann natürlich sein, dass dir das Arduino Universum am Arsch vorbei geht.. Dann ist das allerdings gar nicht deine Baustelle. Also: Gehe woanders Kaggen, da wo es mehr Sinn macht. Alternative Sichtweise: In diesem Thread dreht es sich um millis() und nicht um deine Kagge. Übrigens: Der Vorschlag wurde, von mir, zur Kenntnis genommen und abgelehnt. Seit dem ist dein Verhalten das eines trotzigen Kindes, welches seinen Lieblingslutscher nicht bekommt.
Schlaumaier schrieb: > Um das Problem zu lösen musst du nur einfach eine Abfrage extra machen. > Ich persönlich würde das über eine Funktion lösen. Nein. Was hast du an unsigned int nicht verstanden? Nimm dir einen passenderen Nick und vergiss dein Basic. leo
Schlaumaier schrieb: > Je kleiner die Laufzeit desso geringer die Gefahr. Aber frei nach > "Murphys Gesetz" .... es passiert. Und man wundert sich warum. Nach 49 Tagen gibts einen Überlauf... Na und? Wenn die Interval Zeit kleiner ist, gibts auch keinen "Murphy". Denn dann tuts das, immer, Jahre lang, ohne jeden Aussetzer. > while(not stromausfall) allesGut();
Arduino Fanboy D. schrieb: > Da argumentiert er hier rum, für seine 64 Bit, die man sowieso nie nicht > braucht. Hast du doch selbst verwendet. Hmm ... Zumindest bist du in der Lage eine uint64 Addition fast so schnell wie jeder Compiler nachzuprogrammieren. Toll! Aber wie man die Vergleiche ordentlich macht hast du bis jetzt noch nicht kapiert. Aber das erklärt dann folgendes besser: Arduino Fanboy D. schrieb: > Die Hürde ist: Man wird zum restlichen Arduino Universum inkompatibel. Ist schon gut wenn man verbissen an schlechten Dingen festhält. Das gibt ein Gefühl der Sicherheit. Dir! Mir nicht! Aber leider stimmt das mit dem inkompatibel nicht. Der Überlauf den du behandelst wird nie passieren, ist also nur toter code. Lediglich aufpassen muss man, dass man uint64 verwendet. Aber das würde spätestens ein lint dir schon sagen. Kurz: Du hast schon wieder nicht zu Ende gedacht. Arduino Fanboy D. schrieb: > Seit dem ist dein Verhalten das eines trotzigen Kindes, welches seinen > Lieblingslutscher nicht bekommt. Fachlich kommt jetzt garnichts mehr von dir?
Schlaumaier schrieb: > Ja im Prinzip schon. Und zwar im Prinzip immer. > Nur nicht wenn zwischen der Startzeit und der Abfrageroutine ein > Überlauf von Millis vorkommt und dadurch mills genullt werden. ;) Doch, natürlich. Wegen der unsigned-Arithmetik geht das gut. Denn dann ist im Extremfall die startzeit = 0xffffffff und millis = 0 und somit die Rechnung (millis() - Startzeit) also 0 - 0xffffffff was unsigned gerechnet völlig korrekt wieder 1 ergibt, was genau der dazwischen vergangenen 1ms entspricht.
:
Bearbeitet durch Moderator
Nick M. schrieb: > Hast du doch selbst verwendet. Hmm ... Als "Notlösung"... Ein Einzelfall. Aber DAS kapierst du ja nicht, dass man eine 64Bit Epoche in aller Regel gar nicht benötigt. Nick M. schrieb: > man uint64 verwendet millis() wird an einigen Ecken des Frameworks und der Libraries verwendet. Es ist schlicht unmöglich die 64Bit weltweit durchzusetzen. Darum: Du hast schon wieder nicht zu Ende gedacht. Nick M. schrieb: > Fachlich kommt jetzt garnichts mehr von dir? Was soll da noch kommen! Das "Problem" ist so primitiv, und die Lösungen so naiv, da kann man nichts mehr zu sagen. Es wurde alles gesagt. Vielleicht noch nicht von jedem, aber das wird schon noch.
Arduino Fanboy D. schrieb: > dass man eine 64Bit Epoche in aller Regel gar nicht benötigt. Schon 40 Bit reichen für 256* 49 Tage und mit mit den resultierenden 35 Jahren mit hoher Wahrscheinlichkeit länger als die Schaltung leben wird.
Arduino Fanboy D. schrieb: > Es ist schlicht unmöglich die 64Bit weltweit durchzusetzen. > Darum: Du hast schon wieder nicht zu Ende gedacht. Das war der Designer der Plattform, nicht ich. Aber der ist wohl dein Gott. Deinen Nickname hast du dir schließlich selbst gewählt. Arduino Fanboy D. schrieb: > Was soll da noch kommen! Nichts mehr. Sinnvolles ist von dir auch schon lange nichts mehr gekommen. Schade, aber auch typisch für die Plattform.
Nick M. schrieb: > Das war der Designer der Plattform, nicht ich. Häää... du nörgelst doch die ganze Zeit. Ich bin da der falsche Partner, das hast du schon erkannt, aber noch nicht in der Tiefe begriffen! Tipp: Wende dich an den Designer! Oder ändere es selber, der Arduino Core liegt öffentlich aus, editierbar. Wenn die Änderungen abgesegnet werden, hast du deinen Sieg errungen.
Arduino Fanboy D. schrieb: > Oder ändere es selber, der Arduino Core liegt öffentlich aus, > editierbar. Den Ruhm und die Ehre für dein int64-incrememt will ich dir nicht nehmem! :-))))
jo mei schrieb: > Zeige dein Programm Hast du leider nicht gemacht, schade. Das schränkt unsere Möglichkeiten, dir zu helfen, massiv ein. Du siehst dass hier heiß über alle möglichen Details diskutiert wird, nur nicht mehr über deinen konkreten Code. Wie denn auch? Nick M. schrieb: > Kann man natürlich in zwei Tasks zerlegen, jede eine state machine und > die zwei tasks werden in der mainloop aufgerufen. Das war meiner Meinung nach noch der beste Tipp. Ich habe einen Aufsatz dazu geschrieben, der hier wie der Deckel auf den Topf passt: http://stefanfrings.de/multithreading_arduino/index.html
Wenn man uin64_t nimmt dann aber auch gleich Mikrosekunden statt diesen ungenauen millis(). Läuft allerdings schon nach 500000 Jahren über und nicht erst nach 500 Millionen ... :) LG, Sebastian
Nick M. schrieb: > LOL! Mein Tip: Mach es nicht! :-)) Je, nun. Brauchte ich gerade (im Zusammenhang mit der Ermittlung des aktuellen Stromverbrauchs aus den Impulsen einer Stromzähler-Impuls-LED):
1 | static volatile uint64_t usbase; // Initialised to zero |
2 | static inline void timer1_ovf (void) { |
3 | usbase += 0x8000; |
4 | }
|
5 | ISR(TIMER1_OVF_vect) {timer1_ovf();} |
6 | static uint64_t micros (void) { |
7 | uint8_t oldSREG = SREG; |
8 | cli(); |
9 | uint16_t tcnt = TCNT1; |
10 | uint8_t tov = TIFR1&(1<<TOV1); // Has to happen strictly after accessing TCNTn |
11 | SREG = oldSREG; |
12 | uint64_t us = usbase + tcnt/2; |
13 | if (tov && tcnt<0xFFFF) us += 0x8000; // Pending timer_ovf processing for this TCNT not yet executed |
14 | return us; |
15 | }
|
16 | ...
|
17 | TCCR1A = 0; |
18 | TCCR1B = (1<<CS11); // Prescaler 8 -> 2 ticks per microsecond @ 16MHz |
19 | TCCR1C = 0; |
20 | TIMSK1 = (1<<TOIE1); // Overflow interrupt enable |
21 | ...
|
FWIW. LG, Sebastian PS: Stefan ⛄ F. schrieb: > Das war meiner Meinung nach noch der beste Tipp. Ich habe einen Aufsatz > dazu geschrieben, der hier wie der Deckel auf den Topf passt: > http://stefanfrings.de/multithreading_arduino/index.html Schön verständlich geschrieben, Stefan!
:
Bearbeitet durch User
Schlaumaier schrieb: > Millis = 100 ' gerade übergelaufen > Startzeit = 1000 > Dauer = 500 > > if 100 - 1000 > 500 then > ' Startzeit NICHT Abgelaufen > ' grund : Millis ist viel zu klein gegenüber Startzeit, ergo gibt es > fast immer ein - Wert und da Dauer im + ist ....... > > end if Guck dir einfach noch mal an, wie die Subtraktion von unsigned int läuft. Um die Sache auch für dich überschaubar zu gestalten, probier es dann einfach mal 8-Bit Größen und staune.
Wolfgang schrieb: > Um die Sache auch für dich überschaubar zu gestalten, probier es dann > einfach mal 8-Bit Größen und staune. Das Zauberwort lautet arithmetischer Überlauf und Modulo-Operation.
Nick M. schrieb: > Arduino Fanboy D. schrieb: >> Oder ändere es selber, der Arduino Core liegt öffentlich aus, >> editierbar. > > Den Ruhm und die Ehre für dein int64-incrememt will ich dir nicht > nehmem! :-)))) Mach die Welt besser! Dabei kannst du mir nichts nehmen. (Ganz im Gegenteil) Eins der Probleme ist, auch hier im Forum, dass die Nörgler nur nörgeln wollen. Sie wollen nicht verbessern, denn dann gäbs nix mehr zu nörgeln. Dass sich ein Nörgler selbst abschafft, damit ist eher nicht zu rechnen.
Arduino Fanboy D. schrieb: > dass die Nörgler nur nörgeln wollen. > Sie wollen nicht verbessern, denn dann gäbs nix mehr zu nörgeln. Du willst doch den uint32 um jeden Preis halten. Verbesserungsvorschläge gehen an dir vorbei. Beispiele: uint64 ist zu langsam, dann machst du aber bei jedem Vergleich eine unnötiges Subtrahieren. Dann "verbesserst" du die uint64-Arithmetik auf grandiose Art und Weise. Selbst die Tatsache dass es die Frage wohl einmal im Monat gibt, hält dich nicht davon ab dich an den Designfehler zu klammer. Google mal nach "Arduino millis". Da gehört schon eine gehörige Portion an Starrsinn dazu. Und nörgeln? Wenn du das so auffasst, dann verstehst du mich nicht. Aber ist mir auch egal, nachfragen müsstest du. Der 14 Beitrag, mein erster hier im thread wurde selbst von stefanus (Hört hört!) als bester Tip bezeichnet, während ihr euch an dem tollen millis() aufgeilt weil ihr wisst wie es als Sonderfall funktioniert. Aber zwei Minuspunkte hab ich dafür bekommen, also ist die Welt wieder in Ordnung! :-)) Ich weiß schon, warum mir der Arduino am Arsch vorbeiget. Es ist das Umfeld und dieses unsäglich verkrüppelte C++. Damit kommt dann ein Fanboy drauf, dass man ja auch 40 Bit Integer-Arithmetik bauen könnte. Hält mich aber nicht davon ab, den Leuten bissl die Augen zu öffnen und ihnen zu erklären wie man Sachen ordentlich löst.
Nick M. schrieb: > Du willst doch Nick M. schrieb: > an dir vorbei Nick M. schrieb: > dann machst du Nick M. schrieb: > "verbesserst" du die Nick M. schrieb: > hält dich nicht Nick M. schrieb: > Wenn du das so Nick M. schrieb: > du mich nicht Nick M. schrieb: > müsstest du. Nick M. schrieb: > während ihr euch Nick M. schrieb: > weil ihr wisst Merkst du was? --- Du hast deinen Lieblingsweg gefunden. Schön! Nutze ihn, behalte ihn. Ich gönne ihn dir! Nick M. schrieb: > Ich weiß schon, warum mir der Arduino am Arsch vorbeiget. Hab ich ja gesagt: Ist nicht deine Baustelle. Also? Schaum vorm Mund, wegen nix.
Arduino Fanboy D. schrieb: > Schaum vorm Mund, wegen nix. Ich Schaum? Ich hab eher den Eindruck, dass dein Zitatsgestammle vom Bauschaum im Mund kommt. Edit: Oder ist der Bauschaum gar im Kopf?
Nick M. schrieb: > dass dein Zitatsgestammle Da ist es wieder des dein, du, ihr usw. Das Gestammel, stammt übrigens von dir, habs nur etwas konzentriert. Habe die "Message" da raus operiert: Du bist mit dem Arduino millis Handling nicht zufrieden, es regt dich total auf... Obwohl du doch gar nix damit zu tun hast. Und der einzige, welcher sich gerade anbietet, bin ich. .. ok, auf "von Lothar M. (lkmiller) (Moderator) Benutzerseite" könntest du auch rumhacken... Ich weiß nicht ob er das Arduino "Konzept" liebt, aber eine "Billigung" glaube ich zu erkennen. Also, weitermachen! Wenn es dir Befriedigung verschafft..... Windmühlen gibt es genug.
Stefan ⛄ F. schrieb: > Muss das schon wieder sein Nick? Frag doch lieber den, der damit begonnen hat. Oder noch besser, erinnere dich an deine eigenen Worte. Und schreib den Fanboy auf die Liste mit dem Photo. :-)) Arduino Fanboy D. schrieb: > Nick M. schrieb: >> dass dein Zitatsgestammle > Da ist es wieder des dein, du, ihr usw. Sag bloß, du hast das nicht geschrieben. Auch ich könnte irgendeinen Text möglichst dumm zerhackstückelnd zitieren und dann behaupten dass es eine intelligente Antwort wäre. Jetzt ist es halt leider nur eine minderintelligente Antwort von dir geworden. Und glaub mir, ich kann beliebig lange auf jeden Schwachsinn von dir antworten. Ich muss dabei immer so lächeln.
Nick M. schrieb: > Und glaub mir, ich kann beliebig lange auf jeden Schwachsinn von dir > antworten. OK, das Angebot nehme ich an ... bin ja kooperativ ... manchmal. Merke: Du hast versagt! Hast dich nicht durchsetzen können. Looser!
Arduino Fanboy D. schrieb: > Merke: > Du hast versagt! > Hast dich nicht durchsetzen können. > Looser! Du solltest aber bitte nicht aus Facebook reinkopieren was dir geschickt wurde! Und lerne doch lieber wie man Loser schreibt.
Nick M. schrieb: > Und lerne doch lieber wie man Loser schreibt. Geil! Looooser! Wie auch immer, du hast versagt! Offensichtlich niemanden bekehren können. Tipp: Das ist ganz normal, wenn man auf fremder Leute Baustellen rum nörgelt. Quasi sogar fast der beste anzunehmende Fall.
Hier ist die Thematik ausführlich begandelt: https://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover
Arduino Fanboy D. schrieb: > Offensichtlich niemanden bekehren können. Mag sein. Hat aber primär was mit "fruchtbarer Boden" zu tun. Aber deine Beiträge um die Arduino Fanboys aufs mentale Abstellgleis zu stellen sind dafür um so wirkungsvoller.
Nick M. schrieb: > Hat aber primär was mit "fruchtbarer Boden" zu tun. "Ein Falschfahrer?" "Hunderte!" ;-)
Arduino Fanboy D. schrieb: > "Ein Falschfahrer?" > "Hunderte!" Ja, tragisch, kommt halt vor wenn die Arduino Fanboys Ausflug haben. Darwin regelt das.
Genau! Der letzte 64Bit, auf 8Bit Rechner, Krieger wird dahin siechen. Nachruf: Viel hat er genörgelt, aber nix geändert. Die arme Seele....
Lothar M. schrieb: > Schon 40 Bit reichen Leute!!!!! und Lothar!!! Wozu dieses aufgeregte Gekreische? Der nächste führt 128 Bit Integer ein, um auch den Untergang unserer Galaxis noch berechnen zu können. ALBERN!!! Ich bemühe mal meinen steinalten HP-Taschenrechner: 24 Stunden = 1440 Minuten = 89400 Sekunden = 86400000 ms Natürlich reicht ein beliebiger long bequem für mehrere Tage und wenn eine Systemuhr in der Firmware ordentlich funktioniert, dann setzt sie die Uhrzeit um Mitternacht auf 0 zurück - und wenn sie obendrein auch die Ablaufzeiten für vorgemerkte Ereignisse betreut, dann kann sie problemlos auch von diesen Ablaufzeiten um Mitternacht besagte 86400000 ms subtrahieren und fetig ist die Laube. Ihr alle habt zwar keinen Kaiser vorrätig, aber ihr streitet dennoch um dessen Bart. Fangt doch endlich mal an, rational zu denken. W.S.
W.S. schrieb: > Natürlich reicht ein beliebiger long Da kannst du auch "Hurz" ([c] H.P. Kerkele) statt long schreiben, das passt auch für alles.
W.S. schrieb: > Ich bemühe mal meinen steinalten HP-Taschenrechner: > 24 Stunden = 1440 Minuten = 89400 Sekunden = 86400000 ms Irgendwie kann dein steinalter HP nicht mehr sauber durch 1000 teilen. Edit: er kann 1440 nicht mit 60 multiplizieren.
:
Bearbeitet durch User
J. T. schrieb: > W.S. schrieb: >> Ich bemühe mal meinen steinalten HP-Taschenrechner: >> 24 Stunden = 1440 Minuten = 89400 Sekunden = 86400000 ms > > Irgendwie kann dein steinalter HP nicht mehr sauber durch 1000 teilen. > Edit: er kann 1440 nicht mit 60 multiplizieren. Im großen und ganzen, irgendwas stimmt da nicht :D
Arduino Fanboy D. schrieb: >
1 | //// ----------------------------------
|
2 | uint32_t zeitmerker; |
3 | const uint32_t interval = 1000UL; |
4 | |
5 | void setup() |
6 | {
|
7 | pinMode(LED,OUTPUT); |
8 | }
|
9 | |
10 | void loop() |
11 | {
|
12 | if(millis()-zeitmerker > interval) |
13 | {
|
14 | digitalWrite(LED,!digitalRead(LED)); |
15 | zeitmerker += interval; |
16 | }
|
17 | }
|
>
zu beachten ist in Zeile 15, daß nicht millis() gelesen wird. Damit wird
verhindert, daß das (hier) 1s-Raster wegen der Laufzeit des anderen
loop-Codes wegläuft. Ohne das wird die "Sekunde" immer größer als eine
Sekunde sein.
Vielleicht interessanter als die wöchentliche (tägliche) Frage, warum
das mit millis() funktioniert, wo es doch gar nicht sein kann, und ob
man sich wirklich merken muß, wie sich in C unsigned beim Überlauf
verhält.
:
Bearbeitet durch User
Bei meinen Arduino Sachen mache ich das immer so (stark vereinfacht). Für einfache Timer reicht das locker hin. Wenn es präzise sein muss, sollte aber ein Timerinterrupt mit externem Quarz genommen werden. void loop() { static uint16 timer = 0; if ( timer > 0 ) timer--; if ( TriggerBedingungFuerSchaltvorgang ) { SchalteEin(); timer = 50; //entspricht 1s bei 20ms Taskraster } if (timer == 1) { SchalteAus(); } //um ein genaueres Zeitraster zu bekommen, sollte //hier nicht stumpf gewartet werden sondern die Tasklaufzeit //dynamisch einkalkuliert werden delay(20); [
void schrieb: > //um ein genaueres Zeitraster zu bekommen, sollte > //hier nicht stumpf gewartet werden sondern die Tasklaufzeit > //dynamisch einkalkuliert werden > delay(20); Blödsinn. Man nutzt dafür keine delay() Funktion sondern einen Timer-Interrupt, siehe Multitasking.
Carl D. schrieb: > zu beachten ist in Zeile 15, daß nicht millis() gelesen wird. Damit wird > verhindert, daß das (hier) 1s-Raster wegen der Laufzeit des anderen > loop-Codes wegläuft. Ohne das wird die "Sekunde" immer größer als eine > Sekunde sein. Letztendlich ist dieser Ansatz die Softwarevariane eines Output Compare Interrupts.
Carl D. schrieb: > Vielleicht interessanter als die wöchentliche (tägliche) Frage, warum > das mit millis() funktioniert, wo es doch gar nicht sein kann, und ob > man sich wirklich merken muß, wie sich in C unsigned beim Überlauf > verhält. In dem Artikel https://www.mikrocontroller.net/articles/High-Speed_capture_mit_ATmega_Timer#Keine_Angst_vor_.C3.9Cberl.C3.A4ufen habe ich mal erklärt, wie das mit Überläufen funktioniert und warum das ganz einfach ist, wenn man es mal verstanden hat. Und nein, es passiert dabei keine Katastrophe und man muss den Überlauf auch nicht verhindern sondern einfach mit unsigned Zahlen rechen. Michael
W.S. schrieb: > Natürlich reicht ein beliebiger long bequem für mehrere Tage und wenn > eine Systemuhr in der Firmware ordentlich funktioniert, dann setzt sie > die Uhrzeit um Mitternacht auf 0 zurück - und wenn sie obendrein auch > die Ablaufzeiten für vorgemerkte Ereignisse betreut, dann kann sie > problemlos auch von diesen Ablaufzeiten um Mitternacht besagte 86400000 > ms subtrahieren und fetig ist die Laube. Jetzt fängt auch noch diese Diskussion an. Da ist man froh, einen durchlaufenden Zähler zu haben, der unabhängig von Erdrotation, Zeitzonen und Schaltsekunden läuft und immerhin die direkte Steuerung von Zeitenabläufen mit Abstand der Ereignisse von bis zu 49 Tagen erlaubt, und dann kommst du mit einem Vorschlag, bei dem alle 23/24/25 Stunden ein Bruch im Ablauf ins System reindesignt ist. Willst du unterschiedlich lange Sekunden, damit dein Tag immer "86400000 ms" hat? Da ist die nächste Baustelle vorprogrammiert. Gleichmäßiger Ablauf und Uhrzeit oder gar gesetzliche Zeiten passen nicht zusammen und man muss sich für eins entscheiden.
Falk B. schrieb: > Blödsinn. Man nutzt dafür keine delay() Funktion Naja... eigentlich hast du ja recht. Aus professioneller Sicht würde man es anders machen. Aber: um im Hobby-Bereich auf einem kleinen AVR einfache Zeitabläufe zu steuern, und um eine Zeitbasis (hier ca. 20ms) zu haben, ist es für die meisten meiner (!) AVR Projekte ausreichend. Für mich bietet es viele Vorteile: - einfach in der Handhabung - verschiedenste Prozesse im round-robin-Prinzip möglich - viele unabhängige Timer parallel möglich - globale Variablen kommen ohne Ressourcen-Locking aus
void schrieb: > Für mich bietet es viele Vorteile: > - einfach in der Handhabung > - verschiedenste Prozesse im round-robin-Prinzip möglich > - viele unabhängige Timer parallel möglich > - globale Variablen kommen ohne Ressourcen-Locking aus Das kann die gescheite Variante mit dem Timer ebenso und ist nicht nennenswert aufwändiger oder komplizierter.
void schrieb: > Aber: um im Hobby-Bereich auf einem kleinen AVR einfache Zeitabläufe zu > steuern, und um eine Zeitbasis (hier ca. 20ms) zu haben, ist es für die > meisten meiner (!) AVR Projekte ausreichend. Du musst es wissen - für deine Projekte mag es ausreichen. Dein Nick ist Programm :-(
void schrieb: > Falk B. schrieb: >> Blödsinn. Man nutzt dafür keine delay() Funktion > Naja... eigentlich hast du ja recht. Aus professioneller Sicht würde man > es anders machen. Völlig falscher Denkansatz. Man macht es so, wie es effizient ist und zuverlässig funktioniert. Wenn man etwas einfaches zu programmieren hat (z.B. die "useless machine") kann man das locker mit delay() machen. Es gibt nichts, was man gleichzeitig zu erledigen hat. Also tut's das. Und das hat absolut nichts mit professionell oder Hobby zu tun. Andere Bsp. für ein delay(): Resetgenerator der mehrere reset-Signale zeitversetzt ausgeben muss. In einem meiner (defekten) HP-LAs ist da eine äusserst fragwürdige Schaltung die ich wohl ersetzen werde. Die schafft das Timing nämlich nicht mehr. Dummer Timer für einen Aqariums-Sprudler. Irgend ein kleiner AVR-PIC-China-µC. Da gibts so viel, dass jedem von euch ein besseres Beispiel einfällt als mir.
void schrieb: > Für mich bietet es viele Vorteile: > - einfach in der Handhabung > - verschiedenste Prozesse im round-robin-Prinzip möglich > - viele unabhängige Timer parallel möglich Das könnte ich dir, oder besser die Verfahren welche ich nutze, dir auch bieten. Ohne die Zeit tot zu warten. Suche mal nach "Adam Dunkel Protothreads" > - globale Variablen kommen ohne Ressourcen-Locking aus Das lässt sich nicht wirklich vermeiden. Jede Art von Multitasking benötigt Verriegelungen, hat kritische Bereiche. Kooperatives ist da nur etwas gnädiger... Falk B. schrieb: > sondern einen Timer-Interrupt Die Arduinowelt hat schon einen. Noch einen braucht es nicht. Über millis() kann man vielleicht streiten, aber ein zweiter Timer Interrupt wäre doppelt gemoppelt. Wenn, dann nur, wenn man unbedingt muss. z.B. würde sich ein Timer0 Compare anbieten, der kommt dann mit 980Hz auf einem UNO.
Arduino Fanboy D. schrieb: > Ohne die Zeit tot zu warten. Kostet das was? Oder warum ist das prinzipiell falsch (siehe meine Beispiele oben)? > Suche mal nach "Adam Dunkel Protothreads" Die müssen genauso warten. Halt mit mehr Aufwand. Bei einfachen Anwendungen Overkill. Nichts gegen die Protothreads per se! Das wait() ist fast schon plattformübergreifend (auf µC), Timer oder Interuptgeschichten aber immer Controllerabhängig.
Arduino Fanboy D. schrieb: > Suche mal nach "Adam Dunkel Protothreads" Wenn man mit µIP hantiert, kommt damit früher oder später zwangsläufig in Kontakt. Obwohl ich dazu eine sehr stabile Anwendung und einen schönen Aufsatz geschrieben habe (http://stefanfrings.de/net_io/protosockets.html) mag ich dieses Konstrukt gar nicht. Denn man verzettelt sich damit ganz schnell bezüglich des Lifecycles von Variablen. Da passiert mir zu viel, was nicht mehr offensichtlich ist. Meiner Meinung nach schreien Web-Anwendungen geradezu nach einem Garbage-Collector und den damit verbundenen Möglichkeiten der einfacheren Datenhaltung. Gibt es das überhaupt für C? Vermutlich nicht.
Nick M. schrieb: > Arduino Fanboy D. schrieb: >> Ohne die Zeit tot zu warten. > > Kostet das was? Oder warum ist das prinzipiell falsch (siehe meine > Beispiele oben)? > >> Suche mal nach "Adam Dunkel Protothreads" > > Die müssen genauso warten. Halt mit mehr Aufwand. Bei einfachen > Anwendungen Overkill. Nichts gegen die Protothreads per se! > > Das wait() ist fast schon plattformübergreifend (auf µC), Timer oder > Interuptgeschichten aber immer Controllerabhängig. Du hast doch nicht alle Streusel auf dem Kuchen! Bis eben, war dir das Arduino millis() nicht gut genug, und jetzt spielst du den delay() Fanboy. Nörgeln, nerven. Streitsüchtig.
Schuppeste schrieb: > precF_CPU=timemillisoverflows*256+TCNT0 Das ist in etwa das, was das Arduino micros() tut.
Arduino Fanboy D. schrieb: > Nörgeln, nerven. Streitsüchtig. So bist du halt. Arduino Fanboy D. schrieb: > Du hast doch nicht alle Streusel auf dem Kuchen! Wenn du dich besser im Konditoreiwesen auskennst, dann such dir doch ein passendes Thema dazu aus. Oder lies die Bäckerblume. Arduino Fanboy D. schrieb: > Bis eben, war dir das Arduino millis() nicht gut genug, und jetzt > spielst du den delay() Fanboy. Also Fanboy bin ich nicht, nenn ich mich auch nicht. Eine Begründung für delay hab ich gegeben. Jetzt bleibt noch die Frage: Was hast du daran nicht kapiert? Keine Angst, es gibt keine dummen Fragen.
Nick M. schrieb: > Eine Begründung für > delay hab ich gegeben. > Jetzt bleibt noch die Frage: Was hast du daran nicht kapiert? Dann wollen wir doch mal schauen, wer irgendwas nicht kapiert hat.... Mach mal Eingangsposting lesen.... 1. Ihm verwendet offensichtlich Arduino 2. Ihm will weg von delay() 3. Hin zu millis() 4. Nebenläufigkeiten realisieren Jetzt der Vergleich zu deinen Ergüssen: Einen 64Bit Timer gibts in der Arduino Welt nicht. Man kommt auch mit dem gegebenen 32Bit gut klar. Auf delay() soll verzichtet werden. Also sind deine Lobpreisungen des Wartens, gelinde gesagt, etwas deplatziert. Und Arduino ist sowieso nicht deine Baustelle. Sagste ja selber.... Es geht dir am Arsch vorbei. Jetzt mal Butter bei die Fische: Warum machst du hier so die Welle? Warum gehst du mich so an?
Beitrag #6560561 wurde von einem Moderator gelöscht.
Beitrag #6560568 wurde von einem Moderator gelöscht.
Beitrag #6560616 wurde von einem Moderator gelöscht.
Beitrag #6560636 wurde von einem Moderator gelöscht.
Arduino Fanboy D. schrieb: > Du hast doch nicht alle Streusel auf dem Kuchen! Arduino Fanboy D. schrieb: > Nörgeln, nerven. Streitsüchtig. Arduino Fanboy D. schrieb: > 1. Ihm verwendet offensichtlich Arduino > 2. Ihm will weg von delay() > 3. Hin zu millis() > 4. Nebenläufigkeiten realisieren Junge, das alles hab ich doch lang vor dir beantwortet. Und zwar so, dass er damit tatsächlich weiterkommt. FSM. Such einfach danach. 13. Posting, nachdem die vorhergehenden (nicht von mir) sich am millis elaboriert haben ohne das Problem zu lösen. Natürlich will der TO weg von delay() weil es einfach so nicht geht. Ist mir schon lange klar. War mir sofort klar wie ich sein posting gelesen hab. Bezüglich delay() hab ich auf die Aussage beantwortet: void schrieb: > Falk B. schrieb: >> Blödsinn. Man nutzt dafür keine delay() Funktion > Naja... eigentlich hast du ja recht. Aus professioneller Sicht würde man > es anders machen. > > Aber: um im Hobby-Bereich auf einem kleinen AVR einfache Zeitabläufe zu > steuern, und um eine Zeitbasis (hier ca. 20ms) zu haben, ist es für die > meisten meiner (!) AVR Projekte ausreichend. Mit Beispielen! Aber der void wurde sofort persönlich dafür angegriffen. U.a. von dir. Auch meine Erklärung warum delay() durchaus sinnvoll sein kann hast du versucht pauschal als schlecht hinzustellen. Ohne dann auf meine Frage was denn an den Proto-threads besser sei wenn man einfach nur ganz stumpf warten will. Aber da flippst du aus und antwortest mit deinen Ausfälligkeiten. Mach dir keine Hoffnungen, damit bewirkst du nichts, du bekommst dafür eine Retourkutsche. Arduino Fanboy D. schrieb: > Warum machst du hier so die Welle? > Warum gehst du mich so an? Glaubst du, dass du mich einschüchterst? Ich lass mich nicht einschüchtern. Weder im Netz noch auf der Straße. Den Versuch haben schon paar bereut. Auch 40 Jahre jüngere, auf der Straße, nicht ein Jahr her. Ich bin 64. Lass es einfach bleiben, red mit mir vernünftig und alles ist gut. Lass vor Allem deine Spielchen, die kenn ich.
Jaja, Glaubens- und Kleinkrieg 2.0. Habt ihr das WIRKLICH nötig? Zu kleiner Piephahn?
Falk B. schrieb: > Jaja, Glaubens Ich führe hier keinen Glaubenskrieg. Weil mir es piepegal ist ob AVR, Microchip oder ARM oder gar Propeller. Hängt von der Anwendung ab. Und danach wähle ich die Plattform. Und die löte ich mir dann auch genau passend zusammen. Solange C drauf läuft ist alles gut. :-))
Arduino Fanboy D. schrieb: > Du hast doch nicht alle Streusel auf dem Kuchen! .... > Nörgeln, nerven. Streitsüchtig. Merkste was?
Beitrag #6560746 wurde von einem Moderator gelöscht.
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.