LM34DZ Fahrenheit Temperature Sensor

This started as notes I made to myself long ago for the LogoChip, but they apply equally to the Arduino A/D converters.

The LM34DZ is a temperature sensor in a TO-92 case available from All Electronics for $2.50. It has the handy characteristic of reading an output voltage that directly corresponds to Fahrenheit temperature in a ratio of 10mV per °F. That is, at 70°F it reads 70 * 10mV = 700mV.

LM34DZ Fahrenheit temperature sensor

With a direct output voltage (rather than the varying resistance that many thermal probes provide), it’s perfect for hooking to a microcontroller A/D input. So, how to convert the A/D reading back into Fahrenheit temperature?

Well, the sensor reads 10mV (or .01V) per °F. Microcontroller A/D converters tend to have 5V input and read 1024 steps over the 0-5V range.

1024 steps / 5V ≈ 205 steps / V

So

(.01V / °F) * (205 steps / V) ≈ 2 steps / °F

Thus you can get a “maybe close enough” approximation with code like

tempF = analogRead(lm34Pin) / 2;

With a conversion error of +2.4%, this’ll get you within a couple of degrees at room temperature — close enough to make some macro-level observations about whether it’s getting warmer or colder for a physical computing project. Since the stated accuracy is only 1°F anyway, that’s not too bad.

If you need a more accurate conversion, you’ll need to use floating-point arithmetic if you have it (which the Arduino doesn’t [correction: does]) or find a fixed-point arithmetic library if you don’t. Or if your integer variables are large enough (at least 17 unsigned bits for temperatures up to 127°F, 18 bits up to 255°F), you can rearrange the order of calculation like so:

tempF = (1024 * analogRead(lm34Pin)) / 5;

9 Responses to “LM34DZ Fahrenheit Temperature Sensor”

  1. Jin says:

    I think Arduino does have floating point. I’ve used it, at any rate: http://www.arduino.cc/en/Reference/Float

    A very simple improvement would be to feed the 3.3V output to the AREF pin for ~3.1 steps per degree. Slightly more involved would be to use an op amp to give you full scale for the temperature range of interest.

  2. Keith Neufeld says:

    Jim, I don’t know why I thought there was no floating point on the Arduino — you’re clearly correct. Thanks for pointing that out.

    I like the LM34DZ in part because it doesn’t require external components for preamplification or level-shifting. But I really dig your idea of feeding a different voltage to AREF — thanks!

  3. Dave says:

    There are quite a few temperature sensor ICs in the LM family. In addition to the analog ones, there are some which are digital (e.g., National LM75/Maxim DS75). These have an I2C bus, which means that you can
    put several of them on the same I2C bus (e.g., Sprinkle them around a card, enclosure, etc.).

    Dave

  4. Keith Neufeld says:

    Dave, the I2C chips sound interesting, especially in SMT. Thanks for pointing that out!

  5. iam in uganda trying to design a LED thermometer requiring an LM34DZ temperature sensor IC but i have failed to get it. i would like alternative ICs of LM32DZ

  6. am in uganda trying to design a LED thermometer requiring an LM34DZ temperature sensor IC but i have failed to get it. i would like alternative ICs of LM34DZ.

    i will greatful for your response

  7. JimG says:

    There’s another way to scale an a/d reading that doesn’t involve floating point math, but does require 16 bit variables.

    Lets say your a/d reading is a value of 150, which is about .732 volts / 73 degrees

    using a simple function such as this will allow you to scale a adc count to any value (with some limitations – see the last paragraph).

    By adjusting the value of fs up or down, you can fine tune the output. fs is the value for 1024 counts.

    uint16_t scale_adc(uint16_t adc, uint16_t fs)
    {
    	uint16_t v=adc<>=1;				// divide v by 2
    		if (fs&0x8000) {		// see if fs bit 15 is set
    			result+=v;		// if so, update result
    		}
    		fs<<=1;				// multiply fs by 2
    	}
    	return result;
    }
    // a test program
    int	main(void)
    {
    	uint16_t adc,fs,temp1;
    	adc=150;
    	for (fs=5000; fs<=5010; fs++) {
    		temp1=scale_adc(adc, fs);
    		printf("fs=%d, adc=%d, scale_adc=%d\n", fs, adc, temp1);
    	}
    	return 0;
    }
    

    running this gives:

    fs=5000, adc=150, scale_adc=731
    fs=5001, adc=150, scale_adc=731
    fs=5002, adc=150, scale_adc=731
    fs=5003, adc=150, scale_adc=731
    fs=5004, adc=150, scale_adc=731
    fs=5005, adc=150, scale_adc=731
    fs=5006, adc=150, scale_adc=731
    fs=5007, adc=150, scale_adc=731
    fs=5008, adc=150, scale_adc=732
    fs=5009, adc=150, scale_adc=732
    fs=5010, adc=150, scale_adc=732
    

    So a value of around 5010 would be optimum for 73.2 degrees.

    Going a little further, fixing fs at 5010 and varying the adc count:

    fs=5010, adc=145, scale_adc=708
    fs=5010, adc=146, scale_adc=713
    fs=5010, adc=147, scale_adc=717
    fs=5010, adc=148, scale_adc=723
    fs=5010, adc=149, scale_adc=727
    fs=5010, adc=150, scale_adc=732
    fs=5010, adc=151, scale_adc=736
    fs=5010, adc=152, scale_adc=743
    fs=5010, adc=153, scale_adc=747
    fs=5010, adc=154, scale_adc=752
    fs=5010, adc=155, scale_adc=756
    

    This method isn’t perfect, but it doesn’t require floating point math.

    Try to stay away from fs values that are a power of 2 (128,256,512,1024,etc).

  8. Phew says:

    i am just a beginner in electronics and i want to know the pin configuration for the LM32DZ.. thanks!

  9. Keith Neufeld says:

    Phew, if you follow the link to All Electronics, you can download the datasheet from them. It shows the pinout that you’re looking for.

Leave a Reply