Hi,
vielleicht kann mir jemand weiterhelfen. habe schon etliche Beiträge zu
diesem Thema gelesen, aber keiner hat mir so richtig Antwort auf meine
Frage gegeben. Außerdem versuche ich mein nachgelesenes Wissen für
andere nochmal kompakt zussammenzufassen.
Ich habe einen einen ADC der mir ratiometrisch den Widerstand eines
Platin 1000 widerstandes berechnet. Der ADC hat eine Auflösung von
15Bit, sprich sein maximalwert ist 32768.
Wenn ich einen 2kOhm Widerstand als Refernz dranhänge folgt daraus, dass
er bei 0°C(PT1000) als ADC wert 32768/2 = 16384 hat.
Bei 100°C liefert er dann 1385,06ohm/2000ohm * 32768 = 22693.
Das ist auch der Messbereich der für mich interessant ist.
Jetzt habe ich also 22963-16384 = 6309 Werte die meinen Bereich von 0
bis 100°C widerspiegeln.
So wie es verstanden habe, gibt es jetzt 3 Varianten das ganze zu
realisieren.
1. LookUp Table Variante 1:
Man schreibt in eine LUT für alle 6309 Werte jeweils, welcher
Temperatur sie entsprechen. D.h 100C° = LUT[6309] bzw LUT[ADCwert-
16384]
Das ist sehr schnell verbraucht aber 6309 * 2Byte. Also circa 12kb Flash
Wenn man z.B. 100,05°C also 10005 speichert. Die Auflösung soll 0,05°C
betragen.
2. LookUp Table Variante 2:
Man macht die LUT anders herum. D.h ADCWert = LUT[56,05°C].
Jetzt macht man eine binäre Suche guckt welcher Wert des Wandlers am
nächsten zu einer ADC Stiufe ist, die über die LUT erreichbar ist.
Vorteil ist, dass jeder TempWert einmal abgebildet ist, aber die binäre
Suche länger dauert und dann muss man die Adresse der LUT noch in einen
Temeratur umrechnen.
3. Einfach linearisieren oder Van Dusysen Formel benutzen.
Bei der Linearisierung muss dann folgendes Berechnet werden
Temp = m*ADCWert- b; b und m sind mit zwei Werten einfach zu bestimmen.
Allerdings schrevke ich da von der Floating Point Multiplikation doch
schon sehr zurück.
Was meint ihr dazu? Das Problem ist das halt parrallel noch ein
Webserver betrieben werden soll und ein PI Regler und ich Angst habe,
dass gerade die 3. Variante sehr viel Rechenleistung verbraucht.
Wenn man die erste Variante benutzt, muss ja zur Anzeige der Int Wert
noch in einen Ascii Wert umgerechnet werden. Braucht sowas viel Zeit?
Oder sollte man lieber direkt als Ascii speichern? Das benötigt dann
aber 4 Bytes pro ADC Stufe...
Vielen Dank für eure Hilfe...
Florian_unbekannto schrieb:> Was meint ihr dazu? Das Problem ist das halt parrallel noch ein> Webserver betrieben werden soll und ein PI Regler und ich Angst habe,> dass gerade die 3. Variante sehr viel Rechenleistung verbraucht.> Wenn man die erste Variante benutzt, muss ja zur Anzeige der Int Wert> noch in einen Ascii Wert umgerechnet werden. Braucht sowas viel Zeit?
Nein
Generell denke ich, dass du zuviel Schiss vor Berechnungen hast. So ein
µC ist zwar kein Desktop-System mit ein paar GigaHerz aber ein paar 1000
mal pro Sekunde kann der schon durch die Berechnung durchhacheln. Zumal
ja Temperaturmessungen im Normalfall nicht wirklich zeitkritisch sind
und sich Temperaturen eigentlich nicht besonders schnell ändern. D.h.
zum Beispiel, dass wenn du vom ADC denselben Wert kriegst wie bei der
Messung zuvor, dann kannst du dem µC die komplette Berechnung sparen,
weil du weißt das da nichts anderes als zuvor rauskommen wird.
PS: 0.05°
was misst du und wie gut ist der Klimaschrank, in dem der Sensor sitzt?
0.05°C sind praktisch nie sinnvoll. Wenn da jemand in 3 Meter Entfernung
am Sensor vorbeigeht, ändert sich die Temperatur durch den Luftzug schon
um mehr.
Üblich wäre lineare Interpolation (also 3. erster Fall)
oder lineare Interpolation durch mehr Stützwerte, sagen wir 10,
was nicht weniger aufwändig als 3. ist.
Bei hohen Genauigkeitsanforderungen auch Van Dusen Formel,
dann muss man eben mit der Rechenzeit leben, Temperaturen
ändern sich ja eher langsam, man hat also Zeit, die muss
man nur verteilen.
Ok, erstmal herzlichen Dank für die Antworten.
@Karl Heinz. Der Sensor liegt an einem Rohr. Das Sytem hat also eine
recht hohe Wärmekapazität. Wenn das zu fein ist gehen auch 0,1C. Das
wollte ich einfach mal ausprobieren...Ist das erste mal, dass ich sowas
mache.
Die Angst vor der Rechenzeit habe ich, da ich gelesen habe, dass mit so
einem Webserver( bzw muss der eigentlich erstmal nur ein Socket
bereitstellen) steht noch nicht fest, der XMEGA schon sehr ausgelastet
ist. Hab mal einen Regler gebaut, der lief allerdings auch schneeler
durch als 1/sek, da hat diese floating Rechnerrei das ganze Dingen
lahmgelegt.
Die LUT haltet ihr nicht für gut? Ist ein XMEGA 128. Also genug Speicher
hat der allemal...
Speicherung dann direkt in ASCII oder also double?
Florian_unbekannto schrieb:> da hat diese floating Rechnerrei das ganze Dingen> lahmgelegt.
die Frage ist wozu man floating braucht? Man kann in in 1/10 Grad
rechnen und int verwenden.
Ich bau Temperatur Regler mit einem Mega32, rechne mit Float fuer das
Benutzerinterface, mit integern fuer den Regelalgorithmus, update 3 mal
pro Sekunde und kommuniziere noch nebenbei.
Ich rechne mit 0.01 Kelvin Aufloesung in Integern.
Das waeren dann +-320 Grad Bereich fuer einen 16bit integer.
Ich rechne den Algorithmus aber mit Longint, 32bit.
Der Regler sollte mindestens die 10fache Aufloesung wie spezifiziert
rechnen.
Und dann ist noch Einiges an Luft
Florian_unbekannto schrieb:> Die LUT haltet ihr nicht für gut? Ist ein XMEGA 128.
Warum nicht? Es muss ja nicht für jeden ADC-Wert ein Eintrag in der LUT
vorhanden sein, sondern bspw. nur jeder zweite oder vierte Wert.
Die Zwischenwerte lassen sich dann mit Additionen und Shifts berechnen.
Florian_unbekannto schrieb:> Ich habe einen einen ADC der mir ratiometrisch den Widerstand eines> Platin 1000 widerstandes berechnet.
Huch?! Seit wann berechnet ein ADC irgendwas?
> Jetzt habe ich also 22963-16384 = 6309 Werte die meinen Bereich von 0> bis 100°C widerspiegeln.> 1. LookUp Table Variante 1:
Die schnellste Variante, aber platzraubend.
> 2. LookUp Table Variante 2:
Reiner Blödsinn.
> 3. Einfach linearisieren oder Van Dusysen Formel benutzen.> Temp = m*ADCWert- b; b und m sind mit zwei Werten einfach zu bestimmen.> Allerdings schrevke ich da von der Floating Point Multiplikation doch> schon sehr zurück.
Zu recht. Sowas rechnet man natürlich als Festkomma. Im konkreten Fall
paßt das sehr gut, weil m irgendwas bei 1,x sein muß und 7 Nachkommabits
gebraucht werden, um nix von der Genauigkeit zu verlieren, m paßt also
ideal in ein Byte rein, ein Bit vorm'm Komma, 7 dahinter.
Der Meßwert ist in zwei Bytes. Du machst also eine 8x16Bit unsigned
integer-Multiplikation, shiftest das 3-Byte-Ergebnis ein Bit nach links
und wirfst das unterste Byte dann wech. In den oberen zwei Byte steht
dein Ergebnis. Da brauchst du bloß noch b aufzuaddieren. Manchmal ist es
auch sinnvoller, die den konstanten Teil schon vor der Multiplikation zu
behandeln, aber im konkreten Fall ist's egal.
Das ist die platzsparendste Variante und bei genauerer Betrachtung des
Gesamtkontextes ist sie nicht mal viel langsamer als die mit der LUT.
Jedenfalls auf'm AVR und in Assembler wäre das der Fall.
habe mich jetzt mal hieran orientiert:
http://www.mikrocontroller.net/articles/Festkommaarithmetik
Demnach müsst ich meine (ADC werte -16384)*1585 rechnen.
Dann habe ich ein gutes Ergebnis. Muss nur noch die restlichen 4 Stellen
verwerfen. Das sollte jedoch machbar sein. Wäre das okay? Oder besser
Teilen durch 10000?
Wie lange dauert denn so eine 16*16Bit operation?
Hi,
so kleines update...
habe mal gerade auf meinem avr simulator in studio 6 32bit*32bit = 32bit
ausgeführt. Das soll nur 12 Takte benötigen und ist damit viermal
schneller als mit mehreren Bitshifts und dann aufaddieren...
Kann das sein?
So schnell kann das doch garnicht sein oder?
Ich glaube, die Anzahl der Takte hängt von den Werten ab, die da
multipliziert werden. Das ist keine Konstante.
Ich hab' da noch eine Idee zur Beschleunigung: Man könnte sich eine
Lookup Tabelle anlegen, in der die letzten 10 Berechnungsergebnisse
abgelegt werden, sozusagen als cache.
Peter, genausao habe ich es gemacht und das hat ungefähr viermal so
lange gebraucht..Ich denke mal der Compiler wird so schlau sein, das
mindestens genauso gut zu machen...oder?
Nur kamen mir 12 Takte sau kurz vor. Vorallem weil einen Appnote von
atmel 121 Takte braucht
aaaah, habe gerade noch einen Appnote gefunden.. Die 201.
Die benutzt die Hardware-Multiplikation. Da sind 17 Taktzyklen
angegeben.
Also passt das doch sehr gut. Braucht man sich also nicht so große
Gedanken machen.
Das verwirft natürlich auch meine LookUpTaable, bei 12 Taktzyklen brauch
man garnicht drüber reden:-) Hatte ich niemals so schnell erwartet...