Professional Documents
Culture Documents
Arduino - Car Battery Voltage Logger
Arduino - Car Battery Voltage Logger
Home
Home
Contact me
Blog -
musings and
moaning! This project will no longer run in an ATmega328P. Updated Arduino libraries require more free RAM than when this
project was constructed.
The Wirral
Peninsula An updated version of this project using an ATmega1284P is available by clicking here.
Wirral
contents
page
Weather
Station Data
Car Battery Voltage Logger
Outdoor Air
Quality (PM10
& PM2.5)
Indoor Air
Quality (PM10
& PM2.5)
Cameras
(Experimental)
Map
History
Photographs
Photo Quiz
Wirral's
streams
Main
contents
page
My car is fitted with an (eco-friendly?) engine Start-Stop system and Ford's quirky "smart battery charging" both of which make
ARDUINO - it difficult to power a dash cam based on whether the engine is running.
Projects &
Notes As there is no simple way to determine if the ignition is "on" (wasn't life simple in the old days!), this unit started life as a way to
VFD Clock
try to find - and record - a battery voltage that would satisfy the requirement to automatically switch the dash cam on and off.
Variable DC
Bench PSU Also, as my car had suffered a failed battery after only two years, I wanted to monitor its smart charging system anyway. So I
AVR In-
built this little unit which plugs into the car's 12 volt auxilliary socket to monitor the battery voltage and write the readings to a
System MicroSD card every five seconds.
Programmer
The voltage readings, together with the date and time are saved in comma-separated variables (CSV) format so should be
PICAXE
Weather
reasonably compatible with Microsoft Excel. However, for convenience, I wrote a dedicated Windows program to convert and
Station display the data automatically in a web-based format called Highcharts.
PICAXE Video
Switcher Highcharts licensing requires me to point out that Highcharts software is not free for commercial use but free distribution and use is allowed under their Non-
PICAXE commercial redistribution policy.
Miscellaneous
stuff
Please note that I'm unable to supply the source code for the Windows executable.
Resetting the
Fairmate HP- Download Windows Executable Battery Voltage Plotter
2000
Beginner's
Project
Cure TV
Circuit Diagram
Interference
JavaScript
Calculators
A
temperature-
controlled fan
for the Humax
Inside the
Digihome
PVR80
Webcams (Archive)
Nestbox video
- 2010
Nestbox still
shots - 2010
How the
cameras work
Previous years'
nestbox videos
Video not
working...?
How to set up
video cams
The
weathercam
Using iCam
Basic
Basic network
video
How to stream
video
The nestbox
setup
Working
behind a
router
Windows Software
Downloads
Popular
Downloads
Amateur
Radio
Programs
Internet
Programs
More Internet
& Networking
Other
Programs
Master index
of most
programs
Delphi
Programming
Delphi Basics
DirectShow &
Delphi A potential divider consisting of a 100K resistor and a 22K resistor (R1 and R2) is connected across the incoming 12 volt supply
ASF/Network from the car's auxiliary socket. The fairly high values are chosen deliberately so as to draw very little current from the battery.
Streaming
The input voltage can be up to 28 volts before the voltage at the junction exceeds the microcontroller's 5 volt limit and no over-
Miscellaneous & voltage protection on the controller's input has proved to be necessary in practice..
Temporary Stuff
The ATmega328P "measures" the voltage at the junction of R1 and R2 on its analogue input pin A3.
Comparison of
routers on
Be*
Moving House I wanted to record the elapsed time alongside the voltage measurements but it proved difficult to maintain an accurate software-
(2007) based timer (by using millis() for example) because the unit sleeps for five seconds after each measurement. For this reason, I
Jobs at the
new bungalow fitted a Real Time Clock module.
Quick to make
meals I used a less expensive - and less accurate - DS1307 RTC Module (rather than the DS3231) mainly as I had one in my spares box
Misty
Sooty
and the higher cost of the DS3231 was difficult to justify for something that would only be used occasionally. Using the DS1307
Archived stuff did mean that the timekeeping isn't particularly accurate over more than a few days so I included a few push buttons to adjust the
Gallery date and time easily rather than just setting it in the sketch at compile-time as most example sketches seem to do.
About this site After needing some push buttons anyway, for setting the clock, at least I was able to add some extra functionality to the software
Blog - - such as controlling how filenames are created for the MicroSD card and the ability to adjust the LCD display contrast. There is
musings and one spare IO pin available on the Atmega328P so it would be easy to include a switchable LCD backlight.
moaning!
Contact me
Copyright info The setting menu is accessed by pressing the centre button on a 5-way navigation switch. As the software is likely to be
Credits & somewhere in its 5-second sleep mode, it may be necessary to hold the button for up to five seconds before the menu appears on
references the LCD. The Low Power Arduino library that I used has the option for "timed sleep" or "interrupt wake" but not both. I chose
"timed sleep" for simplicity.
© 1996 - 2023
vwlowen.co.uk I used a "5 volt ready" MicroSD card breakout board from Adafruit as I already had one in my spares box. Although the entire
project could run at 3.3 volts (enabling the use of a "bare" SD card holder without level-shifting), the reduced voltage range
available for the analogue input may affect the accuracy.
Unlike the Arduino SD card example sketches, which halt if no SD card is detected, the sketch below allows the software to
continue. This lets the unit act as a simple voltage monitor - "NO SD CARD!" is displayed on the LCD screen along with the
measured voltage, the current date & time and the elapsed time. When a MicroSD card is detected at power-up, "NO SD
CARD!" is replaced with the filename currently being written to. If an SD card is inserted after power-up, it's necessary to power
off and on again for the card to be detected and to reset the elapsed time.
When asleep, the circuit takes about 3mA thanks to the low quiescent current taken by the OKI-78SR-5/5.1-W36C voltage
regulator which supplies 5 volts to the circuit. My car continues to take about 35mA from the battery when it's locked - due to its
on-board computer, the alarm and the remote key's receiver - so an extra 3mA wasn't considered excessive.
The 12 volt auxilliary socket shuts off its power anyway about 30 minutes after the car is locked. To log the voltage over a longer
period would need the monitor to be connected directly across the battery - in which case it would be advisable to include a fuse.
The plug that I used for the auxilliary socket has its own fuse so I haven't shown one on the circuit diagram.
Once the menu is displayed, the UP and DOWN buttons select Set Clock, Set Contrast, One File, Multi File or Exit.
After resetting the clock, the sketch will also reset the elapsed time to zero (and start a new filename if Multi File is selected).
If One File is selected, the data is always appended to the MicroSD card with the same filename - volts00.csv
If Multi File is selected, a new filename is created each time the unit is restarted - ranging from volts00.csv to volts99.csv
An asterisk (*) is displayed alongside the filename on the main display when Multi File is selected.
The unit can be used as a simple voltage monitor without the MicroSD card, in which case NO SD CARD! is shown on the
LCD display.
The accuracy of the measured voltage can be fine tuned by adjusting the values in the following lines in the sketch:
const float Vref = 5.00; // Actual voltage and resistor values can be set here.
const float R1 = 100950.0; // R1 is nominally 100000.0
const float R2 = 22000.0; // R2 is nominally 22000.0
This sketch uses most of the ATmega328P's dynamic memory so make any changes to the code with caution.
Additional Libraries:
LowPower.h
RTCLib.h
Adafruit_GFX.h
Adafruit_PCD8544.h
#include <SD.h>
#include <EEPROM.h> // Nokia LCD contrast setting is saved in EEPROM.
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#define RST 8 // Define pins for Nokia 5110 LCD
#define CE 9 // Analogue pins used as digital for
#define DC A2 // convenience of PCB layout.
#define DIN A1
#define CLK A0
#define Vin A3 // Analogue pin A3 measures volts at junction R1 and R2.
#define OK 2 // Input pins for clock- and contrast-setting buttons.
#define UP 3 // I used a 5-way tactile navigation switch.
#define DOWN 4
#define LEFT 5
#define RIGHT 6
const float Vref = 5.00; // Actual voltage and resistor values can be set here.
const float R1 = 100950.0; // R1 is nominally 100000.0
const float R2 = 22000.0; // R2 is nominally 22000.0
const float resDiv = (R2/(R1 + R2)); // Resistor divider factor applied to measured voltage.
RTC_DS1307 rtc;
File myFile;
char fileName[] = "volts00.csv"; // DON'T EXCEED THE 8.3 FILENAME FORMAT. MUST END
// WITH "." + 3 CHARACTERS.
bool SDCard = true; // Flag if SD card is present and OK.
bool multiFiles = false;
unsigned long startSeconds; // Unix timestamp for start time of test.
void(* resetFunc) (void) = 0; // Declare reset function at address 0. Calling this
// function re-starts the microcontroller.
int contrast = 45; // Default contrast setting to Nokia LCD.
void setup() {
pinMode(RST, OUTPUT); // Define pins for Nokia LCD as OUTPUTS.
pinMode(CE, OUTPUT);
pinMode(DC, OUTPUT);
pinMode(DIN, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(SD_CS, OUTPUT);
lcd.clearDisplay();
lcd.display();
if(!SD.begin(SD_CS)) {
SDCard = false; // Set 'No SD Card' flag if necessary.
} else {
if (multiFiles) {
while (myFile = SD.open(fileName)) { // Find an unused filename...
if (fileName[sizeof(fileName) - 6] != '9') { // "volts00.csv" to "volts99.csv"
fileName[sizeof(fileName) - 6]++; //
} else //
if (fileName[sizeof(fileName) - 7] != '9') {
fileName[sizeof(fileName) - 7]++;
fileName[sizeof(fileName) - 6] = '0';
}
myFile.close();
}
}
myFile = SD.open(fileName, FILE_WRITE); // Open SD card for WRITE
if (myFile) {
myFile.println(F(" ")); // Blank line.
myFile.println(F("DD/MM/YYYY HH:MM:SS,Battery Volts")); // Write header to SD card
myFile.close();
}
}
DateTime now = rtc.now();
startSeconds = now.unixtime(); // Use unix timestamp (seconds) for start time.
void loop() {
DateTime now = rtc.now(); // Read RTC.
int years = now.year(); // Get date and time from RTC to
int months = now.month(); // display on LCD and write to SD card.
int days = now.day();
unsigned long diffSec = diff; // Calculate difference between start time and now.
unsigned long diffMin = diffSec / 60;
unsigned long diffHour = diffMin / 60;
unsigned long diffDay = diffHour / 24;
lcd.clearDisplay(); // Print the current date & time on the LCD
lcd.setTextSize(1);
if (days < 10) lcd.print(F("0"));
lcd.print(days);
lcd.print(F("/"));
if (months < 10) lcd.print(F("0"));
lcd.print(months);
lcd.print(F(" "));
if (hours < 10) lcd.print(F("0"));
lcd.print(hours);
lcd.print(F(":"));
if (mins < 10) lcd.print(F("0"));
lcd.print(mins);
lcd.print(F(":"));
if (secs < 10) lcd.print(F("0"));
lcd.print(secs);
lcd.setCursor(0, 10);
lcd.print(F(">>")); // Print the time lapsed on the LCD
if (diffDay < 100)
lcd.print(F(" "));
if (diffDay < 10) lcd.print(F("0"));
lcd.print(diffDay);
lcd.print(F(":"));
if (diffHour < 10) lcd.print(F("0"));
lcd.print(diffHour);
lcd.print(F(":"));
if (diffMin < 10) lcd.print(F("0"));
lcd.print(diffMin);
lcd.print(F(":"));
if (diffSec < 10) lcd.print(F("0"));
lcd.print(diffSec);
lcd.setTextSize(2);
lcd.setCursor(5, 20);
lcd.print(volts, 2); // Print voltage on LCD in large text.
lcd.print(F("v"));
lcd.setTextSize(1);
void adjustClock() {
while (digitalRead(OK) == LOW); // Wait for "Set Clock" button to be released.
delay(100);
int x = 0; // Cursor horizontal position
while(digitalRead(OK) == HIGH) { //
lcd.drawLine(x, 10, (x + 10), 10, BLACK); // Draw cursor underneath at x position.
void setLCDContrast() {
Back to Index
This site and its contents are © Copyright 2005 - All Rights Reserved.