Merge pull request #1343 from dalathegreat/feature/configurable-BMS-reset-delay

Feature: Add user configurable BMS reset off time
This commit is contained in:
Daniel Öster 2025-07-27 14:26:14 +03:00 committed by GitHub
commit 2b6ad122bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 27 additions and 3 deletions

View file

@ -75,7 +75,6 @@ unsigned long currentTime = 0;
unsigned long lastPowerRemovalTime = 0; unsigned long lastPowerRemovalTime = 0;
unsigned long bmsPowerOnTime = 0; unsigned long bmsPowerOnTime = 0;
const unsigned long powerRemovalInterval = 24 * 60 * 60 * 1000; // 24 hours in milliseconds const unsigned long powerRemovalInterval = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
const unsigned long powerRemovalDuration = 30000; // 30 seconds in milliseconds
const unsigned long bmsWarmupDuration = 3000; const unsigned long bmsWarmupDuration = 3000;
void set(uint8_t pin, bool direction, uint32_t pwm_freq = 0xFFFF) { void set(uint8_t pin, bool direction, uint32_t pwm_freq = 0xFFFF) {
@ -306,8 +305,9 @@ void handle_BMSpower() {
} }
} }
// If power has been removed for 30 seconds, restore the power // If power has been removed for user configured interval (1-59 seconds), restore the power
if (datalayer.system.status.BMS_reset_in_progress && currentTime - lastPowerRemovalTime >= powerRemovalDuration) { if (datalayer.system.status.BMS_reset_in_progress &&
currentTime - lastPowerRemovalTime >= datalayer.battery.settings.user_set_bms_reset_duration_ms) {
// Reapply power to the BMS // Reapply power to the BMS
digitalWrite(bms_power_pin, HIGH); digitalWrite(bms_power_pin, HIGH);
bmsPowerOnTime = currentTime; bmsPowerOnTime = currentTime;

View file

@ -79,6 +79,10 @@ void init_stored_settings() {
if (temp < 16) { if (temp < 16) {
datalayer.battery.settings.sofar_user_specified_battery_id = temp; datalayer.battery.settings.sofar_user_specified_battery_id = temp;
} }
temp = settings.getUInt("BMSRESETDUR", false);
if (temp != 0) {
datalayer.battery.settings.user_set_bms_reset_duration_ms = temp;
}
#ifdef COMMON_IMAGE #ifdef COMMON_IMAGE
user_selected_battery_type = (BatteryType)settings.getUInt("BATTTYPE", (int)BatteryType::None); user_selected_battery_type = (BatteryType)settings.getUInt("BATTTYPE", (int)BatteryType::None);
@ -187,6 +191,9 @@ void store_settings() {
if (!settings.putUInt("SOFAR_ID", datalayer.battery.settings.sofar_user_specified_battery_id)) { if (!settings.putUInt("SOFAR_ID", datalayer.battery.settings.sofar_user_specified_battery_id)) {
set_event(EVENT_PERSISTENT_SAVE_INFO, 12); set_event(EVENT_PERSISTENT_SAVE_INFO, 12);
} }
if (!settings.putUInt("BMSRESETDUR", datalayer.battery.settings.sofar_user_specified_battery_id)) {
set_event(EVENT_PERSISTENT_SAVE_INFO, 13);
}
settings.end(); // Close preferences handle settings.end(); // Close preferences handle
} }

View file

@ -139,6 +139,9 @@ typedef struct {
/** The user specified maximum allowed discharge voltage, in deciVolt. 3000 = 300.0 V */ /** The user specified maximum allowed discharge voltage, in deciVolt. 3000 = 300.0 V */
uint16_t max_user_set_discharge_voltage_dV = BATTERY_MAX_DISCHARGE_VOLTAGE; uint16_t max_user_set_discharge_voltage_dV = BATTERY_MAX_DISCHARGE_VOLTAGE;
/** The user specified BMS reset period. Keeps track on how many milliseconds should we keep power off during daily BMS reset */
uint16_t user_set_bms_reset_duration_ms = 30000;
/** Parameters for keeping track of the limiting factor in the system */ /** Parameters for keeping track of the limiting factor in the system */
bool user_settings_limit_discharge = false; bool user_settings_limit_discharge = false;
bool user_settings_limit_charge = false; bool user_settings_limit_charge = false;

View file

@ -402,6 +402,10 @@ String settings_processor(const String& var, BatteryEmulatorSettingsStore& setti
return String(datalayer.battery.settings.balancing_max_deviation_cell_voltage_mV / 1.0, 0); return String(datalayer.battery.settings.balancing_max_deviation_cell_voltage_mV / 1.0, 0);
} }
if (var == "BMS_RESET_DURATION") {
return String(datalayer.battery.settings.user_set_bms_reset_duration_ms / 1000.0, 0);
}
if (var == "CHARGER_CLASS") { if (var == "CHARGER_CLASS") {
if (!charger) { if (!charger) {
return "hidden"; return "hidden";
@ -544,6 +548,9 @@ const char* getCANInterfaceName(CAN_Interface interface) {
xhr=new xhr=new
XMLHttpRequest();xhr.onload=editComplete;xhr.onerror=editError;xhr.open('GET','/updateMaxDischargeVoltage?value='+value,true);xhr.send();}else{alert('Invalid value. Please enter a value between 0 and 1000.0');}}} XMLHttpRequest();xhr.onload=editComplete;xhr.onerror=editError;xhr.open('GET','/updateMaxDischargeVoltage?value='+value,true);xhr.send();}else{alert('Invalid value. Please enter a value between 0 and 1000.0');}}}
function editBMSresetDuration(){var value=prompt('Amount of seconds BMS power should be off during periodic daily resets. Requires "Periodic BMS reset" to be enabled. Enter value in seconds (1-59):');if(value!==null){if(value>=1&&value<=59){var
xhr=new XMLHttpRequest();xhr.onload=editComplete;xhr.onerror=editError;xhr.open('GET','/updateBMSresetDuration?value='+value,true);xhr.send();}else{alert('Invalid value. Please enter a value between 1 and 59');}}}
function editTeslaBalAct(){var value=prompt('Enable or disable forced LFP balancing. Makes the battery charge to 101percent. This should be performed once every month, to keep LFP batteries balanced. Ensure battery is fully charged before enabling, and also that you have enough sun or grid power to feed power into the battery while balancing is active. Enter 1 for enabled, 0 for disabled');if(value!==null){if(value==0||value==1){var xhr=new function editTeslaBalAct(){var value=prompt('Enable or disable forced LFP balancing. Makes the battery charge to 101percent. This should be performed once every month, to keep LFP batteries balanced. Ensure battery is fully charged before enabling, and also that you have enough sun or grid power to feed power into the battery while balancing is active. Enter 1 for enabled, 0 for disabled');if(value!==null){if(value==0||value==1){var xhr=new
XMLHttpRequest();xhr.onload=editComplete;xhr.onerror=editError;xhr.open('GET','/TeslaBalAct?value='+value,true);xhr.send();}}else{alert('Invalid value. Please enter 1 or 0');}} XMLHttpRequest();xhr.onload=editComplete;xhr.onerror=editError;xhr.open('GET','/TeslaBalAct?value='+value,true);xhr.send();}}else{alert('Invalid value. Please enter 1 or 0');}}
@ -792,6 +799,8 @@ const char* getCANInterfaceName(CAN_Interface interface) {
<h4 class='%VOLTAGE_LIMITS_ACTIVE_CLASS%'>Target discharge voltage: %DISCHARGE_VOLTAGE% V </span> <button onclick='editMaxDischargeVoltage()'>Edit</button></h4> <h4 class='%VOLTAGE_LIMITS_ACTIVE_CLASS%'>Target discharge voltage: %DISCHARGE_VOLTAGE% V </span> <button onclick='editMaxDischargeVoltage()'>Edit</button></h4>
<h4 style='color: white;'>Periodic BMS reset off time: %BMS_RESET_DURATION% s </span><button onclick='editBMSresetDuration()'>Edit</button></h4>
</div> </div>
<div style='background-color: #2E37AD; padding: 10px; margin-bottom: 10px;border-radius: 50px' class="%FAKE_VOLTAGE_CLASS%"> <div style='background-color: #2E37AD; padding: 10px; margin-bottom: 10px;border-radius: 50px' class="%FAKE_VOLTAGE_CLASS%">

View file

@ -657,6 +657,11 @@ void init_webserver() {
datalayer.battery.settings.max_user_set_discharge_voltage_dV = static_cast<uint16_t>(value.toFloat() * 10); datalayer.battery.settings.max_user_set_discharge_voltage_dV = static_cast<uint16_t>(value.toFloat() * 10);
}); });
// Route for editing BMSresetDuration
update_string_setting("/updateBMSresetDuration", [](String value) {
datalayer.battery.settings.user_set_bms_reset_duration_ms = static_cast<uint16_t>(value.toFloat() * 1000);
});
// Route for editing FakeBatteryVoltage // Route for editing FakeBatteryVoltage
update_string_setting("/updateFakeBatteryVoltage", [](String value) { battery->set_fake_voltage(value.toFloat()); }); update_string_setting("/updateFakeBatteryVoltage", [](String value) { battery->set_fake_voltage(value.toFloat()); });