LM335 Not Accurate

I am having trouble getting accurate temperature readings over time from the lm335 temerature sensor.

I am using the LM335 class below to read the lm335 sensor connected to analog 0. The power is connected direct from the analog +/- pins. By reading other threads on here I believe I ended up with a 1k resistor connected to the sensor (though it’s been a while). I have tried other variations of code that I have found in the forums here too.

A few days ago when I switched to the code below, I tweaked the lm335_offset number, which ended up at 621 in order to calibrate the sensor to match a thermometer in the room. It seemed to be working great for probably almost 2 days, but this morning I could tell it was much hotter in the room than my readings. In fact, it’s about 30 degrees off (too low) this morning! No code changes, no electrical changes, it is just 30 degrees too low for some reason!

Any ideas?

// lm335 code (class):

LM335::LM335(int _ADCpin)
{ ADCpin = _ADCpin;

inline void LM335::initialize()
{ delay(10); // wait for the analog reference to stabilize
  readAdc(); // discard first sample (never hurts to be safe)  

inline int LM335::readAdc()
{ return analogRead(ADCpin);

int LM335::deciCelsius()
{ long averageTemp=0;
  initialize(); // must be done everytime
  for (int i=0; i<lm335_samples; i++) averageTemp += readAdc();
  averageTemp -= lm335_offsetFactor;
  return averageTemp / lm335_divideFactor; // return deci degree Celsius

int LM335::celsius()
{ return deciCelsius()/10;

int LM335::deciFahrenheit()
{ return (9 * deciCelsius()+1600) / 5;

int LM335::fahrenheit()
{ return (9 * deciCelsius()+1600) / 50; // do not use deciFahrenheit()/10;
#ifndef LM335_H
#define LM335_H

// LM335 temperature sensor interface
// Rev 1.0 Albert van Dalen www.avdweb.nl
// Resolution 0.1 degree

// Calibration values, set in decimals
static const float lm335_offset = 621; // change this!
static const float lm335_gain = 2.048;

static const int lm335_samples = 1000; // must be >= 1000, else the gain setting has no effect

// Compile time calculations
static const long lm335_offsetFactor = lm335_offset * lm335_samples;
static const int lm335_divideFactor = lm335_gain * lm335_samples/10; // deci = 1/10

class LM335
  LM335(int _ADCpin);
  int deciCelsius();
  int celsius();
  int deciFahrenheit();
  int fahrenheit();
  inline void initialize();
  inline int readAdc();
  int ADCpin;

Can you measure the analog voltage from the LM335 with a voltmeter (e.g. a multimeter)? The LM335 relies on the resistor to supply enough curent to operate the chip. If it's too high (too many Ohms), not enough current will be supplied. This will usually result in the sensor reading too low. Maybe you could try a slightly smaller resistor, or maybe a connection has become loose?

You ideally need to use a 2k2 resistor, not 1k, to get the best accuracy (the datasheet specifies 1mA for its ratings and 5V - 2.98V is 2V for the resistor.)

You don't say what accuracy you want BTW - unless you have the sensor shielded from heat radiation and under forced-air-circulation you'll easily get 1C or so error from heat radiation from nearby heat sources (that includes you). For some bizarre reason thermal sensors are often encapsulated in black plastic, not metal cans (which pick up far less heat radiation).

Ideally you'd use a constant-current source and measure the voltage at both terminals (treat it as a 4-terminal device) so you don't see IR drops in the leads (although at 1mA that's not such a problem).

If you are using it remotely a 100pF across the leads at both ends will reduce the effect of RF pickup which could affect readings.