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.

/*
 * 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.
 * 
 * http://AdamWelch.Co.Uk
 * 
 * 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 4x6, smallFont 6x8, mediumNumber 12x16, bigNumbers 14x24
  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>

What Others Are Saying

  1. Ruder 30/10/2017 at 22:58

    I realise this is a bit old but are you able to upload the circuit diagram as I’m new to electronics and can only follow instructions so far. I want to use your idea for a solar pump to only work between a certain voltage.

    Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *