Need help - Arduino Uno and LM35

Hi guys,
I’m doing a project to collect body temperature (by LM35 temperature sensor) then transmit it via Bluetooth to an Android device. My problem is the reading from LM35 seems unstable. When I attach the sensor to my body for a certain time (even for a long time), what I receive on my Android tablet is a value which randomly jumps between 33 to 39 Celcius. Sometimes it goes up to 40 or more and sometime it drops to 31 or 32. Following is the code I took from some online tutorials:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);
int tempPin=0;

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

void loop()
{
float reading = analogRead(tempPin);
int tempC = reading5.0/(1024.00.01);
mySerial.println(tempC);
delay(5000); // if I shorten the delay, the instability is worse; if I make it longer, the readings are still unstable
}
I power the Arduino by a USB cable connected to my laptop. The supply power is stable.
What I did check:

  • Measure the output of the sensor and the input power from Android to it and to the Bluetooth module HC-05. All parameters are fine.
  • Use another Bluetooth module (I replaced HC-05 by HC-06 then I don’t have to change the code).
  • I used some simple filtering circuits (by capacitors) on the input power of the sensor and the Bluetooth modules.
    But the problem is still there.
    Additionally, my body temperature is stable; I use a digital multimeter to measure it and it is a stable 37 Celcius reading (the multimeter quickly displays this stable result).
    I appreciate any suggestion provided. Tks in advance.

Did you try averaging a bunch of readings?

int temp=0;
  for(byte i=0; i<5; i++)  //average 5 reads
  {
    temp=temp + analogRead(0)/2;  // should be 500/1024 but wth
    delay(100);
  }
  display.print(temp/5);  
  display.print("C");

I used some simple filtering circuits (by capacitors) on the input power of the sensor

Did you try them on the output of the sensor, that is the input to the Arduino?

Yes, I did, I tried both on the input power of the sensor and its output. Actually, the power is from my laptop, so the supply power for my Arduino, sensor and Bluetooth module it is very stable. I just did the filtering for more sure.

JimboZA:
Did you try averaging a bunch of readings?

int temp=0;

for(byte i=0; i<5; i++)  //average 5 reads
  {
    temp=temp + analogRead(0)/2;  // should be 500/1024 but wth
    delay(100);
  }
  display.print(temp/5); 
  display.print(“C”);

Tks for your suggestion but why “temp=temp + analogRead(0)/2”?

Well the /2 is just my laziness for the way you did it as reading*5.0/(1024.0*0.01); which is x0.488 not my 0.5, close enough for my purposes.

The temp = temp +.... is to keep a running total as it goes thru the for loop, then I divide by 5 afterwards.

Hi JimboZA, could u help me look at the code that I used? For FOR loop, I tried both “byte i=0” and ‘int i=0’ but the result I received is my initianl value of tempC, which is 0.
void loop()
{ int tempC=0;
for(int i=0; i<5; i++)
{
float reading = analogRead(tempPin);
int tempC=tempC + reading5.0/(1024.00.01);
delay(100);
}

mySerial.println(tempC);
delay(5000);
}

I think it’s probably becuase you keep redeclaring your variables in the lines marked with <<<< below.

void loop()
{ int tempC=0;
  for(int i=0; i<5; i++)  
  {
    float reading = analogRead(tempPin);  //<<<<<<<<<<<<<<<<<<<<<<<<<<<,
    int tempC=tempC + reading*5.0/(1024.0*0.01);  <<<<<<<<<<<<<<<<<<<<<<<
    delay(100);
  }
  
  mySerial.println(tempC); 
  delay(5000);
}

You’ll also need to be careful of mixing floats with ints.

Once you sort that, you’ll find your temperature gets quite big becasue you forgot to /5 for the average.

Always observe:

  • No other component must share the ground wire of the LM35.
  • One ground wire by LM35.
  • All ground wires must be connected in one point an the arduino board.
    Don’t forget 10 mV = 1°C.

Recommended :
On the Arduino board AREF track is decoupling at the input connector board . It protects from external noise but not from internal board noise. This explains noisy measurements.

If you have a UNO, solder a 100nF ceramic capacitor on the back of the board between the pin socket AREF and GND .
Any format is convenient but 0805 SMD is ideal.
On the attached pictures there are two capacitors. The right was for a try, it does not improve noise immunity, only this soldered directly on the pin socket improves drastically the measurement .

With this improvement the measure is “naturally” stable and it is not useful to make an averaging .

Forum12.png

Forum13.png

try this out

const int Tpin = A0;

void loop()
{
float x
for (int i=0; i<3; i++)
{
senT = analogRead(Tpin);
x=tempC + reading5.0/(1024.00.01);
delay(20);
}

Tks star-X, but your code did not work, and your code is odd when you don't use "senT", maybe you mean tempC is senT. Moreover, you declare x but didn't initiate it. The result when I tried your code is 0 Celcius.

Tks 68tjs, your suggestions help my reading definitely more stable. But the reading is just max 35.64. It never goes up to 37 C, as I measure by my digital multimeter.

Presumably the code itself is ok now, since you get reasonable values not 0 any more?

Something like the sketch below:

// short sketch to read lm35

float temp;

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

void loop()
{


  temp=0;
  for(byte i=0; i<5; i++)  //average 5 reads
  {
    temp=temp + analogRead(0)/2;  // should be 500/1024
    delay(100);
  }
  Serial.print(temp/5);  
  Serial.println(" C");
  delay(1000);

} //loop

But regarding the 35.64 vs 37… who’s to say which is correct?Unless you have a third reading from another device, you can’t say either of those is right or wrong. (Although 35.6 is low if you’re healthy.)

Apart from 68tjs’s electrical suggestions, also it might depend on how your LM is mounted: mine’s on a breakout board so it’s difficult to get it into good contact with the target.

Hi JimboZA. I used a digital multimeter, a thermometer and my sensor to check my body temperature. I appreciate your help and your suggestions from all of you guys. Anyway my reading is stable around 35-36 (if I declare INT on my output), a reasonable value. I will try on someone having temperature or cold-blooded :smiley:

I had EXACTLY the same problem. The way I got around it was to take 100 readings, sort them in order of size. Discard all except the middle 10 then average those out. Although this sounds drastic, it doesn't take that long. it's all done in microseconds. Since making this change I find that the readings are rock solid steady.

I think they're very susceptible to noise. I could post you the code that I use but it has a lot of dross in it due to the way I store the value, and other issues that are going on in the same function.

PhanNam:
Tks 68tjs, your suggestions help my reading definitely more stable. But the reading is just max 35.64. It never goes up to 37 C, as I measure by my digital multimeter.

Which is true LM35 or digital multimeter ?

I think you have a LM35D which is 0-100°C and less accurate than other model.
All the characteristics of this sensor are in his datasheet.
And perhaps have you always those of your multimeter :grin:

In LM35 datasheet you will found important notice when using LM35 with long wires or capacitive link.
Fig 3 and 4 of datasheet (November 2000 edition).

const int Tpin = A0; //lm35 output pin

void loop()
{
float x
for (int i=0; i<3; i++)
{
senT = analogRead(Tpin);
x= (sentT * 0.48828);
delay(30);
}
T= x - 0.5 // offset value in datasheet

if you want average just change “=” into “+=”,
then T = x/5; // i<5
T = T - 0.5

honestly i do not have problem working on temperature sensor before, very straight forward .

  1. connect all 3 gnd from arduino into breadboard.
  2. use different analog pin
  3. it need to read multiple since adc need switching time, 1st reading would would be fluctuate especially multiple sensor reading, i faced this problem before when i connect 3 sensors alltogather temp, humidity, co2 and co

or just

senT = analogRead(Tpin);
delay(10);
senT = analogRead(Tpin);
delay(10);
x= (sentT * 0.48828); // use this conversion value to save computation time