#include <Metro.h>
#include <Streaming.h>
#include <LiquidCrystal.h>
/*
Simple Solar Battery Monitor
The circuit:
Volts ( pin0) scaled input from 24vdc battery to max 5v for digitize
Amps (pin1) input for hall effect current sensor 0 amps ~ 3.5v
Output to 16x2 LCD display
Metro Library for timing and Streaming for Serial output
created Aug 2010 for Battery Monitor
by Jerry Jeffress
*/
const int voltsInPin = 0;
const int ampsInPin = 1;
const int backLitePin = 5;
const int contrastPin = 6;
const float batterySize = 9.48; //Battery capacity in KwHrs
const float chargeEff = 0.85; //Approx Amount of power into a lead acid battery that is stored
Metro oneSecond = Metro(1000); // Instantiate an one timer
int aSecond;
int blinkit;
int bStatus; //Battery status, 0-6 states
float absorbCtr, chargeCtr, disChargeCtr, eqCtr;
float absorbTimeOut = 60*60*3.0;//3 hours in seconds
float eqTimeOut = 60*60*3.0; //3 Hours in seconds
float tenHours = 60*60*10.0;
float sec2Hr = 1.0/(1000 * 3600.0); //Convert watt-sec to kwHrs
float volts, amps, power;
float bCharge; //This is power monitor variable total effective charge to and from the battery
float bLow; //low battery value
// initialize the LCD library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
void setup(){
Serial.begin(9600); // Start the Serial communication for debug mainly
analogWrite(backLitePin, 64); //LCD backlite 1/4 full 20.6 ma on battery pack
analogWrite(contrastPin, 80); //Set LCD contrast
aSecond = 0;
blinkit = 0;
bCharge = batterySize * 0.95; //init charge 95% full battery
absorbCtr = 0;
eqCtr = 0;
chargeCtr = 60*9;
disChargeCtr = 0;
bLow = 0.5; //Low battery warning when hattery 50% charged
bStatus = 7;//This a an error value must be updated in Calculate bStatus
// set up the LCD's number of rows and columns:
lcd.begin(16, 2);
};
void loop(){
if (oneSecond.check() == 1) { // check if the metro has passed it's interval .
//sample volt and amps from the battery
sampleVoltsAmps();
/* // Output serial time volts amps as to display
Serial << aHour << _BYTE(58) << aMinute << _BYTE(58) <<
aSecond << _BYTE(9) << volts << _BYTE(9) << amps << _BYTE(9) << bCharge << _BYTE(9) <<
(batteryStatus
) << endl;
*/
//Update LCD display each second
calcPower();
calcbStatus();
newDay();
if(aSecond % 6 < 3)
displayStatus();
else
displayCtr();
aSecond = aSecond++;
if (aSecond >= 60)
aSecond = 0;
blinkit = blinkit++;
if (blinkit > 1)
blinkit = 0;
}
}
void sampleVoltsAmps() {
int voltSum = 0.0;
float ampSum = 0.0;
// loop 10 time over one 50hz cycle to smooth
for (int i = 0; i < 10; i++){
volts = map(analogRead(voltsInPin), 0, 1023, 0, 3309);
voltSum = voltSum + volts;
amps = map(analogRead(ampsInPin), 0, 1023, -806, 217);
ampSum = ampSum + amps;
delay(2);
}//end smooth loop
//Get 10 sample average
volts = voltSum /1000.0; //Factor to scale to volts
amps = ampSum * 0.015; //Factor to scale to Amps
}
//Calc power
void calcPower(){
power = volts * amps; //Units are watt-seconds
if (power <= 0){
bCharge = bCharge +(power * sec2Hr);
}
else {
bCharge = bCharge + (power * sec2Hr * chargeEff);
}
}
//Calculate bStatus
void calcbStatus(){
bStatus = 0; //This charge/discharge
if(amps >= 0)
chargeCtr = chargeCtr +1;
if(amps < 0){
disChargeCtr = disChargeCtr + 1;
}
//if(volts < 28.3)
//absorbCtr = absorbCtr -1; //debug only commint
if(absorbCtr < 0)
absorbCtr = 0;
if(volts > 28.3){
bStatus = 1;
absorbCtr = absorbCtr + 1;
}
if(volts > 27.3 && absorbCtr > absorbTimeOut)
bStatus = 2;
}
// New Day
void newDay(){
if(disChargeCtr == tenHours) //10 hours
chargeCtr = 0;
if(chargeCtr > 60*10 && disChargeCtr > tenHours){
Serial << "Debug trap new day" << _BYTE(9) << disChargeCtr <<endl;
disChargeCtr = 0;
absorbCtr = 0;
eqCtr = 0;
//Other saves for a New Day
}
}
//update LCD Display
void displayStatus(){
// Print volts to LCD.
lcd.setCursor(0,0);
lcd.print("BAT ");
lcd.print(volts, 1); //display volts to one decimal place
lcd.print("v ");
// Print % full to display
if(bCharge < batterySize){
lcd.print(100 * bCharge/batterySize,1);
lcd.print("%");
}
else{
lcd.print("Full ");
bCharge = batterySize;
}
//Print Battery Status to Display
lcd.setCursor(0, 1);
switch(bStatus){
case 0:
if(amps >= 0)
lcd.print("Charge ");
else
lcd.print("Discharge ");
break;
case 1:
lcd.print("Absorb ");
break;
case 2:
lcd.print("Float ");
break;
default:
lcd.print("Error ");
}
if(bCharge < bCharge * bLow){//Battery Low blink
if(blinkit==0)
lcd.print("Low ");
else
lcd.print(" Low");
}
if(volts > 29.2 && eqCtr < eqTimeOut){
lcd.setCursor(0, 1);
lcd.print("Equalize ");
eqCtr =eqCtr + 1;
}
//Print Amps to display right justified
if(amps<0){ //All negative
if(amps<-9.9){
lcd.print(amps,1);
}
else{
lcd.print(" ");
lcd.print(amps,1);
}
}
else { //all positive or zero
if(amps>9.9){
lcd.print("+");
lcd.print(amps,1);
}
else{
lcd.print(" +");
lcd.print(amps,1);
}
}
lcd.print(" A");
}
//Counter page
void displayCtr(){
lcd.clear();
lcd.print("Chr ");
lcd.print(chargeCtr/60,0);
lcd.print(" Dis ");
lcd.print(disChargeCtr/60,0
);
lcd.setCursor(0,1);
lcd.print("Abs ");
lcd.print(absorbCtr/60,0);
lcd.print(" eq ");
lcd.print(eqCtr/60,0);
}