Ich versuche einen Countdown Timer mit einem Arduino Mega zu realisieren. Ziel ist, dass ich mit einem Rotary Switch eine Anzahl Minuten setzen kann. Nach einem Tastendruck soll dann auf dem Display die Minuten und Sekunden abgezählt werden und bei 00:00 eine Aktion ausgeführt werden. Leider scheitere ich bereits bei dem millis(). Wieso zählt der nachfolgende Code von 26 Sekunden rückwärts? Vorgesehen wären 20 Minuten.
Ich nehme an, dass du was anderes beabsichtigt hast.
Ach ja eine Meldung kommt da auch noch:
E:\Programme\arduino\portable\sketchbook\sketch_feb08d\sketch_feb08d.ino: In function 'void setup()':
E:\Programme\arduino\portable\sketchbook\sketch_feb08d\sketch_feb08d.ino:8:36: warning: integer overflow in expression of type 'int' results in '20352' [-Woverflow]
8 | cout << F("Interval: ") << (20*60*1000) << endl;
| ~~~~~^~~~~
Hallo, @combie hat Dir ja bereits gezeigt woran es liegt. Du musst dafür sorgen das die Berechnung (20*60*1000)
nicht als eine Integer Berechnung gemacht wird. Das kannst Du erreichen in dem Du mindestens einen Wert als 32 bit Wert angibst.
static unsigned long TargetTime = startTime + (20*60*1000UL);
Oder alle mit dem Suffix versehen, denn kostet ja nix und sorgt dafür, dass man nicht auf die Operatoren Rangfolge achten muss.
(ein + ist schnell übersehen)
Irgendwie ist wirklich der Wurm drin. Wenn ich den Countdown auf z.B. 20Min stelle, zählt er in der Sekundenstelle jede zweite Minute in 10er Schritten von 100 runter, statt von 59 auf 0.
Danke combie für deinen Code! Der Interval soll ja variabel sein. Wie kann ich einer unsigned long Variabel das Suffix "ul" anhängen? Also damit alle Werte 32 Bit haben.
Geht nicht, sie ist ja schon Unsigned Long.
Literale sind default vom Datentyp int. Auf unseren 8Bit AVR Controllern int16_t.
Deswegen muss man aufpassen mit Formeln und Literalen nicht den Wertebereich zu überschreiten. Das Suffix legt den Datentyp vom Literal fest. Eben einen anderen als default int. Eine andere Möglichkeit sind cast Operatoren.
Hab den Code entsprechend dem Vorschlag von combie geändert. Es funktioniert soweit, bis auf dass die Anzeige auf dem Display suboptimal ist. Die Minuten und Sekunden "rutschen", d.h. z.B. jeweils von 9 Sekunden bis 0 Sekunden werden 90, 80, 70 usw. angezeigt. Hab schon versucht das Ganze mit sprintf und einem Buffer zu printen, funktioniert aber irgendwie nicht.
Hier die neue Funktion CountdownTime:
Wichtig war die TargetTime Berechnung.
Einmal die Addition dort, wg. dem drohnden den Überlauf, und die int Multiplikation mit ihrem eigenen Überlauf.
Weniger wichtig, und immer noch vorhanden, ist folgendes:
Die Funktion tut zuviel.
Grundsätzlich sollte eine Funktion nur eine Sache machen.
Dann sollte eine Funktion weder statische Variablen im Bauch haben, noch auf externe bzw. globale Daten zugreifen.
Alles was die Funktion braucht sollte man als Parameter übergeben.
Ergebnisse werden per return übergeben.
Rückgabe über Referenzen ist halbwegs OK, da man das anhand der Funktionssignatur halbwegs gut erkennen kann.
Hallo Leute
Ich hab nun doch noch ein neues Problem. Wenn ich den rotary encoder von 0 rückwärts, also gegen den Uhrzeiger drehe, steht plötlich 429496 aufm Display. Und diese hinteren Zahlen gehen auch nicht mehr weg, wenn ich wieder über 0 hochdrehe..
ganz pauschal, du hast eine Wertebereichsüberschreitung. Das ist erstmal etwas völlig normales. Du musst für dich den gültigen Wertebereich festlegen und alles was drunter oder drüber liegt korrigieren oder begrenzen. Je nachdem was du mit den Werten machen möchtest.
Display. Das Verhalten ist auch normal. Du musst alle Ziffern überschreiben. Du weißt wieviele Digits maximal angezeigt werden. Diese Anzahl musst du immer schreiben. Damit "löschen" sich alte Zahlen wie von selbst. Komme nicht auf die Idee jedesmal das gesamte Display zu löschen.