logging solar data
Genevieve and I now decided to log data from the sun over the course of the month – most likely, voltage, and light level. We will use both a photocell and two large solar panels (during the day one gave about 20 V). (And of course, we will power the arduino sustainably!)
We are using a RTC (real time clock from adafruit), a micro sd card data shield, and the following code (derived from Tom Igoe’s github)
Here is the circuit:

With a 9 V battery plugged in for a few minutes, this is the result (reading voltage once per minute):


#include <EEPROM.h>
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
#include <SD.h>
const int chipSelect = 8;
const int LOCATION_FILE_NUMBER_LSB = 0x00;
const int LOCATION_FILE_NUMBER_MSB = 0x01;
RTC_DS1307 RTC;
File dataFile;
void setup () {
// initialize serial communications:
Serial.begin(9600);
// set up pins A2 and A3 as the power and ground for the real time clock:
pinMode(A2, OUTPUT);
pinMode(A3, OUTPUT);
// A2 is the ground, A3 is the power:
digitalWrite(A2, LOW);
digitalWrite(A3, HIGH);
Serial.print("Initializing SD card...");
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
// start the wire and RTC libraries:
Wire.begin();
RTC.begin();
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
Serial.println("RTC is set");
newlog();
}
void loop () {
// if the file is available, write to it:
if (dataFile) {
DateTime now = RTC.now();
dataFile.print(now.month(), DEC);
dataFile.print('/');
dataFile.print(now.day(), DEC);
dataFile.print('/');
dataFile.print(now.year(), DEC);
dataFile.print(',');
dataFile.print(now.hour(), DEC);
dataFile.print(':');
dataFile.print(now.minute(), DEC);
dataFile.print(':');
dataFile.print(now.second(), DEC);
dataFile.print(",");
// calculate the voltage on A1:
float voltage = 5 * analogRead(A0) / 1024.0;
dataFile.print(voltage);
dataFile.println();
dataFile.flush();
}
// delay for a minute:
delay(60000);
// delay for three seconds:
//delay(3000);
}
void newlog(void)
{
uint8_t msb, lsb;
uint16_t new_file_number;
//Combine two 8-bit EEPROM spots into one 16-bit number
lsb = EEPROM.read(LOCATION_FILE_NUMBER_LSB);
msb = EEPROM.read(LOCATION_FILE_NUMBER_MSB);
new_file_number = msb;
new_file_number = new_file_number << 8;
new_file_number |= lsb;
//If both EEPROM spots are 255 (0xFF), that means they are un-initialized (first time OpenLog has been turned on)
//Let's init them both to 0
if((lsb == 255) && (msb == 255))
{
new_file_number = 0; //By default, unit will start at file number zero
EEPROM.write(LOCATION_FILE_NUMBER_LSB, 0x00);
EEPROM.write(LOCATION_FILE_NUMBER_MSB, 0x00);
}
//The above code looks like it will forever loop if we ever create 65535 logs
//Let's quit if we ever get to 65534
//65534 logs is quite possible if you have a system with lots of power on/off cycles
if(new_file_number == 65534)
{
//Gracefully drop out to command prompt with some error
PgmPrint("!Too many logs:1!");
return; //Bail!
}
//If we made it this far, everything looks good - let's start testing to see if our file number is the next available
//Search for next available log spot
char fileName[] = "LOG00000.TXT";
while(1)
{
new_file_number++;
if(new_file_number > 65533) //There is a max of 65534 logs
{
PgmPrint("!Too many logs:2!");
return;
}
sprintf(fileName, "LOG%05d.TXT", new_file_number); //Splice the new file number into this file name
//Try to open file, if fail (file doesn't exist), then break
if (!SD.exists(fileName)) break;
}
Serial.print(fileName);
//Record new_file number to EEPROM
lsb = (uint8_t)(new_file_number & 0x00FF);
msb = (uint8_t)((new_file_number & 0xFF00) >> 8);
EEPROM.write(LOCATION_FILE_NUMBER_LSB, lsb); // LSB
if (EEPROM.read(LOCATION_FILE_NUMBER_MSB) != msb)
EEPROM.write(LOCATION_FILE_NUMBER_MSB, msb); // MSB
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
dataFile = SD.open(fileName, FILE_WRITE);
}