Blink Without Delay fuer Fortgeschrittene?

Guten Morgen allerseits,

ich grueble gerade, wie ich es hinbekomme, dass meine Animationscode auf jedem Prozessor zu gleichen optischen Ergenbissen fuehrt.

Konkret geht es darum, dass die Oszillatoren(TM) sich immer gleich schnell bewegen sollen.

Mit den Sinusoszillatoren funktioniert das bereits: die Zeitbasis ist millis() und egal wann oder wie oft ich die aufrufe, ist die resultierende Funktionskurve immer auf millis synchronisiert.

Nun sitze ich gerade vor ein paar vollgekritzelten Baettern Papier und ueberlege, wie ich das mit den Linearoszillatoren mache. Problem ist, dass es natuerlich nicht funktioniert, die bei jedem Call um einen statischen Wert hochzuzaehlen.
Vielmehr ist es erforderlich, die auf Basis einer festgelegten Geschwindigkeit als angestrebte Werteveraenderung/s hoch- oder runterzuzaehlen.

Fuehrt da irgendein Weg daran vorbei, fuer jeden einzelnen Oszillator die Zeit des letzten Aufrufs zu speichern, die ins Verhaltnis zur momentanen Zeit zu setzen und dann die Schrittweite fuer den naechsten Schritt zu berechnen?

Ich habe ca. 30 solche linearen Rampen und das wuerde bedeuten, 120 Byte RAM nur fuer die Zeitstempel des letzten Aufrufs zu verwenden.

Geht das auch einfacher?

Danke fuer Ideen,

Helmuth

Mit millis() und einer Modulo Rechnung ?

Sollte einfacher sein als sin(millis())

Die Sinussachen funktionieren gut und schnell. Lookup Tabelle.

Es geht mir um das lineare Hochzaehlen von uint16_t Werten.

Millis und Modulo hat den Nachteil, dass man dann genau im richtigen Moment aufrufen muss. Das kann ich (wegen schwankenden fps) nicht garantieren.

Vielleicht trifft man zufaellig genau z.B. millis() % 2 == 0, vielleicht nicht.
Die resultierende Funktionskurve wird keine Gerade, sondern eine Zig-Zag-Linie.

???
Wenn du eine SägezahnFunktion statt eines Sinus haben willst, bekommst du immer wenn du

uint16_t  value = millis() % periode;

aufrufst, einen richtig synchronisierten Wert im Bereich 0 .. periode-1 zurück.

Vermutlich verstehe ich dein Problem nicht.

...oder ich verstehe Deine Antwort nicht?!

Was Du gerade geposted hast, erzeugt einen Saegezahn.

Ich brauche eine lineare Funktion mit festgelegter Steigung.

Ein Beispiel: Mein Zielwert soll sich nach einer Sekunde um 1000 erhoert haben, nach 2s um weitere 1000, usw.

Es ist nicht bekannt, wie oft der Wert Zielwert innerhalb der Sekunde neu berechnet wird, das schwankt.

Wenn ich ihn 2x update muesste ich jeweils 500 addieren, wenn ich ihn 10x update jeweils 100.

Aber das ist erst hinterher bekannt. Alles, was ich habe, ist die aktuelle Zeit millis() und eine festgelegte Geschwindigkeit 1000/s.

Habe ich gerade wieder ein Brett vor dem Kopf?

Helmuth:
Was Du gerade geposted hast, erzeugt einen Saegezahn.
Ich brauche eine lineare Funktion mit festgelegter Steigung.

Was ist der Unterschied??
Grüße Uwe

Was ist der Unterschied??

Gute Frage! Es gibt keinen...

Ok, ich probiere mal was aus, vielleicht loest sich ja meine Verstaendnisblockade.

Danke Euch beiden!

Alles, was ich habe, ist die aktuelle Zeit millis() und eine festgelegte Geschwindigkeit 1000/s.

Und was fehlt dir ?

Wenn ich ihn 2x update muesste ich jeweils 500 addieren, wenn ich ihn 10x update jeweils 100

Das ist vermutlich völlig Quatsch dein Denkfehler. :wink:
Weiss nicht was du unter "synchron" verstehst, aber am einfachsten ermittelst du das Ergebnis direkt aus millis(), egal wie oft du es berechnest.

Was soll passieren, wenn dein uint16_t überläuft? oder wann soll deine "lineare Funktion" neu anfangen?

Mein Denkfehler war, dass ich mich auf die Berechnung der deltas zum Addieren versteift habe.

Das ist natuerlich hinfaellig, wenn man das Ergebnis direkt aus millis() berechnet.

Der Saegezahn soll eine maximale Amplitude von 16 Bit haben, damit ist der Ueberlauf erstmal egal.

edit: Ja, das funktioniert genau so, wie ich es will. Einfach millis() / speed. Oh, Mann...

Danke nochmal!

Der Saegezahn soll eine maximale Amplidude von 16 Bit haben, damit ist der Ueberlauf erstmal egal.

Sag ich doch, einfacher als sinus:

uint16_t value = millis();  // Sägezahn 0..65535, mit einer Steilheit von 1000/s

:stuck_out_tongue: