/* PROJECT FUGU FIRMWARE V1.10 (DIY 1kW Open Source MPPT Solar Charge Controller) By: TechBuilder (Angelo Casimiro) FIRMWARE STATUS: Verified Stable Build Version (Contact me for the experimental beta versions) ----------------------------------------------------------------------------------------------------------- DATE CREATED: 02/07/2021 DATE MODIFIED: 30/08/2021 ----------------------------------------------------------------------------------------------------------- CONTACTS: GitHub - www.github.com/AngeloCasi (New firmware releases will only be available on GitHub Link) Email - casithebuilder@gmail.com YouTube - www.youtube.com/TechBuilder Facebook - www.facebook.com/AngeloCasii ----------------------------------------------------------------------------------------------------------- PROGRAM FEATURES: - MPPT Perturbed Algorithm With CC-CV - WiFi & Bluetooth BLE Blynk Phone App Telemetry - Selectable Charger/PSU Mode (can operate as a programmable buck converter) - Dual Core ESP32 Unlocked (using xTaskCreatePinnedToCore(); ) - Precision ADC Tracking Auto ADS1115/ADS1015 Detection (16bit/12bit I2C ADC) - Automatic ACS712-30A Current Sensor Calibration - Equipped With Battery Disconnect & Input Disconnect Recovery Protection Protocol - LCD Menu Interface (with settings & 4 display layouts) - Flash Memory (non-volatile settings save function) - Settable PWM Resolution (8bit-16bit) - Settable PWM Switching Frequency (1.2kHz - 312kHz) ----------------------------------------------------------------------------------------------------------- PROGRAM INSTRUCTIONS: 1.) Watch YouTube video tutorial first before using 2.) Install the required Arduino libraries for the ICs 3.) Select Tools > ESP32 Dev Board Board 4.) Do not modify code unless you know what you are doing 5.) The MPPT's synchronous buck converter topology is code dependent, messing with the algorithm and safety protection protocols can be extremely dangerous especially when dealing with HVDC. 6.) Install Blynk Legacy to access the phone app telemetry feature 7.) Input the Blynk authentication in this program token sent by Blynk to your email after registration 8.) Input WiFi SSID and password in this program 9.) When using WiFi only mode, change "disableFlashAutoLoad = 0" to = 1 (LCD and buttons not installed) this prevents the MPPT unit to load the Flash Memory saved settings and will load the Arduino variable declarations set below instead ----------------------------------------------------------------------------------------------------------- GOOGLE DRIVE PROJECT LINK: coming soon INSTRUCTABLE TUTORIAL LINK: coming soon YOUTUBE TUTORIAL LINK: www.youtube.com/watch?v=ShXNJM6uHLM GITHUB UPDATED FUGU FIRMWARE LINK: github.com/AngeloCasi/FUGU-ARDUINO-MPPT-FIRMWARE ----------------------------------------------------------------------------------------------------------- ACTIVE CHIPS USED IN FIRMWARE: - ESP32 WROOM32 - ADS1115/ADS1015 I2C ADC - ACS712-30A Current Sensor IC - IR2104 MOSFET Driver - CH340C USB TO UART IC - 16X2 I2C Character LCD OTHER CHIPS USED IN PROJECT: - XL7005A 80V 0.4A Buck Regulator (2x) - AMS1115-3.3 LDO Linear Regulator - AMS1115-5.0 LDO Linear Regulator - CSD19505 N-ch MOSFETS (3x) - B1212 DC-DC Isolated Converter - SS310 Diodes */ //================================ MPPT FIRMWARE LCD MENU INFO =====================================// // The lines below are for the Firmware Version info displayed on the MPPT's LCD Menu Interface // //==================================================================================================// String firmwareInfo = "V2.10", firmwareDate = "23/06/2022", firmwareContactR1 = "www.youtube.com/", firmwareContactR2 = "TechBuilder "; //====================== ARDUINO LIBRARIES (ESP32 Compatible Libraries) ============================// // You will have to download and install the following libraries below in order to program the MPPT // // unit. Visit TechBuilder's YouTube channel for the "MPPT" tutorial. // //============================================================================================= ====// #include //SYSTEM PARAMETER - EEPROM Library (By: Arduino) #include //SYSTEM PARAMETER - WIRE Library (By: Arduino) #include //SYSTEM PARAMETER - SPI Library (By: Arduino) #include //SYSTEM PARAMETER - WiFi Library (By: Arduino) #include //SYSTEM PARAMETER - WiFi Library (By: Arduino) //#include //SYSTEM PARAMETER - Blynk WiFi Library For Phone App #define BLINKER_WIFI #define BLINKER_ALIGENIE_OUTLET #define BLINKER_WITHOUT_SSL #define BLINKER_ALIGENIE_SENSOR #include //#define BLINKER_ESP_SMARTCONFIG #include //系统参数 - ESP32 LCD 兼容库(作者:Robojax) #include //#include //SYSTEM PARAMETER - ADS1115/ADS1015 ADC Library (By: Adafruit) #include LiquidCrystal_I2C lcd(0x27, 20, 4); //系统参数 - 配置 LCD RowCol 大小和 I2C 地址 TaskHandle_t Core2; //SYSTEM PARAMETER - Used for the ESP32 dual core operation //Adafruit_ADS1015 ads; //SYSTEM PARAMETER - ADS1015 ADC Library (By: Adafruit) Kindly delete this line if you are using ADS1115 //Adafruit_ADS1115 ads; //SYSTEM PARAMETER - ADS1115 ADC Library (By: Adafruit) Kindly uncomment this if you are using ADS1115 INA226 ina1; INA226 ina2; #include #define timezone 8 BlinkerNumber Num1("num-9y2"); BlinkerNumber Num2("num-m2k"); BlinkerNumber Num3("num-5up"); BlinkerNumber Num4("num-ahb"); BlinkerNumber Num5("num-l24"); BlinkerNumber Num6("num-3bm"); BlinkerNumber Num7("num-rgu"); BlinkerNumber Num8("num-ao5"); BlinkerNumber Num9("num-ycz"); BlinkerButton Button1("btn-e6n"); BlinkerButton Button2("btn-e3t"); BlinkerButton Button3("btn-ogw"); BlinkerButton Button4("btn-q4l"); //====================================== USER PARAMETERS ===========================================// //下面的参数是没有MPPT充电器设置时使用的默认参数 // //通过 LCD 菜单界面或手机 WiFi 应用程序设置或保存。这里的一些参数// //将允许您覆盖或解锁高级用户的功能(不在 LCD 菜单上的设置)// //==================================================================================================// #define backflow_MOSFET 27 //SYSTEM PARAMETER - Backflow MOSFET #define buck_IN 33 //SYSTEM PARAMETER - Buck MOSFET Driver PWM Pin #define buck_EN 32 //SYSTEM PARAMETER - Buck MOSFET Driver Enable Pin #define LED 2 //SYSTEM PARAMETER - LED Indicator GPIO Pin #define FAN 16 //SYSTEM PARAMETER - Fan GPIO Pin //#define ADC_ALERT 35 //SYSTEM PARAMETER - ADC_ALERT GPIO Pin #define INA1_ALERT 35 //SYSTEM PARAMETER - INA226 Alert GPIO Pin #define INA2_ALERT 34 //SYSTEM PARAMETER - INA226 Alert GPIO Pin #define TempSensor 39 //SYSTEM PARAMETER - Temperature Sensor GPIO Pin #define buttonLeft 18 //SYSTEM PARAMETER - #define buttonRight 19 //SYSTEM PARAMETER - #define buttonBack 17 //SYSTEM PARAMETER - #define buttonSelect 23 //SYSTEM PARAMETER - #define eeprom_size 4096 #define MPPT_Mode_add 2448 // charging mode setting #define voltageBatteryMax_add 2449 // Max Battery Voltage (whole) #define voltageBatteryMax2_add 2450 // Max Battery Voltage (decimal) #define voltageBatteryMin_add 2451 // Min Battery Voltage (whole) #define voltageBatteryMin2_add 2452 // Min Battery Voltage (decimal) #define currentCharging_add 2453 // Charging Current (whole) #define currentCharging2_add 2454 // Charging Current (decimal) #define enableFan_add 2455 // Fan Enable (Bool) #define temperatureFan_add 2456 // Fan Temp (Integer) #define temperatureMax_add 2457 // Shutdown Temp (Integer) #define enableWiFi_add 2458 // Enable WiFi (Boolean) #define flashMemLoad_add 2459 // Enable autoload (on by default) #define output_Mode_add 2460 // Charger/PSU Mode Selection (1 = Charger Mode) #define backlightSleepMode_add 2461 // LCD backlight sleep timer (default: 0 = never) //========================================= WiFi SSID ==============================================// // This MPPT firmware uses the Blynk phone app and arduino library for controls and data telemetry // // Fill in your WiFi SSID and password. You will also have to get your own authentication token // // from email after registering from the Blynk platform. // //==================================================================================================// char auth[] = "InputBlynkAuthenticationToken", // USER PARAMETER - Input Blynk Authentication Token (From email after registration) ssid[] = "", // USER PARAMETER - Enter Your WiFi SSID pass[] = ""; // USER PARAMETER - Enter Your WiFi Password const char *blinker_id = ""; //Blinker ID //====================================== USER PARAMETERS ==========================================// //下面的参数是没有MPPT充电器设置时使用的默认参数 // //通过 LCD 菜单界面或手机 WiFi 应用程序设置或保存。这里的一些参数// //将允许您覆盖或解锁高级用户的功能(不在 LCD 菜单上的设置)// //=================================================================================================// bool MPPT_Mode = 1, // USER PARAMETER - 启用 MPPT 算法,当禁用充电器时使用 CC-CV 算法 output_Mode = 1, // USER PARAMETER - 0 = PSU 模式, 1 = 充电器模式 disableFlashAutoLoad = 0, // USER PARAMETER - 强制 MPPT 不使用闪存保存的设置,启用此“1”默认为已编程的固件设置 enablePPWM = 1, // USER PARAMETER - 启用预测 PWM,这加快了调节速度(仅适用于电池充电应用) enableWiFi = 1, // USER PARAMETER - 启用 WiFi 连接 enableFan = 1, // USER PARAMETER - 启用冷却风扇 enableBluetooth = 1, // USER PARAMETER - 启用蓝牙连 enableLCD = 1, // USER PARAMETER - 启用 接LCD 显示 enableLCDBacklight = 1, // USER PARAMETER - 启用 LCD 显示器的背光 overrideFan = 0, // USER PARAMETER - 风扇始终开启 enableDynamicCooling = 0; // USER PARAMETER - 启用 PWM 冷却控制 int serialTelemMode = 1, // USER PARAMETER - 选择串行遥测数据馈送(0 - 禁用串行,1 - 显示所有数据,2 - 显示基本,3 - 仅数字) pwmResolution = 11, // USER PARAMETER - PWM 位分辨率 pwmFrequency = 39000, // USER PARAMETER - PWM 开关频率 - Hz(用于降压) temperatureFan = 60, // USER PARAMETER - 风扇开启的温度阈值 temperatureMax = 90, // USER PARAMETER - 过热,超过时系统关闭(摄氏度) telemCounterReset = 0, // USER PARAMETER - 每隔一次重置 Telem 数据(0 = 从不,1 = 日,2 = 周,3 = 月,4 = 年) errorTimeLimit = 1000, // USER PARAMETER - 重置错误计数器的时间间隔(毫秒) errorCountLimit = 5, // USER PARAMETER - 最大错误数 millisRoutineInterval = 250, // USER PARAMETER - 例程函数的时间间隔刷新率 (ms) millisSerialInterval = 5, // USER PARAMETER - USB 串行数据馈送的时间间隔刷新率 (ms) millisLCDInterval = 1000, // USER PARAMETER - LCD 显示器的时间间隔刷新率 (ms) millisWiFiInterval = 1000, // USER PARAMETER - WiFi 遥测的时间间隔刷新率 (ms) millisLCDBackLInterval = 1000, // USER PARAMETER - 用户参数 - WiFi 遥测的时间间隔刷新率 (ms) backlightSleepMode = 2, // USER PARAMETER - - 0 = 从不, 1 = 10 秒, 2 = 5 分钟, 3 = 1 小时, 4 = 6 小时, 5 = 12 小时, 6 = 1 天, 7 = 3 天, 8 = 1 周, 9 = 1个月 baudRate = 500000; // 用户参数 - USB 串行波特率 (bps) float voltageBatteryMax = 12.6000, // USER PARAMETER - 最大电池充电电压(输出 V) voltageBatteryMin = 3.0000, // USER PARAMETER - 最小电池充电电压(输出 V) currentCharging = 1.0000, // USER PARAMETER - 最大充电电流(A - 输出) electricalPrice = 0.6000; // USER PARAMETER - 每千瓦时的输入电价 //================================== CALIBRATION PARAMETERS =======================================// //可以调整以下参数以设计您自己的 MPPT 充电控制器。只修改 // //如果你知道你在做什么,下面的值。以下值已针对 // 进行了预校准 // TechBuilder (Angelo S. Casimiro) 设计的 MPPT 充电控制器 // // //=================================================================================================// const bool ADS1015_Mode = 1; // CALIB PARAMETER - Use 1 for ADS1015 ADC model use 0 for ADS1115 ADC model const int ADC_GainSelect = 2, // 校准参数 - ADC 增益选择 (0→±6.144V 3mV/bit, 1→±4.096V 2mV/bit, 2→±2.048V 1mV/bit) avgCountVS = 3, // 校准参数 - 电压传感器平均采样计数(推荐:3) avgCountCS = 4, // 校准参数 - 电流传感器平均采样计数(推荐:4) avgCountTS = 500; // 校准参数 - 温度传感器平均采样计数 float inVoltageDivRatio = 2.9784, // 校准参数 - 输入分压器传感器比率(更改此值以校准电压传感器) outVoltageDivRatio = 2.8275, // 校准参数 - 输出分压器传感器比率(更改此值以校准电压传感器) vOutSystemMax = 80.0000, // 校准参数 - 最大输入电压 cOutSystemMax = 50.0000, // 校准参数 - 最大输出电压 ntcResistance = 10000.00, // 校准参数 - NTC 温度传感器的电阻。如果您使用 10k NTC,请更改为 10000.00 voltageDropout = 1.0000, // 校准参数 - 降压稳压器的压降电压(由于最大占空比限制而存在 DOV) voltageBatteryThresh = 1.5000, // 校准参数 - 达到此电压时断电(输出 V) currentInAbsolute = 31.0000, // 校准参数 - 系统可以处理的最大输入电流(A - 输入) currentOutAbsolute = 50.0000, // 校准参数 - 系统可以处理的最大输出电流(A - 输入) PPWM_margin = 99.5000, // 校准参数 - 预测 PWM 的最小工作占空比 (%) PWM_MaxDC = 97.0000, // 校准参数 - 最大工作占空比 (%) 90%-97% 是好的 efficiencyRate = 1.0000, // 校准参数 - 理论降压效率(十进制百分比) currentMidPoint = 2.5250, // 校准参数 - 电流传感器中点 (V) currentSens = 0.0000, // 校准参数 - 电流传感器灵敏度 (V/A) currentSensV = 0.0330, // 校准参数 - 电流传感器灵敏度 (mV/A) vInSystemMin = 8.000; // 校准参数 - 系统识别最低电压 //===================================== SYSTEM PARAMETERS =========================================// //不要更改本节中的参数值。下面的值是系统使用的变量 // //进程。更改值可能会损坏 MPPT 硬件。请保持原样!然而, // //您可以访问这些变量来获取您的模组所需的数据。// //=================================================================================================// bool buckEnable = 0, // SYSTEM PARAMETER - Buck Enable Status fanStatus = 0, // SYSTEM PARAMETER - Fan activity status (1 = On, 0 = Off) bypassEnable = 0, // SYSTEM PARAMETER - chargingPause = 0, // SYSTEM PARAMETER - lowPowerMode = 0, // SYSTEM PARAMETER - buttonRightStatus = 0, // SYSTEM PARAMETER - buttonLeftStatus = 0, // SYSTEM PARAMETER - buttonBackStatus = 0, // SYSTEM PARAMETER - buttonSelectStatus = 0, // SYSTEM PARAMETER - buttonRightCommand = 0, // SYSTEM PARAMETER - buttonLeftCommand = 0, // SYSTEM PARAMETER - buttonBackCommand = 0, // SYSTEM PARAMETER - buttonSelectCommand = 0, // SYSTEM PARAMETER - settingMode = 0, // SYSTEM PARAMETER - setMenuPage = 0, // SYSTEM PARAMETER - boolTemp = 0, // SYSTEM PARAMETER - flashMemLoad = 0, // SYSTEM PARAMETER - confirmationMenu = 0, // SYSTEM PARAMETER - WIFI = 0, // SYSTEM PARAMETER - BNC = 0, // SYSTEM PARAMETER - REC = 0, // SYSTEM PARAMETER - FLV = 0, // SYSTEM PARAMETER - IUV = 0, // SYSTEM PARAMETER - IOV = 0, // SYSTEM PARAMETER - IOC = 0, // SYSTEM PARAMETER - OUV = 0, // SYSTEM PARAMETER - OOV = 0, // SYSTEM PARAMETER - OOC = 0, // SYSTEM PARAMETER - OTE = 0; // SYSTEM PARAMETER - int inputSource = 0, // SYSTEM PARAMETER - 0 = MPPT 没有电源,1 = MPPT 使用太阳能作为电源,2 = MPPT 使用电池作为电源 avgStoreTS = 0, // SYSTEM PARAMETER - 温度传感器使用非侵入式平均,这是用于平均平均的累加器 temperature = 0, // SYSTEM PARAMETER - sampleStoreTS = 0, // SYSTEM PARAMETER - TS AVG 第 n 个样本 pwmMax = 0, // SYSTEM PARAMETER - pwmMaxLimited = 0, // SYSTEM PARAMETER - PWM = 0, // SYSTEM PARAMETER - PPWM = 0, // SYSTEM PARAMETER - pwmChannel = 0, // SYSTEM PARAMETER - batteryPercent = 0, // SYSTEM PARAMETER - errorCount = 0, // SYSTEM PARAMETER - menuPage = 0, // SYSTEM PARAMETER - subMenuPage = 0, // SYSTEM PARAMETER - ERR = 0, // SYSTEM PARAMETER - conv1 = 0, // SYSTEM PARAMETER - conv2 = 0, // SYSTEM PARAMETER - intTemp = 0; // SYSTEM PARAMETER - float VSI = 0.0000, // SYSTEM PARAMETER - 原始输入电压传感器 ADC 电压 VSO = 0.0000, // SYSTEM PARAMETER - 原始输出电压传感器 ADC 电压 CSI = 0.0000, // SYSTEM PARAMETER - 原始电流传感器 ADC 电压 CSO = 0.0000, // SYSTEM PARAMETER - Raw current sensor ADC voltage CSI_converted = 0.0000, // SYSTEM PARAMETER - 实际电流传感器 ADC 电压 CSO_converted = 0.0000, // SYSTEM PARAMETER - Actual current sensor ADC voltage TS = 0.0000, // SYSTEM PARAMETER - 原始温度传感器 ADC 值 powerInput = 0.0000, // SYSTEM PARAMETER - 输入功率(太阳能)以瓦特为单位 powerInputPrev = 0.0000, // SYSTEM PARAMETER - 先前存储的 MPPT 算法的输入功率变量(瓦特) powerOutput = 0.0000, // SYSTEM PARAMETER - 输出功率(电池或充电功率,以瓦特为单位) energySavings = 0.0000, // SYSTEM PARAMETER - 法定货币(比索、美元、欧元等)的能源节约 voltageInput = 0.0000, // SYSTEM PARAMETER - 输入电压(太阳能电压) voltageInputPrev = 0.0000, // SYSTEM PARAMETER - 先前存储的 MPPT 算法的输入电压变量 voltageOutput = 0.0000, // SYSTEM PARAMETER - 输入电压(电池电压) currentInput = 0.0000, // SYSTEM PARAMETER - 输出功率(电池或充电电压) currentOutput = 0.0000, // SYSTEM PARAMETER - 输出电流(电池或充电电流,以安培为单位) TSlog = 0.0000, // SYSTEM PARAMETER - NTC 热敏电阻热感应代码的一部分 ADC_BitReso = 0.0000, // SYSTEM PARAMETER - 系统检测 ADS1015/ADS1115 ADC 的适当位分辨率因子 daysRunning = 0.0000, // SYSTEM PARAMETER - 存储 MPPT 设备自上次通电以来运行的总天数 Wh = 0.0000, // SYSTEM PARAMETER - 存储收集到的累积能量(瓦特小时) kWh = 0.0000, // SYSTEM PARAMETER - 存储收集到的累积能量(千瓦时) MWh = 0.0000, // SYSTEM PARAMETER - 存储收集到的累积能量(兆瓦时) loopTime = 0.0000, // SYSTEM PARAMETER - outputDeviation = 0.0000, // SYSTEM PARAMETER - 输出电压偏差 (%) buckEfficiency = 0.0000, // SYSTEM PARAMETER - 测量降压转换器功率转换效率(仅适用于我的双电流传感器版本) floatTemp = 0.0000, vOutSystemMin = 0.0000; // CALIB PARAMETER - unsigned long currentErrorMillis = 0, //SYSTEM PARAMETER - currentButtonMillis = 0, //SYSTEM PARAMETER - currentSerialMillis = 0, //SYSTEM PARAMETER - currentRoutineMillis = 0, //SYSTEM PARAMETER - currentLCDMillis = 0, //SYSTEM PARAMETER - currentLCDBackLMillis = 0, //SYSTEM PARAMETER - currentWiFiMillis = 0, //SYSTEM PARAMETER - currentMenuSetMillis = 0, //SYSTEM PARAMETER - prevButtonMillis = 0, //SYSTEM PARAMETER - prevSerialMillis = 0, //SYSTEM PARAMETER - prevRoutineMillis = 0, //SYSTEM PARAMETER - prevErrorMillis = 0, //SYSTEM PARAMETER - prevWiFiMillis = 0, //SYSTEM PARAMETER - prevLCDMillis = 0, //SYSTEM PARAMETER - prevLCDBackLMillis = 0, //SYSTEM PARAMETER - timeOn = 0, //SYSTEM PARAMETER - loopTimeStart = 0, //SYSTEM PARAMETER - 用于循环循环秒表,记录循环开始时间 loopTimeEnd = 0, //SYSTEM PARAMETER - 用于循环循环秒表,记录循环结束时间 secondsElapsed = 0; //SYSTEM PARAMETER - //====================================== MAIN PROGRAM =============================================// // The codes below contain all the system processes for the MPPT firmware. Most of them are called // // from the 8 .ino tabs. The codes are too long, Arduino tabs helped me a lot in organizing them. // // The firmware runs on two cores of the Arduino ESP32 as seen on the two separate pairs of void // // setups and loops. The xTaskCreatePinnedToCore() freeRTOS function allows you to access the // // unused ESP32 core through Arduino. Yes it does multicore processes simultaneously! // //=================================================================================================// void dataRead(const String &data) { BLINKER_LOG("Blinker readString: ", data); } void heartbeat() { Num1.print(powerInput); Num2.print(voltageInput); Num3.print(currentInput); Num4.print(batteryPercent); Num5.print(voltageOutput); Num6.print(currentOutput); Num7.print(Wh/1000); Num8.print(electricalPrice); Num9.print(temperature); if(buckEnable==1){Button1.print("off");}else{Button1.print("on");} if(batteryPercent >= 99){Button2.print("off");}else{Button2.print("on");} if(batteryPercent <= 10){Button3.print("off");}else{Button3.print("on");} if(IUV == 0){Button4.print("off");}else{Button4.print("on");} } void dataStorage() { Blinker.dataStorage("data-1", powerInput); //数据组件名,数据值 Blinker.dataStorage("data-2", voltageInput); Blinker.dataStorage("data-3", currentInput); Blinker.dataStorage("data-4", powerOutput); Blinker.dataStorage("data-5", voltageOutput); Blinker.dataStorage("data-6", currentOutput); } //================= CORE0: SETUP (DUAL CORE MODE) =====================// void coreTwo(void * pvParameters) { setupWiFi(); //TAB#7 - WiFi Initialization //================= CORE0: LOOP (DUAL CORE MODE) ======================// while (1) { Wireless_Telemetry(); //TAB#7 - Wireless telemetry (WiFi & Bluetooth) } } //================== CORE1: SETUP (DUAL CORE MODE) ====================// void setup() { //SERIAL INITIALIZATION Serial.begin(baudRate); //Set serial baud rate Serial.println("> Serial Initialized"); //Startup message BLINKER_DEBUG.stream(Serial); //GPIO PIN INITIALIZATION pinMode(backflow_MOSFET, OUTPUT); pinMode(buck_EN, OUTPUT); pinMode(LED, OUTPUT); pinMode(FAN, OUTPUT); pinMode(TS, INPUT); //pinMode(ADC_ALERT,INPUT); pinMode(INA1_ALERT, INPUT); pinMode(INA2_ALERT, INPUT); pinMode(buttonLeft, INPUT); pinMode(buttonRight, INPUT); pinMode(buttonBack, INPUT); pinMode(buttonSelect, INPUT); //PWM INITIALIZATION ledcSetup(pwmChannel, pwmFrequency, pwmResolution); //Set PWM Parameters ledcAttachPin(buck_IN, pwmChannel); //Set pin as PWM ledcWrite(pwmChannel, PWM); //Write PWM value at startup (duty = 0) pwmMax = pow(2, pwmResolution) - 1; //Get PWM Max Bit Ceiling pwmMaxLimited = (PWM_MaxDC * pwmMax) / 100.000; //Get maximum PWM Duty Cycle (pwm limiting protection) //ADC INITIALIZATION //ADC_SetGain(); //Sets ADC Gain & Range //ads.begin(); //Initialize ADC Serial.println("Initialize INA226 Slave1 0x40 A1 GND A0 GND"); Serial.println("-----------------------------------------------"); // Default INA226 address is 0x40 ina1.begin(); // Configure INA226 ina1.configure(INA226_AVERAGES_4, INA226_BUS_CONV_TIME_588US, INA226_SHUNT_CONV_TIME_588US, INA226_MODE_SHUNT_BUS_CONT); // Calibrate INA226. Rshunt = 0.01 ohm, Max excepted current = 4A ina1.calibrate(0.002, 40); // Display configuration checkConfig(ina1); Serial.println("-----------------------------------------------"); Serial.println("Initialize INA226 Slave2 0x41"); Serial.println("-----------------------------------------------"); // Default INA226 address is 0x40 ina2.begin(0x41); // Configure INA226 ina2.configure(INA226_AVERAGES_4, INA226_BUS_CONV_TIME_588US, INA226_SHUNT_CONV_TIME_588US, INA226_MODE_SHUNT_BUS_CONT); // Calibrate INA226. Rshunt = 0.01 ohm, Max excepted current = 4A ina2.calibrate(0.002, 40); // Display configuration checkConfig(ina2); Serial.println("-----------------------------------------------"); //GPIO INITIALIZATION buck_Disable(); //ENABLE DUAL CORE MULTITASKING xTaskCreatePinnedToCore(coreTwo, "coreTwo", 10000, NULL, 0, &Core2, 0); //INITIALIZE AND LIOAD FLASH MEMORY DATA EEPROM.begin(eeprom_size); Serial.println("> FLASH MEMORY: STORAGE INITIALIZED"); //Startup message initializeFlashAutoload(); //Load stored settings from flash memory Serial.println("> FLASH MEMORY: SAVED DATA LOADED"); //Startup message //LCD INITIALIZATION if (enableLCD == 1) { lcd.begin(16, 2); lcd.setBacklight(HIGH); lcd.setCursor(0, 0); lcd.print("MPPT INIT"); lcd.setCursor(0, 1); lcd.print("FIRMWARE "); lcd.print(firmwareInfo); delay(1500); lcd.clear(); } uint32_t chipId = 0; for (int i = 0; i < 17; i = i + 8) { chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; } Serial.printf("Chip ID: %d\r\n", chipId); Serial.printf("ESP32 Chip ID = %04X", (uint16_t)(ESP.getEfuseMac() >> 32)); //print High 2 bytes Serial.printf("%08X\r\n", (uint32_t)ESP.getEfuseMac()); //print Low 4bytes. Serial.printf("Chip model = %s Rev %d\r\n", ESP.getChipModel(), ESP.getChipRevision()); Serial.printf("This chip has %d cores CpuFreqMHz = %u\r\n", ESP.getChipCores(), ESP.getCpuFreqMHz()); Serial.printf("get Cycle Count = %u\r\n", ESP.getCycleCount()); Serial.printf("SDK version:%s\r\n", ESP.getSdkVersion()); //获取IDF版本 //获取片内内存 Internal RAM Serial.printf("Total heap size = %u\t", ESP.getHeapSize()); Serial.printf("Available heap = %u\r\n", ESP.getFreeHeap()); Serial.printf("Lowest level of free heap since boot = %u\r\n", ESP.getMinFreeHeap()); Serial.printf("Largest block of heap that can be allocated at once = %u\r\n", ESP.getMaxAllocHeap()); //SPI RAM Serial.printf("Total Psram size = %u\t", ESP.getPsramSize()); Serial.printf("Available Psram = %u\r\n", ESP.getFreePsram()); Serial.printf("Lowest level of free Psram since boot = %u\r\n", ESP.getMinFreePsram()); Serial.printf("Largest block of Psram that can be allocated at once = %u\r\n", ESP.getMinFreePsram()); byte mac[6]; WiFi.macAddress(mac); printf("macAddress 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); //以下是启动OTA,可以通过WiFi刷新固件 ArduinoOTA.setHostname("ESP32_MPPT"); // No authentication by default // ArduinoOTA.setPassword("admin"); // Password can be set with it's md5 value as well // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); ArduinoOTA.onStart([]() { String type; if (ArduinoOTA.getCommand() == U_FLASH) { type = "sketch"; } else { // U_SPIFFS type = "filesystem"; } // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() Serial.println("Start updating " + type); }); ArduinoOTA.onEnd([]() { Serial.println("\nEnd"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) { Serial.println("Auth Failed"); } else if (error == OTA_BEGIN_ERROR) { Serial.println("Begin Failed"); } else if (error == OTA_CONNECT_ERROR) { Serial.println("Connect Failed"); } else if (error == OTA_RECEIVE_ERROR) { Serial.println("Receive Failed"); } else if (error == OTA_END_ERROR) { Serial.println("End Failed"); } }); ArduinoOTA.begin(); Serial.println("OTA Ready"); //设置时间格式以及时间服务器的网址 configTime(timezone * 3600, 0, "pool.ntp.org", "time.nist.gov"); Serial.println("\nWaiting for time"); while (!time(nullptr)) { Serial.print("."); delay(1000); } //SETUP FINISHED Serial.println("> MPPT HAS INITIALIZED"); //Startup message } unsigned long TenthSecondsSinceStart = 0; unsigned long LastMillis = 0; char DateTimeStr[20]; void OnSecond() { time_t now = time(nullptr); //获取当前时间 //转换成年月日的数字,可以更加自由的显示。 struct tm* timenow; timenow = localtime(&now); unsigned char tempHour = timenow->tm_hour; unsigned char tempMinute = timenow->tm_min; unsigned char tempSecond = timenow->tm_sec; unsigned char tempDay = timenow->tm_mday; unsigned char tempMonth = timenow->tm_mon + 1; unsigned int tempYear = timenow->tm_year + 1900; unsigned char tempWeek = timenow->tm_wday; //生成 年月日时分秒 字符串。 sprintf(DateTimeStr, "%d-%02d-%02d %02d:%02d:%02d" , tempYear , tempMonth , tempDay , tempHour , tempMinute , tempSecond ); } void OnTenthSecond() // 100ms 十分之一秒 { if (TenthSecondsSinceStart % 3 == 0) //0.3S刷新数据, { //读取采样数据1 //voltageInput = ina1.readBusVoltage()*(R1_VOLTAGE1+R2_VOLTAGE1)/R1_VOLTAGE1; //voltageOutput = ina2.readBusVoltage()*(R1_VOLTAGE2+R2_VOLTAGE2)/R1_VOLTAGE2; //读取采样数据2 //CSI_converted = ina1.readShuntCurrent(); //CSO_converted = ina2.readShuntCurrent(); } if (TenthSecondsSinceStart % 10 == 0) //10次为1秒 { OnSecond(); } } void TenthSecondsSinceStartTask() //100ms { unsigned long CurrentMillis = millis(); if (abs(int(CurrentMillis - LastMillis)) > 100) { LastMillis = CurrentMillis; TenthSecondsSinceStart++; OnTenthSecond(); } } //================== CORE1: LOOP (DUAL CORE MODE) ======================// void loop() { ArduinoOTA.handle(); TenthSecondsSinceStartTask(); Read_Sensors(); //TAB#2 - Sensor data measurement and computation Device_Protection(); //TAB#3 - Fault detection algorithm System_Processes(); //TAB#4 - Routine system processes Charging_Algorithm(); //TAB#5 - Battery Charging Algorithm Onboard_Telemetry(); //TAB#6 - Onboard telemetry (USB & Serial Telemetry) LCD_Menu(); //TAB#8 - Low Power Algorithm }