Make more settings configurable

This commit is contained in:
Daniel Öster 2025-09-02 19:42:26 +03:00
parent 3e56549498
commit 224c33ec1d
8 changed files with 92 additions and 48 deletions

View file

@ -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();

View file

@ -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");
}

View file

@ -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
*

View file

@ -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) {

View file

@ -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

View file

@ -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) {
<label>Remote BMS reset: </label>
<input type='checkbox' name='REMBMSRESET' value='on' style='margin-left: 0;' %REMBMSRESET% />
<label>External precharge via HIA4V1: </label>
<input type='checkbox' name='EXTPRECHARGE' value='on' style='margin-left: 0;' %EXTPRECHARGE% />
<div class="if-extprecharge">
<label>Precharge, maximum ms before fault: </label>
<input name='MAXPRETIME' type='text' value="%MAXPRETIME%" pattern="^[0-9]+$" />
<label>Normally Open inverter disconnect contactor: </label>
<input type='checkbox' name='NOINVDISC' value='on' style='margin-left: 0;' %NOINVDISC% />
</div>
</div>
<label>Use CanFD as classic CAN: </label>
<input type='checkbox' name='CANFDASCAN' value='on' style='margin-left: 0;' %CANFDASCAN% />
@ -1047,7 +1085,8 @@ const char* getCANInterfaceName(CAN_Interface interface) {
<label>MQTT port: </label><input type='text' name='MQTTPORT' value="%MQTTPORT%" />
<label>MQTT user: </label><input type='text' name='MQTTUSER' value="%MQTTUSER%" />
<label>MQTT password: </label><input type='password' name='MQTTPASSWORD' value="%MQTTPASSWORD%" />
<label>MQTT timeout ms: </label><input name='MQTTTIMEOUT' type='text' value="%MQTTTIMEOUT%" pattern="^[0-9]+$" />
<label>Send all cellvoltages via MQTT: </label><input type='checkbox' name='MQTTCELLV' value='on' style='margin-left: 0;' %MQTTCELLV% />
<label>Customized MQTT topics: </label>
<input type='checkbox' name='MQTTTOPICS' value='on' style='margin-left: 0;' %MQTTTOPICS% />
@ -1057,7 +1096,7 @@ const char* getCANInterfaceName(CAN_Interface interface) {
<label>Prefix for MQTT object ID: </label><input type='text' name='MQTTOBJIDPREFIX' value="%MQTTOBJIDPREFIX%" />
<label>HA device name: </label><input type='text' name='MQTTDEVICENAME' value="%MQTTDEVICENAME%" />
<label>HA device ID: </label><input type='text' name='HADEVICEID' value="%HADEVICEID%" />
</div>
<label>Enable Home Assistant auto discovery: </label>

View file

@ -396,9 +396,10 @@ void init_webserver() {
};
const char* boolSettingNames[] = {
"DBLBTR", "CNTCTRL", "CNTCTRLDBL", "PWMCNTCTRL", "PERBMSRESET", "SDLOGENABLED", "REMBMSRESET",
"USBENABLED", "CANLOGUSB", "WEBENABLED", "CANFDASCAN", "CANLOGSD", "WIFIAPENABLED", "MQTTENABLED",
"HADISC", "MQTTTOPICS", "INVICNT", "GTWRHD", "DIGITALHVIL", "PERFPROFILE", "INTERLOCKREQ",
"DBLBTR", "CNTCTRL", "CNTCTRLDBL", "PWMCNTCTRL", "PERBMSRESET", "SDLOGENABLED",
"REMBMSRESET", "EXTPRECHARGE", "USBENABLED", "CANLOGUSB", "WEBENABLED", "CANFDASCAN",
"CANLOGSD", "WIFIAPENABLED", "MQTTENABLED", "NOINVDISC", "HADISC", "MQTTTOPICS",
"MQTTCELLV", "INVICNT", "GTWRHD", "DIGITALHVIL", "PERFPROFILE", "INTERLOCKREQ",
};
// Handles the form POST from UI to save settings of the common image
@ -459,6 +460,9 @@ void init_webserver() {
} else if (p->name() == "SHUNTCOMM") {
auto type = static_cast<comm_interface>(atoi(p->value().c_str()));
settings.saveUInt("SHUNTCOMM", (int)type);
} else if (p->name() == "MAXPRETIME") {
auto type = atoi(p->value().c_str());
settings.saveUInt("MAXPRETIME", type);
} else if (p->name() == "HOSTNAME") {
settings.saveString("HOSTNAME", p->value().c_str());
} else if (p->name() == "MQTTSERVER") {
@ -472,6 +476,8 @@ void init_webserver() {
settings.saveString("MQTTPASSWORD", p->value().c_str());
} else if (p->name() == "MQTTTOPIC") {
settings.saveString("MQTTTOPIC", p->value().c_str());
} else if (p->name() == "MQTTTIMEOUT") {
settings.saveString("MQTTTIMEOUT", p->value().c_str());
} else if (p->name() == "MQTTOBJIDPREFIX") {
settings.saveString("MQTTOBJIDPREFIX", p->value().c_str());
} else if (p->name() == "MQTTDEVICENAME") {