#include <SPI.h>
#include <SD.h>
#include "RTClib.h"
#define SD_CS 10 //10 for big SD card reader
RTC_DS1307 rtc;
String fileName;
File dataFile;
DateTime time;
float const TEN_BIT = 1023.0;
float const VOLT_RANGE = 5.0;
const int AVGCOUNT = 15000;
const long tenMin = 1800000;
const long twoMin = 120000;
int bytesWritten = 0;
int loopCount = 0;
int v1_int_0, v2_int_0, v3_int_0;
float v1_0, v2_0, v3_0, a, b, c;
float d, e, h, i, j = 0.0, f;
float qAvg, qSum, tAvg, tSum = 0.0, rSum = 0.0, rAvg = 0.0, l = 0.0, uSum = 0.0;
unsigned long totalRunTime = 0;
unsigned long sampleTime = 0;
float g = 0.0, gAvg = 0.0, gSum = 0.0, m, n, o, p;
long tenMinCheck = 0;
long twoMinCheck = 0;
String currentYear = "0", currentMonth = "0", currentMinute = "0", previousMinute = "0";
bool newMinute = false;
String mode = "MODE A";
int k = 60;
void setup() {
Serial.begin(9600);
//Initialize RTC
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}
Serial.print("Initializing SD card...");
if (!SD.begin(SD_CS)) {
Serial.println("failed!");
}
else
{
Serial.println("OK!");
}
// start the SPI library:
SPI.begin();
//Set the max speed to 9MHz
SPI.beginTransaction(SPISettings(9000000, MSBFIRST, SPI_MODE0));
//Grab the current time
time = rtc.now();
previousMinute = time.minute();
currentYear = time.year() - 2000;
currentMonth = time.month();
if (currentMonth.toInt() < 10)
currentMonth = "0" + currentMonth;
currentMinute = time.minute();
if (currentMinute.toInt() < 10)
currentMinute = "0" + currentMinute;
fileName = currentYear + currentMonth + currentMinute;
fileName = fileName + ".CSV";
// Create new file based on the year/month/minute
//Open data file and write headers
dataFile = SD.open(fileName, FILE_WRITE);
dataFile.print("Power on time: ");
dataFile.println(time.timestamp(DateTime::TIMESTAMP_FULL));
dataFile.print("Current percent of the day, ms since last avg (");
dataFile.print(AVGCOUNT);
dataFile.println(" samples)");
dataFile.close();
}
void loop() {
if(loopCount == 0)
totalRunTime = millis();
v1_int_0 = analogRead(A0);
v2_int_0 = analogRead(A1);
v3_int_0 = analogRead(A2);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
v1_0 = v1_int_0 * (VOLT_RANGE / TEN_BIT);
v2_0 = v2_int_0 * (VOLT_RANGE / TEN_BIT);
v3_0 = v3_int_0 * (VOLT_RANGE / TEN_BIT);
a = v3_0 - v2_0;
b = v1_0*4.8 - v2_0 - 2*(a);
c = v2_0/19.9;
d = b/c;
e = b*c;
f = (d - 100.6)/0.4;
g = e/0.000104;
h = e/(0.000104*(f - i));
c = h*g*4*d*8.12*f*g;
b = h*g*4*9888.245/e/f/g;
l = c/h*(4.1782);
m = (912.38012)*(h-f) + g;
n = 567*a/308.83;
if (loopCount == AVGCOUNT)
{
//Only update these averages that will be written to the SD card when in the correct mode
if (mode == "MODE A")
{
gAvg = gSum/AVGCOUNT;
gSum = g;
rAvg = rSum/AVGCOUNT;
rSum = d;
tAvg = tSum/AVGCOUNT;
tSum = f;
l = uSum/AVGCOUNT;
uSum = h;
}
if (mode == "MODE B")
{
i = j/AVGCOUNT;
j = f;
}
qAvg = qSum/AVGCOUNT;
qSum = e;
sampleTime = totalRunTime;
totalRunTime = millis();
sampleTime = totalRunTime - sampleTime;
//Check for 10 or 2 minute thresholds depending on the mode
if (mode == "MODE A")
{
//Check if 10 mins have passed
if (tenMinCheck >= tenMin)
{
tenMinCheck = 0;
mode = "MODE B";
}
else if (tenMinCheck > 40000)
{
mode = "MODE A";
tenMinCheck += sampleTime;
}
else
tenMinCheck += sampleTime;
}
else
{
//Check if 2 mins have passed
if (twoMinCheck >= twoMin)
{
twoMinCheck = 0;
mode = "MODE C";
}
else
{
twoMinCheck += sampleTime;
if (twoMinCheck >= (twoMin - 10000))
mode = "MODE D";
}
}
Serial.print("V1 = ");
Serial.println(v1_0);
Serial.print("V2 = ");
Serial.println(v2_0);
Serial.print("V3 = ");
Serial.println(v3_0);
Serial.print("b = ");
Serial.println(b);
Serial.print("d = ");
Serial.println(d);
//Grab the current time
time = rtc.now();
Serial.print("Hour = ");
Serial.println(time.hour());
Serial.print("Minute = ");
Serial.println(time.minute());
Serial.print("Seconds = ");
Serial.println(time.second());
//Check to see if we have crossed over into the next minute
previousMinute = currentMinute;
Serial.print("previousMinute = ");
Serial.println(previousMinute);
currentMinute = time.minute();
if (currentMinute.toInt() < 10)
currentMinute = "0" + currentMinute;
Serial.print("currentMinute = ");
Serial.println(currentMinute);
if (previousMinute != currentMinute)
{
//We crossed over into the next minute, so we need to create a new file
Serial.println("Creating a new file due to the time");
Serial.print("old fileName = ");
Serial.println(fileName);
currentYear = time.year() - 2000;
currentMonth = time.month();
if (currentMonth.toInt() < 10)
currentMonth = "0" + currentMonth;
currentMinute = time.minute();
if (currentMinute.toInt() < 10)
currentMinute = "0" + currentMinute;
fileName = currentYear + currentMonth + currentMinute;
fileName = fileName + ".CSV";
Serial.print("New filename = ");
Serial.println(fileName);
newMinute = true;
//Open data file and write headers
dataFile = SD.open(fileName, FILE_WRITE);
if (dataFile)
Serial.println("File opened");
else
Serial.println("File did not open");
bytesWritten = dataFile.print("Power on time: ");
Serial.print("Tried to write start of header, wrote ");
Serial.print(bytesWritten);
Serial.println(" bytes");
dataFile.println(time.timestamp(DateTime::TIMESTAMP_FULL));
dataFile.print("Current percent of the day, ms since last avg (");
dataFile.print(AVGCOUNT);
dataFile.println(" samples)");
dataFile.close();
delay(10);
}
//Write data to the file
dataFile = SD.open(fileName, FILE_WRITE);
/*
if (newMinute)
{
dataFile.print("Power on time: ");
dataFile.println(time.timestamp(DateTime::TIMESTAMP_FULL));
dataFile.print("Current percent of the day, ms since last avg (");
dataFile.print(AVGCOUNT);
dataFile.println(" samples)");
newMinute = false;
}
*/
dataFile.print(convertTime(time.hour(), time.minute(), time.second()));
dataFile.print(",");
dataFile.print(sampleTime);
dataFile.print(",");
dataFile.print(mode);
dataFile.print(",");
dataFile.print(qAvg, 6);
dataFile.print(",");
dataFile.print(i, 6);
dataFile.print(",");
dataFile.print(gAvg, 6);
dataFile.print(",");
dataFile.print(m);
dataFile.print(",");
dataFile.print(n);
dataFile.print(",");
dataFile.print(v3_0);
dataFile.print(",");
dataFile.print(rAvg);
dataFile.print(",");
dataFile.print(k);
dataFile.print(",");
dataFile.println(l);
dataFile.close();
loopCount = 0;
}
else
{
loopCount++;
qSum = qSum + e;
if (mode == "MODE A")
j = j + f;
if (mode == "MODE C")
{
gSum = gSum + g;
rSum = rSum + d;
tSum = tSum + f;
uSum = uSum + h;
}
}
//Set the output based on the mode
if (mode == "MODE A")
{
if (d < 150)
k++;
else
k--;
if (k > 150)
k = 150;
if (k < 0)
k = 0;
}
else
k = 0;
analogWrite(5, k);
}
//Convert the time from the RTC format to the Excel format (a percent of a day)
float convertTime(int hour, int minute, int second)
{
float percentDay = 0.0;
//Convert hours into days
percentDay = hour/24.0;
//Convert minutes into days
percentDay += minute/1440.0;
//Convert seconds into days
percentDay += second/86400.0;
return percentDay;
}