Arduino Math-Library: log()- Problem

Hallo Community,

mit einem Arduino Nano und einem NTC-Widerstand möchte ich die Raumtemperatur messen.
Anfangs dachte ich es wird sehr einfach. War es auch, bis mir scheinbar bei der Berechnung der Temperatur die Math-Library von Arduino, bzw. AVR, mit der Funktion zum natürlichen Logarithmus ( log() ) einen Strich durch die Rechnung gemacht hat.

Die Funktion gibt eine Double-Variable zurück, welche keine Vorzeichen beherrscht. Für die Berechnung benötige ich allerdings ein vorzeichenbehafteten Wert.

Gibt es denn alternativen zur Math.h Library, bzw. eine log()-Funktion die auch mit negativen Zahlen umgehen kann? …also eine log()-Funktion die ein Float-Wert zurückgibt…

Freue mich schon auf eure Antworten.

Viele Grüße
kleiner_kaktus

Wie kommst du darauf? Der Datentyp double ist Vorzeichenbehaftet.
Was ist denn der Rückgabewert von log(0.5) ?

Hi,

danke für deine schnelle Antwort.
Hab es getestet und du hast recht.
Verstehe dann jetzt mein Problem nicht mehr so ganz.
Evtl. findet Ihr den Fehler?!?

Die externe Schaltung ist sehr einfach gehalten. Eine einfache Reihenschaltung von zwei Widerständen mit R1 = 10 kOhm und R2 = 100 kOhm. R2 ist der NTC.

Das Umrechnen der Spannung in den aktuellen Wert von R2 scheint einwandfrei zu funktionieren.

Die Formel zur Berechnung der Temperatur habe ich aus Wikipedia entnommen:

Quellcode:

#include <math.h>

int AnalogValueA0;
float u2 = 0.0;
int r1 = 9830;
float r2 = 0.0;

double temp = 0.0; // errechnete Temperatur
double Tn = 25.0;  // Nenntemperatur bei Nennwiderstand
double Rn = 100000.0; // Nennwiderstand
double B = 4000.0; // B-Faktor
float dLog = 0.0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  AnalogValueA0 = analogRead(A0);   // Analogwert einlesen
  u2 = (AnalogValueA0/1024)*5;      // Normieren auf Versorgungsspannung
  r2 = -((u2*r1)/(u2-5));           // Widerstand des NTC berechnen (R2)

  dLog = log(r2/Rn); // Logarithmus wird errechnet
  temp = 1/((1/Tn)+((1/B)*log(dLog))); // Temperatur wird berechnet

  Serial.print("Widerstand R2: "); Serial.print(r2); Serial.print(" -- "); Serial.print("Temperatur: "); Serial.println(temp);
}

Hallo kleiner_kaktus,

für Dich kommt die Antwort vermutlich zu spät. Falls aber jemand ein ähnliches Problem hat und auf Deine Frage trifft, will ich sie trotzdem beantworten.
Du formulierst Dein Problem zwar nicht wirklich aus, aber ich vermute, Du bekommst unsinnige Werte für die Temperatur?

Du hast übersehen, dass die Approximation der Kurve mit absoluten Temperaturen (also Grad Kelvin) arbeitet. Also fehlt noch:

temp = temp - 273;

und die Welt ist wieder in Ordnung.

Hi!

Ja, das Thema ist schon älter. Dennoch… Hier stimmt so einiges nicht…

Fließkommarechnung

u2 = (AnalogValueA0/1024)*5; 

wird fast immer 0 ergeben, denn alle Variablen und Konstanten sind ganze Zahlen, daher wird auch die Division nur ganzzahlig durchgeführt, die Nachkommastellen also abgeschnitten. Nur für nen Analog-Wert von 1024 ergibt die Division garde mal 1.

Besser:

u2 = (float(AnalogValueA0)/1024)*5; 

Jetzt wird der Analog-Wert zunächst in eine Fließkommazahl umgewandelt - dadurch wird die Rechnung dann auch „mit Komma“ durchgeführt.

NTC-Formel

Wie bereits geschrieben wurde, die Temperaturen sind immer in Kelvin, man muss für die Umrechnung 273,15K hinzuaddieren oder wieder abziehen:

    double Tn = 25.0 + 273.15;  // Nenntemperatur bei Nennwiderstand

    ...

    temp = 1/((1/Tn)+((1/B)*log(dLog))) - 273.15; // Temperatur wird berechnet

Noch ein Fehler

Hier wird der Logarithmus zwei mal berechnet… ich nehme das obere mal raus…

  dLog = log(r2/Rn); // Logarithmus wird errechnet
  temp = 1/((1/Tn)+((1/B)*log(dLog))); // Temperatur wird berechnet

Test

Ohne NTC wird’s schwer. Aber rechnen wir mal. Der ADC-Wert bei 25°C sollte bei 100000/(9830+100000)*1024 = ~932. liegen. Schreiben wir mal ne FOR-Schleife, die Werte um 930 durchprobiert:

#include <math.h>

int AnalogValueA0;
float u2 = 0.0;
int r1 = 9830;
float r2 = 0.0;

double temp = 0.0; // errechnete Temperatur
double Tn = 25.0 + 273.15;  // Nenntemperatur bei Nennwiderstand
double Rn = 100000.0; // Nennwiderstand
double B = 4000.0; // B-Faktor
float dLog = 0.0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  for(AnalogValueA0=920; AnalogValueA0<940; AnalogValueA0++){
    //AnalogValueA0 = analogRead(A0);   // Analogwert einlesen
    u2 = (float(AnalogValueA0)/1024)*5;      // Normieren auf Versorgungsspannung
    r2 = -((u2*r1)/(u2-5));           // Widerstand des NTC berechnen (R2)

    //dLog = log(r2/Rn); // Logarithmus wird errechnet
    temp = 1/((1/Tn)+((1/B)*log(r2/Rn))) - 273.15; // Temperatur wird berechnet

    Serial.print("ADC: ");
    Serial.print(AnalogValueA0);
    Serial.print(" Widerstand R2: "); Serial.print(r2); Serial.print(" -- "); Serial.print("Temperatur: "); Serial.println(temp);
  }
}

Dabei kommt jetzt das raus:

ADC: 921 Widerstand R2: 87897.39 -- Temperatur: 27.89
ADC: 922 Widerstand R2: 88855.50 -- Temperatur: 27.65
ADC: 923 Widerstand R2: 89832.57 -- Temperatur: 27.40
ADC: 924 Widerstand R2: 90829.21 -- Temperatur: 27.15
ADC: 925 Widerstand R2: 91845.96 -- Temperatur: 26.90
ADC: 926 Widerstand R2: 92883.47 -- Temperatur: 26.65
ADC: 927 Widerstand R2: 93942.37 -- Temperatur: 26.40
ADC: 928 Widerstand R2: 95023.34 -- Temperatur: 26.14
ADC: 929 Widerstand R2: 96127.06 -- Temperatur: 25.88
ADC: 930 Widerstand R2: 97254.26 -- Temperatur: 25.62
ADC: 931 Widerstand R2: 98405.70 -- Temperatur: 25.36
ADC: 932 Widerstand R2: 99582.17 -- Temperatur: 25.09
ADC: 933 Widerstand R2: 100784.51 -- Temperatur: 24.83
ADC: 934 Widerstand R2: 102013.56 -- Temperatur: 24.56
ADC: 935 Widerstand R2: 103270.22 -- Temperatur: 24.29
ADC: 936 Widerstand R2: 104555.46 -- Temperatur: 24.01
ADC: 937 Widerstand R2: 105870.24 -- Temperatur: 23.74
ADC: 938 Widerstand R2: 107215.58 -- Temperatur: 23.46
ADC: 939 Widerstand R2: 108592.59 -- Temperatur: 23.18

Das ist also genau das, was man erwartet :wink:

Noch ein Elektronik-Tipp

Das mit den 10k und 100k ist unglücklich gewählt. Da liegen fast 5V am NTC an, die ADC-Werte sind recht hoch. Durch Bauteiltoleranzen etc. misst man gerne mal was falsches. Besser ist, wenn der Nennwiderstand des NTCs ziemlich genau so groß wie der Widerstand ist, also z.B. 10k und 10k.

Genau,

und nicht in

!

1 Like