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.

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

Yes I was using the internal 1.1V reference for all tests.

To summarize the initial ADC measurements:

  • I shorted A0 to GND and the ADC was all zeros which is expected

  • I connected A0 to AREF (1.1V) and the ADC was1023 which is expected

  • I connected a resistor string of two 1K resistors between AREF (1.1V) and ground and connected the mid point to A0 and the ADC was 510-511 which is expected

  • I connected a resistor string between +5V USB and GND and connected the midpoint to A0, the ADC was a little noisy, I didn’t investigate it further

  • I connected a resistor string between a 9V (PP3) battery and GND connected the midpoint to A0, the ADC was a little noisy, I didn’t investigate it further

  • I put away the 9V battery and used the +5V USB for the rest of testing.

  • I connected a TMP36 with 4 feet or cable for my project. The ADC was noisy.

  • Adding an RC filter, a 1K and a 0.1uF cap (soldered to the Uno) cleaned up most of the noise.

No, once I added the SD card in with the ADC I used the +5V USB supply.

I put a current probe on the 5V supply to the SD Card, the spikes (CH4 Red) are 25mA and the voltage ripple is 41mV (CH1 Yellow). However, I don’t know which control signal signifies the end of the write.

Is the red Led flashing on the Adafruit SD card signaling the end or the beginning of the Write?

I was able to use the ADC to sample the TMP36 every 2 seconds for several hours.

There are 2 glitches in the samples that I don’t understand. I’m guessing it’s a wiggle on the +5V USB supply but would this be from my laptop or the Arduino?

I'm a little surprised about that. I expected something several times higher. I've heard of some SD cards drawing 100~200mA for short bursts during writing. Perhaps that 25mA isn't truly writing to the flash memory on the SD card, but just buffering the data in its volatile memory until a page of data (however much that is) is ready to be written to flash.

It may be worth experimenting with extra capacitors close to the power pins of the SD card module.

Oh dear - still using a teletype
?

You are reading the ADC very soon after closing the data file.
Would it be better to time in millis and allow a second before and after the data write?

And yes, averaging would be appropriate