Hi,
Ich möchte so schnell wie möglich die Temperatur von einem Thermistor
messen. Das ganze ist auf einem STM32L0 ohne FPU und von daher sehr
ineffizient.
Folgende Zeilen Code verwende ich im Moment um die Temperatur zu
bestimmen, was soweit auch klappt:
Bert S. schrieb:> Ich möchte so schnell wie möglich die Temperatur von einem Thermistor> messen.
Ist denn die float-Berechnung der begrenzende Teil bei der
Geschwindigkeit?
Walter T. schrieb:> Ist denn die float-Berechnung der begrenzende Teil bei der> Geschwindigkeit?
Ja der kostet im Moment am meisten Ressourcen.
Bernadett schrieb:> Konstante Werte vorher zusammenfassen
Yep das kann ich sicher schon einmal machen, danke.
STK500-Besitzer schrieb:> Lookup-Table
Klingt nach einer guten Idee
Bert S. schrieb:> Walter T. schrieb:>> Ist denn die float-Berechnung der begrenzende Teil bei der>> Geschwindigkeit?>> Ja der kostet im Moment am meisten Ressourcen.
Dann guck Dir mal das ASM-Listing an, ob überhaupt durchgehend
float-Operationen stattfinden, oder ob irgendwo eine double promotion
stattfindet.
Warum rechnet man überhaupt in float, wenn es schnell gehen soll?
Ansonsten lookup-Tabelle mit linearer Interpolation zwischen den
Stützstellen sollte das effizienteste sein, sowohl in float als auch in
Festkomma.
(Abgesehen davon, daß ich nicht glaube, daß es wirklich schnell gehen
muß. Temperaturmessungen bekommt man kaum im Millisekundentakt.)
Ich würde die Formel erstmal mathematisch optimieren. Z.b. logf(tmp_f /
((float) ADC_NTC_NOM_RESISTANCE_OHM) ist das gleiche wie logf(tmp_f) -
logf(ADC_NTC_NOM_RESISTANCE_OHM). Lezteres ist konstant und schon bist
du eine Division los. Ich würde alles komplett in einander einsetzen und
durch passendes Umformen erstmal versuchen die Division soweit es geht
los zu werden. Als nächstes kann man sich dann logf genauer anschauen.
Fix-Komma Zahlen ist ein Stichwort.
Da du aber sowieso nur ganzzahlige Temperaturwerte brauchst, reicht
vermutlich einfach eine Lookuptabelle ADC->Temp. Die kann man komplett
vorberechnen und die passt - wenn man sich schlau anstellt - bei
typischen Temperaturbereichen in unter 100 Byte rein. Alleine die logf
Funktion wird mehr Code brauchen.
Temperaturen vom Thermistor ändern sich immer wesentlich langsamer als
ein noch so langsamer uC zum umrechnen braucht.
Jede Floating Point Berechnung lässt sich auch auf Fixed Point
Berechnung umstellen, zumal dir der Wertebereich des Ergebnisses ja
bekannt ist.
Fixed Point ist nichts anderes als Umrechnung an der man den
Dezimalpunkt (oder Binärpunkt) an eine beliebige Stelle hindefiniert
hat.
Dein Problem ist der Logarithmus. Wenn du den umsetzen willst, solltest
fu eine Tabelle nutzen. Die kann dann gleich die Umsetzung zwischen ADV
Wert und Temperatur machen. Eventuell nicht 1024 Einträge, sondern 64
und interpoliert.
MaWin schrieb:> Dein Problem ist der Logarithmus.
Sicher? Eigentlich sollte der Log2 eines normalisierten floats ein
Kaffeekränzchen sein, und alle anderen Logarithmen sind Log2
multipliziert mit einer Konstanten.
Nachtrag: Man kann übrigens alles, was im log() steht, (bis auf den
ADC-Wert) ausklammern. Dann wird der Log2 eines Integers abgefragt. Der
M0 hat zwar kein clz(), aber Raketenwissenschaft ist das auch nicht.
MaWin schrieb:> Temperaturen vom Thermistor ändern sich immer wesentlich langsamer als> ein noch so langsamer uC zum umrechnen braucht.
Deshalb habe ich solche Berechnungen (NTC -> Temperatur, in 0,1 Grad)
schon vor 40 Jahren auf einem Z80 gemacht und der hatte keine Probleme
damit, das so nebenher zu erledigen.
MaWin schrieb:> Dein Problem ist der Logarithmus.
Muss er nicht, ein Näherungspolynom 3. Grades ist genau genug und
braucht nur normale Multiplikationen (die Division habe ich nicht
mitgelinkt).
Heute braucht man mindestens 32bit-Prozessoren mit GHz für etwas was in
der Steinzeit ein 8bitter mit 4 MHz locker erledigt hat - was für ein
Fortschritt.
Georg
Bert S. schrieb:> Ich möchte so schnell wie möglich die Temperatur von einem Thermistor> messen.
So schnell wird das nicht sein müssen. Also könntest du die Berechnung
auch in mehrere Schritte aufteilen und jeweils eine "Teilrechnung" pro
Durchlauf der Mainloop berechnen.
STK500-Besitzer schrieb:> Bert S. schrieb:>> Jemand eine Idee, wie ich das noch optimieren kann?> Lookup-Table
Mit linearer Interpolation zwischen den Stützpunkten. So würde ich das
auch machen. Da wird man ganz schnell genauer als der Sensor an sich
hergibt und kann aufhören, noch weiter zu rechnen.
Sinnvollerweise rechnet man einen Regelagorithmus in ADC Koordinaten und
nicht in Temperatur.
Die Temperatur als float wird nur fuer den Benutzer benoetigt, und der
ist hinreichend mit 2 updates pro sekunde ausgestattet. Mehr
Screenupdates ergibt nur einen nervoesen Eindruck.
ADC Koordinaten bedeutet man rechnent des Sollwert von Temperatur nach
ADC und rechnet den Fehler Soll-ADC- IST-ADC, und macht so weiter.
Der µC hat einen 12-Bit-ADC. Wenn dessen Wertebereich komplett
ausgenutzt wird (was schon eine sehr spezielle Beschaltung des Eingang
benötigen dürfte), sind das 4096 Werte, die in der Lookup-Table
aufgeführt werden müssen.
Man kann hier also schon mal rein überschlagsmäßig die Tabelle
verkleinern, indem man betrachtet, was der realistisch vom ADC
gelieferte Mindest- und Maximalwert ist (was wohl den vom Thermistor
gemessenen Mindest- und Höchsttemperaturen entsprechen dürfte).
Dann sollte man das Thema Messauflösung betrachten. Welche Auflösung ist
bei der Temperaturmessung tatsächlich sinnvoll? Welche Auflösung
sollen denn die am Ende bestimmten Werte haben?
Wenn da Millikelvin rauskommen, hat man mit sehr hoher
Wahrscheinlichkeit irgendwas grundlegendes übersehen.
Bert S. schrieb:> Jemand eine Idee, wie ich das noch optimieren kann?
Ja, fang mal an die geschwindigkeit IMMER zu messen. Und definiere mal
wie schnell du es haben wollst.
"So schnell wie moeglich" hat oft kein zweck
Bert S. schrieb:> Ich möchte so schnell wie möglich die Temperatur von einem Thermistor> messen. Das ganze ist auf einem STM32L0 ohne FPU und von daher sehr> ineffizient.
Was willst du beim Messen mit einer FPU?
Das einzige, was du brauchst, ist ein ADC. Alles andere muss nicht
schneller sein, als sich die Temperatur auf Grund der Zeitkonstante des
Sensors ändert.
Was ist dein eigentliches Problem?
Bert S. schrieb:> Jemand eine Idee, wie ich das noch optimieren kann?
Du schreibst nicht in welchem Temperaturbereich Du es brauchst.
Ansonsten: der Umweg über den Widerstand ist nicht notwendig.
Bei kleinen Temperaturbereichen (z.B. 10-40 Grad) reicht es den Pull-Up
widerstand in die "Mitte" zu legen um bei linearer Interpolation
(Spannung zu Temperatur) maximal 0.3 Grad Linearitätsfehler zu haben.
Bei größeren Temperaturbereichen -40 .. 125 Grad reicht eine
Abschnittsweise lineare Interpolation.
Gruß Anja
Bert S. schrieb:> Ich möchte so schnell wie möglich die Temperatur von einem Thermistor> messen. Das ganze ist auf einem STM32L0 ohne FPU und von daher sehr> ineffizient.
Was ist für dich 'schnell' und was 'ineffizient'? Und wie schnell ist
dein µC?
Ich hab mal kurz deinen Quellabschnitt überflogen und komme auf 2
Multiplikationen, einen Logarithmus und fünf Divisionen. Soweit das
dasteht.
Soweit ich mich erinnere, muß man für die gewöhnliche Steinhart-Hart
Formel nicht x-mal irgend etwas immer wieder umrechnen, mal ganz grob
geht das etwa so:
tmp = ln(R);
T = 1 / (A + B*tmp + C*tmp*tmp*tmp);
Und A, B und C sind Konstanten, die du beim Kalibrieren ermittelst. Ja,
da mußt du deinen Thermistor bei 3 verschiedenen Temperaturen messen.
Und das Nette an der Sache ist, daß der Maßstab, in dem R geliefert
wird, herzlich egal ist, solange R auf die gleiche Weise bei der
Kalibrierung gemessen wird, wie danach bei den Messungen. Der ganze
Aufwand, um R in Ohm zu kriegen, ist dabei überflüssig.
Tja, um den ln kommst du nicht herum, aber wie viele Takte der bei
deiner Implementierung braucht, wäre mal herauszukriegen. Notfalls
kannst du den selber per Pseudodivision machen, das ist schneller als
eine Reihenentwicklung.
W.S.
Lookup-Table-Generator:
https://www.sebulli.com/ntc/
Ich glaube, einfacher, effizienter und schneller wird das nichts werden.
Bei 32-Stützstellen erzeugt die Tabelle im Schnitt einen Fehler von ca.
0,15 °C bei Verwendung eines 12-Bit ADC's
Ralph S. schrieb:> Lookup-Table-Generator:>> https://www.sebulli.com/ntc/>> Ich glaube, einfacher, effizienter und schneller wird das nichts werden.> Bei 32-Stützstellen erzeugt die Tabelle im Schnitt einen Fehler von ca.> 0,15 °C bei Verwendung eines 12-Bit ADC's
Das ist richtig gut! Die Zykluszeit des uC ist von 300us auf 15us
runter, wenn ich in jedem Zyklus einen NTC auslese. Danke dir!
Bert S. schrieb:> Die Zykluszeit des uC ist von 300us auf 15us> runter, wenn ich in jedem Zyklus einen NTC auslese.
Sowas nennt sich Mikrooptimierung, d.h. ohne jeden Effekt.
Kein Temperatursensor kann alle 300µs neue Werte liefern, dazu ist er
viel zu träge. Dazu braucht man Sensoren, die auf Strahlungsmessung
beruhen.
Alle 1s oder 10s eine Messung, ist für viele Aufgaben völlig
ausreichend. Nebenbei kann man dadurch den Fehler durch Eigenerwärmung
deutlich reduzieren, wenn man zwischen den Messungen den Sensor
abschaltet.
Ich arbeite seit Jahren mit digitalen Temperatursensoren und auch mit
NTCs am AD-Wandler.
Diese Sensoren sind meist sehr träge, weil sie ja auch erwärmt werden
müssen, und da die Energie ins Gehäuse erst eindringen muss.
Bei normalen Umweltsensoren meiner Maschinensteuerung wird erst nach
gewisser Zeit ein Temperaturanstieg gemessen. Von daher reicht bei mir
eine Messung pro Sekunde mehr als aus. Die Kühlung dahinter ist immer
noch super regelbar.
Falls du nicht im Millisekundenbereich mit einem Bunsenbrenner auf den
Sensor gehst, ist eine 'schnelle' Abfrage und Umrechnung vollkommen
überflüssig.
Schau erst einmal, wie schnell sich im Normalfall die Werte deines
Sensors sich überhaupt ändern.
Achja, nochwas:
Dein ADC wird rauschen. Es wäre praktischer, erst einmal ein paar
ADC-Werte zu sammeln, und dann einen Mittelwert daraus berechnen, um das
Rauschen zu entfernen. Erst danach mit dem Mittelwert eine Temperatur
berechnen.
Bert S. schrieb:> Die Zykluszeit des uC ist von 300us auf 15us> runter
Und wozu brauchst du 60000 Temperaturwerte pro Sekunde?
Wasserstoffbombenexplosion analysieren?
Vermutlich hast du dich vollkommen verrannt.
Georg