First Project - Using a Thermistor to Make a Digital Thermometer

Hi. I'm new to arduino, and also pretty new to both circuitry and coding in general. I want to build a sous vide or immersion cooker controller, sort of like this project, except I parted it out myself instead of buying a kit.

Before I can turn any cooker on and off, though, I need to be able to read the temperature. I bought this thermistor probe from amazon and some 10K resistors from radioshack to create a voltage divider. I used a screw shield to connect the probe from the 5V pin to the A0 pin, and the resistor from the A0 pin to ground.

The thermistor probe didn't come with a data sheet or really any documentation, just a little slip of paper that (in Chinese) seemed to say which air conditioners it was compatible with. It definitely did not come with a code library like the popular Dallas/OneWire probes. So what I did was record a bunch of analogread() (voltage?) values from the probe in a pot of ice water that I brought slowly to a boil. I also recorded the temperature in the pot according to two different (thermocouple) kitchen thermometers I had and then I fit the data to a 3rd-degree polynomial in excel.

Here is my code with that fit:

#include <SPI.h>
#include <LiquidCrystal.h>
#include <math.h>

//Function Declarations
double Thermistor(int RawADC)
{
  double Temp;
  
//sample code from http://playground.arduino.cc/ComponentLib/Thermistor2 :
// Temp = log(10000.0*((1024.0/RawADC-1))); 
////         =log(10000.0/(1024.0/RawADC-1)) // for pull-up configuration
// Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
// Temp = Temp - 273.15;            // Convert Kelvin to Celcius
// Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit

//temporary readings, course grade
  Temp = (0.00007292585*RawADC*RawADC*RawADC) - (0.2014824*RawADC*RawADC) + (186.2261*RawADC) - (57518.79);
  Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit


 return Temp;
 //return RawADC;
} 


// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

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

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.print("Hello, World!");

}

void loop() 
{ 
  lcd.setCursor(0, 1);
  lcd.print(Thermistor(analogRead(0)));
  lcd.print(" F");
  delay(250);
}

This model provides reasonable temperatures, but there are some problems. Namely, I only get about 1ºC/2ºF resolution. That is between 0ºC and 97ºC, the analogread() value varied (nearly linearly?) from 860 to 964. This is problematic, because I would like (ideally) to have sub-1ºF resolution, but that is impossible if an integer change in my input takes ~2ºF difference.

Is this an unavoidable problem in the hardware—the probe—that I chose? I think the voltage in a voltage divider circuit should change most rapidly when the two resistors are very nearly the same resistance. I checked with a multimeter and both my thermistor and my resistor are within 5% of 10K ohms at room temperature. The voltage drop between the +5V pin and the ground pin is also correct. I would rather not replace the probe I already have if I don't have to, but perhaps this one is not sensitive enough for my needs.

I'm also confused that I'm reading around ~880 (from 0 to 1023 ?) at room temperature, when the resistor and the thermistor are both quite nearly 10K ohm. I expected the voltage drop to be about 2.5V and the analogread() value to be close to 600. Is analogread() not linear with voltage? Or is it possible that components in the LCD or arduino board itself are impacting my desired simple voltage divider circuit?

Thank you for any help or insight,
Daniel

EDIT: I forgot to mention I am using an Arduino Uno as my first board here. The LCD shield I am using, if it matters, is this one: http://www.amazon.com/gp/product/B007MYZF9S?psc=1&redirect=true&ref_=od_aui_detailpages00

You could have bought the same sensor from Adafruit : 10K Precision Epoxy Thermistor [3950 NTC] : ID 372 : $4.00 : Adafruit Industries, Unique & fun DIY electronics and kits
On that page, click on "We have a great detailed tutorial...". Follow that tutorial, and you will be an expert in thermistors soon :stuck_out_tongue:
I think the example code from Adafruit is okay more or less, but I can see a few things that can be improved.

About the value at room temperature, I don't know. Try the Adafruit tutorial first.

You use '0' for the first analog pin. We prefer to use 'A0', so it is clear to everyone that it is an analog pin.

const int thermistorPin = A0;

...

  lcd.print(Thermistor(analogRead(thermistorPin)));

Yreval:
This model provides reasonable temperatures, but there are some problems. Namely, I only get about 1ºC/2ºF resolution. That is between 0ºC and 97ºC, the analogread() value varied (nearly linearly?) from 860 to 964. This is problematic, because I would like (ideally) to have sub-1ºF resolution, but that is impossible if an integer change in my input takes ~2ºF difference.

Is this an unavoidable problem in the hardware—the probe—that I chose? I think the voltage in a voltage divider circuit should change most rapidly when the two resistors are very nearly the same resistance. I checked with a multimeter and both my thermistor and my resistor are within 5% of 10K ohms at room temperature. The voltage drop between the +5V pin and the ground pin is also correct. I would rather not replace the probe I already have if I don't have to, but perhaps this one is not sensitive enough for my needs.

I'm also confused that I'm reading around ~880 (from 0 to 1023 ?) at room temperature, when the resistor and the thermistor are both quite nearly 10K ohm. I expected the voltage drop to be about +2.5V and the analogread() value to be close to 600. Is analogread() not linear with voltage?

Using your multimeter, is the voltage at the mid-point of the voltage divider about 2.5V at room temperature?

For maximum sensitivity, consider placing an amplifier between the voltage divider and the Arduino's input so changing the temperature from (say) 0C to 100C changes the input voltage from 0V to +5V (or vice versa).

There are circuits which linearise the voltage/temperature relationship; Google will find many articles, here is an example. It is probably better to use code to linearise, as you are doing. Your polynomial method is probably adequate but note Equation 1 in that link. I see in the Adafruit table that B (or β) is quoted as 3950K.

Archibald:
Using your multimeter, is the voltage at the mid-point of the voltage divider about 2.5V at room temperature?

No. Instead, I get a drop of about 0.7V from hot to A0, and about 4.3 from A0 to ground. Again, both my reference resistor and my probe are right around 10K ohm at room temperature, though. I don't really understand. My circuit is now set up just as depicted in the second adafruit diagram.

Peter_n:
About the value at room temperature, I don't know. Try the Adafruit tutorial first.

This is peculiar to me. When I run Adafruit's code as written, I always get 1023 on pin A0 and a calculated resistance of "inf." If I comment out

"analogReference(external)"

then I get values around 880 on A0 with a calculated resistance of around 64K ohm, just as I had before.

The "EXTERNAL" for analogReference is used when the Arduino 3.3V is connected to AREF. After that connection is made, you may not run a normal sketch, since that could cause a shortcut in the microcontroller.
Did you use the 3.3V ?
It is either 3.3V to AREF and sensor at 3.3V and EXTERNAL reference, or 5V to sensor and AREF open an no EXTERNAL.

Do you use a breadboard with very bad contacts ?

Could you make a photo so we can check the wiring ?

Can you measure voltage when the resistor and thermister are connected to GND and 5V but not to the A0 ? Perhaps the A0 input is broken.

I don't have a 10k ntc, I did find a 1k ntc.

shortcut? from where to where?

Peter_n:
The "EXTERNAL" for analogReference is used when the Arduino 3.3V is connected to AREF. After that connection is made, you may not run a normal sketch, since that could cause a shortcut in the microcontroller.
Did you use the 3.3V ?
It is either 3.3V to AREF and sensor at 3.3V and EXTERNAL reference, or 5V to sensor and AREF open an no EXTERNAL.

When I made the parent comment in this thread, I was using 5V to sensor with AREF open and no external. Since you posted the adafruit guide I changed to 3.3V which is connected both to sensor and AREF, as depicted (I believe.)

With this set up, I always read 1023. Again, if I comment out the line analogReference(EXTERNAL) then I read ~880 again, as I did with the original 5V set up and my own code.

Do you use a breadboard with very bad contacts ?

Maybe. I will try another one and see what happens.

Could you make a photo so we can check the wiring ?

I'll see if I can find a camera laying around.

Can you measure voltage when the resistor and thermister are connected to GND and 5V but not to the A0 ? Perhaps the A0 input is broken.

Maybe this is the issue (or maybe I'm making some other very silly mistake) When I remove the A0 pin from the circuit the voltage across the reference resistor is about 1.6V, and the voltage across the thermistor is about 1.7V, which seems sane for 3.3V total. When I connect A0 again I get a drop of about 0.7V and 4.3V for the resistor and thermistor respectively.

EDIT: I moved my sensor input over to A3 instead of A0 and now I'm getting input values of around 528 (corresponding to about 10666 ohm) at room temperature. This is much closer to what I would expect. I had the same problems with my circuit when I plugged it in to my sister's arduino board, so I expect either one of the connections on my screwshield is bad or my LCD was interacting with it in a funky way, rather than the arduino itself having a problem.

Thanks for all your help, guys. I'm sure I'll be back with new problems at a later point in this project. :^)

That is not good at all. It might be broken. You could try another analog input, but when an analog input is damaged, often the complete analog section is damaged.
You need another Arduino board :money_mouth_face:

CrossRoads, when the 3.3V pin is connected to AREF (as in the last example of the Adafruit tutorial) and analogRead() is called without a preceding call to analogRefece(EXTERNAL), then ... the internal 5V reference is shortcut to the external 3.3V.

Sounds like maybe ESD damaged A0.

"the internal 5V reference is shortcut to the external 3.3V."
The internal 5V being Avcc routed thru the AVCC/1.1 mux and then the gate that lets the mux connect to Aref.
So if that happens, what occurs? Aref backfeeds to the AVCC pin thru the gate and the mux? AVCC overpowers Aref and 5V is used anyway? We could use some detail about the mux and the gate.

I also notice that my ADC values seem much more stable when I use USB as a power supply than when I use a 9V DC wall adaptor. Is this normal? Maybe my 9V power supply is just cheap?

CrossRoads, I don't know. I'm not willing to risk one of my Arduino boards.
There is a warning here : analogReference() - Arduino Reference
"...possibly damaging the microcontroller on your Arduino board".

Yreval, no, that is not normal. It might happen if it is really really cheap and very bad.
It seems to me, that is not the same problem, but another problem.
When a wall adaptor is used, that changes the noise in the system. Are you sure there are no open contacts ? or bad grounding ?

I had a few cheap power supplies. Some leaked high mains voltages into the system, others were not certified. I threw them all away because of the risks. I should have done that earlier. Now I use only good power supplies.