hallo!
Bis gestern war total klar "kein Floating Point auf einem uC". Jetzt
habe ich vielleicht einen Schatz gefunden, und zwar eine kleine log().
Wenn man sowieso einen Cortex-M4 mit FPU hat, kann man damit einen NTC
per Steinhart-Hart linearisieren. Die steinhart_hart() belegt 68 Byte
und die log() 152 Byte. Damit spare ich gegenüber der Integer-Rechnung
gute 800 Byte (ja, ok, die Tabelle könnte evt. weniger Stützstellen
haben).
Das Beste: es wird absolut nichts aus externen libs eingebunden. Ja, es
ist langsamer, float braucht 160 Taktzyklen, int 38. Aber, zum
Vergleich, die Ausgabe der Temperatur mit Integer-printf() und 115200
Baud braucht über 6000.
Verglichen mit der Tabelle aus dem NTC-Datenblatt macht die Linearisung
praktisch keinen Fehler, der Buckel bei 80 bis 100 Grad ist Absicht, ich
will die Außentemperatur messen.
Die log() selbst ist allerdings, nun ja, etwas speziell. Böse Zungen
sagen
1
This directory was an experiment to use floating-point operations
2
to implement the math library when a processor had a floating-point
3
instruction set. The experiment was a failure in that some of the
4
algorithms chosen (e.g. recursive algorithms for sin/cos, etc..)
5
are too simple and do not provide proper accuracy nor handle very
6
large or very small inputs adequately.
Aber für den Wertebereich aus dem wirklichen Leben passt sie perfekt,
oder? Übersehe ich etwas? Was könnte schief gehen?
Bauform B. schrieb:> Bis gestern war total klar "kein Floating Point auf einem uC".
Und warum gibt es dann Mikrocontroller mit FPU? Klar kann man float
gewinnbringend einsetzen, es gibt eine Menge numerischer Algorithmen die
mit Integer-Arithmetik gar keinen Sinn machen. Natürlich muss man die
numerische Stabilität berechnen um sicher zu gehen, dass das Ergebnis
keinen Fehler von 5000% hat...
Bauform B. schrieb:> Bis gestern war total klar "kein Floating Point auf einem uC".
Wieso war das "total klar"? Ist es natürlich nicht. Spätestens dann,
wenn man die Eigenschaften von FP wirklich braucht, dann nutzt man
natürlich auch FP.
> Wenn man sowieso einen Cortex-M4 mit FPU hat
Wenn man dann auf dem Target auch noch Hardwaresupport dafür hat, fällt
die Entscheidung dafür natürlich noch deutlich leichter.
> kann man damit einen NTC> [...] linearisieren.
Tja, das allerdings ist eine Anwendung, bei der man nicht annähernd
zwingend die Eigenschaften von FP braucht.
D.h.: Du bist hier in der komfortablen Situation, aus mehreren möglichen
Implementierungen wählen zu können. Good luck. Da wägt man dann einfach
die Vor- und Nachteile der verschiedenen Implementierungsmöglichkeiten
bezüglich der konkreten Gesamtanwendung gegeneinander ab und wählt das
bessere.
Wenn's man immer so einfach wäre...
Übrigens: Einen Logarithmus kann man auch mit Integer-Arithmetik (fixed
point) berechnen. Es gibt also sogar (mindestens) eine dritte
Implementierungsmöglichkeit. Die Tabelle (und damit deren
Speicherverbrauch) entfällt auch damit, der Code wäre allerdings etwas
fetter und langsamer als der FP-Code.
Programmierer schrieb:> Klar kann man float> gewinnbringend einsetzen
Absolut richtig.
Ob man float wirklich immer braucht, ist die Frage.
Bei Temp.sensoren ist spätestens die zweite Nachkommastelle komplett
uninteressant. Meist reichen ganze Werte.
Mir hat die Tabelle gute Dienste geleistet, ist für Libre Office (habe
ich sowieso installiert). Spart dir vielleicht noch ein paar Bytes mehr.
http://afug-info.de/Download/tab/NTC/
> Wieso war das "total klar"? Ist es natürlich nicht. Spätestens dann,> wenn man die Eigenschaften von FP wirklich braucht, dann nutzt man> natürlich auch FP.
Naja, man kann bei der Leistungsfaehigkeit heutiger Microcontroller auch
schon mal FP nutzen wo man frueher alles auf Integer skaliert hat.
Braucht im Zweifel vielleicht etwas mehr Strom. Sollte man bedenken wenn
man etwas Batterie betriebenes baut.
Und bei sowas wie Temperaturmessung, was also sicher nicht oefters wie
einmal pro Sekunde passiert kann man schon schludrig bezueglich der
Effizenz sein. :)
Olaf
Guest schrieb:> Bei Temp.sensoren ist spätestens die zweite Nachkommastelle komplett> uninteressant. Meist reichen ganze Werte.
Da könnte ich Dir auf Anhieb ein Gegenbeispiel nennen:
Fieberthermometer.
Und bei TCore(tm) Sensoren, bei denen man von außen gemessenen
Temperaturen in den Körper "hineinrechnet", braucht es dann auch die
1/100er Stellen noch halbwegs genau.
Bauform B. schrieb:> Bis gestern war total klar "kein Floating Point auf einem uC".
Irrtum.
Temperatursensoren sind so träge, da kann selbst ein 8Bitter spielend
das bischen float ausrechnen. Z.B. ein AVR bei 1MHz CPU-Takt sollte
dicke reichen.
Peter D. schrieb:> Bauform B. schrieb:>> Bis gestern war total klar "kein Floating Point auf einem uC".>> Irrtum.
Selber Irrtum bzw. Missverständnis. Wenn ich sage, dass das klar war,
dann ist das eine Tatsache und nicht verhandelbar. Verhandelbar wäre
meine Behauptung "die Erde ist keine Scheibe", da kannst du mit deinem
Irrtum kommen, aber nicht bei Floating Point auf meinem uC.
Ihr habt, glaube ich, das Beste überlesen:
Bauform B. schrieb:> Das Beste: es wird absolut nichts aus externen libs eingebunden.
Damit vermeide ich alle Probleme mit Updates und meistens auch den
Stress mit Lizenzen. In diesem Fall kann ich die log() leider doch nicht
einsetzen, weil die Quelle keinen Hinwies auf eine Lizenz enthält. Die
stammt aus der newlib und da werden zwei Dutzend Lizenzen mitgeliefert,
aber es ist nicht klar, welche wofür gilt.
Peter D. schrieb:> Temperatursensoren sind so träge, da kann selbst ein 8Bitter spielend> das bischen float ausrechnen.
Und dafür müsste ich auf den o.g. Vorteil verzichten oder die Floating
Point Routinen selber programmieren. Beides ist nicht besonders
attraktiv und deshalb würde ich int bzw. fixed point verwenden.
Bauform B. schrieb:> Bis gestern war total klar "kein Floating Point auf einem uC". Jetzt> habe ich vielleicht einen Schatz gefunden, und zwar eine kleine log().> Wenn man sowieso einen Cortex-M4 mit FPU hat, kann man damit einen NTC> per Steinhart-Hart linearisieren. Die steinhart_hart() belegt 68 Byte> und die log() 152 Byte. Damit spare ich gegenüber der Integer-Rechnung> gute 800 Byte (ja, ok, die Tabelle könnte evt. weniger Stützstellen> haben).
Warum nimmst Du nicht einen linearen NTC? Bekommt man schon für 25 Cent.
https://www.ti.com/product/TMP61
Datenblatt
https://www.ti.com/lit/ds/symlink/tmp61.pdf
Angebote von Mouser
https://www.mouser.de/Search/Refine?Ntk=P_MarCom&Ntt=160074969
Ok, bis zum Februar dieses Jahres wuste ich auch nicht, dass es linerare
NTC gibt oder geben könnte. Aber TI liefert welche. Mir persönlich ist
ein PT1000 natürlich lieber.
mfg Klaus
Klaus R. schrieb:> Warum nimmst Du nicht einen linearen NTC? Bekommt man schon für 25 Cent.
Naja, bei 500 Stück. Der aktuelle NTC kostet dann 3.38, kommt aber
komplett mit Edelstahlhülle und langem Anschlusskabel. Bis ich den TMP61
wetterfest verpackt habe, dürfte er ein wenig teurer werden. Die
SMD-Varianten kommen dafür wohl kaum in Frage, deshalb die 500 Stück.
Ein anderer NTC wird z.B. in ein 60 mm tiefes Sackloch mit 3 mm
Durchmesser eingeklebt, da kostet alleine die Bohrung mehr. Vor allem
wäre der TMP61 zu dick.
Dann ist der TMP61 mit 0.6%/K zwar besser als ein Pt1000, aber ein NTC
kommt auf 4.4%/K. Die Anforderungen an die Analogelektronik sind
entsprechend humaner. Ich brauche nichts weiter als den
Referenzwiderstand und ein paar Filter-R/C und der 12-Bit-ADC im uC wird
gut ausgesteuert (3250...400 @ -25...50°C).
Der TMP61 ist kein Widerstand, der wird in einer so einfachen Schaltung
(noch) ungenauer, deshalb wird 200uA Konstantstrom empfohlen. Es gibt
vielleicht Spezial-ADCs die diese Betriebsart unterstützen, aber der
Aufwand für eine genaue Konstantstromquelle ist im Vergleich utopisch.
Der TMP61 ist in der empfohlenen Schaltung nicht mehr linear, man sollte
ein Polynom 4. Grades benutzen. Trotzdem ist die Empfindlichkeit
deutlich schlechter als beim NTC.
Ein Pluspunkt ist das Datenblatt, von meinem aktuellen NTC weiß man nur
10k ±1% bei 25°C. Der TMP61 ist genauso spezifiziert, aber weil er
unempfindlicher ist, entspricht das einem Fehler von ca. 1.5 Grad
gegenüber 0.25 beim NTC. In anderer Hülle gibt es NTCs, die mit ±0.1
Grad von 0...70°C spezifiziert sind. Und die lassen sich immer noch
leichter einbauen als der TMP61.
Früher hat man zwei unterschiedliche NTCs in einer Perle mit zwei
Widerständen kombiniert. Die Kombination war z.B. von -20 bis +50°C mit
±0.2 Grad spezifiziert, also linearer als der TMP61 und genauer sowieso.
Also, wenn ich mal die Temperatur einer Platine schätzen möchte, nehme
ich den TMP61. Oder nicht, weil die meisten Cortex-M können die
Chip-Temperatur messen.
Tut mir leid ;)
Bauform B. schrieb:> bild3.png
Hast du in diesen Plot mal die Abweichungen deines NTC von der
Nennkennlinie im Datenblatt bzw. die Fehler deiner Kalibriereinrichtung
eingezeichnet? ;-)
Wolfgang schrieb:> Bauform B. schrieb:>> bild3.png> Hast du in diesen Plot mal die Abweichungen deines NTC von der> Nennkennlinie im Datenblatt
Wer will das so genau wissen? Bei 25°C garantiert man mir ±0.25 Grad,
das muss reichen.
> Kalibriereinrichtung
gibt's nicht; das Wichtigste ist, dass die Genauigkeit ohne jeglichen
Abgleich ausreicht. Im Betrieb scheint vielleicht mal die Sonne auf
den NTC. Oder, ungeschickt eingebaut, macht ein Linearregler in der Nähe
0.5 Grad Fehler :)
Zum NTC gibt es eine Tabelle Widerstand vs. Temperatur in 1 Grad
Schritten. Daraus hab' ich die Koeffizienten für Steinhart-Hart gewonnen
und dann war ich gespannt, wie gut eine so einfache Gleichung mit der
Natur übereinstimmt.
Bauform B. schrieb:> Damit vermeide ich alle Probleme mit Updates und meistens auch den> Stress mit Lizenzen.Bauform B. schrieb:> die Floating> Point Routinen selber programmieren.
Hä?
Das muß dann aber schon ein sehr besonderer Compiler sein, wo float
nicht Bestandteil der Standard-Libs ist.
Ich binde einfach <math.h> ein und kann dann float uneingeschränkt
nutzen. Von Lizenzen dafür habe ich noch nie was gehört.
Bauform B. schrieb:> Wer will das so genau wissen? Bei 25°C garantiert man mir ±0.25 Grad,> das muss reichen.
Eben, schon die üblichen Probleme bei der Erfassung der Außentempperatur
(was ist das genau?) lassen 0.25° Genauigkeit als Augenwischerei
erscheinen. Und jetzt betrachte diese garantierte Abweichung mal in
Relation zu der Genauigkeit deiner Rechnung: Hübsche Spielerei, aber
Perlen vor die Säue - irgendwie muss der Cortex-M4 natürlich beschäftigt
werden und die FPU ihre Daseinsberechtigung haben ;-)
Peter D. schrieb:> Bauform B. schrieb:>> die Floating Point Routinen selber programmieren.>> Hä?>> Das muß dann aber schon ein sehr besonderer Compiler sein, wo float> nicht Bestandteil der Standard-Libs ist.
Naja, der offizielle gcc und binutils von/für arm zum Beispiel. Damit
werden zwar GigaBytes von allem möglichen auf dem PC installiert, aber
dank magischem Schalter "-nostdlib" wird kein Byte Code aus fremden
libs dazu gelinkt.
Wolfgang schrieb:> jetzt betrachte diese garantierte Abweichung mal in> Relation zu der Genauigkeit deiner Rechnung: Hübsche Spielerei, aber> Perlen vor die Säue - irgendwie muss der Cortex-M4 natürlich beschäftigt> werden und die FPU ihre Daseinsberechtigung haben ;-)
Ja eben, ich bezahle die ja schließlich mit ;) Mich hat halt total
überrascht, wie das Ganze quasi von selbst funktioniert hat, ohne
gravierende Nachteile zu haben. Ja, man braucht für Interrupts mehr
Stack, aber vielleicht 2 Taktzyklen mehr, wenn überhaupt.