diff --git a/Software/Software.ino b/Software/Software.ino index 6696ee02..8394317f 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -388,7 +388,7 @@ void init_stored_settings() { //always save the equipment stop status settings.putBool("EQUIPMENT_STOP", datalayer.system.settings.equipment_stop_active); -#endif +#endif //LOAD_SAVED_SETTINGS_ON_BOOT #ifdef WIFI @@ -404,7 +404,7 @@ void init_stored_settings() { password = tempPasswordString; } else { // Reading from settings failed. Do nothing with SSID. Raise event? } -#endif +#endif //WIFI temp = settings.getUInt("BATTERY_WH_MAX", false); if (temp != 0) { @@ -425,10 +425,20 @@ void init_stored_settings() { temp = settings.getUInt("MAXDISCHARGEAMP", false); if (temp != 0) { datalayer.battery.settings.max_user_set_discharge_dA = temp; - temp = settings.getBool("USE_SCALED_SOC", false); - datalayer.battery.settings.soc_scaling_active = temp; //This bool needs to be checked inside the temp!= block - } // No way to know if it wasnt reset otherwise + } + datalayer.battery.settings.soc_scaling_active = settings.getBool("USE_SCALED_SOC", false); + settings.end(); + settings.begin("batteryExtra", false); + temp = settings.getUInt("TARGETCHARGEVOLTAGE", false); + if (temp != 0) { + datalayer.battery.settings.max_user_set_charge_voltage_dV = temp; + } + temp = settings.getUInt("TARGETDISCHARGEVOLTAGE", false); + if (temp != 0) { + datalayer.battery.settings.max_user_set_discharge_voltage_dV = temp; + } + datalayer.battery.settings.user_set_voltage_limits_active = settings.getBool("USE_VOLTAGE_LIMITS", false); settings.end(); } @@ -1049,20 +1059,48 @@ void store_settings_equipment_stop() { } void storeSettings() { - settings.begin("batterySettings", false); + if (!settings.begin("batterySettings", false)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 0); + return; + } + #ifdef WIFI - settings.putString("SSID", String(ssid.c_str())); - settings.putString("PASSWORD", String(password.c_str())); + if (!settings.putString("SSID", String(ssid.c_str()))) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 1); + } + if (!settings.putString("PASSWORD", String(password.c_str()))) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 2); + } #endif - settings.putUInt("BATTERY_WH_MAX", datalayer.battery.info.total_capacity_Wh); - settings.putUInt("MAXPERCENTAGE", - datalayer.battery.settings.max_percentage / 10); // Divide by 10 for backwards compatibility - settings.putUInt("MINPERCENTAGE", - datalayer.battery.settings.min_percentage / 10); // Divide by 10 for backwards compatibility - settings.putUInt("MAXCHARGEAMP", datalayer.battery.settings.max_user_set_charge_dA); - settings.putUInt("MAXDISCHARGEAMP", datalayer.battery.settings.max_user_set_discharge_dA); - settings.putBool("USE_SCALED_SOC", datalayer.battery.settings.soc_scaling_active); - settings.end(); + + if (!settings.putUInt("BATTERY_WH_MAX", datalayer.battery.info.total_capacity_Wh)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 3); + } + if (!settings.putBool("USE_SCALED_SOC", datalayer.battery.settings.soc_scaling_active)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 4); + } + if (!settings.putUInt("MAXPERCENTAGE", datalayer.battery.settings.max_percentage / 10)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 5); + } + if (!settings.putUInt("MINPERCENTAGE", datalayer.battery.settings.min_percentage / 10)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 6); + } + if (!settings.putUInt("MAXCHARGEAMP", datalayer.battery.settings.max_user_set_charge_dA)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 7); + } + if (!settings.putUInt("MAXDISCHARGEAMP", datalayer.battery.settings.max_user_set_discharge_dA)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 8); + } + if (!settings.putBool("USE_VOLTAGE_LIMITS", datalayer.battery.settings.user_set_voltage_limits_active)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 9); + } + if (!settings.putUInt("TARGETCHARGEVOLTAGE", datalayer.battery.settings.max_user_set_charge_voltage_dV)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 10); + } + if (!settings.putUInt("TARGETDISCHARGEVOLTAGE", datalayer.battery.settings.max_user_set_discharge_voltage_dV)) { + set_event(EVENT_PERSISTENT_SAVE_INFO, 11); + } + settings.end(); // Close preferences handle } /** Reset reason numbering and description diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index 2f2cf3fe..792db0bf 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -125,10 +125,16 @@ #define BATTERY_MAXTEMPERATURE 500 // -250 = -25.0 °C , Min temperature (Will produce a battery frozen event if below) #define BATTERY_MINTEMPERATURE -250 -// 300 = 30.0A , BYD CAN specific setting, Max charge in Amp (Some inverters needs to be limited) +// 300 = 30.0A , Max charge in Amp (Some inverters needs to be limited) #define BATTERY_MAX_CHARGE_AMP 300 -// 300 = 30.0A , BYD CAN specific setting, Max discharge in Amp (Some inverters needs to be limited) +// 300 = 30.0A , Max discharge in Amp (Some inverters needs to be limited) #define BATTERY_MAX_DISCHARGE_AMP 300 +// Enable this to manually set voltage limits on how much battery can be discharged/charged. Normally not used. +#define BATTERY_USE_VOLTAGE_LIMITS false +// 5000 = 500.0V , Target charge voltage (Value can be tuned on the fly via webserver). Not used unless BATTERY_USE_VOLTAGE_LIMITS = true +#define BATTERY_MAX_CHARGE_VOLTAGE 5000 +// 3000 = 300.0V, Target discharge voltage (Value can be tuned on the fly via webserver). Not used unless BATTERY_USE_VOLTAGE_LIMITS = true +#define BATTERY_MAX_DISCHARGE_VOLTAGE 3000 /* Do not change any code below this line unless you are sure what you are doing */ /* Only change battery specific settings in "USER_SETTINGS.h" */ diff --git a/Software/src/datalayer/datalayer.h b/Software/src/datalayer/datalayer.h index e6de68ce..6064aa15 100644 --- a/Software/src/datalayer/datalayer.h +++ b/Software/src/datalayer/datalayer.h @@ -107,10 +107,20 @@ typedef struct { * you want the inverter to be able to use. At this real SOC, the inverter * will "see" 100% */ uint16_t max_percentage = BATTERY_MAXPERCENTAGE; + /** The user specified maximum allowed charge rate, in deciAmpere. 300 = 30.0 A */ uint16_t max_user_set_charge_dA = BATTERY_MAX_CHARGE_AMP; /** The user specified maximum allowed discharge rate, in deciAmpere. 300 = 30.0 A */ uint16_t max_user_set_discharge_dA = BATTERY_MAX_DISCHARGE_AMP; + + /** User specified discharge/charge voltages in use. Set to true to use user specified values */ + /** Some inverters like to see a specific target voltage for charge/discharge. Use these values to override automatic voltage limits*/ + bool user_set_voltage_limits_active = BATTERY_USE_VOLTAGE_LIMITS; + /** The user specified maximum allowed charge voltage, in deciVolt. 4000 = 400.0 V */ + uint16_t max_user_set_charge_voltage_dV = BATTERY_MAX_CHARGE_VOLTAGE; + /** 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; + } DATALAYER_BATTERY_SETTINGS_TYPE; typedef struct { diff --git a/Software/src/devboard/utils/events.cpp b/Software/src/devboard/utils/events.cpp index b0c3e285..d51bd1c4 100644 --- a/Software/src/devboard/utils/events.cpp +++ b/Software/src/devboard/utils/events.cpp @@ -191,6 +191,7 @@ void init_events(void) { events.entries[EVENT_DUMMY_DEBUG].level = EVENT_LEVEL_DEBUG; events.entries[EVENT_DUMMY_WARNING].level = EVENT_LEVEL_WARNING; events.entries[EVENT_DUMMY_ERROR].level = EVENT_LEVEL_ERROR; + events.entries[EVENT_PERSISTENT_SAVE_INFO].level = EVENT_LEVEL_INFO; events.entries[EVENT_SERIAL_RX_WARNING].level = EVENT_LEVEL_WARNING; events.entries[EVENT_SERIAL_RX_FAILURE].level = EVENT_LEVEL_ERROR; events.entries[EVENT_SERIAL_TX_FAILURE].level = EVENT_LEVEL_ERROR; @@ -368,6 +369,8 @@ const char* get_event_message_string(EVENTS_ENUM_TYPE event) { return "The dummy warning event was set!"; // Don't change this event message! case EVENT_DUMMY_ERROR: return "The dummy error event was set!"; // Don't change this event message! + case EVENT_PERSISTENT_SAVE_INFO: + return "Info: Failed to save user settings. Namespace full?"; case EVENT_SERIAL_RX_WARNING: return "Error in serial function: No data received for some time, see data for minutes"; case EVENT_SERIAL_RX_FAILURE: diff --git a/Software/src/devboard/utils/events.h b/Software/src/devboard/utils/events.h index b50d7de4..d410d66f 100644 --- a/Software/src/devboard/utils/events.h +++ b/Software/src/devboard/utils/events.h @@ -6,7 +6,7 @@ // #define INCLUDE_EVENTS_TEST // Enable to run an event test loop, see events_test_on_target.cpp -#define EE_MAGIC_HEADER_VALUE 0x0017 // 0x0000 to 0xFFFF +#define EE_MAGIC_HEADER_VALUE 0x0018 // 0x0000 to 0xFFFF #define GENERATE_ENUM(ENUM) ENUM, #define GENERATE_STRING(STRING) #STRING, @@ -79,6 +79,7 @@ XX(EVENT_DUMMY_DEBUG) \ XX(EVENT_DUMMY_WARNING) \ XX(EVENT_DUMMY_ERROR) \ + XX(EVENT_PERSISTENT_SAVE_INFO) \ XX(EVENT_SERIAL_RX_WARNING) \ XX(EVENT_SERIAL_RX_FAILURE) \ XX(EVENT_SERIAL_TX_FAILURE) \ diff --git a/Software/src/devboard/webserver/settings_html.cpp b/Software/src/devboard/webserver/settings_html.cpp index 484e5021..5a26b745 100644 --- a/Software/src/devboard/webserver/settings_html.cpp +++ b/Software/src/devboard/webserver/settings_html.cpp @@ -67,6 +67,21 @@ String settings_processor(const String& var) { content += "