LM335Z Temperature Sensor

I'm using an LM335Z temperature sensor with an Arduino Mega.
I have the 5V rail going through a 2K resistor and have managed to calibrated it.
At the moment the Arduino is connected to my PC with USB.

I find the reading is quite stable UNTIL I connect my I2C 7-Segment display, and then the readings start to vary jumping from 23 degrees to 31!

I understand that the sensor needs a solid analogue reference voltage to give accurate readings, so plugging the Arduino into a 9V power supply instead of the USB to computer will probably be better.

Why does the display cause these fluctuations? Is it a voltage issue or interference? What can I do to address this issue? Can I use a capacitor is some way to stabilise the voltage???

Arduino uses the potentially unstable 5volt rail as reference for the A/D.
If you're happy with a temp range of ~0-100C, you could use the internal 1.1volt Aref.
Here is an example sketch I wrote.
Change (INTERNAL) to (INTERNAL1V1) for your Mega.
Leo..

// LM35 temp sensor connected to A1
// ~2 to ~102 degrees C
//
float Aref = 1.063; // calibration, change this to the actual Aref voltage of ---YOUR--- Arduino
unsigned long total; // A/D output
float tempC; // Celcius
float tempF; // Fahrenheit
//
void setup() {
  analogReference(INTERNAL); // use the internal ~1.1volt reference, change (INTERNAL) to (INTERNAL1V1) for a Mega
  Serial.begin(115200); // ---set serial monitor to this value---
}
//
void loop() {
  analogRead(A1); // one unused reading to clear old sh#t
  for (int x = 0; x < 100; x++) { // 100 readings for averaging
    total = total + analogRead(A1); // add each value
  }
  // convert value to temp
  tempC = total * Aref / 1024; // value to temp conversion
  tempF = tempC * 1.8 + 32; // Celcius to Fahrenheit conversion
  total = 0; // reset value
  // print to serial monitor
  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");
  delay(1000); // slows readings
}

Thanks for your feedback.
Changing my code to use Aref of 1.063 gives me:

"The temperature is 107.2 Celcius" from the serial monitor.

const int TEMPERATURE = A0;
float Aref = 1.063;

void setup()
{
analogReference(INTERNAL1V1);
...
}

void DisplayTemp()
{
unsigned long total;
float tempC;

analogRead(TEMPERATURE);
for (int x = 0; x < 100; x++)
{
total = total + analogRead(TEMPERATURE);
}
tempC = total * Aref / 1024;
Serial.print("The temperature is ");
Serial.print(tempC, 1); // one decimal place
Serial.println(" Celcius");
}

The raw value from analogRead(TEMPERATURE); is 1023.00!

I get these values with my original code:

Raw: 652 Celcius: 33.30
Raw: 639 Celcius: 26.95
Raw: 631 Celcius: 23.04
Raw: 635 Celcius: 24.99
Raw: 630 Celcius: 22.55
Raw: 655 Celcius: 34.77
Raw: 638 Celcius: 26.46
Raw: 630 Celcius: 22.55
Raw: 646 Celcius: 30.37
Raw: 630 Celcius: 22.55
Raw: 649 Celcius: 31.84
Raw: 638 Celcius: 26.46
Raw: 630 Celcius: 22.55
Raw: 652 Celcius: 33.30

float ConvertKelvinToCelcius(int reading)
{
// float kelvin = ((reading / 1023.0) * Aref) * 100.0;
float kelvin = ((reading / 1023.0) * 5.0) * 100.0;
float celcius = kelvin - 273.15;
return celcius;
}

b4ip:
The raw value from analogRead(TEMPERATURE); is 1023.00!

That is what you get when nothing is connected to the analogue input.
Check your wiring and sensor.
Leo..

No it's not the wiring. I changed back to my original code without Aref and the values are ok, but they fluctuate a lot (see above) from about 21 to 33 degrees

I get reasonably good values ie. not varying too much when I have just the temp sensor and Chronodot connected, but they start varying a lot once I add the 7-segment display.

This is very frustrating, I think I might have to try a different temp sensor, maybe the Dallas version.

The values from post#3 indicate a "floating" input.
No sensor connected.

1023, with 1.1volt Aref also indicate a "floating" input.

All arrows point to a not connected (or broken) sensor.

If you have a DMM, measure the voltage on the analogue input.
It must be 250mV (0.250volt) when the sensor is 25 degrees C.

Post a picture of your wiring.
Leo..

const int TMP335Z= A0;
float Aref = 1.063;
long interval = 1000;

void setup()
{
analogReference(INTERNAL1V1);
pinMode(TMP335Z, INPUT);
Serial.begin(115200);
...
}

void loop()
{
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval)
{
previousMillis = currentMillis;
DisplayTempAref();
// DisplayTempNormal();
}
}

void DisplayTempNormal()
{
int raw = analogRead(TMP335Z);
float kelvin = ((raw / 1023.0) * 5.0) * 100.0;
float celcius = kelvin - 273.15;
Serial.print("Raw: ");
Serial.print(raw);
Serial.print(" Celcius: ");
Serial.println(celcius, 1);
}

void DisplayTempAref()
{
unsigned long total;
float raw = analogRead(TMP335Z);
raw = analogRead(TMP335Z);
for (int x = 0; x < 100; x++)
{
total = total + analogRead(TMP335Z);
}
total = total / 100.0;
float celcius = (total * Aref) / 1024.0;
Serial.print("Raw: ");
Serial.print(raw);
Serial.print(" Celcius: ");
Serial.print(celcius, 2);
Serial.print(" Total: ");
Serial.print(total, 1);
Serial.print(" Aref: ");
Serial.println(Aref, 3);
}

Results from DisplayTempNormal()
Raw: 647 Celcius: 43.1
Raw: 636 Celcius: 37.7
Raw: 628 Celcius: 33.8
Raw: 628 Celcius: 33.8
Raw: 628 Celcius: 33.8
Raw: 643 Celcius: 41.1
Raw: 649 Celcius: 44.1
Raw: 633 Celcius: 36.2
Raw: 646 Celcius: 42.6
Raw: 635 Celcius: 37.2
Raw: 628 Celcius: 33.8

Results from DisplayTempAref()
Raw: 1023.00 Celcius: 1.08 Total: 1042 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063

Note: when using DisplayTempNormal() I rem out the line "analogReference(INTERNAL1V1);"

Connected wrong.

Pin1 to 5volt

Pin2 to analogue input

Pin3 to ground

NO 220ohm resistor.

Leo..

Thanks Wawa for your reply.
Sorry I forgot to mention, the resistor is 2.2K ohms not 220.
At the moment I'm not using the adjust pin (Pin 1)???

Can you clarify?

  • Pin1 (Adjust) to 5V rail
  • Pin2 (Middle pin) to analogue input (A0)
  • Pin3 to GND

No resistor

See attached Fritzing pic, does this look right?

This is what I now get after changing the wiring:

Results from DisplayTempNormal()
Raw: 582 Celcius: 11.3
Raw: 588 Celcius: 14.2
Raw: 583 Celcius: 11.8
Raw: 592 Celcius: 16.2
Raw: 591 Celcius: 15.7
Raw: 587 Celcius: 13.8
Raw: 580 Celcius: 10.3
Raw: 585 Celcius: 12.8

Results from DisplayTempAref()
Raw: 1023.00 Celcius: 1.08 Total: 1038 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063
Raw: 1023.00 Celcius: 1.07 Total: 1033 Aref: 1.063

Last Fritzing diagram is ok.

Why do you call it "adjust pin"
A 3-pin TMP35 has no adjust pin.
Leo..

Yes the LM335 has an adjust pin.
According to what I've read (re- data sheet info) the pins are:

  1. Adjust
  2. Positive
  3. Ground

That's why I wired it up according to this:
http://web.mit.edu/rec/www/workshop/lm335.html

Here is another example of using the LM335:

This is essentially my original wiring which is correct according to the LM335 datasheet and the examples I found on the Net.

I can get reasonably god results UNTIL I connect my 7-Seg LED display. Then I start to get fluctuations in the readings +- 10 degrees!

I thought the display might be causing interference or voltage fluctuations, so maybe I need to add a capacitor to smooth out the voltage, but I'm not sure how to do this properly.

But that still doesn't explain why I'm getting the 1023 readings when using Aref.

I am really at a loss as to why this is happening.

lm335.png

I think we're both mixing up things here.

LM35, TMP35, LM335, are all different parts.
There is no TMP335.

The LM335 has an adjust pin, and needs a current limiting resistor.
The TMP35 and LM35 not.

My code is for the TMP35 and LM35.
Not for the LM335.

The LM335 can't be used with the more stable 1.1volt Aref.

Sorry for the mixup.
Leo..

Yes, I never mentioned any TMPxxx, my post is titled "LM335Z" which is what's written on the sensor.

Okay, then I won't use Aref.

At this stage I don't know what to do about the varying readings, except to try connecting the Mega with a power supply as opposed to via the USB from the PC and see if that makes any difference.

Perhaps I should try another sensor such as the Dallas (aka. Maxim) DS18B20, but that means I will have to use the 1-Wire protocol/library.

Or buy a TMP35 or LM35.
Leo..

The LM335Z doesn't like me, and I've lost patience with it. I will get a TMP36 and DS18B20 and give them a try. At least the TMP36 will work with Aref which should iron out the fluctuations somewhat.

Thanks for your efforts Wawa.

The LM335Z is indeed not easy to use with an Arduino.
Because you have to use default Aref, and that is potentially unstable.

TMP36 will work with 1.1volt Aref only to ~50 degrees C.
But with a Mega, and 2V56 Aref, the full scale can be used.

The code for a TMP36 is slightly different because of the 500mV offset.
Here is some (untested) code to get you started.
Leo..

// TMP36 temp sensor connected to Analogue-in A1, +5volt and ground
// ~ -50 to +55 degrees C
//
unsigned int total;
float tempC;
float tempF;
//
void setup() {
  analogReference(INTERNAL2V56); // ---uncomment this line for a MEGA---
  Serial.begin(115200); // set serial monitor to this value
}
//
void loop() {
  analogRead(A1); // one unused reading
  for (int x = 0; x < 20; x++) { // 20 readings for averaging
    total = total + analogRead(A1); // add each value to a total
  }
  Serial.print("Raw average = "); // debugging
  Serial.print(total * 0.05, 1); // 1/20 of 20 readings, one decimal place

  // leave ONE of these three lines uncommented

  //tempC = total * 3.3 * 5 / 1024 - 50; // ---this line is for 3.3volt Arduinos---
  //tempC = total * 5.0 * 5 / 1024 - 50; // ---this line is for 5volt Arduinos---
  tempC = total * 2.56 * 5 / 1024 - 50; // ---this line is for a MEGA with 2.56volt Aref enabled---
  // calibration: change reference voltages to actual voltage
  
  tempF = tempC * 1.8 + 32; // Fahrenheit conversion
  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");
  delay(1000); // slows readings
  total = 0; // reset value
}