formel gesucht (linearer Wert zwischen zwei anderen)

Hier meine Aufgabenstellung (ist für einen Belichtungsrechner für meine Camera):

tStart = gewünschter Anfangswert tEnd = gewünschter Endwert now = das "Jetzt" seit starten des Programmes runStart = hier wurde das Programm gestartet tDuration = gewünschte Dauer des Programmes Momentanwert = ?

alle Werte sind in ms.

Beispiel:

tStart = 1 tEnd = 1000 now = 5000 runStart = 4000 tDuration = 2000

Hier ist der Momentanwert 499,5, denn ich befinde mich in der Mitte der Zeit (now - runStart = tDuration / 2) und somit habe ich die Hälfte zwischen tEnd und tStart ((tEnd-tStart)/2)

Gewünscht ist zu jedem beliebigen JETZT (now) den aktuellen Wert zwischen tStart und tEnd abfragen zu können, abhängig natürlich von der Dauer der linearen Änderung von "tStart" zu "tEnd" über die Dauer "tDuration".

Ich glaube Du solltest Deine Variablen besser benennen. Dann klappt es auch mit der Rechnerei:

t0:= Startzeit t1:= Zielzeit t := aktuelle Zeit

s0:= Startwert s1:= Zielwert s := aktueller Wert

Wenn der Zusammenhang linear soll, dann also:

(t-t0)/(t1-t0) = (s-s0)/(s1-s0)

oder eben:

t = (t1-t0)/(s1-s0) * (s-s0) + t0 s = (s1-s0)/(t1-t0) * (t-t0) + s0

ergebnis = (now - runStart) * (tEnd - tStart) / tDuration + tStart;

Hallo MaFu, das funktioniert super! Du hast nicht zufällig noch die passende Formel (mit den gleichen werten) für exponentielle Wertänderung in deinem Mathematikerkopf?

Da würde ich glatt Freibier springen lassen ;-)

(exp(t)-exp(t0))/(exp(t1)-(exp(t0)) = (s-s0)/(s1-s0)

oder

s = (s1-s0)/(exp(t1)-exp(t0)) * (exp(t)-exp(t0)) + s0

Für so lineare Sachen kann man einfach die Funktion MAP nehmen

momentanwert = map(now, runStart, runEnd, tStart, tEnd)

du müsstest halt zunächst aus runStart + runDuration dein runEnd ausrechnen.

Hallo Udo,

leider klappt das nicht. Gibt mir immer "0" aus. :-(

Ich komme auch ganz gut klar mit meinen Bezeichnungen, vor allem weil ich immer weiß was es ist (das geht mir mit S0 leider nicht so). Ich halte hier immer eine art Namenskonvention ein, die Variablennamen sind halt relativ lang...

@TelosNox: Da habe ich auch schon dran gedacht, das werde ich mal testen - allerdings glaube ich nicht das die lineare Rampe funktionieren kann...

Dann poste mal Deinen Code. Nimmst Du floats oder ints?

Ich werde das mal ausdünnen und posten, im Moment ist der Code noch recht konfus...

Für die Zeitangaben verwende ich "unsigned long".

Das ist das Problem. Sobald Du mit Exponentialfunktionen arbeitest wird es mit Integers schwierig. Ich will nicht sagen, daß es überhaupt nicht gehen kann, aber dazu muß man dann sehr genau verstehen wie die Formeln funktionieren und auch genau auf die Wertebereiche aufpassen. Deshalb wäre es vermutlich besser wenn Du dazu auf floats umstellst.

Ich habe keine floats genommen, weil ich da immer Probleme bekomme mit der Wandlung in Strings. Ich habe ein Display dran hängen und gebe hier einen String aus. Teilweise sind das dann auch Werte aus den Berechnungen. Bei "long" geht das ohne Probleme, bei float sträubt sich das Arduino erfolgreich.

#include<stdlib.h>
dtostrf(FLOAT,WIDTH,PRECSISION,BUFFER);

Gibt es hier : (weiter unten )

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1205038401

Ja, die Funktion habe ich auch ausprobiert. Wenn ich allerdings da nicht-floats durchjage, gibt's lustige Zeichen auf meinem LCD.

quote author=Udo Klein link=topic=67997.msg501102#msg501102 date=1312096622/(exp(t1)-(exp(t0)) = (s-s0)/(s1-s0)

oder

s = (s1-s0)/(exp(t1)-exp(t0)) * (exp(t)-exp(t0)) + s0 [/quote]Hast Du das mal selber auf dem Arduino ausprobiert? Ich denke, dass bei den Zahlen von derHerrKohler viel zu große Werte rauskommen. Die können auf dem Arduino nicht mehr verarbeitet werden.

TelosNox: Für so lineare Sachen kann man einfach die Funktion MAP nehmen

momentanwert = map(now, runStart, runEnd, tStart, tEnd)

du müsstest halt zunächst aus runStart + runDuration dein runEnd ausrechnen.

Meine obige Formel entspricht weitestgehend der map Funktion. Nur werden da zwei Rechenschritte gespart (runEnd berechnen welches map anschließend wieder für das errechnen der differenz verwendet) und es funktioniert so auch mit float (map ist nur für int definiert).

Wozu ausprobieren? Solange er nicht sagt wie die Wertebereiche sind ist unklar ob das Probleme geben wird oder nicht. Man kann auch andere Exponentielle Formeln nehmen. Genaugenommen ist ein Freiheitsgrad zuviel da. Wie gesagt: solange er das nicht sagt ist es ziemlich nutzlos das auszuprobieren.

Ich für meinen Teil würde keine exponentielle Funktion nehmen sondern Splines.

Und ich würde auch mal schauen was hier: http://openmoco.org/ so getan wird.

Ich habe hier das Projekt kurz vorgestellt, auch der aktuelle Code findet sich hier: http://www.stefankohler.de/de/film/selbstbau/camtimer/

Mein Wertebereich liegt immer im positiven Bereich bis ca. 30.000.000 (8 Stunden in ms) für now , runStart und tDuration. Die Belichtungszeiten (tStart und tEnd) liegen zwischen 5 und 600.000 (ca 10 Minuten). Die Genauigkeit ist hier nicht ausschlaggebend, ob das jetzt 3 ms mehr oder weniger sind, kann ich vernachlässigen denke ich.

Bei so großen Werten würde ich dann statt

(exp(t)-exp(t0))/(exp(t1)-(exp(t0)) = (s-s0)/(s1-s0)

oder

s = (s1-s0)/(exp(t1)-exp(t0)) * (exp(t)-exp(t0)) + s0

eher sowas wie

exp(t/(t1-t0))-exp(t0/(t1-t0)) = (s-s0)/(s1-s0)

oder

s = (s1-s0) * (exp(t/(t1-t0))-exp(t0/(t1-t0))) + s0

nehmen.

Das ist auch exponentiell alle Zwischenergebnisse sind in den Bereichen die mit dem Arduino ohne weitere Probleme zu behandeln sein sollten.

Ich muss hier aber dennoch umstellen auf float's, richtig?

Ich habe das jetzt mit temporären floats gelöst. hier der Code, vielen Dank für Eure hilfe!

       float stepsGesamt = (tDuration*60000) / (tInterval*1000);
       float stepNow = (now - runStart) / (tInterval * 1000);
       float v = stepNow / stepsGesamt;
       v = v * v;
       float X = (tEnd * v) + (tStart * (1 - v));
       belichtungszeit = X;