#include <SPI.h>
#include<EEPROM.h>
#include "RTClib.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//#include <SoftwareSerial.h>
//SoftwareSerial myserial(10,11); // RX, TX
LiquidCrystal_I2C lcd(0x27, 20, 4);
RTC_DS3231 rtc;
#define AVG_NUM 10
#define offsetVoltage 2.5 // for ACS712 sensor
#define Sensitivity 0.066 // 185mV/A for ACS712-5A variant
#define solar_volt_sense 7 // defining the analog pin A0 to read solar panel Voltage
#define bat_volt_sense 1 //defining the analog pin A1 to read battery voltage
#define solar_current_sense 2 //defining the Analog pin A2 to measure load current
#define load_current_sense 3
#define temp_sense 6
#define pwm_pin 3 // defining digital pin D9 to drive the main MOSFET Q1 @ 1KHz
#define load_pin 2
#define gradDetect 26.3157894373 // Gradient for SoC Detect
#define Vb_FULL_SCALE 13.8 //SoC 100% Baterai 13.8 Volt
#define BULK_CHRARGE_SP 14.4
#define FLOAT_CHARGE_SP 13.5
#define Charge_Restart_SP 13.2
#define MIN_SOLAR_VOLT 10
#define LVD 11.5
#define LVR 12.5
#define ABSORPTION_LIMIT 3600000 // 1 hour in milliseconds
#define NIGHT_TIME 3600000 // 1 hour in milliseconds
#define CHARGER_RESTART_TIME 600000 // 10 mins in milliseconds
#define EVENING_TIME 300000 // 5mins in milliseconds
#define MORNING_TIME 180000 // 3mins in milliseconds
const int stsp= A0;
float pwm_duty=0; // PWM Duty Cycle (0 to 255)
float bulk_charge_sp=0; // Bulk charging set point
float float_charge_sp=0; // Float charging set point
int load_status; // 0-off, 1- on
const int bat_type = 1; //Flooded=0,AGM=1
const float BETA = 3950;
float solar_volt=0; // solar panel voltage
float solar_current=0;
float bat_volt=0; // solar panel voltage
float load_current=0;
int celsius;
int temp_change=0;
float temp_val=0;
float solar_watts=0;
float load_watts=0;
float load_wattHours=0;
float solar_wattHours=0;
float bat_volt_k_1 =0;
float SoC_Detect = 0;
float temp_SoC_Detect =0;
float SoCCorr_k_1 =0;
float SoC_VB=0;
int SOC_VB_Temp =0;
float ur =0;
int chargestate; //0 off, 1 on
int jam, menit,detik;
int DI0_State,DI1_State,DI2_State; //State Relay R1,R2,R3 0 Off, 1 On
enum charger_state {off, bulk,absorption,Float} charger_state ;
unsigned long last_time=0;
unsigned long current_time=0;
unsigned long absorption_time; // to keep track of today's time in absorption state
unsigned long charger_millis; // to keep track of time for charger
unsigned long restart_time;
unsigned long load_millis;
int mode =1;
int hrsstate;
double Setpoint, Input, Output;
//====================== PID Parameter Configuration ==============
float err;
float sumerr;
float deverr;
float lasterr = 0;
float kp, ki, kd;
//=================================================================
float PID(float Acuann, float Inputt)
{
kp = 1;ki = 0;kd = 0;
err = Acuann - Inputt;
sumerr += err;
deverr = err - lasterr;
lasterr = err;
return (kp*err)+(ki*sumerr)+(kd*deverr);
}
//====================== Mode Timer Control Watering Parameter ==============
int hrs1 = 7; //Hrs SP Timer Morning at 7 AM
int Min1 = 0; // Mnt SP Timer Morning at 0 AM
int hrs2 = 12; //Hrs SP Timer Afternoon at 12 PM
int Min2 = 0; // Mnt SP Timer Afternoon at 0 PM
int hrs3 = 19; // //Hrs SP Timer Evening at 19 PM
int Min3 = 0; // Mnt SP Timer Evening at 0 PM
int add_hrs1 = 5;
int add_min1 = 7;
int add_hrs2 = 9;
int add_min2 = 11;
int add_hrs3 = 13;
int add_min3 = 15;
bool min_flag1 = true;
bool hrs_flag1 = true;
bool min_flag2 = true;
bool hrs_flag2 = true;
bool min_flag3 = true;
bool hrs_flag3 = true;
//===================================================================
//====================== Water Level Control Parameter ==============
int SPup = 100; //Upper Limit Water Level Setpoint In Cm
int SPDown = 15; //Lower Limit Water Level Setpoint In Cm
unsigned int check_val = 50;
int add_chk = 0;
int add_SPup = 1;
int add_SPDown = 3;
int WL;
String dataIn = {""};
String dt[10] = {""};
String dt1[10] = {""};
int i;
boolean parsing = false;
int j = 0;
char inChar;
int datain1;
//===================================================================
void writeIntIntoEEPROM(int address, int number)
{
EEPROM.write(address, number >> 8);
EEPROM.write(address + 1, number & 0xFF);
}
int readIntFromEEPROM(int address)
{
return (EEPROM.read(address) << 8) + EEPROM.read(address + 1);
}
/////////////////////Push Button Parameter//////////////////////////////
int SW,Up,Down,pumpstate;
int lockSW=0,lockUp=0,lockDown=0;
int dis,sub=0,cc=0;
bool RUN = true;
bool SPup_flag = true;
bool SPDown_flag = true;
///////////////////////DECLARATION OF ALL BIT MAP ARRAY FOR FONTS////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------------------------------------------
byte solar[8] = //icon for solar panel
{
0b11111,0b10101,0b11111,0b10101,0b11111,0b10101,0b11111,0b00000
};
byte battery[8] = //icon for battery
{
0b01110,0b11011,0b10001,0b10001,0b10001,0b10001,0b10001,0b11111
};
byte charge[8] = // icon for battery charge
{
0b01010,0b11111,0b10001,0b10001,0b10001,0b01110,0b00100,0b00100,
};
byte not_charge[8]=
{
0b00000,0b10001,0b01010,0b00100,0b01010,0b10001,0b00000,0b00000,
};
byte temp[8] = //icon for termometer
{
0b00100,0b01010,0b01010,0b01110,0b01110,0b11111,0b11111,0b01110
};
byte energy[8] = // icon for power
{
0b00010,0b00100,0b01000,0b11111,0b00010,0b00100,0b01000,0b00000
};
//**************SoC Detect*************************************************
float SOC_Detect()
{
SoC_Detect = (gradDetect*(bat_volt - 10.0));
return SoC_Detect;
}
void SoC_Estimator(float SOCCOOR_K_1, float BAT_VOLT_K_1, float BAT_VOLT,float *SOC_VB)
{
*SOC_VB = SOCCOOR_K_1 + ((BAT_VOLT - BAT_VOLT_K_1)/(Vb_FULL_SCALE - BAT_VOLT_K_1 )*(100 - SOCCOOR_K_1));
}
void INIT(int Disp,int Pumpstate,int m1)
{
//**********************Raw 0 (SOLAR INDICATOR)***********************
SPup = readIntFromEEPROM(add_SPup);
SPDown = readIntFromEEPROM(add_SPDown);
hrs1 = readIntFromEEPROM(add_hrs1);
Min1 = readIntFromEEPROM(add_min1);
hrs2 = readIntFromEEPROM(add_hrs2);
Min2 = readIntFromEEPROM(add_min2);
hrs3 = readIntFromEEPROM(add_hrs3);
Min3 = readIntFromEEPROM(add_min3);
lcd.createChar(0, solar);
lcd.setCursor(0, 0); //(Kolom, Baris)
lcd.write(0);
lcd.setCursor(2, 0); //(Kolom, Baris)
lcd.print(solar_volt,1);
lcd.setCursor(6, 0); //(Kolom, Baris)
lcd.print('V');
lcd.setCursor(8, 0); //(Kolom, Baris)
lcd.print(solar_current,1);
lcd.setCursor(12, 0); //(Kolom, Baris)
lcd.print('A');
lcd.setCursor(14, 0); //(Kolom, Baris)
lcd.print(solar_watts,1);
lcd.setCursor(19, 0); //(Kolom, Baris)
lcd.print('W');
//*******************Raw 1 (BATTERAI INDICATOR)********************************************
lcd.createChar(1, battery);
lcd.setCursor(0, 1); //(Kolom, Baris)
lcd.write(1);
lcd.setCursor(2, 1); //(Kolom, Baris)
lcd.print(bat_volt,1);
lcd.setCursor(6, 1); //(Kolom, Baris)
lcd.print('V');
lcd.createChar(4, temp);
lcd.setCursor(8, 1); //(Kolom, Baris)
lcd.write(4);
lcd.setCursor(9, 1); //(Kolom, Baris)
lcd.print(celsius,1);
lcd.write(0b11011111);
lcd.setCursor(12, 1); //(Kolom, Baris)
lcd.print('C');
if(chargestate == 1)
{
lcd.createChar(2, charge);
lcd.setCursor(14, 1); //(Kolom, Baris)
lcd.write(2);
lcd.setCursor(15, 1); //(Kolom, Baris)
lcd.print(' ');
}
else if(chargestate == 0)
{
lcd.createChar(2, charge);
lcd.setCursor(14, 1); //(Kolom, Baris)
lcd.write(2);
lcd.createChar(3, not_charge);
lcd.setCursor(15, 1); //(Kolom, Baris)
lcd.write(3);
}
lcd.setCursor(17, 1); //(Kolom, Baris)
lcd.print(SOC_VB_Temp);
lcd.setCursor(19, 1); //(Kolom, Baris)
lcd.print('%');
//**********************RAW 3 (LOAD INDICAtOR)***********************************
lcd.setCursor(0, 2); //(Kolom, Baris)
lcd.print('L');
lcd.setCursor(2, 2); //(Kolom, Baris)
lcd.print(load_current,1);
lcd.setCursor(6, 2); //(Kolom, Baris)
lcd.print('A');
lcd.setCursor(8, 2); //(Kolom, Baris)
lcd.print(load_watts,1);
lcd.setCursor(13, 2); //(Kolom, Baris)
lcd.print('W');
lcd.setCursor(15, 2); //(Kolom, Baris)
switch(m1)
{
case 0: if(load_status == 0)
{
lcd.print("OFF"); //Load State
}
else
{
lcd.print("ON "); //Load State
}
break;
case 1: if(load_status == 0)
{
lcd.print(load_status); //Load State
}
else
{
lcd.print(load_status); //Load State
}
lcd.setCursor(16, 2); //(Kolom, Baris)
lcd.print(DI0_State);
lcd.print(DI1_State);
lcd.print(DI2_State);
break;
}
//**************Raw 3 (Listrik Output-Solar Wh & Load Wh)********************
if(Disp == 0)
{
lcd.createChar(5, energy);
lcd.setCursor(0, 3); //(Kolom, Baris)
lcd.write(5);
lcd.setCursor(2, 3); //(Kolom, Baris)
lcd.print(solar_wattHours,1);
lcd.setCursor(6, 3); //(Kolom, Baris)
lcd.print("Wh");
lcd.setCursor(13, 3); //(Kolom, Baris)
lcd.print(load_wattHours,1);
lcd.setCursor(17, 3); //(Kolom, Baris)
lcd.print("Wh"); //Load State
}
else if(Disp == 1)
{
if(Pumpstate == 0)
{
lcd.setCursor(0, 3); //(Kolom, Baris)
lcd.print("PUMP: ");
lcd.print("OFF");
}
else
{
lcd.setCursor(0, 3); //(Kolom, Baris)
lcd.print("PUMP: ");
lcd.print("ON ");
}
lcd.setCursor(19, 3); //(Kolom, Baris)
lcd.print("1");
}
else if(Disp == 2)
{
lcd.setCursor(0, 3); //(Kolom, Baris)
lcd.print('A');
lcd.setCursor(2, 3); //(Kolom, Baris)
lcd.print('(');
lcd.setCursor(3, 3); //(Kolom, Baris)
lcd.print(SPup);
lcd.setCursor(6, 3); //(Kolom, Baris)
lcd.print(',');
lcd.setCursor(7, 3); //(Kolom, Baris)
lcd.print(SPDown);
lcd.setCursor(9, 3); //(Kolom, Baris)
lcd.print(',');
lcd.setCursor(10, 3); //(Kolom, Baris)
lcd.print(WL);
lcd.print(')');
lcd.print("Cm");
lcd.setCursor(19, 3); //(Kolom, Baris)
lcd.print("2");
}
else if(Disp == 3)
{
lcd.setCursor(0, 3); //(Kolom, Baris)
lcd.print(hrsstate);
lcd.setCursor(2, 3); //(Kolom, Baris)
lcd.print(hrs1);
lcd.print(':');
lcd.print(hrs2);
lcd.print(':');
lcd.print(hrs3);
lcd.print(" ");
lcd.print(jam);
lcd.print(":");
lcd.print(menit);
lcd.print(":");
lcd.print(detik);
lcd.setCursor(19, 3); //(Kolom, Baris)
lcd.print("3");
}
SPup_flag =true;
SPDown_flag = true;
min_flag1 = true;
hrs_flag1 = true;
min_flag2 = true;
hrs_flag2 = true;
min_flag3 = true;
hrs_flag3 = true;
delay(500);
}
void Manual_Mode()
{
if (digitalRead(stsp) == LOW)
{
delay(250);
RUN = true;
while (RUN)
{
if (digitalRead(stsp) == LOW)
{
delay(1000);
if (digitalRead(stsp) == LOW)
{
digitalWrite(4, LOW);
pumpstate = 0;
RUN = false;
break;
}
}
digitalWrite(4, HIGH);
pumpstate = 1;
Run_charge();
INIT(1,pumpstate,0);
}
}
}
void Automatic_Mode() //Mode Water Level Control
{
if (digitalRead(stsp) == LOW)
{
delay(250);
RUN = true;
while (RUN)
{
if (digitalRead(stsp) == LOW)
{
delay(1000);
if (digitalRead(stsp) == LOW)
{
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
DI0_State = 0;
DI1_State = 0;
DI2_State = 0;
pumpstate = 0;
RUN = false;
break;
}
}
if(WL>=SPup)
{
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, HIGH);
DI0_State = 0;
DI1_State = 0;
DI2_State = 1;
}
else if(WL <= SPDown)
{
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, LOW);
DI0_State = 1;
DI1_State = 1;
DI2_State = 0;
}
pumpstate = 0;
Run_charge();
INIT(2,pumpstate,1);
}
}
}
void Timer_Mode()
{
if (digitalRead(stsp) == LOW)
{
delay(250);
RUN = true;
while (RUN)
{
delay(1000);
if (digitalRead(stsp) == LOW)
{
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
DI0_State = 0;
DI1_State = 0;
DI2_State = 0;
pumpstate = 0;
RUN = false;
break;
}
if((jam == hrs1 && menit == Min1) || (jam == hrs2 && menit == Min2) || (jam == hrs3 && menit == Min3))
{
digitalWrite(4, LOW);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
DI0_State = 0;
DI1_State = 1;
DI2_State = 1;
}
else
{
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
DI0_State = 0;
DI1_State = 0;
DI2_State = 0;
}
if(jam == hrs1)
{
hrsstate=1;
}
else if(jam==hrs2)
{
hrsstate=2;
}
else if(jam==hrs3)
{
hrsstate=3;
}
else
{
hrsstate =0;
}
pumpstate = 0;
Run_charge();
INIT(2,pumpstate,1);
}
}
}
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
}
void Initial_setpoint()
{
solar_volt= read_adc(solar_volt_sense)*0.0048828*(37.5/7.5);
solar_current = ((read_adc(solar_current_sense)*0.0048828 - offsetVoltage)/ Sensitivity );
bat_volt= read_adc(bat_volt_sense)*0.0048828*(37.5/7.5);
load_current = ((read_adc(load_current_sense)*0.0048828 - offsetVoltage)/ Sensitivity );
solar_watts = solar_current * solar_volt;
load_watts = load_current * bat_volt; //load Watts now
temp_change =celsius-25.0; // 25deg cel is taken as standard room temperature ( STC)
// for floaded battery
if (bat_type == 0)
{
bulk_charge_sp =BULK_CHRARGE_SP-(0.020*temp_change) ;
float_charge_sp=FLOAT_CHARGE_SP-(0.020*temp_change) ;
}
// for AGM battery // set point is lowered to avoid excess gassing
else
{
bulk_charge_sp =(BULK_CHRARGE_SP-0.2)-(0.020*temp_change) ;
float_charge_sp=(FLOAT_CHARGE_SP-0.2)-(0.020*temp_change) ;
}
}
void Run_charge()
{
solar_volt= read_adc(solar_volt_sense)*0.0048828*(37.5/7.5);
solar_current = ((read_adc(solar_current_sense)*0.0048828 - offsetVoltage)/ Sensitivity );
bat_volt= read_adc(bat_volt_sense)*0.0048828*(37.5/7.5);
load_current = ((read_adc(load_current_sense)*0.0048828 - offsetVoltage)/ Sensitivity );
solar_watts = solar_current * solar_volt;
load_watts = load_current * bat_volt; //load Watts now
last_time = current_time;
current_time = millis();
load_wattHours = load_wattHours + load_watts*(( current_time -last_time) /3600000.0) ; // calculating energy in Watt-Hour
solar_wattHours = solar_wattHours+ solar_watts*(( current_time -last_time) /3600000.0) ; // calculating energy in Watt-Hour
if (solar_current <0)
{
solar_current = 0;
}
if(load_current < 0)
{
load_current = 0;
}
temp_SoC_Detect = SOC_Detect();
if(temp_SoC_Detect < 0)
{
temp_SoC_Detect = 0;
}
current_time = millis();
if(current_time - last_time >= 1000)
{
bat_volt_k_1 = bat_volt;
SoCCorr_k_1 = temp_SoC_Detect;
last_time = current_time;
}
SoC_Estimator(SoCCorr_k_1,bat_volt_k_1,bat_volt,&SoC_VB);
SOC_VB_Temp = (int) SoC_VB;
if(SOC_VB_Temp > 99)
{
SOC_VB_Temp = 99;
}
if(SOC_VB_Temp < 0)
{
SOC_VB_Temp = 0;
}
temp_val = analogRead(temp_sense);
celsius = 1 / (log(1 / (1023. / temp_val - 1)) / BETA + 1.0 / 298.15) - 273.15;
while ((celsius > 50 ) || (celsius < -20 ) || (bat_volt < 9)) // If the temperature is beyond the permisible limit or battery is damaged/disconnected
{
bat_volt= read_adc(bat_volt_sense)*0.0048828*(37.5/7.5);
lcd.createChar(1, battery);
lcd.setCursor(0, 1); //(Kolom, Baris)
lcd.write(1);
lcd.setCursor(2, 1); //(Kolom, Baris)
lcd.print(bat_volt,1);
lcd.setCursor(6, 1); //(Kolom, Baris)
lcd.print('V');
Serial.println(" Error ");
digitalWrite(load_status, LOW);
pwm_duty =0;
analogWrite(pwm_pin, pwm_duty);
}
temp_change =celsius-25.0; // 25deg cel is taken as standard room temperature ( STC)
// for floaded battery
if (bat_type == 0)
{
bulk_charge_sp =BULK_CHRARGE_SP-(0.020*temp_change) ;
float_charge_sp=FLOAT_CHARGE_SP-(0.020*temp_change) ;
}
// for AGM battery // set point is lowered to avoid excess gassing
else
{
bulk_charge_sp =(BULK_CHRARGE_SP-0.2)-(0.020*temp_change) ;
float_charge_sp=(FLOAT_CHARGE_SP-0.2)-(0.020*temp_change) ;
}
switch(charger_state)
{
case off:
if ((bat_volt < float_charge_sp) && (solar_volt > (bat_volt + 0.5)))
{
charger_millis = millis() ;
charger_state = bulk ;
}
else if((bat_volt > float_charge_sp) && (solar_volt > (bat_volt + 0.5)) && (absorption_time > ABSORPTION_LIMIT))
{
charger_millis = millis() ;
restart_time = 0 ;
charger_state = Float ;
}
else
{
chargestate = 0;
absorption_time = 0;
pwm_duty = 0;
analogWrite(pwm_pin, pwm_duty); //generate PWM from D3 @ 0% duty // Shut down the charger
}
break; // end of case off condition
/////////////////////////////////// STAGE-1 (BULK CHARGING)//////////////////////////////////////////////////////
// During this stage the MOSFET is fully on by setting the duty cycle to 100%
// Constant Current Charging
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
case bulk:
if (solar_volt < bat_volt)
{
charger_millis = millis() ;
charger_state = off ;
}
else if ((bat_volt > bulk_charge_sp) && ( solar_volt > ( bat_volt + 0.5)) && (absorption_time < ABSORPTION_LIMIT))
{
charger_millis = millis() ;
charger_state = absorption ;
}
else if ((bat_volt > float_charge_sp) && (solar_volt > (bat_volt + 0.5)) && (absorption_time > ABSORPTION_LIMIT))
{
charger_millis = millis() ;
restart_time = 0 ;
charger_state = Float ;
}
else
{
chargestate = 1;
pwm_duty = 163.3451957294; //Full Scale PWM Duty for Bulk volt charge
analogWrite(pwm_pin,pwm_duty); //generate PWM from D3 @ 100% duty // MOSFET Q1 is ON
if( bat_volt > bulk_charge_sp )
{
charger_state = absorption ;
}
}
break; // end of case bulk condition
/////////////////////////////////// STAGE-2 (ABSORPTION CHARGING)//////////////////////////////////////////////////////
// During this stage the MOSFET is partially on by setting the duty cycle to between 0% and 100%
// Constant voltage
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
case absorption:
if(solar_volt < bat_volt)
{
charger_millis = millis() ;
charger_state = off ;
}
else if(( bat_volt > float_charge_sp) && (solar_volt > (bat_volt + 0.5)) && (absorption_time > ABSORPTION_LIMIT))
{
charger_millis = millis() ;
charger_state = Float ;
}
else
{
// increment absorption timer and test for duration in absorption state
absorption_time = absorption_time + millis() - charger_millis ;
charger_millis = millis();
chargestate =1;
Input = solar_volt;
Setpoint = bulk_charge_sp;
Output = PID(Setpoint,Input);
ur=Input + Output;
pwm_duty = 11.3434163701*ur; // Output = kp * error + ki * errSum + kd * dErr
if(pwm_duty < 0)
{
pwm_duty=0;
chargestate =0;
}
if(pwm_duty > 163.3451957294)
{
pwm_duty=163.3451957294;
chargestate =1;
}
analogWrite(pwm_pin, pwm_duty);
}
break; // end of case absorption condition
/////////////////////////////////// STAGE-3 (FLOAT CHARGING)//////////////////////////////////////////////////////
// During this stage the MOSFET is partially on by setting the duty cycle between 0% and 100%
// Constant Voltage Charging
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
case Float:
if (solar_volt < bat_volt)
{
charger_millis = millis() ;
charger_state = off ;
}
else if((bat_volt < Charge_Restart_SP) && (solar_volt > (bat_volt + 0.5)) && (restart_time > CHARGER_RESTART_TIME))
{
charger_millis = millis() ;
charger_state = bulk ;
}
else if((bat_volt >float_charge_sp) && (solar_volt > (bat_volt + 0.5)) && (absorption_time < ABSORPTION_LIMIT))
{
charger_millis = millis() ;
charger_state = absorption ;
}
else
{
if (bat_volt > float_charge_sp)
{
pwm_duty--;
if(pwm_duty <0)
{
pwm_duty=0;
chargestate =0;
}
analogWrite(pwm_pin, pwm_duty);
}
else
{
chargestate =1;
pwm_duty = 12.75; // setting duty cycle = 5% for trickle charge
analogWrite(pwm_pin, pwm_duty); //generate PWM from D3 @ 5% duty // Q1 is driving @ 5% duty cycle
}
if(bat_volt < Charge_Restart_SP)
{
restart_time = restart_time + millis() - charger_millis ;
charger_millis = millis();
}
}
break; // end of case float condition
}
if((bat_volt < LVD) || load_watts > 100)
{
load_status = 0;
digitalWrite(load_pin,LOW);
}
else
{
load_status = 1;
digitalWrite(load_pin,HIGH);
}
DateTime now = rtc.now();
jam = now.hour();
menit = now.minute();
detik = now.second();
Serial.print(solar_volt);
Serial.print("; ");
Serial.print(solar_current);
Serial.print("; ");
Serial.print(bat_volt);
Serial.print("; ");
Serial.print(load_current);
Serial.print("; ");
Serial.print(celsius);
Serial.print("; ");
// Serial.print(bat_volt_k_1);
// Serial.print("; ");
// Serial.print(temp_SoC_Detect);
// Serial.print("; ");
// Serial.print(SoCCorr_k_1);
// Serial.print("; ");
Serial.print(SOC_VB_Temp);
Serial.print("; ");
Serial.print(absorption_time);
Serial.print("; ");
Serial.print(charger_state);
Serial.print("; ");
Serial.print(Output);
Serial.print("; ");
Serial.print(pwm_duty);
Serial.print("; ");
Serial.print(chargestate);
Serial.print("; ");
Serial.print(String() + jam + ":" + menit + ":" + detik);
Serial.print("; ");
Serial.print(pwm_duty);
Serial.print("\n");
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
//myserial.begin(9600);
pinMode(pwm_pin,OUTPUT);
pinMode(load_pin,OUTPUT);
lcd.init();
lcd.backlight();
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}
pinMode(4,OUTPUT); //R1 (DO1) Pump
pinMode(5,OUTPUT); //R2 (DO2)
pinMode(6,OUTPUT); //R3 (DO3)
pinMode(7,INPUT_PULLUP); //Set (Menu setting Parameter)
pinMode(8,INPUT_PULLUP); //Up
pinMode(9,INPUT_PULLUP); // Down
pinMode(12,INPUT_PULLUP); // Switch Tampilan Display
pinMode(stsp,INPUT_PULLUP); //Start Stop Manual Pompa
lcd.setCursor(0,0); lcd.print("*******************");
lcd.setCursor(0,1); lcd.print(" SOLAR PUMP ");
lcd.setCursor(0,2); lcd.print(" CONTROLLER ");
lcd.setCursor(0,3); lcd.print("*******************");
delay(1000);
lcd.clear();
Initial_setpoint();
temp_val = analogRead(temp_sense);
celsius = 1 / (log(1 / (1023. / temp_val - 1)) / BETA + 1.0 / 298.15) - 273.15;
while ((celsius > 50 ) || (celsius < -20 ) || (bat_volt < 9)) // If the temperature is beyond the permisible limit or battery is damaged/disconnected
{
lcd.setCursor(2,9);
lcd.print(" ERROR ");
Serial.println(" Error ");
}
charger_state = off; // start the charger from off
charger_millis = millis() ; // initialise the local clock
load_millis =millis();
if (EEPROM.read(add_chk) != check_val)
{
writeIntIntoEEPROM(add_chk,check_val);
writeIntIntoEEPROM(add_SPup,SPup);
writeIntIntoEEPROM(add_SPDown,SPDown);
writeIntIntoEEPROM(add_hrs1,hrs1);
writeIntIntoEEPROM(add_min1,Min1);
writeIntIntoEEPROM(add_hrs2,hrs2);
writeIntIntoEEPROM(add_min2,Min2);
writeIntIntoEEPROM(add_hrs3,hrs3);
writeIntIntoEEPROM(add_min3,Min3);
}
else
{
SPup = readIntFromEEPROM(add_SPup);
SPDown = readIntFromEEPROM(add_SPDown);
hrs1 = readIntFromEEPROM(add_hrs1);
Min1 = readIntFromEEPROM(add_min1);
hrs2 = readIntFromEEPROM(add_hrs2);
Min2 = readIntFromEEPROM(add_min2);
hrs3 = readIntFromEEPROM(add_hrs3);
Min3 = readIntFromEEPROM(add_min3);
}
lcd.clear();
INIT(0,pumpstate,0);
// Serial.print("absorption_time: ");
// Serial.print(absorption_time);
// Serial.print("\n");
}
void loop() {
// put your main code here, to run repeatedly:
if (digitalRead(7) == LOW)
{
delay(500);
while (SPup_flag)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET UPPER: ");
lcd.print(SPup);
delay(100);
if (digitalRead(8) == LOW)
{
SPup = SPup + 1;
if (SPup >= 150) SPup = 100;
delay(100);
}
if (digitalRead(9) == LOW)
{
SPup = SPup - 1;
if (SPup <= -1) SPup = 0;
delay(100);
}
if (digitalRead(7) == LOW)
{
SPup_flag = false;
delay(250);
}
}
while (SPDown_flag)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET LOWER: ");
lcd.print(SPDown);
delay(100);
if (digitalRead(8) == LOW)
{
SPDown = SPDown + 1;
if (SPDown > 30) SPDown = 15;
delay(100);
}
if (digitalRead(9) == LOW)
{
SPDown = SPDown - 1;
if (SPDown <= -1) SPDown = 0;
delay(100);
}
if (digitalRead(7) == LOW)
{
SPDown_flag = false;
delay(250);
}
}
while (hrs_flag1)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET HRS1: ");
lcd.print(hrs1);
delay(100);
if (digitalRead(8) == LOW)
{
hrs1 = hrs1 + 1;
if (hrs1 > 23) hrs1 = 7;
delay(100);
}
if (digitalRead(9) == LOW)
{
hrs1 = hrs1 - 1;
if (hrs1 <= -1) hrs1 = 0;
delay(100);
}
if (digitalRead(7) == LOW)
{
hrs_flag1 = false;
delay(250);
}
}
while (min_flag1)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET MIN1: ");
lcd.print(Min1);
delay(100);
if (digitalRead(8) == LOW)
{
Min1 = Min1 + 1;
if (Min1 > 60) Min1 = 0;
delay(100);
}
if (digitalRead(9) == LOW)
{
Min1 = Min1 - 1;
if (Min1 <= -1) Min1 = 0;
delay(100);
}
if (digitalRead(7) == LOW)
{
min_flag1 = false;
delay(250);
}
}
while (hrs_flag2)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET HRS2: ");
lcd.print(hrs2);
delay(100);
if (digitalRead(8) == LOW)
{
hrs2 = hrs2 + 1;
if (hrs2 > 23) hrs2 = 7;
delay(100);
}
if (digitalRead(9) == LOW)
{
hrs2 = hrs2 - 1;
if (hrs2 <= -1) hrs2 = 0;
delay(100);
}
if (digitalRead(7) == LOW)
{
hrs_flag2= false;
delay(250);
}
}
while (min_flag2)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET MIN2: ");
lcd.print(Min2);
delay(100);
if (digitalRead(8) == LOW)
{
Min2 = Min2 + 1;
if (Min2 > 60) Min2 = 0;
delay(100);
}
if (digitalRead(9) == LOW)
{
Min2 = Min2 - 1;
if (Min2 <= -1) Min2 = 0;
delay(100);
}
if (digitalRead(7) == LOW)
{
min_flag2 = false;
delay(250);
}
}
while (hrs_flag3)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET HRS3: ");
lcd.print(hrs3);
delay(100);
if (digitalRead(8) == LOW)
{
hrs3 = hrs3 + 1;
if (hrs3 > 23) hrs3 = 7;
delay(100);
}
if (digitalRead(9) == LOW)
{
hrs3 = hrs3 - 1;
if (hrs3 <= -1) hrs3 = 0;
delay(100);
}
if (digitalRead(7) == LOW)
{
hrs_flag3 = false;
delay(250);
}
}
while (min_flag3)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET MIN3: ");
lcd.print(Min3);
delay(100);
if (digitalRead(8) == LOW)
{
Min3 = Min3 + 1;
if (Min3 > 60) Min3 = 0;
delay(100);
}
if (digitalRead(9) == LOW)
{
Min3 = Min3 - 1;
if (Min3 <= -1) Min3 = 0;
delay(100);
}
if (digitalRead(7) == LOW)
{
min_flag3 = false;
delay(250);
}
}
if (SPup == 0 && SPDown == 0)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" INVALID LEVEL");
delay(2000);
}
else
{
writeIntIntoEEPROM(add_SPup,SPup);
writeIntIntoEEPROM(add_SPDown,SPDown);
}
if (hrs1 == 0 && Min1 == 0)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" INVALID TIME");
delay(2000);
}
else
{
writeIntIntoEEPROM(add_hrs1,hrs1);
writeIntIntoEEPROM(add_min1,Min1);
}
if (hrs2 == 0 && Min2 == 0)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" INVALID TIME");
delay(2000);
}
else
{
writeIntIntoEEPROM(add_hrs2,hrs2);
writeIntIntoEEPROM(add_min2,Min2);
}
if (hrs3 == 0 && Min3 == 0)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" INVALID TIME");
delay(2000);
}
else
{
writeIntIntoEEPROM(add_hrs3,hrs3);
writeIntIntoEEPROM(add_min3,Min3);
}
Run_charge();
INIT(0,pumpstate,0);
dis=0;
}
SW = digitalRead(12);
if (SW==0 && lockSW==0){lockSW=1;}
if (SW!=0 && lockSW==1){lockSW=0; dis++;lcd.clear();}
if(dis == 0)
{
Run_charge();
INIT(0,pumpstate,0);
}
else if(dis==1)
{
Run_charge();
INIT(1,pumpstate,0);
Manual_Mode();
}
else if(dis==2)
{
// if (Serial1.available() > 0)
// {
// delay(10);
// char dato = (char)Serial1.read();
// dataIn += dato;
// if(dato == '\n')
// {
// parsing = true;
// }
// }
// if(parsing)
// {
// parsingData();
// parsing = false;
// dataIn = "";
// }
datain1 = 14;
WL = datain1;
Run_charge();
INIT(2,pumpstate,1);
Automatic_Mode();
}
else if(dis==3)
{
Run_charge();
INIT(3,pumpstate,1);
Timer_Mode();
}
if(dis > 3)
{
dis = 0;
}
}
// void parsingData()
// {
// int j=0;
// //kirim data yang telah diterima sebelumnya
// //Serial.print("data masuk : ");
// //Serial.print(dataIn);
// //inisialisasi variabel, (reset isi variabel)
// dt[j]="";
// //proses parsing data
// for(i=1;i<=dataIn.length();i++)
// {
// //pengecekan tiap karakter dengan karakter (#) dan (,)
// if ((dataIn[i] == '$') || (dataIn[i] == ','))
// {
// //increment variabel j, digunakan untuk merubah index array penampung
// j++;
// dt[j]=""; //inisialisasi variabel array dt[j]
// }
// else
// {
// //proses tampung data saat pengecekan karakter selesai.
// dt[j] = dt[j] + dataIn[i];
// }
// }
// datain1 = dt[0].toInt();
// }