ADC noise/drift with a resistor divider

Hello,

I wanted to test the ADC on the UNO with a resistor divider. First I powered the Uno with USB cable then I tried powering it with a 9V battery.

The resistor divider was always fed with a 9V battery because I know the USB supply is a little noisy.

I also soldered a 0.1uF cap on the Arduino between the ADC pin and ground.

I used two Fluke 87 meters to measure Vin ( input supply) and Vref.

Here’s the code I used :

Test 1:

Arduino is usb powered

Vin = 5.072

Vref = 1.090V

The 10 bit ADC varied from 668 to 670

Test 2:

Arduino is powered from a 9V battery (USB cable is still plugger in for serial monitor)

Vin = 4.972

Vref = 1.091V

The 10 bit ADC varied from 639 to 642

Is it normal for the 10 bit ADC to move around that much?

I also I see the Vref moved from 1.090 to 1.091 with a small change in Vin (5.072 to 4.972) is this expected?

-kooner

Print the ACTUAL return value in hex and see if more than the low order bit is changing. Then compute the error percentage and see if that is within spec.

Please read the forum guide so you know how to post code correctly on the forum. For example so that others can help you by copy & pasting it for themselves, rather than having to re-type it and risk making an error.

A variation of 2 or 3 out of 1024. That's less than 0.5%. What were your expectations? Have you considered averaging over a larger number of readings?

With an LM36 you should use the internal 1V1 reference.
That will give a more stable readout, independent of the 5volt/USB variations,
and an almost five times higher resolution.
Resolution of the LM36 on a 10-bit A/D on default Aref is terrible (steps of 0.5 degrees).
With 1V1Aref and a bit of averaging that becomes steps of 0.1C.

This has been beaten to death, so do a search with the field top/right of this page.

Once you got it working, then throw the ancient analogue LM36 in the bin, and buy a proper digital temp sensor, like the DS18B20.
Leo..

Thanks for your responses. I got the ADC working with a TMP36 and tried combining it with code to write it to the SD card.

With the added code to write to the SD card the ADC gives a different reading.

The decimal ADC reading should be 682 and it drops to 620 when the SD card is written to.

It’s related to the line of code:

dataFile.println(ADC_value);

if I comment this line out the ADC reading is fine.

Or, Instead of commenting out that line, if I move the 2000ms delay to the line BEFORE

int ADC_value = analogRead(A0); // Range is from 0 to 1023

then the ADC reading is fine.

Is there some minimum wait time after the SD card is written and before the ADC is called?

My code is here:

/*
  SD card datalogger

  This example shows how to log data from one analog sensor
  to an SD card using the SD library. Pin numbers reflect the default
  SPI pins for Uno and Nano models

  The circuit:
   analog sensors on analog pins 0, 1, and 2
   SD card attached to SPI bus as follows:
 ** SDO - pin 11
 ** SDI - pin 12
 ** CLK - pin 13
 ** CS - depends on your SD card shield or module.
 		Pin 10 used here for consistency with other Arduino examples
    (for MKR Zero SD: SDCARD_SS_PIN)

*/

#include <SPI.h>
#include <SD.h>

const int chipSelect = 10;

void setup() {
  analogReference(INTERNAL);
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  // wait for Serial Monitor to connect. Needed for native USB port boards only:
  while (!Serial);

  Serial.print("Initializing SD card...");

  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("1. is a card inserted?");
    Serial.println("2. is your wiring correct?");
    Serial.println("3. did you change the chipSelect pin to match your shield or module?");
    Serial.println("Note: press reset button on the board and reopen this Serial Monitor after fixing your issue!");
    while (true);
  }

  Serial.println("initialization done.");
}

void loop() {
  
  int ADC_value = analogRead(A0); // Range is from 0 to 1023
   
   Serial.println(ADC_value);
   delay (2000);

 
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("TMP36.txt", FILE_WRITE);
  
  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(ADC_value);
    dataFile.close();

  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening TMP36.txt");
  }
  
}

What does your build look like.
Common problem is that analogue sensors, like the LM36, don't like ground to be shared with other devices. Connect LM36 ground directly to an Arduino ground pin (not via a breadboard).
Leo..

When writing to SD card, it can pull quite a lot of current. Maybe this is dragging down the supply voltage a little, which seems to be affecting your readings. The delay may be allowing the writing process to finish, after which the current drops and the voltages return to the previous levels.

Are you still using the 9V battery? If that is a PP3 size, they are really not suitable for powering most Arduino, especially with SD card in the circuit.

1 Like

@kooner is using that, and has measured its value at the Vref pin and found that it changes slightly with supply voltage.