Nein, im Beispiel vergleichen wir die Differenz mit einer Dauer ungleich Null und verwenden> = nicht <
Hmm ....
Hast du nicht alles gelesen, was ich geschrieben habe?
Dabei habe ich doch zu begründen versucht, warum ich da < verwendet habe.
Sogar ein Beispiel, welches zeigt, dass > und >= auch , für manch einen überraschende Ergebnisse bringt.
Aber extra für dich nochmal in Klartext:
byte Rechnungen unterliegen der "Integer Promotion"
Das gilt es zu beachten.
Entschuldigung, ich hätte genaueres lesen sollen!
selbstverständlich.
Ich habe mal auf die Schnelle einen Sketch zusammengestellt, der bestimmt nicht ganz schön ist, aber das Testen eigentlich ohne Verstellen der realen Zeit ermöglichen sollte.
Vielleicht schauen die übrigen hier im Forum sich mal den Code an, ob er den Zweck erfüllt oder ggf. ein Denkfehler vorliegt . Wie gesagt (vom Hirn ins Terminal gehackt und einmal laufen lassen):
#include <limits.h>
#include <arduino.h>
#define test
#define TIMEOFFSET 10000
unsigned long starttime;
unsigned long lasttime;
unsigned long interval;
unsigned long _millis(){
#ifdef test
return starttime + millis();
#else
return millis();
#endif
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
#ifdef test
starttime = ULONG_MAX - millis() - TIMEOFFSET;
#endif
lasttime = _millis();
interval = 1000;
}
void loop() {
// put your main code here, to run repeatedly:
if (_millis() - lasttime > interval) {
lasttime = _millis();
Serial.println(_millis());
}
}
Ich kenne den Zweck nicht.
Weiß aber, dass das "Blink Without Delay" Prinzip funktioniert!
Sehe aber auch nicht, wo dein wirkliches Problem liegt.
Oder wie dieser komplexe Code dir helfen soll.
Zudem habe ich
Schon vor langer Zeit aus meinem Programmen eliminiert. In die Tiefe geschickt.
Mindestens drei Libraries erfunden, welche das Problem von eben so vielen Seiten angehen.
a) Zum Zweck: Habe mich auf den Eingangspost bezogen: Dort möchte man testen, wie sich ein Overflow bei millis() auf das Programm auswirkt. Ersetzt man millis() durch _millis() nach der hier angeführten Methode, kann man den Rückgabewert von _millis() - zumindest für die selbstgeschriebenen Anteile, nicht für Anwendungen in den integrierten Libs - auf einen weitgehend beliebigen Zeitraum vor dem Overflow der unsigned long-Werte setzen.
Ich habe den Sketch noch etwas angepasst, damit die Idee klarer wird:
#include <limits.h>
#include <arduino.h>
#define MILLISBEFOREOVERFLOW 10000
#define INTERVAL 1000
#define test
unsigned long starttime;
unsigned long lasttime;
unsigned long interval;
unsigned long _millis(){
return starttime + millis();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
#ifdef test
starttime = ULONG_MAX - millis() - MILLISBEFOREOVERFLOW;
#else
starttime = 0;
#endif
lasttime = _millis();
interval = INTERVAL;
}
void loop() {
// put your main code here, to run repeatedly:
if (_millis() - lasttime >= interval) {
lasttime = _millis();
Serial.println(_millis());
}
}
Lässt man den Beispielsketch durchlaufen, so kann man den Zeitpunkt des Überlaufs gut erkennen. Wer also unbedingt den Überlauf in den selbstgeschriebenen Anteilen testen will, könnte das nach dem o.a. Schema tun, ohne in die eigentlichen Zeitangaben eingreifen zu müssen.
b) Ist (mindestens) eine der erfundenen Libraries öffentlich zugänglich? Das würde sicher bei manchem unnötiges Haareraufen vermeiden ...
Durchaus!
Hier eine Sammlung:
CombieLib.zip (975 KB)
Kann allerdings auch zu zusätzlichem Haare raufen führen.
Das kann ich in gewissen Grenzen nachvollziehen.
Bin aber der Überzeugung, dass ein millis() Überlauf keine Auswirkungen haben darf.
Und es auch nicht hat, wenn man es richtig macht.
Das stimmt sicher, wenn man sowohl die binäre Arithmetik wie auch die verwendete Plattform korrekt berücksichtigt (wie ja in zahlreichen Beiträgen dargestellt wird). Das Grundprinzip kann man aber auch auf andere Variable (und deren jeweilige Deklaration byte, integer, ...) ausweiten, bei denen man Probleme wittert ...
Wer bei einem Arduino unsigned long im Umfeld mit millis() verwendet, hat fast 50 Tage Zeit, bis das Problem nach Neustart auftritt. In vielen (nur kurzfristig betriebenen) Anwendungen wird das wohl nicht zum Zuge kommen, aber das Prinzip von Anfang an einzuhalten, verhindert auf jeden Fall böse Überraschungen.
Danke für die Zip-Datei; warum das Rad erneut erfinden ...
Heute wird es nix mehr mit Testen, aber ich werde es sicher machen! Einen schönen Abend!
Moin, ich konnte die Libs nun auch teilweise auf github lokalisieren (bei CombieTimer stößt man derzeit auf ein leeres Repository).
Um die Funktionsweise (einigermaßen) nachvollziehen zu können, bin ich in den Quellcode eingetaucht: Die Handschrift des erfahrenen und disziplinierten Entwicklers ist nicht zu zu verkennen (das darf auch mal gesagt werden, kein Schleimen sondern ehrliche Anerkennung ).
Leider trifft man in den Foren auch immer wieder auf Leute , die sich mehr um ihre persönliche Selbstdarstellung kümmern, als darum Dritte an ihrem "Herrschaftswissen" teilhaben zu lassen ...
Hintergründe und Zusammenhänge erläutern bringt weiter, das benötigt aber vor allem geduldiges Mitnehmen ... In diesem Sinne weiterhin viel Geduld
Ja, herzlichen Glückwunsch!
Hoffentlich macht dich der Kram nicht Wahnsinnig.
Bei Fragen: Fragen!
Und Anregungen für Verbesserungen, gerne.
Das mit der Selbstdarstellung ist alternativlos, denn das Forum ist die Bühne.
Und mit "Herrschaftswissen" habe ich nichts am Hut.
Eine konkrete Frage, bekommt eine konkrete Antwort.
So gut und knapp eben möglich.
Das ist auch so ein Talent.....
Wer will, findet Wege.
Wer nicht will, findet Gründe.
Wenn ich den Willen, auch mal ein Jammertal zu durchschreiten, nicht "spüre", ist das Talent ganz schnell am Ende.
Ansonsten+sowieso: Herzlichen Dank für die Blumen.
Editiert!!
Den Quatsch entfernt.
noInterrupts(); und interrupts();
oder
cli() und sei()
Sind nicht immer ausreichend.
Das ist nicht richtig.
cli() und sei() implementieren die Memory Barriere schon.
Die Ursache des Problems lag schon in der Memory Barriere.
Ich bitte um Verzeihung, für diese Nebelkerze.
.
Da Funktionsaufrufe immer Nebenwirkungen haben können, und der einzige Grund einer
void func(void);
ja deren "Nebenwirkungen" ist, halte ich deine Besorgnis für übertrieben.
Dann bleibe ich beruhigt
Macht er das auch bei ausgeschalteter Optimierung?
Das macht heute kein brauchbarer Compiler mehr. Instruction reordering und parallele Ausführung gehören zu den grundlegenden Fähigkeiten eines Compilers, bei C/C++ explizit zur Sprache.
Das Ein- und Ausschalten aller Interrupts gehört verboten, das hat - als prominentes Beispiel - schon vor über 30 Jahren dazu geführt, daß Eingaben auf PCs verloren gehen konnten.
In einem richtigen Echtzeit-System sollte es keine solchen Probleme geben. Das ist aber Arduino und C/C++ sicher nicht
Da hast du wahr. Und ist mir sehr wohl auch bekannt.
Heißt aber nicht, dass das keine Fallen birgt.
Ich versuche das Problem noch mal runter zu schrumpfen, zu einem minimal Beispiel.
Anmerkung:
Ein Teilaspekt, welcher zu meinem Irrtum beigetragen hat:
Der Atomic Block macht intern z.B
cli();
__asm__ __volatile__ ("" ::: "memory");
Dabei ist cli() schon so definiert:
# define cli() __asm__ __volatile__ ("cli" ::: "memory")
Die Memory Barrier ist also dort doppelt vorhanden.
Damit habe ich nicht gerechnet.
Diskutieren Sie immer noch die Frage von @domapi ...? (oder haben Sie den thread gekapert??)
Ich hatte geglaubt, in deinem Code einen Fehler gefunden zu haben, bzw. ihn anhand deines Codes zeigen zu können.
Und der Code findet sich in diesem Thread.
Allerdings:
Das war ein Irrtum!
Dein Code ist korrekt so.
Ich bitte dich nochmal um Verzeihung.
Und wenn du möchtest gerne auch noch mehrmals.
Wie kann ich diesen Fehler/Irrtum wieder bei dir gut machen?
es ist immer gut zu lernen und mein Code ist nicht immer fehlerfrei. Sie müssen sich nicht entschuldigen.
Da der Code zu funktionieren scheint, können wir dieses topic wohl beruhigen.
Hallo,
das stimmt nicht. Erkläre einmal was du unter einem Echtzeitsystem verstehst?
Multitasking mit gegeneinander gekapselten Tasks. Kontrollierter gemeinsamer wie exklusiver Zugiff auf die Hardware (HAL).
Was mich von Anfang an gestört hat waren die vielen Probleme bei der Verwendung mehrerer Bibliotheken, die meist von der konkurrierenden Benutzung von Timern kommen.
Von einem ordentlichen System erwarte ich, daß solche Konflkte zumindest erkannt werden, damit der Programmierer bzw. Benutzer weiß, wo er ansetzen muß. Dazu würde mir schon reichen, wenn jede Bibliothek mehr oder weniger freiwillig meldet, welcher Timer benutzt wird, so daß alle nachfolgenden Bibliotheken feststellen können, daß es Probleme gibt.