(SOLVED) Issues reading battery voltage (DC) on analog pins for a data logger

Solved...go to end of thread for working sketch.

Hardware
Arduino Mega 2560
Ethernet Shield W5100

Sketch

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

const int chipSelect = 4;


void setup() {

  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 or reopen this serial monitor after fixing your issue!");

    while (true);

  }

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

void loop() {

  // make a string for assembling the data to log:

  String dataString = "";

  // read three sensors and append to the string:

  for (int analogPin = 0; analogPin < 2; analogPin++) {

    int sensor = analogRead(analogPin);

    dataString += String(sensor);

    if (analogPin < 1) {

      dataString += ",";

    }

  }

  // 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("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:

  if (dataFile) {

    dataFile.println(dataString);

    dataFile.close();

    // print to the serial port too:

    Serial.println(dataString);

  }

  // if the file isn't open, pop up an error:

  else {

    Serial.println("error opening datalog.txt");

  }
}

Please forgive syntax or noobish errors as I am effectively brand new to Arduino.

I am trying to develop a data logger that will read and then store the voltage for 2 batteries that will be simultaneously discharging to other devices. Both batteries are lipos and have operating voltages between 3.7 and 4.2V.

I used this example sketch as a starting point, modified it to use A0 and A1. I successfully read the values of the pins, view the Serial Monitor, and confirm that the file was saved to the SD card. However, when I connect the batteries, both pins are pegged at 1023. Oddly enough, even when only one battery is connected both pins still read 1023 or very close to it.

My understanding is that the Mega has a 10-bit resolution thus reading 0 and 1023 for 0V and 5V, respectively. I hope this is not a stupid question and I don't get flamed for asking it - if there is a resource I have missed please kindly redirect me to it.

Image 1 - overview of setup

Image 2 - pinout

Hi,

Try the A8 and A9 just in the case your shield is using A0 and A1 (having them connected to something)
Good luck :slight_smile:
Jim

I had a very similar problem as you can see here where you will find the solution.

I see you are using USB to power the Mega.
Because the spec for usb voltage is so loose (Vbus = 4.45V - 5.25V ) you cant usefully use it to measure your battery voltage directly. However at least its always higher then the battery voltage you are measuiring.

You CAN use the "magic voltmeter" to measure Vcc against the "INTERNAL" reference (1.1V approx) but again you lose precision because its such a small fraction of Vcc.

And if you are logging battery voltage it would seem important to get an accurate value.

My solution would be to use an external reference as described on my site here

Another approach is to use an external reference for continuous calibration

Hi,
Welcome to the forum.

Please read http://forum.arduino.cc/index.php/topic,148850.0.html.

Attach your images and they will be automatically inserted into your post.


Tom... :slight_smile:

Hi,
What code did you use to test the analog inputs, the link does not work for me.
Try this code to check your analog inputs.
Set the IDE monitor to 115200baud.

int rawAnalog0;
int rawAnalog1;
int analog0Pin = A0;
int analog1Pin = A1;

void setup()
{
  Serial.begin(115200);
  pinMode(analog0Pin, INPUT);
  pinMode(analog1Pin, INPUT);
}

void loop()
{
  rawAnalog0 = analogRead(analog0Pin);
  rawAnalog0 = analogRead(analog0Pin); // read A0 twice to ensure ADC input reading A0 accurately.
  rawAnalog1 = analogRead(analog1Pin);
  rawAnalog1 = analogRead(analog1Pin); // read A1 twice to ensure ADC input reading A1 accurately.

  Serial.print ("Analog Input A0 = ");
  Serial.print (rawAnalog0);
  Serial.print ("   Analog Input A1 = ");
  Serial.println (rawAnalog1);
  delay(500);
}

Do you have a DMM?
Tom... :slight_smile:

the "magic voltmeter" to measure Vcc is not applicable it seems, as OP is just trying to measure the battery voltage, which is best measured against the internal 1.1V (or another, the Mega has more voltages available) reference. Of course the battery voltage has to be brought down to <1.1V using a voltage divider to do so.

the "magic voltmeter" to measure Vcc is not applicable it seems, as OP is just trying to measure the battery voltage, which is best measured against the internal 1.1V (or another, the Mega has more voltages available) reference. Of course the battery voltage has to be brought down to <1.1V using a voltage divider to do so.

Sorry vwmarle, I didnt think I needed to explain further. Obviously it wasnt as clear as I thought.

If you measure Vcc against the internal reference you can then use it to calibrate the ADC reading gained using the "DEFAULT" reference.
Which has the benefit of not then needing a voltage divider that would impose a drain on the battery being measured.

However as I also said a better reference would also be an improvement.

Its explaineed fully on my page here

Try the A8 and A9 just in the case

Went ahead and tried this - same results, pegged whenever battery voltage is applied

I see you are using USB to power the Mega.

I had it plugged into my computer USB so I could read the Serial Monitor. I also have a 5V power supply...more on that at the end.

Another approach is to use an external reference for continuous calibration

I gave that a read. Your data logger article was actually the inspiration for this project. Unfortunately I found it far too technical for a starting place so I have been moving incrementally. I also don't have access to many of the components you use in your projects, e.g. the LM4040AIZ4.1 diode or the MCP6042 chip. At least not without some unwanted additional effort but I suspect I'll be forced to explore these routes since my existing efforts have not worked out as anticipated.

Try this code to check your analog inputs.
Set the IDE monitor to 115200baud.

Same results with this code. As soon as battery is applied, the pin gets maxed. I tried with several baud rates inc both 115200 and 9600 - not sure what the effect should be but I certainly didn't notice any behavioral differences.

DMM?

Yes

I also measured the voltage across 5V and GND with my multimeter and to my surprise it was 4.14 volts on USB, 3.35 on a 5V DC power supply (output confirmed to be nominal 5V). Again this was on the 5V pin so unless I'm missing something this suggests to me that the internal voltage regulator is off by >20% margin (!!!)

So I found a spare Mega and measured the 5V pin again. Nearly the exact same results, 4.04V on USB and 3.20V on the power supply.

I'm so confused. Something must be configured wrong. I find it unlikely that Arduino would label this pin as 5V if the voltage is never 5V.

I would also like to add that the 3.3V pin was nominal on both boards.

Hi,
What is your PC?
What is your OS?

3.20V on what power supply?
Where are you connecting the external 5V, I hope not the Vin pin or DC jack.
It should be to the 5V pin.
(But you need to check with Mega schematic if back feed protection is on the Mega PCB.)
I have been and checked, a ridgy didge Arduino Mega has back feed protection, so you can connect an external 5V while still having the USB connected.

4.04V USB from your PC is tool low in my opinion.

Have you changed your USB cable.

Next thing to do is to check using a potentiometer instead of your batteries.
OR
At least two 4k7 resistors, or similar paired values.
Place one resistor from A0 to gnd.
Place one resistor from A0 to the 5V pin.

Do the same with A1, but use the 3.3V pin on the Mega.

Measure A0 and A1 and the 5V and 3.3V pins.

The 115200 baud has nothing to do with the ADC, it is just a faster comms speed for inconvenience, 9600 is an old custom back when PCs were not that quick.

Tom.... :slight_smile:

I hope not the Vin pin or DC jack.

erm....that's precisely what I've been doing, with a 5V power supply

I just checked and it looks like the input power is rated 6-20V but >=7 volt is recommended, I'll try that and report back

So I found a spare Mega and measured the 5V pin again. Nearly the exact same results, 4.04V on USB and 3.20V on the power supply.

I dont have a spare Mega to check, so cant compare results; however while the connection isssue (partly) explains the 3.2V it DOESNT explain the low voltage when running on USB. It could possibly be your cable.

Can you check the USB voltage? I have a natty little gadget from ebay that shows USB voltage and current. Indispensable.

Basic fault-finding - can you check with everything else disconnected - especially the ethernet shield?

Didn't see anybody else already mention it, but connecting a voltage source (battery) directly to a pin is a sure way of eventually blowing the pin (or the whole processor).
Always use a (10k) resistor between batt+ and pin, so you don't phantom-power the processor through the pin in case you forget to connect (USB) power to the board.
Leo..

You really need to use the internal reference and a voltage divider on your inputs .
Even if you get your power supply sorted , by default that is used for the analog reference , so if that changes so will your measured voltages

I'm blown away by the speed and quality of the responses by this community. Thanks so much to everyone in this thread who pitched suggestions and helped me solve my issue.

I was successfully able to accomplish my goal. Here is the sketch with comments:

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

const int chipSelect = 4; //select coms pin, for ethernet shield this is pin 4
float deltaT = 0; //declare the loop timer float variable
unsigned long currentMillis = 0; //loop timer
unsigned long previousMillis = 0; //loop timer

//setup will check for SD card and report success or failure in the serial monitor
void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed. Check SD card.");
    while (true);
  Serial.println("initialization done.");
  previousMillis = millis(); //assign time to unsigned long variable
}
}

//loop reads voltage of both batteries and writes to file and outputs the processing time
//the processing time and both voltages are then written to a file
void loop() {
  currentMillis = millis();
  deltaT = (currentMillis - previousMillis);
  previousMillis = millis();
  delay(10000); //10 second delay

//declare the datastring which will hold the data for the given loop iteration
String dataString = "";

//append the processing time to the string
dataString += deltaT;
dataString += ",";
  
//read sensors A0 and A1, then append to the string
  for (int analogPin = 0; analogPin < 2; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 1) {
      dataString += ",";
    }
  }
 
//open the file, necessary before any read or write functions involving the file can be called
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

//write the data string to the file then close it
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();

//write the data string to the serial monitor
    Serial.println(dataString);
  }
//error message if the file fails to open
  else {
    Serial.println("error opening datalog.txt");
  }
}

Here are some notes on this setup: the Mega has an internal 5V reference. A voltage that exceeds 5V will require a voltage divider circuit.

Adding a large resistor (10k used here) between the positive battery terminals and the sensor terminals is a recommended preventative measure, since without it there is a risk of bleeding voltage into the chip and skewing the data.

As soon as the board is powered on, it immediately starts writing to file (after the 10 second delay). Therefore one should attach the batteries (or whatever DC voltage source being measured) before applying power to the board. The sketch could be modified to write the data to file only when the voltage is within a given range, for example.

The sketch won't overwrite any info on the file if it already exists on the SD card. That means that you'll have to remove the file from the SD card when you're starting a fresh run of data collection. With some additional modifications to the sketch, one could create a file naming system that checks for existing files and adds a version number to the new file when it's being created. But that exceeded the needs of my scope.

Here are some photos of the final setup

Well done! please change topic title & add "SOLVED"

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.