Reading the LM35... again

Hello there!

Total arduino noob here, so please bear with me.

I believe I have the LM35 wired up correctly and I believe I'm calculating the analog value of the LM35 to °C correctly.

My problem is that the sensor reads the temperature 5 °C too high. My room has 22 °C but the sensor reads 27 - 28 °C.

I've been googling for hours like crazy. I have found many different ways to calculate the analog value to °C, I tried all of them and all of them result in about the same degree celsius value.

So the standard formula to calculate the temperature is:

int reading = analogRead(sensorPin);
float temp = (5.0 * reading * 100.0) / 1023.0;

So my question is, is it possible that my LM35 is faulty? It is a brand new LM35 that was included in the Fritzing starter kit.
The temperature is always 5 - 6 °C too high. When I touch the LM35, the temperature goes up. When I release it the temperature goes slowly down back to 27 °C again. So the sensor does seem to work... kinda.

I'm kinda frustrated that I don't get the right temperature reading from the sensor and I've been looking for a mistake on my part for hours. Now I start to believe it is the sensor that is faulty.

how did u wire it up?
if u suck too much current from the output pin, it heats itself...

furthermore u shouldnt rely on the "5V"... they might well be lower or higher...
4.1V would explain those 27°C...
4.155100/1023

maybe this helps:

The 1023 in your calculation should be 1024, however that will make only a small difference. If the LM35 shares a ground connection with any output devices, resistance in that ground connection will affect the reading. To avoid this, connect the ground side of the LM35 to one of the Arduino ground pins, and use the remaining Arduino ground pins for all other ground connections.

Use a good multimeter to measure the +5V to the LM35 and analog output of the LM35. Then you will know instantly if the LM35 is okay.

@Krodal: and maybe the current at the 3 pins...?

Also you need to be aware of self-heating and heat radiation before you dismiss the values as wrong.

Any small electronic device will self-heat according to the power dissipated in it and the thermal resistance to getting rid of this heat energy. In still air this can be a noticeable effect even for 1mW or less. A temperature probe would normally have the sensor thermally bonded to a metal heatsink that both reduces self-heating and allows the sensor to be brought to the temperature of the thing to be sensed.

You can eliminate this effect by forced air flow - place in the airflow from a small computer fan and let it equilibrate - switch off the fan and see how much it warms up.

Secondly you are at about 30 to 35 degrees and you radiate far infra-red at about 500W/m^2. The room at 20C will radiate IR back to you at about 420W/m^2 - that's a net difference of around 80W/m^2 heat radiation from you to anything at 20C (8mW/cm^2). If you are leaning over the temperature sensor as you take the reading you will be warming it up - perhaps enough to raise it by a degree or two.

Again forced air-flow will reduce this heating effect and bring the sensor close to the actual air temperature of the room.

dc42:
The 1023 in your calculation should be 1024, however that will make only a small difference. If the LM35 shares a ground connection with any output devices, resistance in that ground connection will affect the reading. To avoid this, connect the ground side of the LM35 to one of the Arduino ground pins, and use the remaining Arduino ground pins for all other ground connections.

This was exactly my problem. Thank you very much for your help!

Try a sketch that uses the stable 1.1volt reference.
Like the one I wrote for the TMP35, TMP36 and LM35.
Works on serial monitor and LCD shield.
Read the comments.
Leo..

// TMP35 or TMP36 temp sensor connected to Analogue input A1, 3.3volt and ground
// or LM35 temp sensor connected to A1, 5volt and ground
// temp range ~2C to ~105C
// display on serial monitor and/or LCD
// for a TMP36 (-40C to ~55C), change line 45 to:   tempC = total * Aref * 0.1 / numReadings - 50.0;
//
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // your LCD pins could be different
byte ledPin = 10; // backlight pin
const byte numReadings = 32; // number of readings for smoothing (max 64)
int readings[numReadings]; // readings from the analog input
byte index = 0; // index of the current reading
unsigned int total = 0; // running total
int inputPin = A1; // the pin that the TMP35 is connected to
float Aref = 1.0759; // change this value to the actual Aref voltage of ---YOUR--- Arduino (1.0 - 1.2), or adjust to get accurate readings
float tempC; // Celcius
float tempF; // Fahrenheit

void setup() {
  //analogWrite(ledPin, 200); // optional dimming
  analogReference(INTERNAL); // use the internal ~1.1volt reference | change (INTERNAL) to (INTERNAL1V1) for a Mega
  Serial.begin(115200); // ---set serial monitor to this value---
  lcd.begin(16, 2); // shield with 2x16 characters
  lcd.print("Thermometer"); // info text
  lcd.setCursor(0, 1); // second row
  lcd.print("0-100 Celcius");
  for (index = 0; index < numReadings; index++) { // fill the array for faster startup
    readings[index] = analogRead(inputPin);
    total = total + readings[index];
  }
  index = 0; // reset
  delay(2000); // info display time
}

void loop() {
  total = total - readings[index]; // subtract the last reading
  readings[index] = analogRead(inputPin); // one unused reading to clear ghost charge
  readings[index] = analogRead(inputPin); // read from the sensor
  total = total + readings[index]; // add the reading to the total
  index = index + 1; // advance to the next position in the array
  if (index >= numReadings) // if we're at the end of the array
    index = 0; // wrap around to the beginning

  // convert value to temp
  tempC = total * Aref * 0.1 / numReadings; // value to celcius conversion
  tempF = tempC * 1.8 + 32; // Celcius to Fahrenheit conversion

  // print to LCD
  if (total == 1023 * numReadings) { // if overflow
    lcd.clear();
    lcd.print("---TOO HOT---");
  }
  else {
    lcd.clear();
    lcd.print(tempC, 2); // two decimal places
    lcd.setCursor(6, 0); // position 6, first row
    lcd.print("Celcius");
    lcd.setCursor(0, 1); // second row
    lcd.print(tempF, 1); // one decimal place
    lcd.setCursor(6, 1); // position 6, second row
    lcd.print("Fahrenheit");
  }

  // print to serial monitor
  Serial.print("Raw average = ");
  Serial.print(total / numReadings);
  if (total == 1023 * numReadings) {
    Serial.println("  ----too hot----");
  }
  else {
    Serial.print("   The temperature is  ");
    Serial.print(tempC, 2);
    Serial.print(" Celcius  ");
    Serial.print(tempF, 1);
    Serial.println(" Fahrenheit");
  }

  delay(1000); // use a non-blocking delay when combined with other code
}

dc42:
The 1023 in your calculation should be 1024, however that will make only a small difference.

There have been many threads about this.
Do a search.
Both are "wrong".
Leo..

Try a sketch that uses the stable 1.1volt reference.

Be careful the datasheet indicates that vref is given for 1.1V +/- 0.1V.

You can measure the exact value of the reference voltage:

  • set reference to "external reference".
  • with a voltmeter measure voltage on Aref: it is equal to vref: you have to get a measure between 1.0 V and 1.2 V.

Second point:
Whenever you change the configuration of the ADC:

  • first measurement
  • Change Reference
  • change of input pin
  • and so on ..
    NEVER keep the first measure: IT IS WRITTEN IN THE DATASHEET !

The 1,1 V reference is not available on all boards.
The easiest way to get some better accuracy is to wire AREF to 3,3 V (if it is a 5V Arduino and if the 3,3 V isn't heavily used). An unused 3,3V is usually precise to +- 2-3%.

68tjs:
Be careful the datasheet indicates that vref is given for 1.1V +/- 0.1V.

The 1.1volt A ref is STABLE, but not precise.
How to calibrate is in the comments of the sketch.

68tjs:
You can measure the exact value of the reference voltage:

  • set reference to "external reference".
  • with a voltmeter measure voltage on Aref: it is equal to vref: you have to get a measure between 1.0 V and 1.2 V.

Sure. Done that.
Better to finetune to the right temperature.
The reference voltage isn't the only variable.

68tjs:
Second point:
Whenever you change the configuration of the ADC:

  • first measurement
  • Change Reference
  • change of input pin
  • and so on ..
    NEVER keep the first measure: IT IS WRITTEN IN THE DATASHEET !

Don't get the "first measure" part.
Is you look through the sketch, you see that the pin IS read twice.

MiFi:
The 1,1 V reference is not available on all boards.
The easiest way to get some better accuracy is to wire AREF to 3,3 V (if it is a 5V Arduino and if the 3,3 V isn't heavily used). An unused 3,3V is usually precise to +- 2-3%.

Can you make a list of the boards that don't have 1.1vot Aref.

Be carefull to wire Aref directly to an external voltage.
You could damage the Aref that way.

A Mega also has a 2.56volt Aref.
Leo..

@Wava
I never said your program were bad, in fact I do not read it and I did not answer it.
I think it is probably perfect.
I replied to Simon 83 and I gave him advice and information on the operation of the ADC from Atmel.
I think this kind of advice is not to be included in a program because it is general knowledge, but I admit that you thought otherwise.

@Simon83
I give you advice : read the information on the microcontroller on the Arduino site is to do but always check the Atmel datasheet because the site Arduino contains errors such as famous 40 mA per pin: if you read the datasheet you will see that :

  1. 40 mA per pin are actually 20 mA per pin in permanent use.
  2. Imax for Vcc and Vee (GND) does not exceed 200 mA --> 10 pins at 40 mA = 400 mA !
    So with Arduino Information: mistrust,mistrust.

68tjs:
I think this kind of advice is not to be included in a program because it is general knowledge, but I admit that you thought otherwise.

I try to over-comment these posted sketches, because it might help a beginner to better understand.
Leo..