2016-09-23 3 views
2

Ich versuche, die Steinhart-Hart-Temperaturberechnung auf einem Arduino zu tun. Die Gleichung ist enter image description hereBessere Präzision mit Arduino (Schwimmer)

ich ein System von 3 Gleichungen gelöst, um die Werte von A, B und C zu erhalten, die ist:

A = 0.0164872 
B = -0.00158538 
C = 3.3813e-6 

Als ich stecke diese in Wolfram zu lösen für T I einen Wert zu erhalten in Grad Kelvin, das macht Sinn:

T=1/(0.0164872-0.00158538*log2(10000)+3.3813E-6*(log2(10000))^3) solve for T

T = 298.145 Kelvins = 77 Fahrenheit

Wenn ich jedoch versuche, diese Gleichung auf meinem Arduino zu verwenden, bekomme ich eine sehr falsche Antwort, ich vermute, weil Doppelgänger nicht genug Präzision haben. Hier ist, was ich verwende:

double temp = (1/(A + B*log(R_therm) + C*pow(log(R_therm),3)));

Das gibt 222 Kelvin statt, die Art und Weise ausgeschaltet ist.

Also, wie kann ich eine Berechnung wie diese in Arduino ?? Jeder Rat wird sehr geschätzt, danke.

+6

'log2' bezeichnet den Basis-2-Logarithmus und' log' den "natürlichen" oder Basis-E-Logarithmus. Das könnte schon den Unterschied erklären. –

+0

Auch 'C = 000003.3813' und' 3.3813E-6' sind nicht die gleiche Nummer. –

+0

Ja, hier bezieht sich "ln" wahrscheinlich auf den neperischen Logarithmus, der "ln (x) = log2 (x)/log2 (exp (1))" – MayeulC

Antwort

3

Präzision ist nicht das Hauptproblem. Könnte sogar float und powf() verwenden. Eine Thermistortemperaturberechnung ist nicht , die genau ist. Nach alledem ist die Temperatur sicherlich nicht besser als ±0.1°C accurate. Die Selbsterwärmung des Thermistors ist ein größerer Faktor.

C OP-Code des übernimmt log Basis 2, die Verwendung Logbase elog() als die Konstanten abgeleitet wurden unter Verwendung von Logarithmus zur Basis 2. @Martin R

// double temp = (1/(A + B*log(R_therm) + C*pow(log(R_therm),3))); 
double temp = (1/(A + B*log(R_therm)/log(2) + C*pow(log(R_therm)/log(2),3)));` 

Beispielimplementierung, die einen unnötigen langsam pow() Anruf vermeidet.

static const inv_ln2 = 1.4426950408889634073599246810019; 
double ln2_R = log(R_therm)*inv_ln2; 
double temp = 1.0/(A + ln2_R*(B + C*ln2_R*ln2_R)); 
1

Ja, Gleitkommaarithmetik hat auf den meisten Arduinos eine begrenzte Genauigkeit.

Haben Sie überlegt, feste Genauigkeit zu verwenden? Bei korrekter Verwendung könnte dies zu besseren Ergebnissen führen. Voraussetzung dafür ist jedoch, dass die Parameter sehr eng sind und die Einheitenumrechnung sorgfältig ist.

Ein unsigned long auf Arduino ist auch 4 Bytes, so kann es Zahlen bis 2^32-1 enthalten. Wenn Sie einen Fixpunkt verwenden, möchten Sie vielleicht 1/T durch etwas wie 100000/T ersetzen, wobei die Zählerkonstante und T entsprechend der gewünschten Genauigkeit skaliert wurden.

Sie müssen auch ein (geistiges oder Papier) Modell der Anzahl der Dezimalstellen, die jede Variable enthält, behalten, um die Operationsreihenfolge zu optimieren, damit die Genauigkeit nicht verloren geht.

Für die log2 Funktion, bezweifle ich, dass es out of the Box für Ganzzahlen verfügbar ist. Sie können entweder das Ergebnis oder reimplement it werfen. Es gibt viele Ressourcen für dieses Problem, auch hier auf SO.

+0

Ich würde sagen, dass Fließkomma-Arithmetik nicht nur auf den meisten Arduinos, sondern auf allen und auch auf allen anderen Computern eine begrenzte Genauigkeit hat ... –

+0

@ ThomasPadron-McCarthy: Jede Zahl Darstellung hat irgendwann begrenzte Präzision, wenn du willst nitpick. Aber avr-basierte Arduinos haben nur 4-Byte Fließkommazahlen. Keine doppelte Präzision. Das Due hat beispielsweise Gleitkommazahlen doppelter Genauigkeit. Aber das könnte hier das Problem sein. – MayeulC