Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
AngeloCasi authored Aug 22, 2021
1 parent 3066c4a commit 550141b
Show file tree
Hide file tree
Showing 8 changed files with 1,132 additions and 0 deletions.
86 changes: 86 additions & 0 deletions 2_Read_Sensors.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
void ADC_SetGain(){
if(ADS1015_Mode==true){ //FOR ADS1015 12-BIT ADC MODEL
if(ADC_GainSelect==0){ads.setGain(GAIN_TWOTHIRDS);ADC_BitReso=3.0000;} // Gain: 2/3x Range: +/- 6.144V
else if(ADC_GainSelect==1){ads.setGain(GAIN_ONE);ADC_BitReso=2.0000;} // Gain: 1x Range: +/- 4.096V
else if(ADC_GainSelect==2){ads.setGain(GAIN_TWO);ADC_BitReso=1.0000;} // Gain: 2x Range: +/- 2.048V
}
else{ //FOR ADS1115 16-BIT ADC MODEL
if(ADC_GainSelect==0){ads.setGain(GAIN_TWOTHIRDS);ADC_BitReso= 0.1875;} // Gain: 2/3x Range: +/- 6.144V
else if(ADC_GainSelect==1){ads.setGain(GAIN_ONE);ADC_BitReso= 0.125;} // Gain: 1x Range: +/- 4.096V
else if(ADC_GainSelect==2){ads.setGain(GAIN_TWO);ADC_BitReso= 0.0625;} // Gain: 2x Range: +/- 2.048V
}
}
void resetVariables(){
secondsElapsed = 0;
energySavings = 0;
daysRunning = 0;
timeOn = 0;
}
void Read_Sensors(){

/////////// TEMPERATURE SENSOR /////////////
if(sampleStoreTS<=avgCountTS){ //TEMPERATURE SENSOR - Lite Averaging
TS = TS + analogRead(TempSensor);
sampleStoreTS++;
}
else{
TS = TS/sampleStoreTS;
TSlog = log(9000.00*(4095.00/TS-1.00));
temperature = (1.0/(1.009249522e-03+2.378405444e-04*TSlog+2.019202697e-07*TSlog*TSlog*TSlog))-273.15;
sampleStoreTS = 0;
TS = 0;
}
/////////// VOLTAGE & CURRENT SENSORS /////////////
VSI = 0.0000; //Clear Previous Input Voltage
VSO = 0.0000; //Clear Previous Output Voltage
CSI = 0.0000; //Clear Previous Current

//VOLTAGE SENSOR - Instantenous Averaging
for(int i = 0; i<avgCountVS; i++){
VSI = VSI + ads.computeVolts(ads.readADC_SingleEnded(3));
VSO = VSO + ads.computeVolts(ads.readADC_SingleEnded(1));
}
voltageInput = (VSI/avgCountVS)*39.9000;
voltageOutput = (VSO/avgCountVS)*24.5000;

//CURRENT SENSOR - Instantenous Averaging
for(int i = 0; i<avgCountCS; i++){
CSI = CSI + ads.computeVolts(ads.readADC_SingleEnded(2));
}

CSI_converted = (CSI/avgCountCS)*1.3300;
currentInput = ((CSI_converted-currentMidPoint)*-1)/currentSensV;
if(currentInput<0){currentInput=0.0000;}
if(voltageOutput<=0){currentOutput = 0.0000;}
else{currentOutput = (voltageInput*currentInput)/voltageOutput;}

//////// AUTOMATIC CURRENT SENSOR CALIBRATION ////////
if(buckEnable==0 && FLV==0 && OOV == 0){
currentMidPoint = ((CSI/avgCountCS)*1.3300)-0.003;
}

//POWER COMPUTATION - Through computation
powerInput = voltageInput*currentInput;
powerOutput = voltageInput*currentInput*efficiencyRate;
outputDeviation = (voltageOutput/voltageBatteryMax)*100.000;

//STATE OF CHARGE - Battery Percentage
batteryPercent = ((voltageOutput-voltageBatteryMin)/(voltageBatteryMax-voltageBatteryMin))*101;
if(batteryPercent<0){batteryPercent=0;}
else if(batteryPercent>100){batteryPercent=100;}

//TIME DEPENDENT SENSOR DATA COMPUTATION
currentRoutineMillis = millis();
if(currentRoutineMillis-prevRoutineMillis>=millisRoutineInterval){ //Run routine every millisRoutineInterval (ms)
prevRoutineMillis = currentRoutineMillis; //Store previous time
Wh = Wh+(powerInput/(3600.000*(1000.000/millisRoutineInterval))); //Accumulate and compute energy harvested (3600s*(1000/interval))
kWh = Wh/1000.000;
MWh = Wh/1000000.000;
daysRunning = timeOn/(86400.000*(1000.000/millisRoutineInterval)); //Compute for days running (86400s*(1000/interval))
timeOn++; //Increment time counter
}

//OTHER DATA
secondsElapsed = millis()/1000; //Gets the time in seconds since the was turned on and active
energySavings = electricalPrice*(Wh/1000.0000); //Computes the solar energy saving in terms of money (electricity flag rate)
}
24 changes: 24 additions & 0 deletions 3_Device_Protection.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
void Device_Protection(){
//ERROR COUNTER RESET
currentRoutineMillis = millis();
if(currentErrorMillis-prevErrorMillis>=errorTimeLimit){ //Run routine every millisErrorInterval (ms)
prevErrorMillis = currentErrorMillis; //Store previous time
if(errorCount<errorCountLimit){errorCount=0;} //Reset error count if it is below the limit before x milliseconds
}

//////// PV BACKFLOW CONTROL (INPUT MOSFET) ////////
if(voltageInput>voltageOutput+voltageDropout||MPPT_Mode==0){bypassEnable=1;} //Normal Condition - Turn on Backflow MOSFET (on by default when not in MPPT charger mode)
else{bypassEnable=0;} //Input Undervoltage - Turn off bypass MOSFET and prevent PV Backflow (SS)
digitalWrite(backflow_MOSFET,bypassEnable); //Signal backflow MOSFET GPIO pin

//FAULT DETECTION
ERR=0; //Reset local error counter
if(temperature>temperatureMax) {OTE=1;ERR++;errorCount++;}else{OTE=0;} //OTE - OVERTEMPERATURE: System overheat detected
if(voltageOutput<vInSystemMin&&MPPT_Mode==1) {BNC=1;ERR++;} else{BNC=0;} //BNC - BATTERY NOT CONNECTED (Does not treat BNC as error when not under MPPT mode) //Do not treat BNC as error when not under PPWM mode
if(currentInput>currentInAbsolute) {IOC=1;ERR++;errorCount++;}else{IOC=0;} //IOC - INPUT OVERCURRENT: Input current has reached absolute limit
if(currentOutput>currentOutAbsolute) {OOC=1;ERR++;errorCount++;}else{OOC=0;} //OOC - OUTPUT OVERCURRENT: Output current has reached absolute limit
if(voltageInput<voltageBatteryMax+voltageDropout&&MPPT_Mode==1) {IUV=1;ERR++;REC=1;} else{IUV=0;} //IUV - INPUT UNDERVOLTAGE: Input voltage is below battery voltage (for MPPT mode only)
if(voltageOutput>voltageBatteryMax+voltageBatteryThresh) {OOV=1;ERR++;errorCount++;}else{OOV=0;} //OOV - OUTPUT OVERVOLTAGE: Output voltage has reached absolute limit
if(voltageInput<vInSystemMin&&voltageOutput<vInSystemMin){FLV=1;ERR++;errorCount++;}else{FLV=0;} //FLV - Fatally low system voltage (unable to resume operation)

}
74 changes: 74 additions & 0 deletions 4_Charging_Algorithm.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
void buck_Enable(){ //Enable MPPT Buck Converter
buckEnable = 1;
digitalWrite(LED,HIGH);
digitalWrite(buck_EN,HIGH);
}
void buck_Disable(){ //Disable MPPT Buck Converter
PWM = 0;
buckEnable = 0;
digitalWrite(LED,LOW);
digitalWrite(buck_EN,LOW);
}
void predictivePWM(){ //PREDICTIVE PWM ALGORITHM
if(enablePPWM==0){PPWM=0;} //PPWM Disabled - PPWM is set to the corresponding PPWM value for the voltage slightly beneath output voltage

else if(MPPT_Mode==0){ //PPWM Enabled (CC-CV PSU Mode) - PPWM is set to 0 (maximum PWM floor will be set to 0)
if(voltageInput<=0){PPWM=0;} //Prevents Indefinite Answer when voltageInput is zero
else{PPWM=(PPWM_margin*pwmMax*voltageBatteryMax)/(100.00*voltageInput);} //Compute for predictive PWM Floor and store in variable
if(PPWM>pwmMaxLimited){PPWM=pwmMaxLimited;} //PPWM Exceeded allowable PWM ceiling; Limit PPWM to maximum allowable PWM value
else if(PPWM<0){PPWM=0;} //PPWM Exceeded allowable PWM floor value; Limit PPWM to 0
}

else{ //PPWM Enabled (MPPT Mode) - PPWM is set to 0 (maximum PWM floor will be set to 0)
if(voltageInput<=0){PPWM=0;} //Prevents Indefinite Answer when voltageInput is zero
else{PPWM=(PPWM_margin*pwmMax*voltageOutput)/(100.00*voltageInput);} //Compute for predictive PWM Floor and store in variable
if(PPWM>pwmMaxLimited){PPWM=pwmMaxLimited;} //PPWM Exceeded allowable PWM ceiling; Limit PPWM to maximum allowable PWM value
else if(PPWM<0){PPWM=0;} //PPWM Exceeded allowable PWM floor value; Limit PPWM to 0
}
}

void Charging_Algorithm(){
if(ERR>0||chargingPause==1){buck_Disable();} //ERROR PRESENT - Turn off MPPT buck when error is present or when chargingPause is used for a pause override
else{ //NO ERROR FOUND - Resume to normal operation
if(REC==1&&MPPT_Mode==1){ //IUV RECOVERY - (Only active for MPPT mode)
REC=0; //Reset IUV recovery boolean identifier
buck_Disable(); //Disable buck before PPWM initialization
Serial.println("> Solar Panel Detected"); //Display serial message
Serial.print("> Computing For Predictive PWM "); //Display serial message
for(int i = 0; i<20; i++){Serial.print(".");delay(20);} //For loop "loading... effect
Serial.println(""); //Display a line break on serial for next lines
Read_Sensors();
predictivePWM();
PWM = PPWM;
}
//NORMAL OPERATION
else{
buck_Enable();
/////////////////////// MPPT & CC-CV CHARGING ALGORITHM ///////////////////////
if(currentOutput>currentCharging){PWM--;} //Current Is Above → Decrease Duty Cycle
else if(voltageOutput>voltageBatteryMax){PWM--;} //Voltage Is Above → Decrease Duty Cycle
else if(voltageOutput<voltageBatteryMax && MPPT_Mode==0){PWM++;} //Increase duty cycle when output is below charging voltage (for CC-CV only mode)
else{
if(MPPT_Mode==1){ //MPPT ALGORITHM
if(powerInput>powerInputPrev && voltageInput>voltageInputPrev) {PWM--;} // ↑P ↑V ; →MPP //D--
else if(powerInput>powerInputPrev && voltageInput<voltageInputPrev){PWM++;} // ↑P ↓V ; MPP← //D++
else if(powerInput<powerInputPrev && voltageInput>voltageInputPrev){PWM++;} // ↓P ↑V ; MPP→ //D++
else if(powerInput<powerInputPrev && voltageInput<voltageInputPrev){PWM--;} // ↓P ↓V ; ←MPP //D--
else if(voltageOutput<voltageBatteryMax && MPPT_Mode==1) {PWM++;} // MP MV ; MPP Reached -
else{} // MP MV ; MPP Reached -
powerInputPrev = powerInput; //Store Previous Recorded Power
voltageInputPrev = voltageInput; //Store Previous Recorded Voltage
}
}
}
/////////////////////// PWM MODULATION ///////////////////////
predictivePWM();
if(PWM>pwmMaxLimited){PWM=pwmMaxLimited;} //PWM Ceiling Limiter - Limits maximum PWM value
else if(PWM<PPWM){PWM=PPWM;} //PWM Floor Limiter - Limits minimum PWM value
ledcWrite(pwmChannel,PWM); //Set PWM duty cycle and write to GPIO when buck is enabled
}




}
91 changes: 91 additions & 0 deletions 5_System_Processes.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
void System_Processes(){
///////////////// FAN COOLING /////////////////
if(enableFan==true){
if(enableDynamicCooling==false){ //STATIC PWM COOLING
if(overrideFan==true){fanStatus=true;} //Force on fan
else if(temperature>=temperatureFan){fanStatus=1;} //Turn on fan when set fan temp reached
else if(temperature<temperatureFan){fanStatus=0;} //Turn off fan when set fan temp reached
digitalWrite(FAN,fanStatus); //Send a digital signal to the fan MOSFET
}
else{} //DYNAMIC PWM COOLING
}
else{digitalWrite(FAN,LOW);} //Fan Disabled

//////////// LOOP TIME STOPWATCH ////////////
loopTimeStart = micros(); //Record Start Time
loopTime = (loopTimeStart-loopTimeEnd)/1000.000; //Compute Loop Cycle Speed (mS)
loopTimeEnd = micros(); //Record End Time

///////////// AUTO DATA RESET /////////////
if(telemCounterReset==0){} //Never Reset
else if(telemCounterReset==1 && daysRunning>1) {resetVariables();} //Daily Reset
else if(telemCounterReset==2 && daysRunning>7) {resetVariables();} //Weekly Reset
else if(telemCounterReset==3 && daysRunning>30) {resetVariables();} //Monthly Reset
else if(telemCounterReset==4 && daysRunning>365){resetVariables();} //Yearly Reset

///////////// LOW POWER MODE /////////////
if(lowPowerMode==1){}
else{}
}

void loadSettings(){
MPPT_Mode = EEPROM.read(0); // Load saved charging mode setting
voltageBatteryMax = EEPROM.read(1)+(EEPROM.read(2)*.01); // Load saved maximum battery voltage setting
voltageBatteryMin = EEPROM.read(3)+(EEPROM.read(4)*.01); // Load saved minimum battery voltage setting
currentCharging = EEPROM.read(5)+(EEPROM.read(6)*.01); // Load saved charging current setting
enableFan = EEPROM.read(7); // Load saved fan enable settings
temperatureFan = EEPROM.read(8); // Load saved fan temperature settings
temperatureMax = EEPROM.read(9); // Load saved shutdown temperature settings
enableWiFi = EEPROM.read(10); // Load saved WiFi enable settings
flashMemLoad = EEPROM.read(11); // Load saved flash memory autoload feature
}

void saveSettings(){
int conv1, conv2; //Temporary float to integer converters
EEPROM.write(0,MPPT_Mode); //STORE: Charge Mode
conv1 = voltageBatteryMax*100; //STORE: Maximum Battery Voltage (gets whole number)
conv2 = conv1%100; //STORE: Maximum Battery Voltage (gets decimal number and converts to a whole number)
EEPROM.write(1,voltageBatteryMax);
EEPROM.write(2,conv2);
conv1 = voltageBatteryMin*100; //STORE: Minimum Battery Voltage (gets whole number)
conv2 = conv1%100; //STORE: Minimum Battery Voltage (gets decimal number and converts to a whole number)
EEPROM.write(3,voltageBatteryMin);
EEPROM.write(4,conv2);
conv1 = currentCharging*100; //STORE: Charging Current
conv2 = conv1%100;
EEPROM.write(5,currentCharging);
EEPROM.write(6,conv2);
EEPROM.write(7,enableFan); //STORE: Fan Enable
EEPROM.write(8,temperatureFan); //STORE: Fan Temp
EEPROM.write(9,temperatureMax); //STORE: Shutdown Temp
EEPROM.write(10,enableWiFi); //STORE: Enable WiFi
//EEPROM.write(11,flashMemLoad); //STORE: Enable autoload (must be excluded from bulk save, uncomment under discretion)
EEPROM.commit(); //Saves setting changes to flash memory
}
void saveAutoloadSettings(){
EEPROM.write(11,flashMemLoad); //STORE: Enable autoload
EEPROM.commit(); //Saves setting changes to flash memory
}

void factoryReset(){
EEPROM.write(0,1); //STORE: MPPT Mode (bool)
EEPROM.write(1,12); //STORE: Max Battery Voltage (float whole)
EEPROM.write(2,0); //STORE: Max Battery Voltage (float decimal)
EEPROM.write(3,10); //STORE: Min Battery Voltage (float whole)
EEPROM.write(4,0); //STORE: Min Battery Voltage (float decimal)
EEPROM.write(5,30); //STORE: Charging Current (float whole)
EEPROM.write(6,0); //STORE: Charging Current (float decimal)
EEPROM.write(7,1); //STORE: Fan Enable (Bool)
EEPROM.write(8,60); //STORE: Fan Temp (Integer)
EEPROM.write(9,90); //STORE: Shutdown Temp (Integer)
EEPROM.write(10,1); //STORE: Enable WiFi (Boolean)
EEPROM.write(11,1); //STORE: Enable autoload (on by default)
EEPROM.commit();
loadSettings();
}
void initializeFlashAutoload(){
if(disableFlashAutoLoad==0){
flashMemLoad = EEPROM.read(11); //Load saved WiFi enable settings
if(flashMemLoad==1){loadSettings();} //Load stored settings from flash memory
}
}
Loading

0 comments on commit 550141b

Please sign in to comment.