Inconsistent Analog Readings

By playing with the LM35 temperature sensor I noticed that the analog readings are inconsistent.
It seems that the voltage on the inputs are stable, but the readings are inconsistent. It deviates with +- 70 mV sometimes, sometimes even more. It gets even worse when the USB is not plugged in and the circuit is powered only by a 5V battery.

I cannot use this as a reliable measurement.
I saw there are some threads regarding this but didn't helped me solving the problem.

I am using an Arduino nano board.

Are there any solutions to solve this?

I order to determine the cause, I decided to measure A0->A4 pins together on different inputs, cause I read that some pins are not reliable or might be broken.

Code used:

#include <Arduino.h>

const unsigned int sensors[5] = { A0, A1, A2, A3, A4 };
float voltages[5];

void setup()
{
  Serial.begin(115200);
  for (int i = 0; i < 5; i++) {
    pinMode(sensors[i], INPUT);
  }
}

void loop()
{
  for (int i = 0; i < 5; i++) {
    voltages[i] = analogRead(sensors[i]);
    Serial.print(String(voltages[i], 0) + " - ");
  }

  Serial.println();
  delay(500);
}

Here are the results when the A0 is pinned to(VIN|GND|LM35):

  • VIN - this looks very stable
1023.00 - 1023.00 - 1023.00 - 1023.00 - 1023.00 -
1023.00 - 1023.00 - 1023.00 - 1023.00 - 1023.00 -
1023.00 - 1023.00 - 1023.00 - 1023.00 - 1023.00 -
1023.00 - 1023.00 - 1023.00 - 1023.00 - 1023.00 -
  • GND - this shows already variations
0.00 - 0.00 - 0.00 - 0.00 - 0.00 -
0.00 - 0.00 - 0.00 - 0.00 - 0.00 -
0.00 - 11.00 - 0.00 - 0.00 - 0.00 -
0.00 - 0.00 - 0.00 - 0.00 - 0.00 -
0.00 - 0.00 - 0.00 - 0.00 - 0.00 -
0.00 - 0.00 - 0.00 - 0.00 - 0.00 -
15.00 - 0.00 - 15.00 - 0.00 - 0.00 -
0.00 - 0.00 - 0.00 - 0.00 - 0.00 -
0.00 - 0.00 - 0.00 - 0.00 - 0.00 -
  • TM35 sensor input
50.00 - 50.00 - 51.00 - 49.00 - 50.00 -
49.00 - 52.00 - 51.00 - 56.00 - 49.00 -
49.00 - 50.00 - 60.00 - 50.00 - 44.00 -
49.00 - 50.00 - 50.00 - 49.00 - 47.00 -
49.00 - 50.00 - 50.00 - 50.00 - 49.00 -
49.00 - 62.00 - 49.00 - 49.00 - 49.00 -
63.00 - 51.00 - 36.00 - 48.00 - 49.00 -
50.00 - 49.00 - 51.00 - 36.00 - 48.00 -
49.00 - 50.00 - 50.00 - 49.00 - 50.00 -
48.00 - 50.00 - 49.00 - 49.00 - 50.00 -
48.00 - 46.00 - 50.00 - 49.00 - 51.00 -
50.00 - 52.00 - 40.00 - 46.00 - 49.00 -
47.00 - 48.00 - 49.00 - 51.00 - 50.00 -
51.00 - 37.00 - 48.00 - 48.00 - 50.00 -
49.00 - 50.00 - 50.00 - 48.00 - 47.00 -
49.00 - 50.00 - 49.00 - 50.00 - 50.00 -
48.00 - 48.00 - 52.00 - 48.00 - 48.00 -

Here is the breadboard I am using. It's not visible on it, the VIN, GND its connected to a 5V battery.

What do you mean by this ?

Please post a small but complete sketch that illustrates the problem you are seeing

Like they are all linked to the same wire. I'll create a sketch.

Why ?

Because I read on other threads that readings are inconsistent on different input pins, so I wanted to try it out... seems indeed that they are inconsistent.

I've added the sketch I am using to do the measurement "experiment".

I don't know about Arduino Nano, but in general analog or ADC readings on CPUs are not very stable.

I dont see your sketch.
Can you post it pleasee and also show a set of RAW readings from the ADC so we can see how much it REALLY changes?

4995.12

that is not a realistic way to represent the reading. Its (best case) 4995 +_ 5mV

Without using a preset Aref then Aref is based on the input voltage supplied, which would cause different readings when moving from one voltage source to another. Use the internal Aref as one way to solve this issue.

Put a 103 ceramic cap into the Aref pin and ground for more stable A:D readings.

Use a software filter like a moving average or a Kalman filter to smooth the values.

For a stable reading of the LM35 you must use the internal 1.1Aref, not default Aref.
That also increases resolution 5x.
Leo..

// connect LM35 to 5volt A0 and ground
// calibrate temp by changing the last digit(s) of "0.1039"

const byte tempPin = A0;
float calibration = 0.1039;
float tempC; // Celcius
float tempF; // Fahrenheit

void setup() {
  Serial.begin(9600);
  analogReference(INTERNAL); // use internal 1.1volt Aref
  // change INTERNAL to INTERNAL1V1 for a Mega
}

void loop() {
  tempC = analogRead(tempPin) * calibration; // get temp

  tempF = tempC * 1.8 + 32.0; // C to F
  Serial.print("Temperature is  ");
  Serial.print(tempC, 1); // one decimal place resolution is all you get
  Serial.print(" Celcius  ");
  Serial.print(tempF, 1);
  Serial.println(" Fahrenheit");

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

The board is attached, I didn't create a schematic for it.
I've updated the POST in order to reflect the raw values, code attached to avoid more confusion.

That will always display 1023, independent on the value if VCC.
If VCC gets higher, Aref will get higher too, resulting in the same value.

Try this sketch.
Leo..


const byte sensors[5] = { A0, A1, A2, A3, A4 };
float tempC[5];
float calibration = 0.1039; // calibrate temp by changing last digit(s)

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

void loop() {
  for (int i = 0; i < 5; i++) {
    analogRead(sensors[i]); // dummy read if needed
    tempC[i] = analogRead(sensors[i]) * calibration;
    Serial.print(tempC[i], 1);
    if (i < 4) Serial.print(" - ");
  }
  Serial.println();
  delay(500);
}

Thank you for this input. Indeed analogReference(INTERNAL); smoothes things out a bit.

I will probably combine this with a moving average in order to get less deviations.

Did you try with one sensor first, because cross-talk between sensors could be a problem too (added a dummy read for that). Analogue sensors also must have their own (not shared) ground.
Leo..

What do you mean by this? Can you point me to an example how to do this? (diodes maybe?)

How did you get to this value?

Connect the LM35 ground to the Arduino GND as directly as possible, on your picture, connect a jumper (short as possible) from LM35 ground pin to Nano GND. Excessively long jumpers will pick up noise like an antenna.
The 0.1039 comes from dividing the Nano's internal AREF voltage (typically around 1.09V for mine), by 10 (0.1090) and then adjusting to agree with a known accurate thermometer.

Yes, and don't share LM35 ground(s) with LEDs, and other devices on a breadboard.
It doesn't take much (millivolts) to upset an analogue sensor.

Aref was in my case about 1.064volt, and the LM35 outputs 100 degrees per volt.
The formule for the compound number is: actual Aref x 100 / 1024 = 0.1039
Leo..

Thank you for your inputs.
Very valuable when learning how to handle sensors.

I'll give them a try and see what happens.

I see the OP has a series RC on the output, and this could possibly make the sensor unstable.

I'd LIKE to see a small series R from Vin and a bypass cap to ground to reduce noise on the power rails.

I'd also like the sensor readings to be integers!

As the device produces 10mV / deg c the OP would be well advised to use the INTERNAL reference to get a range of measurement of 0 - 100C

Having made all efforts to reduce the noise then