/*****************************
** Main program **
** (runs in infinite loop) **
*****************************/
void loop(void)
{
// Get current time from RTC chip
now = RTC.now();
// Do following tasks once every second
if (now.second() != nLastSecond)
{
nLastSecond = now.second();
// Read serial data provided by BMS
// every odd second and disable interface
// afterwards (to avoid interference
// with hardware serial communication)
if (nLastSecond % 2 == 1)
{
readBMSData();
// Disable BMS serial data communication
BMS.end();
}
// Read incoming serial data over USB line
// every even second and disable interface
// afterwards (to avoid interference
// with software serial communication)
if (nLastSecond % 2 == 0)
{
while (Serial.available() > 0)
{
cIncomingSerialChar = Serial.read();
// Set flags according to external control request
// via serial data (toggels solar power circuit):
// 0 = SOFT ON (keeps Arduino battery control active)
// 1 = SOFT OFF (keeps Arduino battery control active)
// y = HARD ON (ATTENTION ! Disables Arduino battery control until cleared !)
// n = HARD OFF (ATTENTION ! Disables Arduino battery control until cleared !)
// c = CLEAR external control request (deactivates hard on / off flags)
if (cIncomingSerialChar == '0' ||
cIncomingSerialChar == '1' ||
cIncomingSerialChar == 'y' ||
cIncomingSerialChar == 'n' ||
cIncomingSerialChar == 'c')
cExternalControl = cIncomingSerialChar;
}
// Disable BMS & host serial data communication
Serial.end();
}
// Increase board online timer
// (simple counter to track time since last reset)
nBoardOnlineTimer++;
// Check if SD card is present
if (!digitalRead(6))
{
// Check if SD card is NOT initialized
if (!bSDCardInitialized)
{
// Initialize SD card
SD.begin(10);
bSDCardInitialized = true;
// Set warning LED off
digitalWrite(5, LOW);
}
}
else
{
bSDCardInitialized = false;
// Blink red LED
if (nLastSecond % 2 == 0)
digitalWrite(5, HIGH);
else
digitalWrite(5, LOW);
}
// If a power impulse occurred during last second
// (eliminates most errors caused by external interferences
// as a boolean variable can only be set to true once even
// if multiple triggering events should occur due to bouncing)
if (bImpulseOccurred)
{
// Increment impulse counter
fPowerImpulsesDuringThisHour++;
// Backup current value of current hour counter
// (in order to restore its value during initialization after a board reset)
noInterrupts();
backupPowerImplusesOfHour();
interrupts();
}
// Reset impulse occurrence flag
bImpulseOccurred = false;
// If a new hour has begun
if(now.hour() != nLastHour)
{
// Set time object for logging to
// current time (for next log cycle)
oLogTimestamp = now;
nLastHour = now.hour();
// Log power impulse count of last hour
// as well as current BMS dataset
noInterrupts();
logPowerImplusesOfHour();
logBMSValues();
interrupts();
// If a new day has begun
// (log impulses of last day to seperate file)
if(now.day() != nLastDay)
{
noInterrupts();
logPowerImplusesOfDay();
interrupts();
nLastDay = now.day();
}
}
// Retrieve solar power curcuit state by measuring
// corresponding input pin (maximum value is 1024
// which means that whole reference voltage of
// 5 volts is applied)
int nSolarCircuitVoltage = analogRead(3);
if (nSolarCircuitVoltage > 500)
bSolarCircuitState = true;
else
bSolarCircuitState = false;
// Re-enable BMS serial data communication
// only every EVEN second (to avoid interference
// with hardware serial communication)
if (nLastSecond % 2 == 0)
BMS.begin(19200);
// Re-enable serial data over USB line
// only every ODD second (to avoid interference
// with hardware serial communication)
if (nLastSecond % 2 == 1)
{
Serial.begin(19200);
// Send current BMS data to serial output (USB / host PC)
sendBMSData();
}
// Check status of solar battery in order to trigger
// relay of supply circuit
checkSolarBatteryStatus();
}
}