LM35 showing erratic reading when external power supply is used.

Hi,

I am creating a simple LM 35 based thermostat for an Incubator project. An incandescent bulb is switched on or off based on a particular temp.
I am using a 16X2 LCD, a relay and LM35. I am facing following peculiar problem. Code is given below.

1> The same code works perfectly i.e. shows correct room temp. when I use the USB cable.The readings also are stable and do not vary more than a degree if at all.

BUT

2>I get erratic readings ( readings sometimes are +/- 15 degrees fluctuating) when I use an external power supply.

Pl. note.
1> I have tested the code with 2 boards a>Arduino Uno and b> Freeduino but with similar behaviour.
2> I have used 3 different LM 35s but observations are similar.
3> My external power supply is regulated and it has 5v, 3.3v and 12v outputs. I have also tested with a different power supply again with similar results.
4> The power supply output is constant at 4.97 V , even though the LM35 output is fluctuating. There’s absolutely no drop in the o/p voltage. (I checked with 2 different multi-meters )
5> As you can see in the code, I am using averaging and that too 100 times while reading the sensor, little extreme maybe but earlier I have used 20,30, 50 times but with same result.
6> I have also tested the code without connecting Relay ( just to avoid any interference if any) but with same behaviour.

The code is:

#include <LiquidCrystal.h>

boolean bulb_Status = 0;
int relay = 7;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
{

lcd.begin(16,2);
pinMode (relay,OUTPUT);
digitalWrite(relay,HIGH);//Relay is triggered when the pin goes LOW, hence initially it should be set high
bulb_Status = 0;
float celsius = readSensor(); //Call readSensor function and store the value into "celsius"
display_Temp(celsius);

}

void loop()
{

  ReadTemp: 
        delay(3000);
        float celsius = readSensor();
        display_Temp (celsius);
 
if ((celsius >=26) && (celsius <= 35))
    {
      goto ReadTemp;// this is the continous loop of reading temperature; basically do nothing till temp is either less than or greater than the set limit
    }
    else if (celsius > 35)// condition to check whether bulb is on and temp. has crossed the limit
            {
               if(bulb_Status == 1)
                 {
                   //digitalWrite (LED0,LOW);
                   digitalWrite (relay,HIGH);
                   bulb_Status = 0;
                   goto ReadTemp;
                  }
                  else {goto ReadTemp;}
            }   
                  else if (bulb_Status == 0) // this loop will run when temp. is less than limit
                  {
                    //digitalWrite (LED0,HIGH);
                    digitalWrite (relay,LOW);
                    bulb_Status = 1;
                    goto ReadTemp;
                  }
                  else 
                   {
                   goto ReadTemp;
                   }
}
// My functions start here ****************************************************************************************
void display_Temp (float celsius)
{
      lcd.setCursor(0,0);
      lcd.print(celsius);
      lcd.setCursor(6,0);
      lcd.print(" :Celsius");

      lcd.setCursor(0,1);
      lcd.print((celsius * 9)/5 + 32);
      lcd.setCursor(6,1);
      lcd.print(" :F'heit");
      
}
//**************************************************************************************
float readSensor()
{
float sensorValue = 0;
for (int i=0; i<100; i++)
{
sensorValue = sensorValue + analogRead(A0);
delay(20);
}
sensorValue = sensorValue/100;// take average
float millivolts= (sensorValue/1024.0)*5000;
sensorValue = millivolts/10;
return sensorValue;
}
//**************END*********************************************************************

Any suggestions?

Thanks,[/code]

you did quite some decent testing already, (thanks for that!)

code hint:

goto ReadTemp;

should be replaced with

return;

same effect, much cleaner code…

void loop()
{
  delay(3000);
  float celsius = readSensor();
  display_Temp (celsius);

  if ((celsius >= 26) && (celsius <= 35)) return;

  if (celsius > 35) // condition to check whether bulb is on and temp. has crossed the limit
  {
    if (bulb_Status == 1)
    {
      //digitalWrite (LED0,LOW);
      digitalWrite (relay, HIGH);
      bulb_Status = 0;
    }
    return;
  }
  
  if (bulb_Status == 0) // this loop will run when temp. is less than limit
  {
    //digitalWrite (LED0,HIGH);
    digitalWrite (relay, LOW);
    bulb_Status = 1;
  }
}

but it does not explain the faulty readings

is the project on a breadboard or soldered?
how much volts can the power supply deliver?
how much amps can the power supply deliver?

can you write a small sketch and read your power supply by the analogRead() in a tight loop? (UNO on USB) Use a voltage divider to get some range between 0…5V

I have several power supplies at home that shows the 50Hz fluctuations of the mains. A voltmeter does averaging and does not show it.

cannot think of another cause yet…

What is the external power supply, and how is the ground tied to the Arduino?

Be carrefull to : - the LM35 does not share his ground wire with any other component - As much other CMOS IC, LM35 hate to be connected to a capacitive line. This ocurs frequently with long wires. Solution is in the LM35 datasheet : put a serial resistor between LM35 output and the wire. Manufacturer preconize 2.2 kohms, I obtain best result with 4,7 kohms (with 50m ethernet cable), 10 k ohms is too high.

LM35 is VERY sensitive to the actual voltage that you give it.

sensorValue = sensorValue/100;// take average
float millivolts= (sensorValue/1024.0)*5000;
sensorValue = millivolts/10;

You are making assumptions that you get exactly 5V (the 5000 in your formula) and this may not be the case. Have you checked the external voltage source? Suggestions around grounding have also already been given, as these change the voltage seem by the analog input.

I wrote a small LM35 library that uses the internal Arduino reference voltage to work out what the actual sensor voltage is, also because I was getting different values depending on the Power Supply. This provides consistent readings if the source voltage changes. You can look at that code in my libraries link in the signature below.

Hi,

robtillaart : Thanks for the “Return;” suggestion, I’ll definitely incorporate the same. Now to answer your other queries.

1> I am using breadboard only to connect +5 and gnd to the various components i.e. LCD, Relay, and Arduino.

2> LM35 is directly connected to the arduino board’s +5v - Gnd and A0.

3> I have also tested with connecting LM35’s power lines to Power supply’s +5V and gnd, but again with the same observation.

4> The PS delivers exactly 4.95 v, even when the LM35 is showing fluctuating readings.

5> The PS is stated to give 1 amp.

6> Reg. your last suggestion writing a small sketch, will try it.

I am trying to source another PS, different manufacturer with higher current rating (the ones that I have are by the same manufacturer). The amp rating given by the manufacturer could be little overstated :).


cattledog:
The PS has typical screw terminals and the +5v output is connected to Arduino by soldering at Arduino’s external input terminal. Pl. refer the photo attached.


68tjs:
Not sure I understand your first comment; LM35 does not share gnd with any other component?

As stated in my response above ( robtillaart: point 2 &3), the gnd line “will” become common between various components.


Marco_c:
1> As stated earlier, yes , the PS output is constant at 4.95V

I will definitely check your libraries.

20141215_104420.jpg

BB showing gnd&5V.jpg

PSupply.jpg

You can get a precision reading of Vcc using the internal “secret voltmeter”.
https://code.google.com/p/tinkerit/wiki/SecretVoltmeter

If the AnalogRead reference voltage is jumping around, you should be able to see it. I have also called this function in the code before doing an AnalogRead and using the return value for Vcc to be a little more precise than using the nominal 5.0v.

long readVcc() {
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1126400L / result; // Back-calculate AVcc in mV
  return result;
}

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

void loop() {
  Serial.println( readVcc(), DEC );
  delay(200);
}

This may be what marco_c was referring to. I did not look at his libraries.

Hi All,

The problem is solved. :) . The external PS (2 from the same manufacturer :'( ) was the culprit. I used another PS (a typical mobile phone charger with USB o/p) which worked beautifully.

Now I am going to put all the leads onto a GPB and later house all the components in a box. Will then test extensively for 3- 4 days continuously.

Thanks again and Regards,

PS:Already(while writing this) It looks like the LCD is displaying garbage after few on and offs of the relay. May be the internal register is getting corrupted.