Need Help with LM35

Hello There! I hope you all are doing good.

I am working on a controller which is supposed to control heater light and fans this system has Arduino Nano integrated in it and has a nokia display and menu system that lets user set the threshold values for the above mentioned devices. The home screen of this menu system is supposed to display temperature from two different LM35 connected on A0 and A1 respt. everything works fine but the temperature that my LM35 gives is not stable and gives some lot of garbage and meaningless values.

The code is attached below as it exceeds the word limit.

Vcc of both LM35 goes in 5V not from arduino but from onboard power supply. GND to the circuit GND made common and sensor pin to A0 of one sensor and to A1 of other sensor.

What am I missing here? Any help?

sketch_jul13d_temp_cntrler_V0.2.ino (9.2 KB)

I assume you drive many relays. How are they connected?

What’s your power supply’s power (watts or amps spec ) and what does your system require?

Are the LM35s and/or their wires submersed in water? Even encapsulated, that can make them go bananas.

-jim lee

Hi count,

So what are the values that are displayed?

Did you run a small testcode that does nothing more than showing the temperature as
raw ADC-value and as caclulated centigrade degree?

The LM35 is an analog sensor. with a low voltage at 20°C = 0,2V
How long are the wires from Sensor to Arduino? Did you use a shielded wire to protect the signal against EMV/electromagnetic noise?

is there a special reason for you to use this analog sensor?
I prefed digital sensors like the DS18B20. As the signal is transferred digital from sensor to microcontroller which is much more robust against EMV / electromagnetic noise,

There are libraries available that make the use of this sensors quite easy.As they are onewire-sensors only one digital IO-pin is requiered to drive them. Additional +5V and GND

best regards Stefan

jimLee:
Are the LM35s and/or their wires submersed in water? Even encapsulated, that can make them go bananas.

-jim lee

No sir, LM 35 aren't submersed in water nor encapsulated. one of the LM35 connected to A1 is on board and the other one stays off board with wires of about 6 inches long without shielded wires

StefanL38:
Hi count,

So what are the values that are displayed?

Did you run a small testcode that does nothing more than showing the temperature as
raw ADC-value and as caclulated centigrade degree?

The LM35 is an analog sensor. with a low voltage at 20°C = 0,2V
How long are the wires from Sensor to Arduino? Did you use a shielded wire to protect the signal against EMV/electromagnetic noise?

is there a special reason for you to use this analog sensor?
I prefed digital sensors like the DS18B20. As the signal is transferred digital from sensor to microcontroller which is much more robust against EMV / electromagnetic noise,

There are libraries available that make the use of this sensors quite easy.As they are onewire-sensors only one digital IO-pin is requiered to drive them. Additional +5V and GND

best regards Stefan

Hello Stefan,

The offboard sensor is connected to A0 it displays negative values and the onboard connected on A1 shows positive values. Both keeps on running like a stop watch

I have a test code but I didn't thought of running it.

The offboard sensor is connected with regular unshielded wires which are around 6 inches long.

LM35 is on client's request

I ran a test code as below

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

// Declare LCD object for software SPI
// Adafruit_PCD8544(CLK,DIN,D/C,CE,RST);
Adafruit_PCD8544 display = Adafruit_PCD8544(8, 9, 10, 11, 12);

const int sensor1 = A1; // Assigning analog pin A1 to variable 'sensor'
int tempc1;  //variable to store temperature in degree Celsius
int vout1;  //temporary variable to hold sensor reading

const int sensor2 = A0; // Assigning analog pin A1 to variable 'sensor'
int tempc2;  //variable to store temperature in degree Celsius
int vout2;  //temporary variable to hold sensor reading


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

  //Initialize Display
  display.begin();

  // you can change the contrast around to adapt the display for the best viewing!
  display.setContrast(57);

  // Clear the buffer.
  display.clearDisplay();

   // Display Text
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(10,0);
  display.println("TEMPERATURE");
  display.drawFastHLine(0,10,83,BLACK);
  

   vout1  = analogRead(sensor1);
  vout1  = (vout1*500)/1023;
  tempc1 = vout1; // Storing value in Degree Celsius
  
     display.setTextSize(1);
     display.setTextColor(BLACK, WHITE);
     display.setCursor(5, 15);
     display.print("Temp1:");
     display.setTextSize(2);
     display.setCursor(5, 25);
     display.print(tempc1);

     vout2  = analogRead(sensor2);
     vout2  = (vout2*500)/1023;
     tempc2 = vout2; // Storing value in Degree Celsius
  
     display.setTextSize(1);
     display.setTextColor(BLACK, WHITE);
     display.setCursor(47, 15);
     display.print("Temp2:");
     display.setTextSize(2);
     display.setCursor(47, 25);
     display.print(tempc2);
     
       display.display();
       delay(2000);
       display.clearDisplay();
}

void loop() 
{}

and it works completely fine. Shows stable values. but when I try to embed it in my main project code the values becomes gibberish

Apparently If I move the test code from setup to loop same problem occurs

can you answer the question #1 about the power supply and the wiring of the relays - if any?

if you have a drop in the voltage - not enough to crash the arduino, but enough to impact AREF, analogRead() will go nuts as its reference won't be 5V anymore.

J-M-L:
can you answer the question #1 about the power supply and the wiring of the relays - if any?

if you have a drop in the voltage - not enough to crash the arduino, but enough to impact AREF, analogRead() will go nuts as its reference won't be 5V anymore.

I answered it. Again, my power supply is 12V 1amp. No relays, BJT BC547 and power BJT BD139 both are NPN general purpose transistors

int vout2;  //temporary variable to hold sensor reading
...
vout2  = analogRead(sensor2);
  vout2  = (vout2*500)/1023;

vout1 and vout2 are 16 bit ints. What is 1023 times 500?

Count:
I answered it. Again, my power supply is 12V 1amp.

not sure where. I guess I need glasses.

Eagle's eyes of aarg -> integer overflow is indeed a good one..

Vcc of both LM35 goes in 5V not from arduino but from onboard power supply. GND to the circuit GND made common and sensor pin to A0 of one sensor and to A1 of other sensor.

Post a diagram of that.

Here's a LM35 lib I wrote awhile ago..

The .h file..

#ifndef LM35_H
#define LM35_H

/*
 This is a little class to run the TI-LM35 temp
 sensing chip from an analog pin on an Arduino.
 
 Constructor takes a pin number. 
 Foe example : LM35 mySensor(A2);
 When you want a reading just call either tempC()
 for centigrade or tempF() for Farenheight.
 
 This assumes you have the sensor hooked directly to
 5V & Ground with the data out pin conected to the 
 analog input on your Arduino. No fancy circuits, 
 just the 3 wires.
 
 Enjoy!
 
 -jim lee
 */

class LM35 {
  
  public:
    LM35(int inPin);
    ~LM35(void);
    
    float centToDegF(float cent);
    float tempC(void);
    float tempF(void);
    
 private:
    int     pin;
};

#endif

The .cpp file

#include "LM35.h"
#include <mapper.h>

// We all need the mappers and they are always the same. So just
// make up the two and share em.
mapper intToVolts(0,1023,0,5.0);    // From Arduinoland..
mapper voltsToTemp(0,1.5,0,150);    // From the LM35 datasheet.


// Constructor, saves off our input pin.
LM35::LM35(int inPin) { pin = inPin; }

// Destructor, nothing to see here..
LM35::~LM35(void) { }
 

// How to convert centagratde to Farenheight. From the web.
float LM35::centToDegF(float cent) { return (cent * 1.8) + 32; }
 

// This is the only call that actually talks to the sensor.
// Returns the temp. in centagrade.
float LM35::tempC(void) {
  
  unsigned int count = analogRead(pin);
  double volts = intToVolts.Map(count);
  return voltsToTemp.Map(volts);
}
  
// To get Farenheight we first grab centagrade then convert
// the value. If you want, you can do this yourself using
// the centToDegF(tempC); function.
float LM35::tempF(void) { return centToDegF(tempC()); }

You'll need the float mapper class found in this library here : LC_baseTools

-jim lee

I've found that the LM35 needs a decoupling cap, 0.1uF ("100nF") -- leads short as possible, close by it.

Using default Aref with an LM35 is asking for trouble, especially with a Nano on USB power.
Not only will the result be varying with supply variations (other devices that draw varying currents),
but also the resolution will suffer (0.5C steps at best).

Analogue sensors, like the LM35/TMP36, are a pain to use. Go digital (I2C) if you can.
That said, there are some rules.
Decouple the supply of the LM35, close to the LM35.
Don't share ground with anything else (breadboard). LM35 ground must go directly to a Nano ground pin.
(power can come from the 5volt pin, no need to use stable/external power)
Use shielded wiring for longer runs.
Put this in setup: analogReference(INTERNAL); // switch to 1.1volt Aref
Any LM35 code without that line can't be trusted (written by a somebody who doesn't know how).
Only then can you expect a ~5-100C display with 0.1C resolution.
Leo..

Thanks all of you guys for your valuable inputs.

The point I mentioned was, the test code posted below, works completely fine when it is in void setup, if the same code is moved to void loop, the same problem occurs with this one too

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

// Declare LCD object for software SPI
// Adafruit_PCD8544(CLK,DIN,D/C,CE,RST);
Adafruit_PCD8544 display = Adafruit_PCD8544(8, 9, 10, 11, 12);

const int sensor1 = A1; // Assigning analog pin A1 to variable 'sensor'
int tempc1;  //variable to store temperature in degree Celsius
int vout1;  //temporary variable to hold sensor reading

const int sensor2 = A0; // Assigning analog pin A1 to variable 'sensor'
int tempc2;  //variable to store temperature in degree Celsius
int vout2;  //temporary variable to hold sensor reading


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

  //Initialize Display
  display.begin();

  // you can change the contrast around to adapt the display for the best viewing!
  display.setContrast(57);

  // Clear the buffer.
  display.clearDisplay();

   // Display Text
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(10,0);
  display.println("TEMPERATURE");
  display.drawFastHLine(0,10,83,BLACK);
 

   vout1  = analogRead(sensor1);
  vout1  = (vout1*500)/1023;
  tempc1 = vout1; // Storing value in Degree Celsius
 
     display.setTextSize(1);
     display.setTextColor(BLACK, WHITE);
     display.setCursor(5, 15);
     display.print("Temp1:");
     display.setTextSize(2);
     display.setCursor(5, 25);
     display.print(tempc1);

     vout2  = analogRead(sensor2);
     vout2  = (vout2*500)/1023;
     tempc2 = vout2; // Storing value in Degree Celsius
 
     display.setTextSize(1);
     display.setTextColor(BLACK, WHITE);
     display.setCursor(47, 15);
     display.print("Temp2:");
     display.setTextSize(2);
     display.setCursor(47, 25);
     display.print(tempc2);
     
       display.display();
       delay(2000);
       display.clearDisplay();
}

void loop()
{}

if I move the code in loop and comment out output from any one sensor then too it works completely fine. the code works completely fine if either:

  1. when the code is in void setup

or

  1. If the code is in void loop any one of the sensor should be commented off.

Is this has to be a programming problem? or a hardware problem?

Your original code,

Delete this.

int vout1;  //temporary variable to hold sensor reading
int vout2;  //temporary variable to hold sensor reading

pinMode(sensor1, INPUT);
pinMode(sensor2, INPUT);

vout1  = analogRead(sensor1);
vout1  = (vout1*500)/1023;

vout2  = analogRead(sensor2);
vout2  = (vout2*500)/1023;

Add this to setup().

analogReference(INTERNAL);

Change this

tempc1 = vout1; // Storing value in Degree Celsius
to
tempc1 = analogRead(sensor1) * 0.1039; // change last digit(s) to calibrate, if needed

and

tempc2 = vout2; // Storing value in Degree Celsius
to
tempc2 = analogRead(sensor2) * 0.1039; // change last digit(s) to calibrate, if needed

Leo..

Wawa:
Your original code,

Delete this.

int vout1;  //temporary variable to hold sensor reading

int vout2;  //temporary variable to hold sensor reading

pinMode(sensor1, INPUT);
pinMode(sensor2, INPUT);

vout1  = analogRead(sensor1);
vout1  = (vout1*500)/1023;

vout2  = analogRead(sensor2);
vout2  = (vout2*500)/1023;




Add this to setup().


analogReference(INTERNAL);




Change this


tempc1 = vout1; // Storing value in Degree Celsius
to
tempc1 = analogRead(sensor1) * 0.1039; // change last digit(s) to calibrate, if needed

and

tempc2 = vout2; // Storing value in Degree Celsius
to
tempc2 = analogRead(sensor2) * 0.1039; // change last digit(s) to calibrate, if needed



Leo..

Just a quick thing to ask if I delete that entire part that reads and calculate the sensor would it work?

Just follow the recipe.
It just calculates tempc1 in a different way, using a more stable reference than the potentially dirty supply.

This will of course only work if the build quality is up to standard as well.
Leo..