forked from AngeloCasi/FUGU-ARDUINO-MPPT-FIRMWARE
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3066c4a
commit 550141b
Showing
8 changed files
with
1,132 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
|
||
|
||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
Oops, something went wrong.