Hallo an alle Habe folgendes problem Muss x= e^(-t/Tau) berechnen auf einem Mikro. Und habe aber keine floating point unit zur verfügung kleine info (-t/Tau) liegen im bereich zwischen ~-0.1 und ~-0.005 also -100 [mikro s] bzw 5[mikro s] Als ergebniss hätte ich gerne ein wert der in etwa so aussieht x= 123 /* Wert mal 10^-3 */ Diese zahlen sind nur Sinnbildlich. Benutzen kann ich von u/sint8 bis u/sint32 alles Hat einer eine Idee wie da vorgehen kann? Habe Überlegt es durch eine näherung zu versuchen E X^n/n! kam aber aus laufzeitgründen auf nicht ausrichende ergebnisse Wäre Super wenn einer eine Idee hat
Wenn -t und Tau bzw -t/Tau in der Realität der Anlage nur eine kleine Anzahl endlicher Werte annehmen kann, beziehungsweise keine allzu hohen Anforderungen an die Genauigkeit gestellt werden, kann man immer mit vorgefertigten Tabellen arbeiten. Geht am schnellsten braucht aber auch am meisten Speicherplatz.
hi danke für die rasche antworte die überlegnung der Arbeit mit lookup tabels ist auch schon da, da aber tau stark schwankt wegen erwärmung der bauteile und t auch nicht konstant ist wird es vermutlich ein riesen brocken an tabelle geben der dann mit ausreichender genauigkeit in einem bereich von ca 1-2k Ram liegen wird und dass leider nicht passt fällt diese lösung ERSTMAL weg. Wenn sich natürlich keine andere möglichkeit bietet muss ich sowas verwenden und dann deutlich an genauigkeit einbüßen. Die frage stellt sich ob es eine Lösung gibt bei der durch shiften, multiplikationen .... auf einen etwa genauen wert kommen kann.
> da aber tau stark schwankt wegen erwärmung der bauteile und t auch > nicht konstant ist wird es vermutlich ein riesen brocken an tabelle > geben der dann mit ausreichender genauigkeit in einem bereich von ca > 1-2k Ram liegen wird und dass leider nicht passt fällt diese lösung > ERSTMAL weg. Je nach Controller kann man solche Tabellen auch im Programmflash,internen EEPROM oder einem externen EEPROM/Flash ablegen.
Kann ich leider nicht )-: Da es sich um ein größeres Projekt handelt und diese berechnung nur ein bestandteil einer funktion sein soll bietet sich diese möglichkeit mit gewünschter genauigkeit aufgrund plattzmangels leider nicht an. extern kann ich leidern gar nichts machen.
Ich habe die Folgende Formel genutzt unendlich E (x^k)/k! k=0 Da diese Formel aber Sehr Laufzeitintensiv ist, wird es schwerig damit auf ein gutes ergebnis in ausreichender zeit zu kommen.
wenn ich dabei k sagen wir auf 10 setzte sind schon große laufzeiten vorhanden die dann dazu führen dass andere interrupts entwedere die berechnugen unterbrechen oder gar nicht aufgerufen werden während dessen.
1. Möglichkeit unvollständige Tabellen: weniger Speicherplatz; aber ungenauer --> Genauigkeit kann durch lineare Interpolation zwischen 2 Werten verbessert werden 2. Offline ein Polynom durch Polynominterpolation berechnen (z.B. Newtonsche Interpolation, Langrange Interpolation, Taylerpolynom) mit möglichst wenigen Stützstellen dabei arbeiten, vermindert der Rechenaufwand. Am besten benutzt man dafür so ein Programm wie Mupad oder Oktave. Online Funktionswerte des Polynoms mit Hilfe des Hornerschemas berechnen. --> Genau aber langsamer 3. Mitelweg wäre der CORDIC Algorithmus. Interpolationsalgorithmus, kommt in der Regel mit 15 Durchläufen aus. Benutzt im Kern nur Additionen, Subtraktionen und Schiebebefehle. Ist nicht nur andwendbar bei Winkelfunktionen sondern auch zur Berechnung der e-Funktion. --> eine gute erreichbare Genauigkeit; mittelschnell
Und nur mit Integerwerten arbeiten!!! Vermute du hast float benutzt. Dann werden auf einem Mikrocontroller ohne Gleitkommaeinheit, alle Floatberechnungen in Software nachgebildet. Das ist dann langsam.
Dankeschön erstmal werde mich mal an option 3 versuchen und mir die laufzeiten betrachten. Ansonsten wähle ich option 1.
nein habe kein float genutzt. Habe x durch division umskaliert damit es passt (-; Danke für die tipps
Potenzreihen sind nicht sonderlich gut geeignet für sowas weil man schnell Überläufe aus dem Wertebereich bekommt auch wenn der Endwert im Rechenbereich liegt. Beispiel: exp(-10) ≈ 0, hier werden die Summanden x^k/k! in der Reihenentwicklung recht groß und neben dem Überlauf-Problem handelt man sich noch Ungenauigkeit durch Auslöschung ein. http://de.wikipedia.org/wiki/Auslöschung_(numerische_Mathematik%29 Das Überlauf-Problem bekommt man in den Griff, indem man ein Polynam anders darstellt und auswertet, zB zur Basis von Bernsteinpolynomen. Im Endeffekt führt das zu Bézierkurven, die besser bekannt sein dürften. Für exp(-t), t \in {0, 4/3} Kann man die Funktion zB so berechnen:
1 | #include <stdio.h> |
2 | #include <math.h> |
3 | |
4 | double y[] = { 1, 0.56, 0.385, 0.2636 }; |
5 | |
6 | double castelj (double t0) |
7 | {
|
8 | double t = t0*3.0/4.0; // t in {0,1} |
9 | |
10 | double y00 = y[0] + t * (y[1] - y[0]); |
11 | double y01 = y[1] + t * (y[2] - y[1]); |
12 | double y02 = y[2] + t * (y[3] - y[2]); |
13 | |
14 | double y10 = y00 + t * (y01 - y00); |
15 | double y11 = y01 + t * (y02 - y01); |
16 | |
17 | double y20 = y10 + t * (y11 - y10); |
18 | |
19 | printf ("y[%f] = %f, %f\n", t0, y20, exp(-t0)-y20); |
20 | }
|
21 | |
22 | int main() |
23 | {
|
24 | castelj (0); |
25 | castelj (0.25); |
26 | castelj (0.5); |
27 | castelj (0.75); |
28 | castelj (1); |
29 | castelj (1.25); |
30 | castelj (4.0/3.0); |
Die Ausgabe des Programms ist
1 | y[0.000000] = 1.000000, 0.000000 |
2 | y[0.250000] = 0.779056, -0.000255 |
3 | y[0.500000] = 0.605649, 0.000882 |
4 | y[0.750000] = 0.471418, 0.000948 |
5 | y[1.000000] = 0.368003, -0.000124 |
6 | y[1.250000] = 0.287042, -0.000537 |
7 | y[1.333333] = 0.263600, -0.000003 |
Am interessantesten hier ist die letzte Spalte, die den absoluten Fehler der Näherung vom Grade 3 zu exp(-t) angibt. Wichtig sind eigentlich nur die Auswertung (kein Hornerschema etc!) und die Konstanten y[]. Die Umstellung auf Festpunkt-Arithmetik ist dann nur noch ein bisschen Technik :-)
>Muss x= e^(-t/Tau)
Das ist doch die klassische Ausgleichskurve.
Vielleicht bringts ja was, wenn du nur ein paar Daten als Lookup
ablegst.
Etwa sowas:
1 | t/T in 0.1 | 0 1 2 ... 10 ... 20 .... 30 .... 40 .... 50 |
2 | -----------+------------------------------------------------------------------------------ |
3 | x | 100 90 82 37 14 5 2 0 |
Also das Verhältnis -t/T und das Ergebnis, skaliert in 10tel, oder in 256stel zB. Hm...
Hi @all Danke für die Felißige hilfe habe es ganz einfach gemacht habe mir Überlegt welche x Werte vorkommen können und habe dann dies in kleinere schritte aufgeteilt. Dann habe ich dass ganze in eine Lookuptabelle gelegt und einen algorithmus zugefügt der für den gewünschten x wert den mittleren aus x-1 und x+1 (welche festgelegt wurden) bestimmt. In einem bereich von -4 < x < 0 und 0,1 schrittweite bin ich sehr genau und habe bei meinen ergebnisse eine genauigkeit von ca 97-98 % erreicht also bis auf die 3 stelle hinter dem komma richtig. Damit funktioniert es genau genug Grüße
ihr müsst bei dem eben geschrieben kommentar x durch -t/Tau ersetzten Fehler von mir
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.