-
Arduino Snippets: Temperature Measurement
Temperature seems an obvious thing to measure, so a bit of rummaging disgorged a classic LM335 temperature sensor that produce an output voltage directly calibrated in Kelvin at 10 mV/K: room temperature runs 296 K = 2.96 V. Nothing could be easier than this:

LM335 Temperature Sensor The downside: a 1 °C temperature change corresponds to only 10 mV, which is barely two LSB of the Arduino ADC. In round numbers, a 1 °F change = 1 LSB, which doesn’t leave much room for measurement noise. I average five successive readings, which may be excessive, but the result seems stable enough:
const float AVREF = 4.94; // Arduino analog reference #define TAVG 5 float ReadLM335(byte Pin) { float Kelvin; Kelvin = (float)analogRead(Pin); for (byte i = 1; i < TAVG; i++) Kelvin += (float)analogRead(Pin); return Kelvin * (100.0 * AVREF) / (TAVG * 1024.0); }For better accuracy, you must measure VCC on the Arduino board and plug that into the
AVREFconstant, because the ADC reference voltage comes from the power supply. If you’re powering the Arduino from a USB port, then don’t bother worrying about analog conversion accuracy, because VCC depends on which PC you use, the USB cable length, what load current you draw from the regulator, and probably the phase of the moon.The magic number
100.0converts 10 mV/K to K.The four character DL1414 LED display works well enough for the kind of temperatures you might find around a human being and, if you have an LED bargraph display, you may as well throw that into the mix, too.

LM335 Temperature Sensor – 19 C The bargraph has RRYYGGYYRR LEDs, so I scaled the temperature at 5 °C/bar and put 0 °C on the bottom of the display, which means 15-19 and 20-24 °C occupy the green bars in the middle. Fingertip temperatures light up the two yellow bars and body heat gets you into the red, so it’s a reasonable display. Just to show it works, here’s a closer look (0 °C is on the right, but you can reverse that easily enough):

LM335 Temperature Sensor – 25 C The Arduino source code:
// LM335 Temperature sensor sensor // Ed Nisley - KE4ANU - November 2012 //#include <stdio.h> //#include <math.h> //---------- // Pin assignments const byte PIN_TEMPERATURE = A1; // Temperature sensor - LM335 = 10 mV/K const byte PIN_MOSI = 8; // data to shift reg const byte PIN_SCK = 6; // shift clock to shift reg const byte PIN_RCKB = 7; // latch clock for LED Bargraph const byte PIN_RCKC = 12; // latch clock for LED character display const byte PIN_HEARTBEAT = 13; // DO - Arduino LED //---------- // Constants const int UPDATEMS = 1000; // update LEDs only this many ms apart const float AVREF = 4.94; // Arduino analog reference const float KTOC = -273.2; // Kelvin to Centigrade offset const float BARSCALE = 5.0; // degrees per bar increment #define TCCRxB 0x02 // Timer prescaler #define LED_SIZE 4 // chars per LED #define LED_DISPLAYS 1 // number of displays #define LED_CHARS (LED_DISPLAYS * LED_SIZE) union DL1414_ { word ShiftWord; // word overlay struct { // bitfield sent to the display unsigned int Addr:2; unsigned int NotWrite:1; unsigned int Ctl3_7:5; // unused bits unsigned int Data:7; unsigned int Data7:1; // unused bit } ShiftBits; }; //---------- // Globals int Temperature, BaseTemperature; word LEDBits; char LEDCharBuffer[LED_CHARS + 1] = "HELO"; // raw char buffer, can be used as a string unsigned long MillisNow; unsigned long MillisThen; //-- Helper routine for printf() int s_putc(char c, FILE *t) { Serial.write(c); } //-- Send bits to LED bar driver register void SetBarBits(word Pattern) { shiftOut(PIN_MOSI,PIN_SCK,MSBFIRST,Pattern >> 8); shiftOut(PIN_MOSI,PIN_SCK,MSBFIRST,Pattern & 0x00ff); digitalWrite(PIN_RCKB,HIGH); digitalWrite(PIN_RCKB,LOW); } void PulsePinHigh(byte PinID) { digitalWrite(PinID,HIGH); digitalWrite(PinID,LOW); } //-- Write single char to DL1414 void WriteLEDChar(char Char,char CharID) { union DL1414_ DL1414; DL1414.ShiftBits.Data = Char & 0x7F; DL1414.ShiftBits.Addr = ~CharID & 0x03; // reverse order of chars DL1414.ShiftBits.NotWrite = 1; // set up data and address shiftOut(PIN_MOSI,PIN_SCK,MSBFIRST,DL1414.ShiftWord >> 8); shiftOut(PIN_MOSI,PIN_SCK,MSBFIRST,DL1414.ShiftWord & 0x00ff); PulsePinHigh(PIN_RCKC); // delay(1000); DL1414.ShiftBits.NotWrite = 0; // write the character shiftOut(PIN_MOSI,PIN_SCK,MSBFIRST,DL1414.ShiftWord >> 8); shiftOut(PIN_MOSI,PIN_SCK,MSBFIRST,DL1414.ShiftWord & 0x00ff); digitalWrite(PIN_RCKC,HIGH); PulsePinHigh(PIN_RCKC); // delay(1000); DL1414.ShiftBits.NotWrite = 1; // disable write shiftOut(PIN_MOSI,PIN_SCK,MSBFIRST,DL1414.ShiftWord >> 8); shiftOut(PIN_MOSI,PIN_SCK,MSBFIRST,DL1414.ShiftWord & 0x00ff); PulsePinHigh(PIN_RCKC); // delay(1000); } void WriteLEDString(char *pString) { for (byte i=0; (i < LED_CHARS) && *pString; ++i) WriteLEDChar(*pString++,i); return; } //-- Sample temperature with a dab of averaging #define TAVG 5 float ReadLM335(byte Pin) { float Kelvin; Kelvin = (float)analogRead(Pin); for (byte i = 1; i < TAVG; i++) Kelvin += (float)analogRead(Pin); return Kelvin * (100.0 * AVREF) / (TAVG * 1024.0); } //------------------ // Set things up void setup() { pinMode(PIN_HEARTBEAT,OUTPUT); digitalWrite(PIN_HEARTBEAT,LOW); // show we arrived // TCCR1B = TCCRxB; // set frequency for PWM 9 & 10 // TCCR2B = TCCRxB; // set frequency for PWM 3 & 11 pinMode(PIN_MOSI,OUTPUT); digitalWrite(PIN_MOSI,LOW); pinMode(PIN_SCK,OUTPUT); digitalWrite(PIN_SCK,LOW); pinMode(PIN_RCKB,OUTPUT); digitalWrite(PIN_RCKB,LOW); pinMode(PIN_RCKC,OUTPUT); digitalWrite(PIN_RCKB,LOW); Serial.begin(9600); fdevopen(&s_putc,0); // set up serial output for printf() printf("Temperature sensor - LM335\r\nEd Nisley - KE4ZNU - November 2012\r\n"); BaseTemperature = KTOC + ReadLM335(PIN_TEMPERATURE); WriteLEDString(LEDCharBuffer); LEDBits = 0x5555; SetBarBits(LEDBits); printf("Base Temperature: %d C\n",(int)BaseTemperature); delay(1000); MillisThen = millis(); } //------------------ // Run the test loop void loop() { MillisNow = millis(); if ((MillisNow - MillisThen) > UPDATEMS) { digitalWrite(PIN_HEARTBEAT,HIGH); Temperature = KTOC + ReadLM335(PIN_TEMPERATURE); printf("Temperature: %d C\n",(int)Temperature); LEDBits = 0x0200 >> (1 + (int)(Temperature/BARSCALE)); // move upward on display! SetBarBits(LEDBits); sprintf(LEDCharBuffer,"%-3dC",(int)Temperature); WriteLEDString(LEDCharBuffer); digitalWrite(PIN_HEARTBEAT,LOW); MillisThen = MillisNow; } }