Automatic Grid Tie Switch Verision 3.0!

Posted on 17/08/2015 by Adam

The latest version of my Arduino based automatic grid tie switch is now finished. This improved version includes a new screen which displays more information and now uses an Arduino Nano (clone). Further more I’ve created my own voltage divider to increase the voltmeter resolution.

You can read about the first and second versions and watch the youtube videos here and here.

The software has been tweeked to take two voltage sensor pin readings and average them. Although this does slow the readings a little, it is proving to display a more accurate value.

Watch the video – scrutinize the code below.  Feel free to comment and share.

[code]
/*
* Automated Grid Tie Switch v3.0 – Nokia5110 version
*
* Switching based on battery voltage or can be manually overriden using a three position switch.
*
* New voltage divider using a 10k and 7.4k resistor. Absolute maximum battery input voltage is 15 volts.
* Damage will occur if battery voltage exceeds this level.
*
* .
*
* Fritzing Diagram:
*
* Required Library – U8gLib – https://code.google.com/p/u8glib/
*/

#include "LCD5110_Graph.h"
LCD5110 myGLCD(5,6,7,9,8); // Setup Nokia 5110 Screen SCLK/CLK=5, DIN/MOSI/DATA=6, DC/CS=7, RST=9 Chip Select/CE/SCE=8,

//Constant vars

const int gridSwitchPin = 2; //Declare arduino pin for manual grid switch pin
const int battSwitchPin = 3; //Delare arduino pin for manual battery switch pin
const int relayPositivePin = 11; //Declare arduino pin for positive relay
const int relayNegativePin = 12; //Declare arduino pin for negative relay
const int statusLEDPin = 13; //Decalre arduino pin for status LED
const int battAnalogPin = A6; //Declare arduino analog input pin for voltage sensor

// vars that will change

int gridSwitchState = 0; //Grid Tie manual switch initial value
int battSwitchState = 0; //Battery manual switch initial value
int voltReading = 0; //Voltage sensor initial value
int lastVoltReading = 0; //Voltage sensor averaging value
int previousState = 0; //previous switch mode. 0 is battery charge, 1 is grid tie
int battPercent = 0; //declare int for bar graph
float battVoltage = 0.0; //set initial battery voltage
float battFull = 13.8; //Set your battery full voltage
float battLow = 12.5; //Set batt low voltage
float voltageReference = 4.8; //Using a multimeter check voltage between REF Pin and ground on arduino and state it here
float voltageFactor = 1.0; //Factor used to calculate difference between 5 volts and real 5 volt rail. Initialize to 1
// Declare relays

#define RELAY_ON 0
#define RELAY_OFF 1

// Get external Font
extern uint8_t SmallFont[];

void setup()
{
digitalWrite(relayPositivePin,RELAY_OFF); //Deafult relay off
digitalWrite(relayNegativePin,RELAY_OFF); //Default relay off
pinMode(statusLEDPin,OUTPUT); //initialize the led pin as output
pinMode(relayPositivePin,OUTPUT); //initialize the positive relay pin as output
pinMode(relayNegativePin,OUTPUT); //initialize the negative relay pin as output
pinMode(gridSwitchPin,INPUT); //initialize the manual Grid switch as input
pinMode(battSwitchPin,INPUT); //initialize the manual Battery switch as input
myGLCD.InitLCD(68); //initialize LCD with default contrast of 70
myGLCD.setFont(SmallFont); // Set default font size. tinyFont 4×6, smallFont 6×8, mediumNumber 12×16, bigNumbers 14×24
myGLCD.clrScr();
//Serial.begin(9600);

}
/**********************************/

void loop()
{
digitalWrite(statusLEDPin,HIGH);//turn on status indicator LED
gridSwitchState = digitalRead(gridSwitchPin); //read state of GTI Switch
battSwitchState = digitalRead(battSwitchPin); //read the state of battery switch

//Start reading voltage

analogRead(battAnalogPin); //Read Voltage pin
delay(10); // Wait for pin to settle
voltReading = analogRead(battAnalogPin); //Read more accurate voltage pin reading
voltReading = (voltReading + lastVoltReading) /2; //Average last two results
lastVoltReading = voltReading;
voltageFactor = (5.0 / voltageReference);
battVoltage = (voltReading * 15.0 / 1024.0 * voltageFactor); //calculate the voltage
battPercent = analogRead(battAnalogPin);
battPercent = map(battPercent, 800, 910, 0, 100);

//Display voltage on LCD

if (battSwitchState == HIGH && gridSwitchState == LOW)
{
//Display mode on LCD
myGLCD.clrScr(); //clear screen
myGLCD.print("Manual Mode",CENTER,0); //Print branding to line 0
myGLCD.print("Charging",CENTER,12); //Print mode to line 1
myGLCD.print("Batt:",0,24); //Print start of line 2
myGLCD.printNumF(battVoltage, 2,40,24); //print float battVoltage to two decimal places after Batt: in row 2 (24)
myGLCD.print("v",76,24); //Print "v" near the end of line 2
printBar(); //run printBar loop
fillBar(battPercent); //run fillBar loop
myGLCD.update();

//Switch relays
digitalWrite(relayPositivePin,RELAY_OFF); //send solar positive to Batt Charge
delay(500); //wait half a second
digitalWrite(relayNegativePin,RELAY_OFF); //send solar negative to Batt Charge

/*Print information to Serial
Serial.print("Manual Battery Charge Mode!");//Serial print Auto Battery Charge Mode
Serial.print(" Battery Voltage: ");
Serial.print(battVoltage);
Serial.println("v");
Serial.print("voltReading = ");
Serial.println(voltReading);
delay(500);
*/
}

else if (battSwitchState == LOW && gridSwitchState == HIGH)
{

//Display mode on LCD
myGLCD.clrScr(); //clear screen
myGLCD.print("Manual Mode",CENTER,0); //Print branding to line 0
myGLCD.print("Grid Tie",CENTER,12); //Print mode to line 1
myGLCD.print("Batt:",0,24); //Print start of line 2
myGLCD.printNumF(battVoltage, 2,40,24); //print float battVoltage to two decimal places after Batt: in row 2 (24)
myGLCD.print("v",76,24); //Print "v" near the end of line 2
printBar(); //run printBar loop
fillBar(battPercent); //run fillBar loop
myGLCD.update();

//Switch relays
digitalWrite(relayPositivePin,RELAY_ON); //send solar positive to Grid Tie
delay(500); //wait half a second
digitalWrite(relayNegativePin,RELAY_ON); //send solar negative to Grid Tie

//Print information to Serial
/*Serial.print("Manual Grid Tie Mode!");//Serial print Auto Battery Charge Mode
Serial.print(" Battery Voltage: ");
Serial.print(battVoltage);
Serial.println("v");
Serial.print("voltReading = ");
Serial.println(voltReading);
delay(500);
*/
}

else if (battSwitchState == LOW && gridSwitchState == LOW)
{

if (battVoltage <= battLow )
{
//Display mode on LCD
myGLCD.clrScr(); //clear screen
myGLCD.invertText(true); //Invert Text
myGLCD.print("Automatic Mode",CENTER,0); //Print branding to line 0
myGLCD.invertText(false); //Invert Text
myGLCD.print("Charging",CENTER,12); //Print mode to line 1
myGLCD.print("Batt:",0,24); //Print start of line 2
myGLCD.printNumF(battVoltage, 2,40,24); //print float battVoltage to two decimal places after Batt: in row 2 (24)
myGLCD.print("v",76,24); //Print "v" near the end of line 2
printBar(); //run printBar loop
fillBar(battPercent); //run fillBar loop
myGLCD.update();

//Switch relays
digitalWrite(relayPositivePin,RELAY_OFF); //send solar positive to Batt Charge
delay(500); //wait half a second
digitalWrite(relayNegativePin,RELAY_OFF); //send solar negative to Batt Charge

previousState = 0; //Set previous mode to batt
delay(500);

//Print information to Serial
/*Serial.print("Automatic Battery Charge Mode!");//Serial print Auto Battery Charge Mode
Serial.print(" Battery Voltage: ");//Print second line
Serial.print(battVoltage);
Serial.println("v");
Serial.print("voltReading = ");
Serial.println(voltReading);
*/
}

else if (battVoltage > battLow && battVoltage < battFull && previousState == 0) //Battery voltage higher than battLow voltage and lower than battFull voltage and previous state was charge – keep charging.
{
//Display mode on LCD
myGLCD.clrScr(); //clear screen
myGLCD.invertText(true); //Invert Text
myGLCD.print("Automatic Mode",CENTER,0); //Print branding to line 0
myGLCD.invertText(false); //Invert Text
myGLCD.print("Charging",CENTER,12); //Print mode to line 1
myGLCD.print("Batt:",0,24); //Print start of line 2
myGLCD.printNumF(battVoltage, 2,40,24); //print float battVoltage to two decimal places after Batt: in row 2 (24)
myGLCD.print("v",76,24); //Print "v" near the end of line 2
printBar(); //run printBar loop
fillBar(battPercent); //run fillBar loop
myGLCD.update();

//Switch relays
digitalWrite(relayPositivePin,RELAY_OFF); //send solar positive to Batt Charge
delay(500); //wait half a second
digitalWrite(relayNegativePin,RELAY_OFF); //send solar negative to Batt Charge

previousState = 0; //Set previous mode to batt
delay(500);

//Print information to Serial
/*Serial.print("Automatic Battery Charge Mode!");//Serial print Auto Battery Charge Mode
Serial.print(" Battery Voltage: ");//Print second line
Serial.print(battVoltage);
Serial.println("v");
Serial.print("voltReading = ");
Serial.println(voltReading);
*/
}

else if (battVoltage > battLow && battVoltage < battFull && previousState == 1) //Battery high than battLow voltage and less than battery full voltage and previous state was grid tie – stay at grid tie.
{
//Display mode on LCD
myGLCD.clrScr(); //clear screen
myGLCD.invertText(true); //Invert Text
myGLCD.print("Automatic Mode",CENTER,0); //Print branding to line 0
myGLCD.invertText(false); //Invert Text
myGLCD.print("Grid Tie",CENTER,12); //Print mode to line 1
myGLCD.print("Batt:",0,24); //Print start of line 2
myGLCD.printNumF(battVoltage, 2,40,24); //print float battVoltage to two decimal places after Batt: in row 2 (24)
myGLCD.print("v",76,24); //Print "v" near the end of line 2
printBar(); //run printBar loop
fillBar(battPercent); //run fillBar loop
myGLCD.update();

//Switch relays
digitalWrite(relayPositivePin,RELAY_ON); //send solar positive to Grid Tie
delay(500); //wait half a second
digitalWrite(relayNegativePin,RELAY_ON); //send solar negative to Grid Tie

previousState = 1; //Set previous mode to grid
delay(500);
//Print information to Serial

/*Serial.print("Automatic Grid Tie Mode!");//Serial print Auto Battery Charge Mode
Serial.print(" Battery Voltage: ");
Serial.print(battVoltage);
Serial.println("v");
Serial.print("voltReading = ");
Serial.println(voltReading);
delay(500);
*/

}
else if (battVoltage >= battFull) //Battery high than battery full voltage – go to grid tie.
{
//Display mode on LCD
myGLCD.clrScr(); //clear screen
myGLCD.invertText(true); //Invert Text
myGLCD.print("Automatic Mode",CENTER,0); //Print branding to line 0
myGLCD.invertText(false); //Invert Text
myGLCD.print("Grid Tie",CENTER,12); //Print mode to line 1
myGLCD.print("Batt:",0,24); //Print start of line 2
myGLCD.printNumF(battVoltage, 2,40,24); //print float battVoltage to two decimal places after Batt: in row 2 (24)
myGLCD.print("v",76,24); //Print "v" near the end of line 2
printBar(); //run printBar loop
fillBar(battPercent); //run fillBar loop
myGLCD.update();

//Switch relays
digitalWrite(relayPositivePin,RELAY_ON); //send solar positive to Grid Tie
delay(500); //wait half a second
digitalWrite(relayNegativePin,RELAY_ON); //send solar negative to Grid Tie

previousState = 1; //Set previous mode to grid
delay(500);

//Print information to Serial
/*Serial.print("Automatic Grid Tie Mode!");//Serial print Auto Battery Charge Mode
Serial.print(" Battery Voltage: ");
Serial.print(battVoltage);
Serial.println("v");
Serial.print("voltReading = ");
Serial.println(voltReading);
*/
}
}
else
{
//Unkown state – protect system
//Display mode on LCD
myGLCD.clrScr(); //clear screen
myGLCD.print("Unknown",CENTER,0); //Print branding to line 0
myGLCD.print("Error 1",CENTER,12); //Print mode to line 1
myGLCD.print("Batt:",0,24); //Print start of line 2
myGLCD.printNumF(battVoltage, 2,40,24); //print float battVoltage to two decimal places after Batt: in row 2 (24)
myGLCD.print("v",76,24); //Print "v" near the end of line 2
printBar(); //run printBar loop
fillBar(battPercent); //run fillBar loop

//Disconnect solar from both systems

digitalWrite(relayPositivePin,RELAY_OFF); //send solar positive to Batt Charge
delay(500); //wait half a second
digitalWrite(relayNegativePin,RELAY_ON); //send solar negative to Grid

digitalWrite(statusLEDPin,HIGH); //Turn on status LED
delay(100); //wait a tenth of a second
digitalWrite(statusLEDPin,LOW); //Turn off status LED
delay(100); //wait a tenth of a second
}
}

void printBar()
{
myGLCD.drawRect(0, 42, 83, 47);
myGLCD.update();
}

void fillBar(int percent)
{
percent = map(percent,0,100,2,81);
myGLCD.drawLine(1, 43, percent, 43);
myGLCD.drawLine(1, 44, percent, 44);
myGLCD.drawLine(1, 45, percent, 45);
myGLCD.drawLine(1, 46, percent, 46);
/*Serial.print("Bar Graph");
Serial.print(percent);
Serial.println("%");
*/
}

/************************************/</blockquote>
[/code]