LM335 thermometer

I've basically put together an Arduino on a breadboard as a test bed for a standalone project.

For my power supply I'm using either a 9V battery or 3xAA batteries. When I'm using a 9V battery I'm putting this through a 10uF electrolytic capacitor through a 7805 regulator connected to my power rails which has another 10uF electrolytic capacitor. If I use the 3xAA as the power source I just connect this to the power rail that still has the 10uF capacitor, and disregard the 7805.

I'm using a ATmega168P which I've set to run at 8MHz.

I have an LM335 temperature sensor; Pin#1 isn't connected, Pin#2 is connected to the Vcc through a 2.2k resistor. This then feeds back to A0 [pin#23] on the 168P. Pin#3 is connected to ground.

For the readout of the temperature in Celsius, I'm using a 2-digit 7-segment LED.

When I use the 9V as power source the LED shows a value of 31! and When I use the 3xAA it shows 96!!

When I connect a multi-meter to the power rail, I get a reading of:

9V => 4.91V
3xAA => 4.69V

and the voltage reading off of the LM335 pin#2 is:

9V => 3.02V
3xAA => 3.02V

The sketch is:

#include "SevSeg.h"

SevSeg sevseg; //Instantiate a seven segment controller object

int outputPin = 0;
unsigned long timer = 0;
int refreshTime = 5000;

void setup() 
{
    byte numDigits = 2;   
    byte digitPins[] = {1, 0};
    byte segmentPins[] = {12, 11, 9, 8, 7, 10, 6};

    sevseg.begin(COMMON_CATHODE, numDigits, digitPins, segmentPins);
    sevseg.setBrightness(90);
}

void loop() 
{
    int rawvoltage= analogRead(outputPin);
    float millivolts= (rawvoltage/1024.0) * 5000;
    float kelvin= (millivolts/10);

    float celsius= kelvin - 273.15;
    
    unsigned long mils = millis();
    
    if (mils - timer >= refreshTime)
    {
        timer = mils;
        sevseg.setNumber(celsius, 0);
    }

    sevseg.refreshDisplay();
}

Can anyone advise on a way to accuratley use the LM335 with 3xAA power source? As I don't want to use the 7805 regulator.

I have experimented and put my sketch on another 168P which is still running at 16MHz, and added a 16MHz crystal and two 22pF capacitors. I have also added a step down converter connected to the 9V battery and trimmed the power to 5V.

I'm now getting a reading of 3.04V off of the LM335 and the LED is showing the temperature at 25C.

But connecting an LM335 with a 2.2K resistor, to an Arduino Uno, and sending the temperature reading to the serial monitor, I get a temperature reading of 21.92C.

I can't see why the two would still be showing different temperature readings.

The uno is running this sketch:

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    Serial.print(readTemp());
    Serial.println(" degress Celsius");

    delay(3000);
}

float readTemp()
{
    float val = analogRead(A0);
    float volt = (5.0/1024.0) * val;
    float kelvin = volt * 100;
    return (kelvin - 273);
}

and the standalone 168P @ 16HMz is running this:

#include "SevSeg.h"

SevSeg sevseg; //Instantiate a seven segment controller object

int outputPin = 0;
unsigned long timer = 0;
int refreshTime = 5000;

void setup() 
{
    byte numDigits = 2;   
    byte digitPins[] = {1, 0};
    byte segmentPins[] = {12, 11, 9, 8, 7, 10, 6};

    sevseg.begin(COMMON_CATHODE, numDigits, digitPins, segmentPins);
    sevseg.setBrightness(90);
}

void loop() 
{
    float celsius = readTemp();
    
    unsigned long mils = millis();
    
    if (mils - timer >= refreshTime)
    {
        timer = mils;
        sevseg.setNumber(celsius, 0);
    }

    sevseg.refreshDisplay(); // Must run repeatedly
}

float readTemp()
{
    float val = analogRead(A0);
    float volt = (5.0/1024.0) * val;
    float kelvin = volt * 100;
    return (kelvin - 273);
}

Further observation. On taking a reading of the voltage being supplied by the uno which is taking its power through the USB port, I see that this shows 5.08V. If I trim the step down converter on the standalone circuit to also supply 5.08V, the LED is then showing the same temperature as the uno. Now we're getting somewhere.

I have an LM335 temperature sensor; Pin#1 isn't connected,

Then how do you expect it to work?

Make a pencil drawing showing how you have everything connected and post a photo of it.

I have been using an Atmega328 and an LM335 to control my fridge continuously since 2013.

...R

Robin2:
Make a pencil drawing showing how you have everything connected and post a photo of it.

I have been using an Atmega328 and an LM335 to control my fridge continuously since 2013.

...R

This is an image of my Fritzing PCB. On the left at the top the input for the step down converter small PCB IN - and IN + take the 9V input from the 9V battery and outputs back to my PCB at OUT - and OUT + with 5.08V. All the grounds are set to ground and as such don't have a trace as this will be fed to them from the ground plane. I hope this is ok:

IC1 is the ATmega168P @ 16MHz, and IC2 is the 2-digit 7-segment common cathode LED. Since my post above with the sketch I have re-routed the traces to the LED as the circuit has been re-designed.

R1 = 10k ohm
R2 = 220 ohm
R3 = 220 ohm
R4 = 2.2k ohm
C1 = 10nF
C2 = 22pF
C3 = 22pF
crystal is 16MHz
J1 is connected to on/off switch
J2 connected to 9V battery

Where is the LM335?

Can you label the pins please?

For that sort of thing I would get the LM335 working on a breadboard with the output sent to the Serial Monitor before I ever tried either a PCB layout or an LED display.

...R

The LM335 is T1 with its resister being R4.

I do have an Arduino UNO with just an LM335 connected to a 2.2K resister. As mentioned above that was feeding to the Serial Monitor showing ~21 C. I also had an Arduino on a breadboard which when powered from a 9V battery via a step down converter (set to output 5.08V, i.e. same as uno), that then outputs the same temperature to the LED.

I think I misunderstood the original question.

Perhaps you need to use the Atmega's internal 1.1v voltage reference for your ADC as that will be independent of the power supply voltage.

...R

The output value of the A/D depends on two things.

  1. The input voltage (from the temp sensor).
  2. A reference voltage (the ruler that measures it).

If the reference voltage goes down (ruler shrinks), you measure more A/D values.
Default reference of an Arduino is the (unstable) supply.

The LM335 is a zener diode with a Kelvin output voltage.
Not very good to use with an Arduino for several reasons.

  1. The base output voltage (~3volt at room temp) is rather high.
    The A/D starts at 0volt, so anything under the minimum temp that you want to measure are wasted A/D values.

  2. You need a high Aref voltage because of that high base voltage.
    Then the only option is default Aref (supply), and that is not stable enough for temp measurements.

Dump that sensor.

If you want to stay analogue, change the sensor for an LM35 or TMP36.
Which one you need depends on the temp range you want to measure.
About 5C to 105C for the LM35 (indoors), and about -45C to +55C for the TMP36 (indoors and outdoors).
These temps assume that you are going to use the stable internal 1.1volt bandgap Aref of the Arduino.

Another (easier) option is to use a digital sensor, like the DS18B20.
Leo..

Hi,
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Not a PCB pattern but a schematic with labels on pins and components.

Thanks.. Tom... :slight_smile:

You could use a cheap NTC thermistor in a pot divider from the arduino '+5' supply driving an analog input - that way the actual drive voltage is irrelevant.

Need to calibrate, of course

regards

Allan

You always need to calibrate an analogue temp sensor.

Don't like the "crooked * crooked = straight" part of a thermistor (Steinhart-Hart).
And the different amount of A/D values returned at different temps.
Advantage is the big change around the temp where the NTC is the same value of the pull up resistor.
But this is not significantly more than a TMP36 type sensor.
Leo..

Wawa:
You always need to calibrate an analogue temp sensor.

IIRC (it's 3 years ago) the LM335 was pretty good straight out of the box.

...R

I won't be able to do much on this until next weekend, and maybe not then either! Having said that, I'm going to get an LM35 IC and will then try and use it with the internal 1.1V.

Thanks for all your help. I'll report back idc...

Robin2:
IIRC (it's 3 years ago) the LM335 was pretty good straight out of the box.

All analogue sensors like the LM335 LM35 TMP36 do output a rather accurate voltage according to temp.
The problem is Arduino's Aref (that ruler that measures sensor voltage).
Default 5volt Aref is known but not stable, and the 1.1volt bandgap Aref is stable but unknown.
1.1volt Aref of the Arduino you're working with can be anything between 1volt and 1.2volt.
That's why you have to calibrate.
Once you know the exact 1.1volt Aref voltage of that Arduino, you can write it on the board.

If you can't be bothered with temp calibration, then connect a DMM to the sensor and note the voltage.
Change the "voltage to temp" maths line in your code untill the temp readout matches the voltage on the DMM.
e.g. you measure 765mV on a TMP36, temp readout must show 765 - 500 (offset of a TMP36) = 265.
265 / 10 (10 mV per degree C) = 26.5C.
if you measure 310mV on the output of an LM35 (no offset), the temp must be 310 / 10 = 31C.
Leo..

AndyInSurrey:
I'm going to get an LM35 IC and will then try and use it with the internal 1.1V.

So +5C to +105C.
Here is a sketch to get you started.
Leo..

// LM35 temp sensor connected A0

unsigned int total; // A/D readings
float tempC; // Celcius
float tempF; // Fahrenheit

void setup() {
  analogReference(INTERNAL); // use the internal ~1.1volt reference | change to (INTERNAL1V1) for a Mega
  Serial.begin(9600);
}

void loop() {
  // read the sensor
  for (int x = 0; x < 64; x++) { // 64(max) analogue readings for averaging
    total = total + analogRead(A0); // add each value
  }
  // temp conversion
  tempC = total * 0.001632; // Calibrate by slightly changing 0.0016xx
  tempF = tempC * 1.8 + 32; // Celcius to Fahrenheit

  Serial.print("The temperature is  ");
  Serial.print(tempC, 1); // one decimal place
  Serial.print(" Celcius  ");
  Serial.print(tempF, 0); // no decimal places
  Serial.println(" Fahrenheit");

  total = 0; // reset total
  delay(1000); // slows readings
}

Wawa:
The problem is Arduino's Aref (that ruler that measures sensor voltage).
Default 5volt Aref is known but not stable, and the 1.1volt bandgap Aref is stable but unknown.
1.1volt Aref of the Arduino you're working with can be anything between 1volt and 1.2volt.
That's why you have to calibrate.

I had not realized that that is what you meant.

...R

I bought some LM35 temperature sensors. I put together a breadboard with a 2-digit 7-segment LED and the LM35. Connected these up to an Arduino UNO, with the following sketch:

#include "SevSeg.h"

SevSeg sevseg; //Instantiate a seven segment controller object

int outputPin = 0;
unsigned long timer = 0;
int refreshTime = 5000;

void setup() 
{
    Serial.begin(9600);
    analogReference(INTERNAL);
    byte numDigits = 2;   
    byte digitPins[] = {3,4};
    byte segmentPins[] = {5,6,7,8,9,10,11};

    sevseg.begin(COMMON_CATHODE, numDigits, digitPins, segmentPins);
    sevseg.setBrightness(90);
}

void loop() 
{
    float celsius = readTemp();
    
    unsigned long mils = millis();
    
    if (mils - timer >= refreshTime)
    {
        timer = mils;
        sevseg.setNumber(celsius, 0);
        Serial.println(celsius, 0);
    }

    sevseg.refreshDisplay();
}

float readTemp()
{
    float celsius = analogRead(A5) / 9.31;
    return celsius;
}

This works fine. The problem only occurs when I create a ATmega168 running on a breadboard. D1 shows up fine, but D0 just lights up segment 'A' and that's it. I've re-wired a few times and used a different LED but always get this same issue! It's got me baffled.

Here's a copy of my schematic for a standalone ATmega168 with the LM35 and 7-segment LED (edit, just noticed that the schematic doesn't show pin#7 and pin#8 connected to Vcc and Gnd, which they are)

You've only used one current limiting resistor in the anode drives - this means that the current each LED gets depends on how many are on and the match between LEDs. You need a resistor in the cathode of each LED instead.

And for the anode drives you'll need eg a p-channel logic mosfets - it you have all 7 LEDs ON you'll demand far more current than an arduino output can deliver...

Get that right and we can see about sorting out the software

regards

Allan