diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index 30e2a80a..e2873c17 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -7,10 +7,6 @@ /* Shunt/Contactor settings (Optional) */ //#define BMW_SBOX // SBOX relay control & battery current/voltage measurement -/* Automatic Precharge settings (Optional) If you have a battery that expects an external voltage applied before opening contactors (within the battery), configure this section */ -//#define PRECHARGE_CONTROL //Enable this line to control a modified HIA4V1 via PWM on the HIA4V1_PIN (see Wiki and HAL for pin definition) -//#define INVERTER_DISCONNECT_CONTACTOR_IS_NORMALLY_OPEN //Enable this line if you use a normally open contactor instead of normally closed - /* Connectivity options */ //#define WIFICONFIG //Enable this line to set a static IP address / gateway /subnet mask for the device. see USER_SETTINGS.cpp for the settings diff --git a/Software/src/communication/nvm/comm_nvm.cpp b/Software/src/communication/nvm/comm_nvm.cpp index 8869fc15..2cb7a89e 100644 --- a/Software/src/communication/nvm/comm_nvm.cpp +++ b/Software/src/communication/nvm/comm_nvm.cpp @@ -8,6 +8,7 @@ #include "../../devboard/wifi/wifi.h" #include "../../inverter/INVERTERS.h" #include "../contactorcontrol/comm_contactorcontrol.h" +#include "../precharge_control/precharge_control.h" // Parameters Preferences settings; // Store user settings @@ -142,6 +143,10 @@ void init_stored_settings() { remote_bms_reset = settings.getBool("REMBMSRESET", false); use_canfd_as_can = settings.getBool("CANFDASCAN", false); + precharge_control_enabled = settings.getBool("EXTPRECHARGE", false); + precharge_inverter_normally_open_contactor = settings.getBool("NOINVDISC", false); + precharge_max_precharge_time_before_fault = settings.getUInt("MAXPRETIME", 15000); + datalayer.system.info.performance_measurement_active = settings.getBool("PERFPROFILE", false); datalayer.system.info.CAN_usb_logging_active = settings.getBool("CANLOGUSB", false); datalayer.system.info.usb_logging_active = settings.getBool("USBENABLED", false); @@ -154,8 +159,9 @@ void init_stored_settings() { wifiap_enabled = settings.getBool("WIFIAPENABLED", true); passwordAP = settings.getString("APPASSWORD", "123456789").c_str(); mqtt_enabled = settings.getBool("MQTTENABLED", false); + mqtt_timeout_ms = settings.getUInt("MQTTTIMEOUT", 2000); ha_autodiscovery_enabled = settings.getBool("HADISC", false); - + mqtt_transmit_all_cellvoltages = settings.getBool("MQTTCELLV", false); custom_hostname = settings.getString("HOSTNAME").c_str(); mqtt_server = settings.getString("MQTTSERVER").c_str(); diff --git a/Software/src/communication/precharge_control/precharge_control.cpp b/Software/src/communication/precharge_control/precharge_control.cpp index be7a01ce..31acf342 100644 --- a/Software/src/communication/precharge_control/precharge_control.cpp +++ b/Software/src/communication/precharge_control/precharge_control.cpp @@ -4,29 +4,21 @@ #include "../../datalayer/datalayer_extended.h" #include "../../devboard/hal/hal.h" -#ifdef PRECHARGE_CONTROL -const bool precharge_control_enabled_default = true; -#else -const bool precharge_control_enabled_default = false; -#endif +// Parameters adjustable by user in Settings page +bool precharge_control_enabled = false; +bool precharge_inverter_normally_open_contactor = false; +uint16_t precharge_max_precharge_time_before_fault = 15000; -bool precharge_control_enabled = precharge_control_enabled_default; - -// Parameters -#define MAX_PRECHARGE_TIME_MS 15000 // Maximum time precharge may be enabled +// Hardcoded parameters #define Precharge_default_PWM_Freq 11000 #define Precharge_min_PWM_Freq 5000 #define Precharge_max_PWM_Freq 34000 #define Precharge_PWM_Res 8 #define PWM_Freq 20000 // 20 kHz frequency, beyond audible range #define PWM_Precharge_Channel 0 -#ifndef INVERTER_DISCONNECT_CONTACTOR_IS_NORMALLY_OPEN -#define ON 0 //Normally closed contactors use inverted logic -#define OFF 1 //Normally closed contactors use inverted logic -#else -#define ON 1 -#define OFF 0 -#endif +#define CONTACTOR_ON (precharge_inverter_normally_open_contactor ? 1 : 0) +#define CONTACTOR_OFF (precharge_inverter_normally_open_contactor ? 0 : 1) + static unsigned long prechargeStartTime = 0; static uint32_t freq = Precharge_default_PWM_Freq; static uint16_t delta_freq = 1; @@ -66,7 +58,7 @@ void handle_precharge_control(unsigned long currentMillis) { if (datalayer.system.status.precharge_status == AUTO_PRECHARGE_FAILURE) { pinMode(hia4v1_pin, OUTPUT); digitalWrite(hia4v1_pin, LOW); - digitalWrite(inverter_disconnect_contactor_pin, ON); + digitalWrite(inverter_disconnect_contactor_pin, CONTACTOR_ON); return; // Exit immediately - no further processing allowed. Reboot required to recover } @@ -86,7 +78,7 @@ void handle_precharge_control(unsigned long currentMillis) { prechargeStartTime = currentMillis; datalayer.system.status.precharge_status = AUTO_PRECHARGE_PRECHARGING; logging.printf("Precharge: Starting sequence\n"); - digitalWrite(inverter_disconnect_contactor_pin, OFF); + digitalWrite(inverter_disconnect_contactor_pin, CONTACTOR_OFF); break; case AUTO_PRECHARGE_PRECHARGING: @@ -120,14 +112,14 @@ void handle_precharge_control(unsigned long currentMillis) { datalayer.battery.status.bms_status != ACTIVE || datalayer.system.settings.equipment_stop_active) { pinMode(hia4v1_pin, OUTPUT); digitalWrite(hia4v1_pin, LOW); - digitalWrite(inverter_disconnect_contactor_pin, ON); + digitalWrite(inverter_disconnect_contactor_pin, CONTACTOR_ON); datalayer.system.status.precharge_status = AUTO_PRECHARGE_IDLE; logging.printf("Precharge: Disabling Precharge bms not standby/active or equipment stop\n"); - } else if (currentMillis - prechargeStartTime >= MAX_PRECHARGE_TIME_MS || + } else if (currentMillis - prechargeStartTime >= precharge_max_precharge_time_before_fault || datalayer.battery.status.real_bms_status == BMS_FAULT) { pinMode(hia4v1_pin, OUTPUT); digitalWrite(hia4v1_pin, LOW); - digitalWrite(inverter_disconnect_contactor_pin, ON); + digitalWrite(inverter_disconnect_contactor_pin, CONTACTOR_ON); datalayer.system.status.precharge_status = AUTO_PRECHARGE_FAILURE; logging.printf("Precharge: CRITICAL FAILURE (timeout/BMS fault) -> REQUIRES REBOOT\n"); set_event(EVENT_AUTOMATIC_PRECHARGE_FAILURE, 0); @@ -137,7 +129,7 @@ void handle_precharge_control(unsigned long currentMillis) { } else if (datalayer.system.status.battery_allows_contactor_closing) { pinMode(hia4v1_pin, OUTPUT); digitalWrite(hia4v1_pin, LOW); - digitalWrite(inverter_disconnect_contactor_pin, ON); + digitalWrite(inverter_disconnect_contactor_pin, CONTACTOR_ON); datalayer.system.status.precharge_status = AUTO_PRECHARGE_COMPLETED; logging.printf("Precharge: Disabled (contacts closed) -> COMPLETED\n"); } diff --git a/Software/src/communication/precharge_control/precharge_control.h b/Software/src/communication/precharge_control/precharge_control.h index 0262ebd7..f02e082e 100644 --- a/Software/src/communication/precharge_control/precharge_control.h +++ b/Software/src/communication/precharge_control/precharge_control.h @@ -3,6 +3,11 @@ #include "../../devboard/utils/events.h" +// TODO: Ensure valid values at run-time +// User can update all these values via Settings page +extern bool precharge_control_enabled; +extern bool precharge_inverter_normally_open_contactor; +extern uint16_t precharge_max_precharge_time_before_fault; /** * @brief Contactor initialization * diff --git a/Software/src/devboard/mqtt/mqtt.cpp b/Software/src/devboard/mqtt/mqtt.cpp index 525df501..c5a5ee2f 100644 --- a/Software/src/devboard/mqtt/mqtt.cpp +++ b/Software/src/devboard/mqtt/mqtt.cpp @@ -16,6 +16,8 @@ bool mqtt_enabled = false; bool ha_autodiscovery_enabled = false; +bool mqtt_transmit_all_cellvoltages = false; +uint16_t mqtt_timeout_ms = 2000; const int mqtt_port_default = 0; const char* mqtt_server_default = ""; @@ -29,10 +31,7 @@ bool mqtt_manual_topic_object_name = // This naming convention was in place until version 7.5.0. Users should check the version from which they are updating, as this change // may break compatibility with previous versions of MQTT naming -#define MQTT_PUBLISH_CELL_VOLTAGES // Enable this line to publish cell voltages to MQTT -#define MQTT_QOS 0 // MQTT Quality of Service (0, 1, or 2) -#define MQTT_TIMEOUT 2000 // MQTT timeout in milliseconds - //TODO: Should all these defines be a configurable option? +#define MQTT_QOS 0 // MQTT Quality of Service (0, 1, or 2) //TODO: Should this be configurable? esp_mqtt_client_config_t mqtt_cfg; esp_mqtt_client_handle_t client; @@ -67,17 +66,17 @@ static void publish_values(void) { return; } -#ifdef MQTT_PUBLISH_CELL_VOLTAGES - if (publish_cell_voltages() == false) { - return; + if (mqtt_transmit_all_cellvoltages) { + if (publish_cell_voltages() == false) { + return; + } } -#endif -#ifdef MQTT_PUBLISH_CELL_VOLTAGES - if (publish_cell_balancing() == false) { - return; + if (mqtt_transmit_all_cellvoltages) { + if (publish_cell_balancing() == false) { + return; + } } -#endif } static bool ha_common_info_published = false; @@ -655,7 +654,7 @@ bool init_mqtt(void) { mqtt_cfg.session.last_will.retain = true; mqtt_cfg.session.last_will.msg = "offline"; mqtt_cfg.session.last_will.msg_len = strlen(mqtt_cfg.session.last_will.msg); - mqtt_cfg.network.timeout_ms = MQTT_TIMEOUT; + mqtt_cfg.network.timeout_ms = mqtt_timeout_ms; client = esp_mqtt_client_init(&mqtt_cfg); if (client == nullptr) { diff --git a/Software/src/devboard/mqtt/mqtt.h b/Software/src/devboard/mqtt/mqtt.h index 46261d5b..4189ca91 100644 --- a/Software/src/devboard/mqtt/mqtt.h +++ b/Software/src/devboard/mqtt/mqtt.h @@ -42,6 +42,10 @@ extern const char* version_number; // The current software version, used for mqtt +extern bool mqtt_enabled; +extern bool mqtt_transmit_all_cellvoltages; +extern uint16_t mqtt_timeout_ms; +extern bool ha_autodiscovery_enabled; extern std::string mqtt_server; extern std::string mqtt_user; extern std::string mqtt_password; @@ -57,7 +61,4 @@ bool init_mqtt(void); void mqtt_loop(void); bool mqtt_publish(const char* topic, const char* mqtt_msg, bool retain); -extern bool mqtt_enabled; -extern bool ha_autodiscovery_enabled; - #endif diff --git a/Software/src/devboard/webserver/settings_html.cpp b/Software/src/devboard/webserver/settings_html.cpp index 0517962b..74825e3d 100644 --- a/Software/src/devboard/webserver/settings_html.cpp +++ b/Software/src/devboard/webserver/settings_html.cpp @@ -270,6 +270,18 @@ String settings_processor(const String& var, BatteryEmulatorSettingsStore& setti return settings.getBool("REMBMSRESET") ? "checked" : ""; } + if (var == "EXTPRECHARGE") { + return settings.getBool("EXTPRECHARGE") ? "checked" : ""; + } + + if (var == "MAXPRETIME") { + return String(settings.getUInt("MAXPRETIME", 15000)); + } + + if (var == "NOINVDISC") { + return settings.getBool("NOINVDISC") ? "checked" : ""; + } + if (var == "CANFDASCAN") { return settings.getBool("CANFDASCAN") ? "checked" : ""; } @@ -330,6 +342,10 @@ String settings_processor(const String& var, BatteryEmulatorSettingsStore& setti return settings.getString("MQTTTOPIC"); } + if (var == "MQTTTIMEOUT") { + return String(settings.getUInt("MQTTTIMEOUT", 2000)); + } + if (var == "MQTTOBJIDPREFIX") { return settings.getString("MQTTOBJIDPREFIX"); } @@ -338,6 +354,10 @@ String settings_processor(const String& var, BatteryEmulatorSettingsStore& setti return settings.getString("MQTTDEVICENAME"); } + if (var == "MQTTCELLV") { + return settings.getBool("MQTTCELLV") ? "checked" : ""; + } + if (var == "HADEVICEID") { return settings.getString("HADEVICEID"); } @@ -807,6 +827,11 @@ const char* getCANInterfaceName(CAN_Interface interface) { display: contents; } + form .if-extprecharge { display: none; } + form[data-extprecharge="true"] .if-extprecharge { + display: contents; + } + form .if-sofar { display: none; } form[data-inverter="17"] .if-sofar { display: contents; @@ -1008,6 +1033,19 @@ const char* getCANInterfaceName(CAN_Interface interface) { + + + +