0

schematic

simulate this circuit – Schematic created using CircuitLab

This is the code that I'm using to get the temperature:

#define COEFF_A 0.8662984364E-03
#define COEFF_B 2.780704551E-04
#define COEFF_C -0.9395108479E-07

float VRT, Temp;
float Vref = 2.52;


void setup() {
  Serial.begin(9600);
  analogReference(EXTERNAL);
}

void loop() {
  long Resistance;
  VRT = analogRead(A3);
  Resistance = 10000 / ((1023.0 / VRT) - 1);
  Temp = log(Resistance);
  Temp = 1 / (COEFF_A + (COEFF_B * Temp) + (COEFF_C * pow(Temp, 3)));
  Temp += -273.15;
  Serial.println(Temp);
  delay(500);
}

I know that the calculation should be: V = Vref × VRT ÷ 1023 but i don't know how to implant it in this code, any help appreciated.


Update

After Edgar Bonet answer, the edited code is:

#define COEFF_A 0.8662984364E-03
#define COEFF_B 2.780704551E-04
#define COEFF_C -0.9395108479E-07

float VRT, Temp, VR;


void setup() {
  Serial.begin(9600);
  analogReference(EXTERNAL);
}

void loop() {
  long Resistance;
  VRT = analogRead(A3);
  VR = 2.52 * VRT / 1024;
  Resistance = 10000 * VR / (2.52 - VR);
  Temp = log(Resistance);
  Temp = 1 / (COEFF_A + (COEFF_B * Temp) + (COEFF_C * pow(Temp, 3)));
  Temp += -273.15;
  Serial.println(Temp);
  delay(500);
}

But the temperature reading is 2 centigrade less than what it should be, when i remove the analogReference(EXTERNAL); it shows the normal/correct temperature readings.

2 Answers 2

2

The formula to get the analog voltage from the ADC reading is:

    V = Vref × reading ÷ 1024

(yes, it's 1024, not 1023). The formula to get the thermistor resistance from the measured voltage is:

    R = Rref × V ÷ (Vref − V)

where Rref is your 10 kΩ pull-up. You can combine these two formulas in order to get the resistance directly from the ADC reading:

    R = Rref × reading ÷ (1024 − reading)

You may notice that, while doing this simplification, Vref cancels out. It's not an error. The readings you get with this setup are indeed independent of your reference voltage.


Update 1: After the OP's edit, we now have a completely different question. The question is now: how come the readings do depend on the reference voltage that is used, whereas in theory they should not.

The answer lies most likely in the ADC calibration. If high accuracy is a requirement, the correct formula for the measured voltage is

    V = Vref × (reading + Eoff) ÷ (1024 + Egain)

where Eoff and Egain are the offset error and the gain error respectively. These errors are not knows a priori, and they are usually neglected when the accuracy requirement is low. The datasheet only gives constraints on how big these errors can be. The actual values depend on the specific microcontroller and can somewhat depend on the reference voltage. The only solution to get rid of these errors is to calibrate your own ADC. See Response of the Arduino ADC for an example on how this could be done.


Update 2: If I had to program this in an Arduino, I would rather simplify the calculations as much as possible before coding:

  • do not compute the measured analog voltage, nor the resistance, as they are not needed
  • compute instead the ratio R/Rref directly from the analog reading
  • rewrite the calibration polynomial as a function of log(R/Rref) instead of log(R) (which actually means log(R/(1 Ω)))
  • optimize the evaluation of the polynomial by using Horner's method.

With these optimizations, we get:

// Coefficients of polynomial fit of log(R/Rref) -> 1/T.
const float c0 = 3.3540165e-3;
const float c1 = 2.5416075e-4;
const float c2 = -2.5959644e-6;
const float c3 = -9.3951087e-8;

// Convert ADC reading to temperature in deg. C.
static float temperature(int reading)
{
    float R_ratio = reading / (1024.0 - reading);  // = R / Rref
    float x = log(R_ratio);
    float inverse_T = c0 + x*(c1 + x*(c2 + x*c3));
    return 1/inverse_T - 273.15;
}

void loop()
{
    int reading = analogRead(A3);
    Serial.println(temperature(reading));
    deay(500);
}
9
  • so in this example it should be this: Resistance = 2.52 * VRT / (1024 - VRT);, correct? Aug 30, 2019 at 13:21
  • No. Your reference resistance is 10 kΩ, not 2.52 Ω. Aug 30, 2019 at 13:23
  • but the readings is wrong, Resistance = 10000 * VRT / (1024 - VRT); did i missed something? it's like 2C less... Aug 30, 2019 at 13:27
  • I don't understand your last comment. Please, edit your original question if there is something missing. Aug 30, 2019 at 13:28
  • when i use your suggested formula Resistance = 10000 * VRT / (1024 - VRT); the temperature is 2 centigrade less than what it should be. Aug 30, 2019 at 13:29
0

Note: I formulated this answer on your previous, deleted question.

Whether the voltage increases or decreases with rising temperature depends on your circuit: if you use the ntc with R1 as a pull-down, the voltage will increase on rising temperature. If R1 is a pullup the voltage will fall respectively.

Concerning your calculation: I highly recommend using a look-up table instead. Those are some hard calculations, and at the arduinos resolution you'll be fine with a LUT with about 64 entries. There're tools out there which generate LUTs for a given NTC setup (I personally like this tool).

2
  • uh i feel so bad now that i deleted that question while you was answering it! sorry... Aug 30, 2019 at 12:54
  • the code that i posted in my question does all the calculations, i don't need to re-do it, i just need to add the Vref into the calculation and don't know how... it's a pull-down btw. Aug 30, 2019 at 12:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.