analogRead() is not accurate compared to multimeter

I am still pretty new to Arduino and electronics in general, so this is probably something obvious. I am reading a temperature sensor (LM35) that has a Vout pin with analogRead(). I am converting the raw value, 0-1023, to a voltage with rawVal * 5.0 / 1023.0. The results I am seeing in the serial monitor are not agreeing with an actual multimeter measurement. The Arduino analogRead() measurement is showing about 0.53V, while the multimeter is showing 0.272V.

Translating this to a temperature sensor, I am getting some very inaccurate readings now.

I tried reading A0 and A1, thinking maybe the pin was bad, but I got the same results on both.

  • Is there something wrong with my conversion from raw input value to volts?
  • Why doesn't the analogRead() measurement agree with my multimeter?
  • Is it reasonable to expect a somewhat accurate temperature sensor reading out of the analog pins?

Here is my Tinkercad schematic. I commented out all the lines relating to the LCD in the code since I can't import the library I was using to control it.

Here is a picture of my physical hardware setup

Any guidance or tips are greatly appreciated!

Measure the voltage at the AREF pin on the Arduino. It should be 5.0V

1 Like

Hi Jim,
I am measuring 4.766V on AREF

Note also that the correct formula I think should be rawVal*Vref/1024

See also analogReference() - Arduino Reference

1 Like

We need to see your code

Sure, here is exactly what I am running:

/* Use a temperature sensor and character LCD to make a thermometer
that displays the temperature. You can use either Celsius or Fahrenheit.
*/
// JP 07/01/2023


//https://github.com/duinoWitchery/hd44780
#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header


hd44780_I2Cexp lcd(0x27); // define LCD at SPI address
// SPI address is optional.  If omitted, the line
// will be searched for the correct SPI address

// don't use CONST because the hd44780 library will assume
// any char declared with const is utilizing PROGMEM from AVR
// not sure what that is, but we don't need it.
uint8_t degreeSymbol[8]= {0x06,0x09,0x09,0x06,0x00,0x00,0x00,0x00};
// uint8_t degreeC[8]     = {0x18,0x18,0x03,0x04,0x04,0x04,0x03,0x00};
// uint8_t degreeF[8]     = {0x18,0x18,0x07,0x04,0x07,0x04,0x04,0x00};

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  // put your setup code here, to run once:
  lcd.begin(16,02);
  lcd.clear();
  lcd.createChar(0, degreeSymbol);
  lcd.setCursor(0,0);
  lcd.print("Temp: ");
  int v = 10;
  lcd.print(v);
  lcd.write((byte)0); // write the customer char 0, the deg symbol
  Serial.begin(9600);
}

void loop() {
  int rawVal = analogRead(A1);
  float vOut = rawVal * 5.0 / 1023.0;
  Serial.print("raw: "); Serial.println(rawVal);
  Serial.print("volts: "); Serial.println(vOut);
  float temp = vOut * 100; // * 1000 to get to mV, / 10 to get 1 deg per 10 mV
  temp = temp * (9.0/5.0) + 32; // convert to F

  lcd.clear();
  lcd.print("Temp: ");
  lcd.print(temp);
  lcd.write((byte)0);
  lcd.setCursor(0,1);
  // lcd.print(analogRead(A1));
  lcd.print(rawVal);
  delay(1000);
}

It's not a schematic. It's a wiring diagram. A schematic is different. Google for examples. But in this case it's quite clear how you have wired the components.

Please post diagrams and photos here on this forum. You may not be able to do this until you have read a few more posts on the forum (it's an anti-spammer thing).
LhG4DcO_d

OK, I will post directly in the page in the future.
Here is the diagram.

1 Like

Your photo is very fuzzy, making it difficult to check for wiring errors. Some designs of breadboards have breaks in the power rails, so check for that.

I don't see anything wrong, yet.
It's strange that the reading is about twice of what it should be.

The only part that matters --
image

Even if the breadboard had issues, shouldn't analogRead() and the multimeter agree? I even took the pin hole I was reading the multimeter on, plugged in the A1 jumper wire, and got different values.

Fundamentally though...I'm not doing anything wrong, correct? This should be working?

My breadboard is the cheap version that came with an electronic parts pack at Microcenter. The jumper wires are also included in the parts pack. Could cheap components be causing the difference?

I don't yet understand how a multimeter can get one reading, and analogRead() get a very different reading, using the same pin hole in the breadboard.

What are the "raw numbers", the analogRead result?

raw: 121
volts: 0.59
raw: 122
volts: 0.60
raw: 122
volts: 0.60
raw: 122
volts: 0.60
raw: 122
volts: 0.60
raw: 123
volts: 0.60

The multimeter was showing between .28-.30V at the same time

They should be in the neighborhood of 1 count / 4.8mV.

122 X 0.0048 = 0.585V

Maybe you have a crappy wire jumper to A1.
But your voltmeter is less.
How's that otherwise (5V, 3.3V, etc.)

Do analog reads change if you remove the multimeter from the circuit?

I replaced the jumper wire with a new one, and no real change

raw: 129
volts: 0.63
raw: 129
volts: 0.63
raw: 129
volts: 0.63
raw: 129
volts: 0.63

Multimeter was steady at .265V

Do analog reads change if you remove the multimeter from the circuit?

No, there was no change observed when I pulled the multimeter jumper.

Sounds like I am doing everything right, so I am just going to write it off as cheap parts. My main concern was that I wasn't grasping a fundamental, and you all have given me the impression that I set it up correctly. Maybe there is some EM noise near the board that my multimeter is able to filter out? Who knows.

Run the A1 wire to 3.3V and what's the result?
Run the A1 wire to 5V and what's the result?

5v: raw value 1023
3.3V: raw value 711 (3.47v calculated)

That was a good test idea...I should have thought of that. Test the A1 pin and analogRead() independently.

It's seldom shown, but I think there should be a decoupling cap at the LM35 V_in.
I found that out with an LM34.
And a 10kΩ 'load resistor' on the output was beneficial.