Forum: Mikrocontroller und Digitale Elektronik ADC Temperaturwert umwandeln in Temperatur


von Florian_unbekannto (Gast)


Lesenswert?

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...

von Karl H. (kbuchegg)


Lesenswert?

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.

von MaWin (Gast)


Lesenswert?

Ü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.

von Florian_unbekannto (Gast)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

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.

von Florian_unbekannto (Gast)


Lesenswert?

das wäre cool! kannst du mir kurz erklären wie du das meinst anhand 
meines Beispiels von onben?

von Purzel H. (hacky)


Lesenswert?

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

von Arc N. (arc)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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.

von Florian_unbekannto (Gast)


Lesenswert?

also bei mir kommt für m = 0.015199878... raus. mach ich irgendwas 
falsch? Weil du meinst mitr  1,x??

von Florian_unbekannto (Gast)


Lesenswert?

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?

von Florian_unbekannto (Gast)


Lesenswert?

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?

von Wusel D. (stefanfrings_de)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

(ADC werte -16384)*1585
1
x = ADC;
2
ADC -= 16384;
3
4
tmp = ADC << 10;// * 1024
5
tmp+= ADC << 9; // * 512  ( * 1536 )
6
tmp+= ADC << 5; // * 32   ( * 1568 )
7
tmp+= ADC << 4; // * 16   ( * 1584 )
8
tmp+= ADC;      // * 1    ( * 1585 )

keine ahnung ob die interne mulitplikation es auch so macht.

von Florian_unbekannto (Gast)


Lesenswert?

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

von Florian_unbekannto (Gast)


Lesenswert?

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...

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
Noch kein Account? Hier anmelden.