Project tutorial

Home Made Arduino Based MPPT Charge Controller © GPL3+

In This Tutorial, I will Show You How to Make an Arduino Based MPPT Charge Controller

  • 195 views
  • 0 comments
  • 3 respects

Components and supplies

Apps and online services

About this project

Arduino Based MPPT Charge Controller | Alternative energy |renewable energy sources | clean energy

What is Mppt ( Maximum power point tracking)?

We use MPPT algorithm to Extract the maximum available power from the Photovoltaic module under certain conditions. MPPT is a Most Popular tool that helps us to use Solar Energy (Renewable Energy Source) in an efficient way. If we want to Reduce the Graph of Carbon footprints then we must need to move towards clean Energy which is called Renewable Energy ( Energy we can get from Natural resources) Like SOLAR, HYDRO, WIND e.t.c otherwise we will directly move toward Global Warming.

Every Country needs to Move towards the Green Energy especially the CHINA because it is the Main contributor by producing 63% Co2.

How MPPT works? Why 150W solar panel does not equal to 150 w?

For example, you bought a new solar panel from the market which can deliver 7 amps current, under charge the setting of a battery is configured to 12 volts: 7 amps times 12 volts = 84w (P=V*I) You lost over 66 watts - but you paid for 150 watts. That 66 watt is not going anywhere, but it,s due to the poor match of the solar output current and battery voltage.

After using MPPT algorithm we can get the Maximum available power Battery gets is now 12 amps at 12 volts Output power is equal to p= V*I p=12*12=144w Now you still have almost 144 watts, and everyone is happy.

Specification of the project

2. LED indication to show the low mid and high level of charge stat

3. LCD (20x4 character ) display for displaying power,current,voltages etc

4. Lightning /Overvoltage Protection

5. Protection For Reverse power flow

6. Overload & Short Circuit Protection

7. Logging data through WiFi

8.Charge your Cellphone, tablets any gadgets through USB port

Electrical specifications:

1.Rated Voltage= 12V

2.Maximum input current = 5A

3.Load current support up to =10A

4. Input Voltage = Solar panel 12 to 24V

5.power of Solar panel = 50 Watts

PARTS REQUIRED:

  • Resistors ( 3 x 200R ,3 x330R,1 x 1K, 2 x 10K, 2 x 20K, 2x 100k, 1x 470K )
  • TVS diode ( 2x P6KE36CA )
  • Arduino Nano 
  • ( ACS712-5A ) Current Sensor 
  • Buck Converter ( LM2596 )
  • Wifi Module ( ESP8266 )
  • LCD display ( 20x4 I2C )
  • MOSFETs ( 4x IRFZ44N )
  • MOSFET driver ( IR2104 )
  • 3.3V Linear regulator ( AMS 1117 )
  • Transistor ( 2N2222 )
  • Diodes ( 2x IN4148 , 1 x UF4007 )
  • Capacitors ( 4 x 0.1 uF, 3 x 10uF ,1 x100 uF ,1x 220uF)
  • Inductor ( 1x 33uH -5A )
  • LEDs ( Red, Yellow, Green )
  • Fuses ( 5A)

Libraries Required For Arduino IDE : 

Remember: Make a New Folder ( Folder name should be same as library names like TimerOne and LiquidCrystal_I2C. Paste these Two Folders in Arduino/LIbrary.

---------------------------------------------------------------------------------

Model of Arduino Based MPPT Algorithm Charge Controller

Simulation of MPPT Charge Controller Project in Proteus software

This Simulation has been designed in Proteus Software 8.6 version. You can make your own by using Arduino Library for Proteus and a simulation tool known as Proteus. Kindly Contact Us if you want to Buy a proteus simulation source file for this project. 

WiFi Data Logging by using a Wifi module ESP8266

Read This Article: Learn How to Setup the Wifi Module ESP8266 by Using Just Arduino IDE

After Reading The Above article I am assuming that you have successfully connected your ESP8266 module to your Wifi. 

  • Make a New Channel and write "Solar Panel Data" in Field 1 and leave other fields blanks and save it. 
  • You will Get API key, Copy that Api Key and Paste in Source Code.
  • Done

Project Images 

"Do not forget to install all the necessary libraries before uploading the code to Arduino Nano "

If you found any difficulty while making this project so don't hesitate to ask first we are here to help you 24 hours a day and 7 days a week 24/7 thanks 

Schematics

SCHEMATIC Diagram Of Mppt Charge Controller Project

Code

Source Code C/C++
//----------------------------------------------------------------------------------------------------
// ARDUINO MPPT SOLAR CHARGE CONTROLLER (Version-3) 
//  Author: Debasish Dutta/deba168
//          www.opengreenenergy.in
//
//  This code is for an arduino Nano based Solar MPPT charge controller.
//  This code is a modified version of sample code from www.timnolan.com
//  updated 06/07/2015
//
//  Mods by Aplavins 19/06/2015 

////  Specifications :  //////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                                                            //
//    1.Solar panel power = 50W                                            
                                                                                                                            //
//    2.Rated Battery Voltage= 12V ( lead acid type )

//    3.Maximum current = 5A                                                                                                //

//    4.Maximum load current =10A                                                                                            //

//    5. In put Voltage = Solar panel with Open circuit voltage from 17 to 25V                                               //

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "TimerOne.h"                // using Timer1 library from http://www.arduino.cc/playground/Code/Timer1
#include <LiquidCrystal_I2C.h>      // using the LCD I2C Library from https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
#include <Wire.h>  
#include <SoftwareSerial.h>         // using the Software Serial library Ref : http://www.arduino.cc/en/Reference/SoftwareSerialConstructor
//----------------------------------------------------------------------------------------------------------
 
//////// Arduino pins Connections//////////////////////////////////////////////////////////////////////////////////

// A0 - Voltage divider (solar)
// A1 - ACS 712 Out
// A2 - Voltage divider (battery)
// A4 - LCD SDA
// A5 - LCD SCL
// D2 - ESP8266 Tx
// D3 - ESP8266 Rx through the voltage divider
// D5 - LCD back control button
// D6 - Load Control 
// D8 - 2104 MOSFET driver SD
// D9 - 2104 MOSFET driver IN  
// D11- Green LED
// D12- Yellow LED
// D13- Red LED

// Full scheatic is given at http://www.instructables.com/files/orig/F9A/LLR8/IAPASVA1/F9ALLR8IAPASVA1.pdf

///////// Definitions /////////////////////////////////////////////////////////////////////////////////////////////////


// Turn this on to use the ESP8266 chip. If you set this to 0, the periodic updates will not happen
#define ENABLE_DATALOGGER 0

// Load control algorithm
// 0 - NIGHT LIGHT: Load ON when there is no solar power and battery is above LVD (low voltage disconnect)
// 1 - POWER DUMP: Load ON when there is solar power and the battery is above BATT_FLOAT (charged)
#define LOAD_ALGORITHM 0

#define SOL_AMPS_CHAN 1                // Defining the adc channel to read solar amps
#define SOL_VOLTS_CHAN 0               // defining the adc channel to read solar volts
#define BAT_VOLTS_CHAN 2               // defining the adc channel to read battery volts
#define AVG_NUM 8                      // number of iterations of the adc routine to average the adc readings

// ACS 712 Current Sensor is used. Current Measured = (5/(1024 *0.185))*ADC - (2.5/0.185) 

#define SOL_AMPS_SCALE  0.026393581        // the scaling value for raw adc reading to get solar amps   // 5/(1024*0.185)
#define SOL_VOLTS_SCALE 0.029296875        // the scaling value for raw adc reading to get solar volts  // (5/1024)*(R1+R2)/R2 // R1=100k and R2=20k
#define BAT_VOLTS_SCALE 0.029296875        // the scaling value for raw adc reading to get battery volts 

#define PWM_PIN 9                    // the output pin for the pwm (only pin 9 avaliable for timer 1 at 50kHz)
#define PWM_ENABLE_PIN 8            // pin used to control shutoff function of the IR2104 MOSFET driver (hight the mosfet driver is on)
#define PWM_FULL 1023                // the actual value used by the Timer1 routines for 100% pwm duty cycle
#define PWM_MAX 100                  // the value for pwm duty cyle 0-100%
#define PWM_MIN 60                  // the value for pwm duty cyle 0-100% (below this value the current running in the system is = 0)
#define PWM_START 90                // the value for pwm duty cyle 0-100%
#define PWM_INC 1                    //the value the increment to the pwm value for the ppt algorithm

#define TRUE 1
#define FALSE 0
#define ON TRUE
#define OFF FALSE

#define TURN_ON_MOSFETS digitalWrite(PWM_ENABLE_PIN, HIGH)      // enable MOSFET driver
#define TURN_OFF_MOSFETS digitalWrite(PWM_ENABLE_PIN, LOW)      // disable MOSFET driver

#define ONE_SECOND 50000            //count for number of interrupt in 1 second on interrupt period of 20us

#define LOW_SOL_WATTS 5.00          //value of solar watts // this is 5.00 watts
#define MIN_SOL_WATTS 1.00          //value of solar watts // this is 1.00 watts
#define MIN_BAT_VOLTS 11.00         //value of battery voltage // this is 11.00 volts          
#define MAX_BAT_VOLTS 14.10         //value of battery voltage// this is 14.10 volts
#define BATT_FLOAT 13.60            // battery voltage we want to stop charging at
#define HIGH_BAT_VOLTS 13.00        //value of battery voltage // this is 13.00 volts 
#define LVD 11.5                    //Low voltage disconnect setting for a 12V system
#define OFF_NUM 9                   // number of iterations of off charger state
  
//------------------------------------------------------------------------------------------------------
//Defining led pins for indication
#define LED_GREEN 11
#define LED_YELLOW 12
#define LED_RED 13
//-----------------------------------------------------------------------------------------------------
// Defining load control pin
#define LOAD_PIN 6       // pin-2 is used to control the load
  
//-----------------------------------------------------------------------------------------------------
// Defining lcd back light pin
#define BACK_LIGHT_PIN 5       // pin-5 is used to control the lcd back light

// ---------------------------For ESP8266--------------------------------------------------------------

// replace with your channel's thingspeak API key
String apiKey = "your Api key from thing speak";
const char* ssid = "your wifi name";

const char* password = "your wifi password";

const char* server = "api.thingsspeak.com";

// connect 2 to TX of Serial USB
// connect 3 to RX of serial USB

SoftwareSerial ser(2,3); // RX, TX
//---------------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------------
/////////////////////////////////////////BIT MAP ARRAY//////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------------

byte battery_icons[6][8]=
{{
  0b01110,
  0b11011,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b11111,
},
{
  0b01110,
  0b11011,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b11111,
  0b11111,
},
{
  0b01110,
  0b11011,
  0b10001,
  0b10001,
  0b10001,
  0b11111,
  0b11111,
  0b11111,
},
{
  0b01110,
  0b11011,
  0b10001,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
},
{
  0b01110,
  0b11011,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
},
{
  0b01110,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
}};
#define SOLAR_ICON 6
byte solar_icon[8] = //icon for termometer
{
  0b11111,
  0b10101,
  0b11111,
  0b10101,
  0b11111,
  0b10101,
  0b11111,
  0b00000
};
#define PWM_ICON 7
byte _PWM_icon[8]=
{
  0b11101,
  0b10101,
  0b10101,
  0b10101,
  0b10101,
  0b10101,
  0b10101,
  0b10111,
};
byte backslash_char[8]= 
{
  0b10000,
  0b10000,
  0b01000,
  0b01000,
  0b00100,
  0b00100,
  0b00010,
  0b00010,
};
//-------------------------------------------------------------------------------------------------------

// global variables

float sol_amps;                       // solar amps 
float sol_volts;                      // solar volts 
float bat_volts;                      // battery volts 
float sol_watts;                      // solar watts
float old_sol_watts = 0;              // solar watts from previous time through ppt routine 
unsigned int seconds = 0;             // seconds from timer routine
unsigned int prev_seconds = 0;        // seconds value from previous pass
unsigned int interrupt_counter = 0;   // counter for 20us interrrupt
unsigned long time = 0;               // variable to store time the back light control button was pressed in millis
int delta = PWM_INC;                  // variable used to modify pwm duty cycle for the ppt algorithm
int pwm = 0;                          // pwm duty cycle 0-100%
int back_light_pin_State = 0;         // variable for storing the state of the backlight button
boolean load_status = false;          // variable for storing the load output state (for writing to LCD)
  
enum charger_mode {off, on, bulk, bat_float} charger_state;    // enumerated variable that holds state for charger state machine
// set the LCD address to 0x27 for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x38, 2, 1, 0, 4, 5, 6, 7, 3, NEGATIVE);  // Set the LCD I2C address


//------------------------------------------------------------------------------------------------------
// This routine is automatically called at powerup/reset
//------------------------------------------------------------------------------------------------------

void setup()                           // run once, when the sketch starts
{
  pinMode(PWM_ENABLE_PIN, OUTPUT);     // sets the digital pin as output
  TURN_OFF_MOSFETS;                    // turn off MOSFET driver chip
  charger_state = off;                 // start with charger state as off
  lcd.begin(20,4);                     // initialize the lcd for 16 chars 2 lines, turn on backlight

  // create the LCD special characters. Characters 0-5 are the various battery fullness icons
  // icon 7 is for the PWM icon, and icon 8 is for the solar array
  lcd.backlight();
  for (int batchar = 0; batchar <   6; ++batchar) {
    lcd.createChar(batchar, battery_icons[batchar]);
  }
  lcd.createChar(PWM_ICON,_PWM_icon);
  lcd.createChar(SOLAR_ICON,solar_icon);
  lcd.createChar('\\', backslash_char);
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_YELLOW, OUTPUT);
  Timer1.initialize(20);               // initialize timer1, and set a 20uS period
  Timer1.pwm(PWM_PIN, 0);              // setup pwm on pin 9, 0% duty cycle
  Timer1.attachInterrupt(callback);    // attaches callback() as a timer overflow interrupt
  Serial.begin(9600);                  // open the serial port at 9600 bps:
  ser.begin(9600);                     // enable software serial
  ser.println("AT+RST");               // reset ESP8266
  pwm = PWM_START;                     //starting value for pwm  
  pinMode(BACK_LIGHT_PIN, INPUT);
  pinMode(LOAD_PIN,OUTPUT);
  digitalWrite(LOAD_PIN,LOW);          // default load state is OFF
  digitalWrite(BACK_LIGHT_PIN,LOW);    //  default LCd back light is OFF

  // display the constant stuff on the LCD
  lcd.setCursor(0, 0);
  lcd.print("SOL");
  lcd.setCursor(4, 0);
  lcd.write(SOLAR_ICON);
  lcd.setCursor(8, 0);
  lcd.print("BAT");
}

//------------------------------------------------------------------------------------------------------
// Main loop
//------------------------------------------------------------------------------------------------------
void loop()
{
  read_data();                         // read data from inputs
  run_charger();                       // run the charger state machine
  print_data();                        // print data
  load_control();                      // control the connected load
  led_output();                        // led indication
  lcd_display();                       // lcd display
#if ENABLE_DATALOGGER
  wifi_datalog();                    // sends data to thingspeak
#endif
}

//------------------------------------------------------------------------------------------------------
// This routine reads and averages the analog inputs for this system, solar volts, solar amps and 
// battery volts. 
//------------------------------------------------------------------------------------------------------
int read_adc(int channel){
  
  int sum = 0;
  int temp;
  int i;
  
  for (i=0; i<AVG_NUM; i++) {          // loop through reading raw adc values AVG_NUM number of times  
    temp = analogRead(channel);        // read the input pin  
    sum += temp;                       // store sum for averaging
    delayMicroseconds(50);             // pauses for 50 microseconds  
  }
  return(sum / AVG_NUM);               // divide sum by AVG_NUM to get average and return it
}

//------------------------------------------------------------------------------------------------------
// This routine reads all the analog input values for the system. Then it multiplies them by the scale
// factor to get actual value in volts or amps. 
//------------------------------------------------------------------------------------------------------
void read_data(void) {
  
  sol_amps = (read_adc(SOL_AMPS_CHAN) * SOL_AMPS_SCALE -13.51);    //input of solar amps
  sol_volts = read_adc(SOL_VOLTS_CHAN) * SOL_VOLTS_SCALE;          //input of solar volts 
  bat_volts = read_adc(BAT_VOLTS_CHAN) * BAT_VOLTS_SCALE;          //input of battery volts 
  sol_watts = sol_amps * sol_volts ;                               //calculations of solar watts                  
}

//------------------------------------------------------------------------------------------------------
// This is interrupt service routine for Timer1 that occurs every 20uS.
//
//------------------------------------------------------------------------------------------------------
void callback()
{
  if (interrupt_counter++ > ONE_SECOND) {        // increment interrupt_counter until one second has passed
    interrupt_counter = 0;                       // reset the counter
    seconds++;                                   // then increment seconds counter
  }
}

//------------------------------------------------------------------------------------------------------
// This routine uses the Timer1.pwm function to set the pwm duty cycle.
//------------------------------------------------------------------------------------------------------
void set_pwm_duty(void) {

  if (pwm > PWM_MAX) {					   // check limits of PWM duty cyle and set to PWM_MAX
    pwm = PWM_MAX;		
  }
  else if (pwm < PWM_MIN) {				   // if pwm is less than PWM_MIN then set it to PWM_MIN
    pwm = PWM_MIN;
  }
  if (pwm < PWM_MAX) {
    Timer1.pwm(PWM_PIN,(PWM_FULL * (long)pwm / 100), 20);  // use Timer1 routine to set pwm duty cycle at 20uS period
    //Timer1.pwm(PWM_PIN,(PWM_FULL * (long)pwm / 100));
  }												
  else if (pwm == PWM_MAX) {				   // if pwm set to 100% it will be on full but we have 
    Timer1.pwm(PWM_PIN,(PWM_FULL - 1), 20);                // keep switching so set duty cycle at 99.9% 
    //Timer1.pwm(PWM_PIN,(PWM_FULL - 1));              
  }												
}	

//------------------------------------------------------------------------------------------------------
// This routine is the charger state machine. It has four states on, off, bulk and float.
// It's called once each time through the main loop to see what state the charger should be in.
// The battery charger can be in one of the following four states:
// 
//  On State - this is charger state for MIN_SOL_WATTS < solar watts < LOW_SOL_WATTS. In this state isthe solar 
//      watts input is too low for the bulk charging state but not low enough to go into the off state. 
//      In this state we just set the pwm = 99.9% to get the most of low amount of power available.

//  Bulk State - this is charger state for solar watts > MIN_SOL_WATTS. This is where we do the bulk of the battery
//      charging and where we run the Peak Power Tracking alogorithm. In this state we try and run the maximum amount
//      of current that the solar panels are generating into the battery.

//  Float State - As the battery charges it's voltage rises. When it gets to the MAX_BAT_VOLTS we are done with the 
//      bulk battery charging and enter the battery float state. In this state we try and keep the battery voltage
//      at MAX_BAT_VOLTS by adjusting the pwm value. If we get to pwm = 100% it means we can't keep the battery 
//      voltage at MAX_BAT_VOLTS which probably means the battery is being drawn down by some load so we need to back
//      into the bulk charging mode.

//  Off State - This is state that the charger enters when solar watts < MIN_SOL_WATTS. The charger goes into this
//      state when there is no more power being generated by the solar panels. The MOSFETs are turned
//      off in this state so that power from the battery doesn't leak back into the solar panel. 
//------------------------------------------------------------------------------------------------------
void run_charger(void) {
  
  static int off_count = OFF_NUM;

  switch (charger_state) {
    case on:                                        
      if (sol_watts < MIN_SOL_WATTS) {                      // if watts input from the solar panel is less than
        charger_state = off;                                // the minimum solar watts then 
        off_count = OFF_NUM;                                // go to the charger off state
        TURN_OFF_MOSFETS; 
      }
      else if (bat_volts > (BATT_FLOAT - 0.1)) {            // else if the battery voltage has gotten above the float
        charger_state = bat_float;                          // battery float voltage go to the charger battery float state
      }
      else if (sol_watts < LOW_SOL_WATTS) {                 // else if the solar input watts is less than low solar watts
        pwm = PWM_MAX;                                      // it means there is not much power being generated by the solar panel
        set_pwm_duty();			                    // so we just set the pwm = 100% so we can get as much of this power as possible
      }                                                     // and stay in the charger on state
      else {                                          
        pwm = ((bat_volts * 10) / (sol_volts / 10)) + 5;    // else if we are making more power than low solar watts figure out what the pwm
        charger_state = bulk;                               // value should be and change the charger to bulk state 
      }
      break;
    case bulk:
      if (sol_watts < MIN_SOL_WATTS) {                      // if watts input from the solar panel is less than
        charger_state = off;                                // the minimum solar watts then it is getting dark so
        off_count = OFF_NUM;                                // go to the charger off state
        TURN_OFF_MOSFETS; 
      }
      else if (bat_volts > BATT_FLOAT) {                 // else if the battery voltage has gotten above the float
        charger_state = bat_float;                          // battery float voltage go to the charger battery float state
      }
      else if (sol_watts < LOW_SOL_WATTS) {                 // else if the solar input watts is less than low solar watts
        charger_state = on;                                 // it means there is not much power being generated by the solar panel
        TURN_ON_MOSFETS;                                    // so go to charger on state
      }
      else {                                                // this is where we do the Peak Power Tracking ro Maximum Power Point algorithm
        if (old_sol_watts >= sol_watts) {                   // if previous watts are greater change the value of
          delta = -delta;			            // delta to make pwm increase or decrease to maximize watts
        }
        pwm += delta;                                       // add delta to change PWM duty cycle for PPT algorythm (compound addition)
        old_sol_watts = sol_watts;                          // load old_watts with current watts value for next time
        set_pwm_duty();				            // set pwm duty cycle to pwm value
      }
      break;
    case bat_float:

      if (sol_watts < MIN_SOL_WATTS) {                      // if watts input from the solar panel is less than
        charger_state = off;                                // the minimum solar watts then it is getting dark so
        off_count = OFF_NUM;                                // go to the charger off state
        TURN_OFF_MOSFETS; 
        set_pwm_duty();					
      }
      else if (bat_volts > BATT_FLOAT) {                    // If we've charged the battery abovethe float voltage                
        TURN_OFF_MOSFETS;                                   // turn off MOSFETs instead of modiflying duty cycle
        pwm = PWM_MAX;                                      // the charger is less efficient at 99% duty cycle
        set_pwm_duty();                                     // write the PWM
      }
      else if (bat_volts < BATT_FLOAT) {                    // else if the battery voltage is less than the float voltage - 0.1
        pwm = PWM_MAX;                                      
        set_pwm_duty();	                                    // start charging again
        TURN_ON_MOSFETS; 		
        if (bat_volts < (BATT_FLOAT - 0.1)) {               // if the voltage drops because of added load,
        charger_state = bulk;                               // switch back into bulk state to keep the voltage up
        }
      }
      break;
    case off:                                               // when we jump into the charger off state, off_count is set with OFF_NUM
      TURN_OFF_MOSFETS;
      if (off_count > 0) {                                  // this means that we run through the off state OFF_NUM of times with out doing
        off_count--;                                        // anything, this is to allow the battery voltage to settle down to see if the  
      }                                                     // battery has been disconnected
      else if ((bat_volts > BATT_FLOAT) && (sol_volts > bat_volts)) {
        charger_state = bat_float;                          // if battery voltage is still high and solar volts are high
        TURN_ON_MOSFETS;
      }    
      else if ((bat_volts > MIN_BAT_VOLTS) && (bat_volts < BATT_FLOAT) && (sol_volts > bat_volts)) {
        charger_state = bulk;
        TURN_ON_MOSFETS;
      }
      break;
    default:
      TURN_OFF_MOSFETS; 
      break;
  }
}

//----------------------------------------------------------------------------------------------------------------------
/////////////////////////////////////////////LOAD CONTROL/////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------  

void load_control(){
#if LOAD_ALGORITHM == 0
  // turn on loads at night when the solar panel is not producing power
  // as long as the battery voltage is above LVD
  load_on(sol_watts < MIN_SOL_WATTS && bat_volts > LVD);
#else
  // dump excess solar energy into the load circuit
  load_on(sol_watts > MIN_SOL_WATTS && bat_volts > BATT_FLOAT);
#endif
}

void load_on(boolean new_status) {
  if (load_status != new_status) {
    load_status = new_status;
    digitalWrite(LOAD_PIN, new_status ? HIGH : LOW);
  }
}

//------------------------------------------------------------------------------------------------------
// This routine prints all the data out to the serial port.
//------------------------------------------------------------------------------------------------------
void print_data(void) {
  
  Serial.print(seconds,DEC);
  Serial.print("      ");

  Serial.print("Charging = ");
  if (charger_state == on) Serial.print("on   ");
  else if (charger_state == off) Serial.print("off  ");
  else if (charger_state == bulk) Serial.print("bulk ");
  else if (charger_state == bat_float) Serial.print("float");
  Serial.print("      ");

  Serial.print("pwm = ");
  if(charger_state == off)
  Serial.print(0,DEC);
  else
  Serial.print(pwm,DEC);
  Serial.print("      ");

  Serial.print("Current (panel) = ");
  Serial.print(sol_amps);
  Serial.print("      ");

  Serial.print("Voltage (panel) = ");
  Serial.print(sol_volts);
  Serial.print("      ");

  Serial.print("Power (panel) = ");
  Serial.print(sol_volts);
  Serial.print("      ");

  Serial.print("Battery Voltage = ");
  Serial.print(bat_volts);
  Serial.print("      ");

  Serial.print("\n\r");
  //delay(1000);
}

//-------------------------------------------------------------------------------------------------
//---------------------------------Led Indication--------------------------------------------------
//-------------------------------------------------------------------------------------------------
// light an individual LED
// we remember which one was on before in last_lit and turn it off if different
void light_led(char pin)
{
  static char last_lit;
  if (last_lit == pin)
      return;
  if (last_lit != 0)
      digitalWrite(last_lit, LOW);
  digitalWrite(pin, HIGH);
  last_lit = pin;
}
// display the current state via LED as follows:
// YELLOW means overvoltage (over 14.1 volts)
// RED means undervoltage (under 11.9 volts)
// GREEN is between 11.9 and 14.1 volts
void led_output(void)
{
  static char last_lit;
  if(bat_volts > 14.1 )
      light_led(LED_YELLOW);
  else if(bat_volts > 11.9)
      light_led(LED_GREEN);
  else
      light_led(LED_RED);
}

//------------------------------------------------------------------------------------------------------
//-------------------------- LCD DISPLAY --------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
void lcd_display()
{
  static bool current_backlight_state = -1;
  back_light_pin_State = digitalRead(BACK_LIGHT_PIN);
  if (current_backlight_state != back_light_pin_State) {
    current_backlight_state = back_light_pin_State;
    if (back_light_pin_State == HIGH)
      lcd.backlight();// finish with backlight on
    else
      lcd.noBacklight();
  }

  if (back_light_pin_State == HIGH)
  {
    time = millis();                        // If any of the buttons are pressed, save the time in millis to "time"
  }
 
 lcd.setCursor(0, 1);
 lcd.print(sol_volts);
 lcd.print("V ");
 lcd.setCursor(0, 2);
 lcd.print(sol_amps);
 lcd.print("A");  
 lcd.setCursor(0, 3);
 lcd.print(sol_watts);
 lcd.print("W "); 
 lcd.setCursor(8, 1);
 lcd.print(bat_volts);
 lcd.setCursor(8,2);

 if (charger_state == on) 
 lcd.print("on   ");
 else if (charger_state == off)
 lcd.print("off  ");
 else if (charger_state == bulk)
 lcd.print("bulk ");
 else if (charger_state == bat_float)
 {
 lcd.print("     ");
 lcd.setCursor(8,2);
 lcd.print("float");
 }
 
 //-----------------------------------------------------------
 //--------------------Battery State Of Charge ---------------
 //-----------------------------------------------------------
 int pct = 100.0*(bat_volts - 11.3)/(12.7 - 11.3);
 if (pct < 0)
     pct = 0;
 else if (pct > 100)
     pct = 100;

 lcd.setCursor(12,0);
 lcd.print((char)(pct*5/100));

 lcd.setCursor(8,3);
 pct = pct - (pct%10);
 lcd.print(pct);
 lcd.print("%  ");
 
//--------------------------------------------------------------------- 
//------------------Duty Cycle-----------------------------------------
//---------------------------------------------------------------------
 lcd.setCursor(15,0);
 lcd.print("PWM");
 lcd.setCursor(19,0);
 lcd.write(PWM_ICON);
 lcd.setCursor(15,1);
 lcd.print("   ");
 lcd.setCursor(15,1);
 if( charger_state == off)
 lcd.print(0);
 else
 lcd.print(pwm); 
 lcd.print("% ");
 //----------------------------------------------------------------------
 //------------------------Load Status-----------------------------------
 //----------------------------------------------------------------------
 lcd.setCursor(15,2);
 lcd.print("Load");
 lcd.setCursor(15,3);
 if (load_status)
 {
    lcd.print("On  ");
 }
 else
 {
   lcd.print("Off ");
 } 
 spinner();
 backLight_timer();                      // call the backlight timer function in every loop 
}

void backLight_timer(){
  if((millis() - time) <= 15000)         // if it's been less than the 15 secs, turn the backlight on
      lcd.backlight();                   // finish with backlight on  
  else 
      lcd.noBacklight();                 // if it's been more than 15 secs, turn the backlight off
}
void spinner(void) {
  static int cspinner;
  static char spinner_chars[] = { '*','*', '*', ' ', ' '};
  cspinner++;
  lcd.print(spinner_chars[cspinner%sizeof(spinner_chars)]);
}

//-------------------------------------------------------------------------
//----------------------------- ESP8266 WiFi ------------------------------
//--------------------------Plot System data on thingspeak.com-------------
//-------------------------------------------------------------------------
void wifi_datalog()
{
  // thingspeak needs 15 sec delay between updates
  static int lastlogged;
  if ( seconds - lastlogged < 16 )
      return;
  lastlogged = seconds;
 // convert to string
  char buf[16];
  String strTemp = dtostrf( sol_volts, 4, 1, buf);
  
  Serial.println(strTemp);
  
  // TCP connection
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += "184.106.153.149"; // api.thingspeak.com
  cmd += "\",80";
  ser.println(cmd);
   
  if(ser.find((char *)"Error")){
    Serial.println("AT+CIPSTART error");
    return;
  }
  
  // prepare GET string
  String getStr = "GET /update?api_key=";
  getStr += apiKey;
  getStr +="&field1=";
  getStr += String(strTemp);
  getStr += "\r\n\r\n";

  // send data length
  cmd = "AT+CIPSEND=";
  cmd += String(getStr.length());
  ser.println(cmd);

  if(ser.find((char *)">")){
    ser.print(getStr);
  }
  else{
    ser.println("AT+CIPCLOSE");
    // alert user
    Serial.println("AT+CIPCLOSE");
  } 
}
Bitbucket
https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads

Comments

Similar projects you might like

Hacking My Toaster

Project tutorial by javier muñoz sáez

  • 461 views
  • 5 comments
  • 11 respects

Rickroll Box

Project showcase by slagestee

  • 1,454 views
  • 0 comments
  • 6 respects

Gyroscope Fun with NeoPixel Ring

Project tutorial by danionescu

  • 2,174 views
  • 0 comments
  • 8 respects

START: A STandalone ARduino Terminal

Project tutorial by Alessio Villa

  • 1,475 views
  • 0 comments
  • 6 respects

Music Reactive LED Strip

Project showcase by buzzandy

  • 499 views
  • 2 comments
  • 10 respects

Pavlov's Cat

Project tutorial by Arduino

  • 943 views
  • 0 comments
  • 2 respects
Add projectSign up / Login