Contents[Hide]

Intro

Here we describe a class for reading out the LM335 temperature sensor. This class is based on Chiptemp. See here for a detailed description of the software: http://www.avdweb.nl/arduino/temperature-measurement.html

Differential amplifier

The LM335 output voltage is 2.73V ... 3.73V for 0/°C to 100/°C. This differential amplifier converts the output voltage to 0 ... 5V for the Arduino ADC:

Arduino temperature measurement with LM335
Arduino temperature measurement with LM335

Electronic circuit calculation with wolframalpha

Although the circuit is simple, the calculation isn't. We have to solve a system of multiple variable equations. Manually solving cost a lot of work, but wolframalpha can solve it automatically. For Rc we take a value of 100kΩ, the resistors Ra and Rb have to be determined.

Gain calculation:

The gain is (Rc + Ry) / Ry, where Ry is the equivalent resistance Ry = Ra*Rb / (Ra+Rb)

Kirchhoff's circuit law:

iRa = iRb + iRc
(5V - 2.98V) / Ra = 2.98V / Rb + (2.98V - 1.25V) / Rc

So there are 4 equations which have to be filled in into wolframalpha:
c = 100e3, y = a*b / (a+b), (c + y) / y = 5, (5 - 2.98) / a = 2.98 / b + (2.98 - 1.25) / c

After a short time wolframalpha comes with the solution:
Ra=36630Ω, Rb=78740Ω

Electronic circuit calculation with wolframalpha
Electronic circuit calculation with wolframalpha

http://www.wolframalpha.com/input/?i=y+%3D+a*b+%2F+%28a%2Bb%29%2C+%28c+%2B+y%29+%2F+y+%3D+5%2C+c+%3D+100e3%2C+%285+-+2.98%29+%2F+a+%3D+2.98+%2F+b+%2B+%282.98+-+1.25%29+%2F+c

LM335 class

For troubleshooting see HERE.

LM335.pde

#include "LM335.h"

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;
}

LM335.h 

#ifndef LM335_H
#define LM335_H

// LM335 temperature sensor interface
// Rev 1.0 Albert van Dalen

// Resolution 0.1 degree

// Calibration values, set in decimals
static const float lm335_offset = 559; // 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
{
public:
  LM335(int _ADCpin);
  int deciCelsius();
  int celsius();
  int deciFahrenheit();
  int fahrenheit();
 
private:  
  inline void initialize();
  inline int readAdc();
  int ADCpin;
};

#endif

Do you have any comments? Please let me know.
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.