Unter dem IAR kommt schon bei x1 0 Raus !!! Und bei T= zerlegt es das ganze Programm ( Stack overflow ??)
Verwendet wird ein AtMega88.
Der IAR soll verwendet werden, weil der wohl der einzige AVR Compiler ist der double unterstützt.
Im Moment verwenden wir zum Test die 30 Tage Eval Version. Wenn das mit der Genauigkeit funktioniert wie gewünscht, dann würden wir die Vollversion kaufen. Im Moment haben wir daher auch keinen Support von IAR.
Kenne den IAR nicht, aber hast du acuh die entsprechende Bibliothek eingebunden? 64-bit-Fliesskomma-Arithmetik auf einem 8-bit Processor zu implementieren, duerfte so viel Code/Performance erfordern, dass der Compiler/Linker dass bestimmt nicht automatisch unterstuetzt, sondern nur auf Anforderung.
Warum eigentlich? In deinem geposteten Code Beispiel, kann ich nicht unmittelbar sehen, warum 32-bit Fliesskomma nicht ausreichend sein sollte. Und du willst vermutlich auch nicht Temperatur einer Aufloesung von mehr als 5-6 Nachkommastellen messen.
Ich denke, wenn du denen sagst, dass dieses Feature kaufentscheiden ist, dann werden dir die schon weiterhelfen.
AVR Compiler benutze ich nicht, aber diverse andere für µC. Im Zweifelsfalle würde ich IAR trotzdem kontaktieren, genau mit deinem Argument des Kaufes wenn es ok ist. Wenn die nicht auf den Kopp gefallen sind, dann werden sie schon helfen. Ansonsten was soll das Ding machen? Die Routine scheint ziemlich "um die Ecke" gedacht. Die Konstanten ausmultiplizieren, ansonsten die Multiplikationen aufteilen. Manche Kompiler reagieren merkwürdig, wenn die Formel zu kompliziert werden. Wenn die Konstanten veränderbar sein sollten, dann bitte schön als const deklarieren (oder per #define) und die Berechnungen beim Startup machen.
Waldemar
PS.
Unten habe ich etwas bereinigt, wenigstens den Anfang
double PT100_Temp(double R) {
double T = 0; double x1 , x2 , x3 , x4 , x5 ;
// besser so, wenn man sowieso nicht von vorne es ausrechnet und // einsetzt. Hier erspart man mehrere Multiplikationen und Konversionen x1 = 3.908302E-3; x1 *= (double) 100.0; x4 = -x1; x1 *= x1;
Der IAR ist (im Gegensatz zum GCC) ein zwei-Stack-Compiler, d. h. der Parameterstack unterscheidet sich vom Returnstack. Zwar wird die Behandlung der Parameter (und lokalen Variablen) auf dem Stack damit einfacher, aber der Preis ist, dass man keinen "automatischen" Stack mehr für beide implementieren kann, einer von beiden ist in der Größe zwangsläufig limitiert (und bei zu großer Reservierung ist er nicht genutzter RAM).
Langer Rede kurzer Unsinn: hast du dir die Stack-Einstellungen mal angeguckt? Ich weiß nicht mehr ganz genau, welcher von beiden den anderen zerstören könnte.
Ich sehe gerade, daß "double" beim avr-gcc "nur" 32 Bit hat.
Ich weiß ja nicht, was am Ende herauskommen soll, aber wenn die Datenquelle 12Bit Auflösung hat, kann ich mir nicht vorstellen, welche Anwendung für einen Microcontroller 64Bit-Operationen erfordern sollte...
irgendwie glaube ich, dass du etwas von der Arschseite an das Problem rangehst, aber vielleicht irre ich mich. Benutzt du irgendwelche Filter, die sehr empfindlich auf Koeffizientengenauigkeit sind? Hast du es schon simmuliert auf einem PC? Manchmal kann solche Analyse ziemlich viel Ärger ersparen. Dann sieht man, wo sich die Fehler kummulieren und ob 64 Bit wirklich notwendig sind. Auf einem 8-Bitter würde ich es vermeiden wollen. Bei 12 Bit ADC hast du 10-11 signifikante Stellen. Bis 32 ist noch ziemlich viel Luft.
Stimmt. Ist die Frage wie genau willst du sein. Ich glaube, bei 32 Bit hast du 24+8 für Mantisse und Exponent. Ansonsten kann man im Integer-Bereich herumwursteln, aber das ist für hard-cores :-)
Spätestens ab dem Moment nicht mehr, wenn die per ADC gewonnene Größe als Eingangsgröße für Gleitkommaberechnungen dient. Insbesondere auch dann nicht, wenn es, wie in diesem Fall, gar die einzige Eingangsgröße ist.
12 Bit? Welcher Mega88 hat denn einen 12Bit-ADC?
Und selbst, wenn tatsächlich eine externe hochgenaue 12Bit-ADC am Werkeln sein sollte, unterstützt von einem fiktiven Pt100-Meßwiderstand, der die Kennlinie um Größenordungen genauer einhält, als der Standard verlangt, und das beides samt Verkabelung in einer Umgebung existiert, die einen SNR von 120 dB garantiert, sind es am Ende immer noch nur exakt 4096 diskrete Werte, die da letztlich aus dem ADC rauspurzeln können. Da kannst du dir den Arsch aufreißen für deinen IAR, das werden nicht mehr Werte und nicht mehr Bits, die zu ihrer Darstellung nötig sind.
Ich möchte jetzt nicht weiter ausführen, was das bezüglich der sinnvollen Rechengenauigkeit bedeutet, weil sich diese Frage für jeden Normalbegabten zumindest im Fall der konkreten Funktion erst garnicht stellt. Für die mit dem ADC-Output als einziger Input-Größe tritt nämlich eher in den Vordergrund, daß man die paar tausend Werte bzw. ihre Funktionsergebnisse locker zur Entwurfszeit (oder noch davor) vorberechnen und als (ggf. sogar massiv komprimierte) Tabelle in den Flash legen kann.
Diese Tabelle wird wahrscheinlich sogar kleiner sein als der Code für die benötigten Double-Operationen und die Laufzeiteffezienz des Table-Lookup selbst in einer stark komprimierten Tabelle dürfte gegen diese unsäglichen Double-Operationen zur Laufzeit mindestens um den Faktor 1E4 im Vorteil sein. Natürlich ohne jeden Verlust bei der von dir so dringend geforderten "Genauigkeit"...
Fazit: Leute wie du sollten lieber weiter die Fortschritte der PC-Hardware mit möglichst langsamer Software ausbremsen. Laßt die Finger von den µC. Ihr seid einfach noch nicht soweit, die wirklich effizient durch eure Unfähigkeit auszubremsen. Da müssen zuvor z.B. erst noch die Compiler beschafft werden, mit denen man den Keim der Ineffizienz wirklich so richtig sprießen lassen kann. Aber tröste euch: Auch Microsoft ist noch nicht soweit, Windows 7 auf dem ATMega88 vorzustellen. Auch Intel ist derzeit zu stark beschäftigt, die eigenen Atome auszubremsen, hat also keine freien Spitzen, um auch zu Hilfe zu kommen.
Eventuell kann man die Berechnungen aber etwas geschickter umformen, um mit weniger Aufwand hinzukommen. Und vielleicht noch andere Fehlerquellen betrachten: Wie genau rechnet z.B. die sqrt-Funktion in dieser Library?
64Bit-Gleitkommaoperationen auf einem schnöden Temperaturwert sehen doch ein wenig nach der Taktik "Hilfe, ein Spatz - wo ist meine FLAK?" aus. Im Extremfall (und mit viel Vorüberlegungen) könnte man sowas sogar in ausreichend langen Integern rechnen, da weiss man auch genau wann Bits wegfallen.
Das ist aus dem obigen Code aber nicht ersichtlich - lauter Konstanten. Eventuell ließe sich auch eine Kennlinie oder ein Kennfeld im Flash ablegen und noch dynamisch verschieben?
Guck' mal in den Header. Diesen Newsreader verwenden nicht so viele Pöbler ;-)
...
Wahrscheinlich wirst Du um die Berechnung der Rundungsfehler ohnehin nicht herumkommen. Dann kannst Du evtl. auch gleich auf 32Bit oder sogar
16Bit Integer umstellen. Am Ende könnte das deutlich zuverlässiger funktionieren.
...
Die Funktion PT100_Temp() kann nur 4096 verschiedene Werte (12 Bit) liefern weil es nur 4096 mögliche Parameter gibt. Das könnte man auch mit einer Tabelle lösen, wenn man alle Rückgabewerte im Flash unterbringen könnte ;-)
Einem Datentyp, mit dem man nie (foo == bar) schreiben kann, vertraue ich sowieso nicht.
Das ist richtig. Aber bei der konkreten Funktion der Fehler auch bei der Verwendung von single längst nicht groß genug, um stören zu können.
Natürlich ändern sie sich, aber sie können niemals andere Werte annehmen, als in zwölf Bit unterzubringen sind. Und da es die einzige variable Größe der Funktion ist, kann es auch nur exakt 4096 mögliche Funktionsergebnisse geben. Und die kann man mit jeder gewünschten Genauigkeit vorberechnen und die Ergebnisse als Tabelle von 12 Bit-Werten ablegen. Eine viel genauere Darstellung der Ergebnisse macht keinerlei Sinn, weil eben am Eingang auch schon nur 12 Bit Genauigkeit vorhanden sind. Aus praktischen Gründen würde man aber wohl mit 16 Bit für die Ergebnisse arbeiten. Es werden dann exakt 8192 Byte für die unkomprimierten Ergebnisse benötigt.
Wenn man sich aber die Eigenschaften der Ergebnisse anschaut, wird sich einen gewaltige Redundanz ergeben, sie werden sich also ganz hervorragend komprimieren lassen. Dazu ist nichtmal ein richtig guter Entropie-Encoder nötig, sondern selbst mit einfachsten Mitteln (Speicherung der Differenzen benachbarter Werte mit einigen Stützpunkten in voller Genauigkeit zur Verringerung des Rechenzeitaufwandes für die "Dekomprimierung", also den Lookup in die Tabelle) ist schon eine Komprimierung knapp um den Faktor 4 erreichbar. Wir sind dann also bei gut 2k Platzbedarf.
Und in gut 2k bringst du sicher keine Double-Bibliothek unter. Die Lösung mit vorberechneten Werten ist also in absolut jeder Hinsicht weit überlegen. Sie ist zur Laufzeit viel schneller und benötigt weniger Platz im Flash.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.