Hallo Ich habe hier schon einige Beiträge zum Thema PT1000 gelesen. Bin allerdings immernoch nicht richtig weiter gekommen. Vorneweg, ich habe diese Temperaturmessung so auf meinem Board. Ein Digitaler Sensor ist auch vorhanden, dieser soll aber mit dem Analogen verglichen werden. Also brauche ich diese Analoge Messung. Die Umrechnung soll auf einem 8051 in C erfolgen. Der Strom durch den PT1000 kommt aus einer Konstantstromquelle. Wenn ich mir den "Rohwert" der Messung ausgeben lasse, komme ich bei Zimmertemperatur (22°C) auf 3700. Ich habe jetzt mal so angefangen dass ich diesen Wert durch die Verstärkung und den Strom geteilt hab. Dann sollte ich ja den Widerstand herausbekommen. Dann wollte ich über die Geradengleichung die Temperatur errechnen. Allerdings funktioniert das so nicht. Habt ihr mir hier ein paar Tipps wie ich das am besten hin bekomme? Vielen Dank schonmal! Grüße Bean
Du musst erst in Widerstand (Ohm) umrechnen, dann siehe hier: Beitrag "PT100 Berechnung der Temperatur @ Widerstand"
Ja, vielen Dank. Diesen Beitrag habe ich mir auch schon durchgelesen. Allerdings möchte ich mir die Wurzelberechnung sparen, da ich nicht die math.h includieren will. (8051, wenig resourcen). Ich wollte das über eine Geradengleichung annähern. dann wäre ich auf: Temp = (R - b) / m gekommen. Wobei m die Steigung (4,0) und b der Achsenabschnitt mit 984 wären. Das wäre denke ich einfacher zu rechnen auf dem Controller. Natürlich muss ich dann die Genauigkeit noch überprüfen... Wie rechne ich denn bei obiger Schaltung sinnvoll den Widerstand aus!? Grüße Bean
Ich berechne den Widerstand so: Messwert: aktueller ADC-Wert Rconst: autokalibrierter Wert mittels zwei Widerständen (0°C / 100°C) kann aber auch einmalig ausgemessen werden R_null_cal: autokalibrierter Wert für 0°C R_ende_cal: autokalibrierter Wert für 100°C ADC_Null: autokalibrierter ADC-Wert für 0°C ADC_Ende: autokalibrierter ADC-Wert für 100°C
1 | double Rconst = (R_ende_cal-R_null_cal)/(ADC_Ende-ADC_Null); |
2 | |
3 | double R = ((1000+((Messwert-ADC_Null)*Rconst))+(1000-R_null_cal)); |
und die Temperatur:
1 | double r = R/R0-1; |
2 | |
3 | double T = (r*(255.8723+r*(9.6+r*0.878))); // Temperatur berechnen |
Ich hoffe, dukanns damit 'was anfangen. ;-)
Du brauchst um den Widerstand auszurechnen keine Wurzel. Ein Spannungsteiler von: - ----1k------#-----1k----- + | | A ergibt an A genau die Hälfte an Spannung. So kannst du den Wiederstand berechnen. U=R*I
Allerdings.... mul und div auf einem 8051er sind mehr als nur ungenau... Für ein 22,x° Zimmerthermometer wirds wohl noch reichen, aber mehr auch nicht.
>> Zimmertemperatur (22°C) auf 3700.
Dann verwende doch eine 2te Stützstelle z.B. 0 C = ? dann hast du ein
Wertepaar DeltaU / Delta ADC und fertig.
Ausgang dann auf deine Temperaturmessung skalieren und das Ganze dann
mittels "fixed point" berechnen.
Hallo Danke für die Antworten. Dass ich den Widerstand über R = U/I berechnen kann ist mir schon klar. Allerdings weiß ich nicht wie ich den OP (Verstärkung = 23) in meine Berechnung mit einfließen lassen soll. Muss ich den vom AD-Wandler ausgegebnen Wert durch 23 teilen? Im Moment siehr mein Code zur Berechnug folgendermaßen aus:
1 | uint8_t GetAnalogTemp(int16_t *temp) |
2 | {
|
3 | int16_t analogTemp = 0; |
4 | uint16_t current = 9950; |
5 | uint8_t gain = 23; |
6 | |
7 | calcAverage(TEMPSENSOR, 8, &analogTemp); |
8 | analogTemp = analogTemp / gain; |
9 | analogTemp = analogTemp / current; |
10 | analogTemp = analogTemp >> 10; |
11 | analogTemp = analogTemp - 984; |
12 | analogTemp = analogTemp / 4; |
13 | |
14 | *temp = analogTemp; |
15 | |
16 | return SUCCESS; |
17 | }
|
Wobei calcAverage in diesem Fall 8 mal den AD wandler bemüht, und einen Mittelwert aus diesen 8 zurückliefert. Den Strom habe ich mal 1000 genommen und dann wieder geschoben. Kann aber auch sein dass ich hier noch einen Fehler drin hab. Die Zeilen:
1 | analogTemp = analogTemp - 984; |
2 | analogTemp = analogTemp / 4; |
Kommen aus der Geradengleichung des PT1000. Wo liegt mein Denkfehler? Grüße Bean
Mr Bean schrieb: > Muss ich den vom AD-Wandler ausgegebnen Wert durch 23 teilen? Im Moment > siehr mein Code zur Berechnug folgendermaßen aus: > > [c] > uint8_t GetAnalogTemp(int16_t *temp) > { > int16_t analogTemp = 0; > uint16_t current = 9950; > uint8_t gain = 23; > > calcAverage(TEMPSENSOR, 8, &analogTemp); > analogTemp = analogTemp / gain; > analogTemp = analogTemp / current; > analogTemp = analogTemp >> 10; > analogTemp = analogTemp - 984; > analogTemp = analogTemp / 4; Für meine Begriffe gehst du hier etwas zu naiv an die Dinge ran. Du musst dir eines merken: Rechnen auf dem Papier wie ein Mathematiker und Rechnen in einem Computer sind 2 Paar Schuhe. Bits die dir in einer Berechnung verloren gehen, sind verloren! Das bedeutet: Wenn man eine Formel implementiert, dann geht man erst her und macht seine Hausaufgaben auf dem Papier. Und das bedeutet: Die Formel aufschreiben und umformen. Das Ziel: Man will die Berechnungen so umformen, dass Divisionen möglichst zum Schluss auftauchen. Denn bei einer Division (insbesondere einer Integer Division) gehen dir Bits verloren. Sie sind einfach nicht mehr da. In einer Integer Division ergibt dir 10 / 3 nun mal eine glatte 3. Die Berechnungen 10/3*4 und 10*4/3 liefern unterschiedliche Ergebnisse! 10/3 gibt 3 und das mal 4 macht 12. 10*4 macht 40 und das durch 3 ergibt aber 13! Und den Rechtsshift mit 10: Mach erst mal den Rest richtig und dann kümmerst du dich um Geschwindigkeit. Ein schnell errechnetes Ergebnis bringt dir nichts, wenn es falsch ist. ALso: Hausaufgaben machen und die Formeln auf dem Papier rechnertauglich zusammenfassen und umformen. Das dann implementieren. Und zwar ohne Haken und Ösen. Dann Testen Und erst dann nachsehen, wie man die Operationen noch schneller machen kann. Und nein: Wenn man während der Programmierung darüber nachdenken muss, in welcher Reihenfolge Dinge berechnet werden müssen, dann hat man seine Hausaufgaben definitiv nicht gemacht. Im Idealfall hat man vorher schon auf dem Papier mit ein paar fiktiven Messwerten die Berechnung durchgeführt und sich davon überzeugt, dass die Formeln stimmen.
> Der Strom durch den PT1000 kommt aus einer Konstantstromquelle. > Wenn ich mir den "Rohwert" der Messung ausgeben lasse, komme ich > bei Zimmertemperatur (22°C) auf 3700. Ich habe jetzt mal so > angefangen dass ich diesen Wert durch die Verstärkung und den > Strom geteilt hab. Dann sollte ich ja den Widerstand herausbekommen. > Dann wollte ich über die Geradengleichung die Temperatur errechnen. Das heißt du hast doch im Grunde 2 lineare Transformationen hintereinander geschaltet. In der einen berechnest du aus dem ADC Wert den Widerstand und in der anderen berechnest du aus dem Widerstand die Temperatur. Das kann man auch zu einer einzigen zusammenfassen. Denn: Im Grunde interessiert der tatsächliche Widerstandswert keinen Menschen. Deine ganze Umrechnung von ADC auf Temperatur lässt sich also zu Temperatur = k * ADC + d eindampfen. Die einzige Frage ist: wie gross ist k, wie gross ist d. Und da musst du jetzt deine Hausaufgaben machen und Vorarbeit auf dem Papier leisten. (oder aber ganz einfach die Werte empirisch bestimmen)
Meine Vorredner haben dir ja schon alles bestens erklärt. Eine weitere
Möglichkeit ist deine Ganzen Ideen zu verwerfen und dir einen 2ten
Referenzpunkt zu definieren, einen hast du ja schon.
>> Zimmertemperatur (22°C) auf 3700
Der 2te Wert wäre der ADC Wert bei z.B. 0 Celsius. Die Linearisierung
erfolgt dann über die 2 Stützpunkte.
Beispiel:
1 | #define AdcRawHigh 3700 // ADC Wert bei OutHigh
|
2 | #define AdcRawLow ? // ADC Wert bei OutLow
|
3 | #define DeltaRaw (AdcRawHigh - AdcRawLow) // Differenz der Rawwerte
|
4 | |
5 | /*
|
6 | Ausgabewerte für die Stützpunkte mit Skalierungsfaktor. Mittels Skalierung werden die Werte
|
7 | von Steigung und Offset um die Kommastellen erweitert "Fixed-point Arithmetik".
|
8 | */
|
9 | #define OutHigh 0.0 // Ausgabewert für AdcRawHigh (00 Grad Celsius)
|
10 | #define OutLow 370.0 // Ausgabewert für AdcRawLow (37 Grad Celsius)
|
11 | #define Scale 65536 // zur Basis 2^16
|
12 | #define DeltaOut (OutHigh - OutLow) // Differenz der Ausgangswerte
|
13 | |
14 | /*
|
15 | Berechnung der ADC Korrekturwerte mittels Referenzpunkte.
|
16 | Theorie: Steigung = DeltaOut Ausgabewert / DeltaOut ADC-Wert.
|
17 | Daraus ergibt sich: Ausgangswert min = ADC-Wert min * Steigung + Offset.
|
18 | Nach Offset aufgelöst: Offset = Ausgangswert min - (ADC-Wert min * Steigung)
|
19 | */
|
20 | #define Slope (DeltaOut / DeltaRaw) // DeltaOut / DeltaRaw = Steigung
|
21 | #define Nullpunkt (OutLow - AdcRawLow * Slope)
|
22 | #define Offset (int32_t) (Nullpunkt * Scale) // Offset zur Basis 2^16
|
23 | #define Factor (int32_t) (Slope * Scale) // Faktor zur Basis 2^16
|
Nun ist jedweder Fehler herausgerechnet und das Ausgabeformat paßt auch, ledigilich das Komma an die richtige Stelle setzen und fertig.
1 | return (((ADC * Factor) + Offset) >> 16); |
In den Beispiel hatte ich lediglich eine 1N4148 als Temp. Sensor und es funktioniert.
Hallo Vielen Dank nochmal für die Antworten. Habe mir fast alle irgendwie geholfen. :-) Meine Funktion sieht mittlerweile folgendermaßen aus:
1 | uint8_t GetAnalogTemp(int16_t *temp) |
2 | {
|
3 | int16_t analogTemp = 0; |
4 | int16_t b = 3544; |
5 | int16_t m = 408; |
6 | |
7 | calcAverage(TEMPSENSOR, 8, &analogTemp); |
8 | |
9 | analogTemp = analogTemp - b; |
10 | analogTemp = analogTemp << 6; |
11 | analogTemp = analogTemp / m; |
12 | |
13 | *temp = analogTemp; |
14 | |
15 | return SUCCESS; |
16 | }
|
Funktioniert soweit auch. Ich hab mir einfach euren Rat zu Herzen genommen, zwei Werte gemessen und dann über die Zweipunkteformel m und b berechnet. Brauche es nur aufs Grad genau. Verglichen zum ebenfalls verbauten lm75 haut das ganze sehr gut hin. Vielen Dank! Grüße Bean
:-) Wenn man die Lösung erkennt dann wirds sehr einfach, gut gemacht.
Mr Bean schrieb: > Ich hab mir einfach euren Rat zu Herzen genommen, zwei Werte gemessen > und dann über die Zweipunkteformel m und b berechnet. > Brauche es nur aufs Grad genau. Verglichen zum ebenfalls verbauten lm75 > haut das ganze sehr gut hin. Jetzt hast du deine Hausaufgaben richtig gemacht :-) Es ist nicht ungewöhnlich, dass sich mit ein bischen Vorarbeit einfache unkomplizierte Berechnungen ergeben, die auf Anhieb funktionieren.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.