Temperaturmessung mit KTY84 und 2-Punkt Kalibrierung

OP #6676543
Lesenswert?

Ich möchte mit einem KTY84 eine Temperatur im Bereich von etwa 0-230°C 
messen. Habe kaum Wahl beim Sensor, es soll der vorhandene, an einem 
einfachen Spannungsteiler angeschlossene KTY84 weiterverwendet werden.
Der wird noch für eine andere Aufgabe benutzt.
Genauigkeitsanforderung von +/- 2°C wäre ausreichend.
Möchte den Sensor an einen 10 Bit ADC eines uC (Attiny841) anschließen. 
Eingangsspannungsbereich passt.

Die Frage ist nach der Auswertung: der Temperaturbereich ist groß. Die 
Tabelle im Datenblatt möchte ich ungern abschreiben.
Habe zwar keine Fehlerbetrachtung durchgeführt, aber ich denke ein 
quadratisches Polynom mit einigen Kalibierwerten sollte den Zweck 
erfüllen.

Man findet jede Menge Beispiele einer Linearisierung im Netz. Und bei 
größeren Temperaturbereichen den Hinweis, man solle doch einen PT1000 
nehmen. Hilft hier nicht.
Frage: hat jemand schon eine quadratische Annäherung für einen KTY 
umgesetzt, und hätte vielleicht sogar Beispielcode für eine 
Integer-Arithmetik?

Es gibt ein Datenblatt mit einem Polynom höherer Ordnung, müsste man 
aber entweder nach T umstellen oder Intervall-Schachteln.

Vielleicht hat jemand was zur Hand und ich muss das Rad nicht neu 
erfinden :-)
#6676750
Lesenswert?

Wenn Du die Kennlinie des Sensors hast (Datenblatt oder Messung), dann 
kannst du auch einfach die zugehörigen Digitalwerte (incl. 
Spannungsteiler) berechnen und in einer Tabelle/Array ablegen. Damit 
dann eine lineare Interpolation zwischen 2 Stützstellen durchführen.
Einfacher wird es, wenn die Temperaturwerte der Stützstellen einen 
konstanten Abstand haben.
Mit zwei bekannten Punkten (X0, Y0) und (X1, Y1) kann entlang der 
Geraden der Wert Y(X) gefunden werden. Der Wert von X muss dabei im 
Intervall X0, X1 liegen. (In Arduino könnte man da einfach für jeden 
Bereich jeweils eine map-Funktion drauf loslassen.)
Zunächst muss das Intervall gefunden werden, in dem der gesuchte 
Ausgabewert liegt. Eine einfache Suchfunktion geht das Array durch, bis 
der gemessene Analogwert über dem Wert X1 liegt. Die Tabelle für den 
Sensor liegt hier z.B. in gleichmäßigen Temperaturabständen von 5°C vor, 
beginnend bei 0°C. Die Suche nach dem Intervall sieht dann so aus 
(stetig steigende Funktion vorausgesetzt):
1
// Digialwerte fuer     0°C  5°C  10°C etc.
2
unsigned int Tabelle[]={100, 150, 200, 250...}; // für deinen Aufbau anpassen
3
#define T_low 0                 // unterste Temperatur in der Tabelle
4
i = 0;        // erster Tabelleneintrag
5
while (Tabelle[i] < ADWert) { i++; }
6
// Jetzt ist die Suche beendet und bei i ist der Punkt (X1, Y1)
7
X1 = Tabelle[i];    // X = ADWert
8
X0 = Tabelle[i-1];    // Y = gesuchte Temperatur 
9
Y1 = 5 * i  T_low ;    // Temperatur in 5°C-Schritten ab T_low 
10
Y0 = 5 * (i1)  T_low ;   // 
11

12
Temperatur = Y0 + (ADWert  X0) * 5 / (X1  X0);// Y1–Y0 ist konstant 5°C.
Wenn man Nachkommastellen haben will, dann rechnet man einfach in 1/10°C 
oder 1/100°C ganzzahlig. Mit signed int und 1/100°C kommt man dann von 
-273°C bis +327,67°C.
Gast #6676814
Lesenswert?

Wulf D. schrieb:
> Die Tabelle im Datenblatt möchte ich ungern abschreiben.

Um eine Parabel durchzulegen, brauchst du mindestens 3 Punkte.
Das ist gerade noch abtipbar.
Aber nicht jede krumme Kurve wird gut durch eine Parabel beschrieben, 
also sind ein paar "Kontrollpunkte" auf jeden Fall angeraten.
OP #6677260
Lesenswert?

Habe mir den Polynom aus den Phillips / NXP Datenblatt genauer 
angesehen. Im Temperaturbereich bis 230°C braucht man den kubischen Teil 
nicht.
Mittels der bekannten p-q Formel nach T umgestellt und ein kleines 
Programm mit 16 Bit Festkomma-Arithmetik getestet:
1
int16_t KTY84temp(uint16_t rt)
2
{
3
uint16_t p=rt>>2;
4
p=p*91;
5
p=p>>2;
6
p=p-846;
7
p=SQRT16(p);
8
p=p<<2;
9
int16_t q=-179+p;
10
return(q+3);
11
}
Integer Wurzelziehen wurde schon im Forum gepostet, wiederhole ich der 
Vollständigkeit halber:
1
/*
2
Hier ein Algorithmus der aus einer Integer die Wurzel zieht. Er ist
3
schnell (kleiner 200 Takte) und kurz (ca. 100 Bytes).
4
Quelle:
5
https://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2
6
*/
7
uint16_t SQRT16(uint16_t op)
8
{
9
  uint16_t res = 0;
10
  uint16_t one = 1 << 14; // The second-to-top bit is set: 1L<<30 for long
11
  // "one" starts at the highest power of four <= the argument.
12
  while (one > op)
13
  {
14
    one >>= 2;
15
  }  
16
  while (one != 0)
17
  {
18
    if (op >= res + one)
19
    {
20
      op -= res + one;
21
      res += 2 * one;
22
    }
23
    res >>= 1;
24
    one >>= 2;
25
  }
26
  return (res);
27
}

Die Ergebnisse:
1
Widerstand  Temperatur  Temperatur
2
gemessen    Datenblatt  16Bit gerechnet
3
[Ohm]       [°C]        [°C]
4
498         0           0
5
1000        100         100
6
1982        230         232
7
2166        250         252

Die Auflösung des ADC sollte kein Problem darstellen, um einen 16Bit 
Überlauf zu verhindern, wird der Widerstand in der Rechnung gleich um 
Faktor 4 geteilt (Fractional).

Was ist nun effektiver: Rechnen oder Tabelle?
Ich weiß es nicht. Egal, es funktioniert so.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren