#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.
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
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.
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.
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 (!!!)
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.
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.