Feature: Huawei: add SoC stop threshold and verbose logging switch

This commit is contained in:
eu-gh 2023-09-18 21:33:28 +02:00 committed by Bernhard Kirchen
parent b9ad1e3054
commit 0ed09aeb4c
10 changed files with 82 additions and 3 deletions

View File

@ -238,13 +238,16 @@ struct CONFIG_T {
struct {
bool Enabled;
bool VerboseLogging;
uint32_t CAN_Controller_Frequency;
bool Auto_Power_Enabled;
bool Auto_Power_BatterySoC_Limits_Enabled;
bool Emergency_Charge_Enabled;
float Auto_Power_Voltage_Limit;
float Auto_Power_Enable_Voltage_Limit;
float Auto_Power_Lower_Power_Limit;
float Auto_Power_Upper_Power_Limit;
uint8_t Auto_Power_Stop_BatterySoC_Threshold;
} Huawei;

View File

@ -155,5 +155,6 @@
#define HUAWEI_AUTO_POWER_ENABLE_VOLTAGE_LIMIT 42.0
#define HUAWEI_AUTO_POWER_LOWER_POWER_LIMIT 150
#define HUAWEI_AUTO_POWER_UPPER_POWER_LIMIT 2000
#define HUAWEI_AUTO_POWER_STOP_BATTERYSOC_THRESHOLD 95
#define VERBOSE_LOGGING true

View File

@ -214,13 +214,16 @@ bool ConfigurationClass::write()
JsonObject huawei = doc.createNestedObject("huawei");
huawei["enabled"] = config.Huawei.Enabled;
huawei["verbose_logging"] = config.Huawei.VerboseLogging;
huawei["can_controller_frequency"] = config.Huawei.CAN_Controller_Frequency;
huawei["auto_power_enabled"] = config.Huawei.Auto_Power_Enabled;
huawei["auto_power_batterysoc_limits_enabled"] = config.Huawei.Auto_Power_BatterySoC_Limits_Enabled;
huawei["emergency_charge_enabled"] = config.Huawei.Emergency_Charge_Enabled;
huawei["voltage_limit"] = config.Huawei.Auto_Power_Voltage_Limit;
huawei["enable_voltage_limit"] = config.Huawei.Auto_Power_Enable_Voltage_Limit;
huawei["lower_power_limit"] = config.Huawei.Auto_Power_Lower_Power_Limit;
huawei["upper_power_limit"] = config.Huawei.Auto_Power_Upper_Power_Limit;
huawei["stop_batterysoc_threshold"] = config.Huawei.Auto_Power_Stop_BatterySoC_Threshold;
// Serialize JSON to file
if (serializeJson(doc, f) == 0) {
@ -463,13 +466,16 @@ bool ConfigurationClass::read()
JsonObject huawei = doc["huawei"];
config.Huawei.Enabled = huawei["enabled"] | HUAWEI_ENABLED;
config.Huawei.VerboseLogging = huawei["verbose_logging"] | VERBOSE_LOGGING;
config.Huawei.CAN_Controller_Frequency = huawei["can_controller_frequency"] | HUAWEI_CAN_CONTROLLER_FREQUENCY;
config.Huawei.Auto_Power_Enabled = huawei["auto_power_enabled"] | false;
config.Huawei.Auto_Power_BatterySoC_Limits_Enabled = huawei["auto_power_batterysoc_limits_enabled"] | false;
config.Huawei.Emergency_Charge_Enabled = huawei["emergency_charge_enabled"] | false;
config.Huawei.Auto_Power_Voltage_Limit = huawei["voltage_limit"] | HUAWEI_AUTO_POWER_VOLTAGE_LIMIT;
config.Huawei.Auto_Power_Enable_Voltage_Limit = huawei["enable_voltage_limit"] | HUAWEI_AUTO_POWER_ENABLE_VOLTAGE_LIMIT;
config.Huawei.Auto_Power_Lower_Power_Limit = huawei["lower_power_limit"] | HUAWEI_AUTO_POWER_LOWER_POWER_LIMIT;
config.Huawei.Auto_Power_Upper_Power_Limit = huawei["upper_power_limit"] | HUAWEI_AUTO_POWER_UPPER_POWER_LIMIT;
config.Huawei.Auto_Power_Stop_BatterySoC_Threshold = huawei["stop_batterysoc_threshold"] | HUAWEI_AUTO_POWER_STOP_BATTERYSOC_THRESHOLD;
f.close();
return true;

View File

@ -8,6 +8,7 @@
#include "PowerMeter.h"
#include "PowerLimiter.h"
#include "Configuration.h"
#include "Battery.h"
#include <SPI.h>
#include <mcp_can.h>
@ -274,6 +275,8 @@ void HuaweiCanClass::loop()
return;
}
bool verboseLogging = config.Huawei.VerboseLogging;
processReceivedParameters();
uint8_t com_error = HuaweiCanComm.getErrorCode(true);
@ -285,7 +288,7 @@ void HuaweiCanClass::loop()
}
// Print updated data
if (HuaweiCanComm.gotNewRxDataFrame(false)) {
if (HuaweiCanComm.gotNewRxDataFrame(false) && verboseLogging) {
MessageOutput.printf("[HuaweiCanClass::loop] In: %.02fV, %.02fA, %.02fW\n", _rp.input_voltage, _rp.input_current, _rp.input_power);
MessageOutput.printf("[HuaweiCanClass::loop] Out: %.02fV, %.02fA of %.02fA, %.02fW\n", _rp.output_voltage, _rp.output_current, _rp.max_output_current, _rp.output_power);
MessageOutput.printf("[HuaweiCanClass::loop] Eff : %.01f%%, Temp in: %.01fC, Temp out: %.01fC\n", _rp.efficiency * 100, _rp.input_temp, _rp.output_temp);
@ -382,7 +385,21 @@ void HuaweiCanClass::loop()
// Calculate new power limit
float newPowerLimit = -1 * round(PowerMeter.getPowerTotal());
newPowerLimit += _rp.output_power;
MessageOutput.printf("[HuaweiCanClass::loop] PL: %f, OP: %f \r\n", newPowerLimit, _rp.output_power);
if (verboseLogging){
MessageOutput.printf("[HuaweiCanClass::loop] newPowerLimit: %f, output_power: %f \r\n", newPowerLimit, _rp.output_power);
}
if (config.Battery.Enabled && config.Huawei.Auto_Power_BatterySoC_Limits_Enabled) {
uint8_t _batterySoC = Battery.getStats()->getSoC();
if (_batterySoC >= config.Huawei.Auto_Power_Stop_BatterySoC_Threshold) {
newPowerLimit = 0;
if (verboseLogging) {
MessageOutput.printf("[HuaweiCanClass::loop] Current battery SoC %i reached "
"stop threshold %i, set newPowerLimit to %f \r\n", _batterySoC,
config.Huawei.Auto_Power_Stop_BatterySoC_Threshold, newPowerLimit);
}
}
}
if (newPowerLimit > config.Huawei.Auto_Power_Lower_Power_Limit) {
@ -415,7 +432,9 @@ void HuaweiCanClass::loop()
float outputCurrent = std::min(calculatedCurrent, permissableCurrent);
outputCurrent= outputCurrent > 0 ? outputCurrent : 0;
MessageOutput.printf("[HuaweiCanClass::loop] Setting output current to %.2fA. This is the lower value of calculated %.2fA and BMS permissable %.2fA currents\r\n", outputCurrent, calculatedCurrent, permissableCurrent);
if (verboseLogging) {
MessageOutput.printf("[HuaweiCanClass::loop] Setting output current to %.2fA. This is the lower value of calculated %.2fA and BMS permissable %.2fA currents\r\n", outputCurrent, calculatedCurrent, permissableCurrent);
}
_autoPowerEnabled = true;
_setValue(outputCurrent, HUAWEI_ONLINE_CURRENT);

View File

@ -186,13 +186,16 @@ void WebApiHuaweiClass::onAdminGet(AsyncWebServerRequest* request)
const CONFIG_T& config = Configuration.get();
root["enabled"] = config.Huawei.Enabled;
root["verbose_logging"] = config.Huawei.VerboseLogging;
root["can_controller_frequency"] = config.Huawei.CAN_Controller_Frequency;
root["auto_power_enabled"] = config.Huawei.Auto_Power_Enabled;
root["auto_power_batterysoc_limits_enabled"] = config.Huawei.Auto_Power_BatterySoC_Limits_Enabled;
root["emergency_charge_enabled"] = config.Huawei.Emergency_Charge_Enabled;
root["voltage_limit"] = static_cast<int>(config.Huawei.Auto_Power_Voltage_Limit * 100) / 100.0;
root["enable_voltage_limit"] = static_cast<int>(config.Huawei.Auto_Power_Enable_Voltage_Limit * 100) / 100.0;
root["lower_power_limit"] = config.Huawei.Auto_Power_Lower_Power_Limit;
root["upper_power_limit"] = config.Huawei.Auto_Power_Upper_Power_Limit;
root["stop_batterysoc_threshold"] = config.Huawei.Auto_Power_Stop_BatterySoC_Threshold;
response->setLength();
request->send(response);
@ -253,13 +256,16 @@ void WebApiHuaweiClass::onAdminPost(AsyncWebServerRequest* request)
CONFIG_T& config = Configuration.get();
config.Huawei.Enabled = root["enabled"].as<bool>();
config.Huawei.VerboseLogging = root["verbose_logging"];
config.Huawei.CAN_Controller_Frequency = root["can_controller_frequency"].as<uint32_t>();
config.Huawei.Auto_Power_Enabled = root["auto_power_enabled"].as<bool>();
config.Huawei.Auto_Power_BatterySoC_Limits_Enabled = root["auto_power_batterysoc_limits_enabled"].as<bool>();
config.Huawei.Emergency_Charge_Enabled = root["emergency_charge_enabled"].as<bool>();
config.Huawei.Auto_Power_Voltage_Limit = root["voltage_limit"].as<float>();
config.Huawei.Auto_Power_Enable_Voltage_Limit = root["enable_voltage_limit"].as<float>();
config.Huawei.Auto_Power_Lower_Power_Limit = root["lower_power_limit"].as<float>();
config.Huawei.Auto_Power_Upper_Power_Limit = root["upper_power_limit"].as<float>();
config.Huawei.Auto_Power_Stop_BatterySoC_Threshold = root["stop_batterysoc_threshold"];
WebApi.writeConfig(retMsg);
response->setLength();

View File

@ -835,9 +835,12 @@
"ChargerSettings": "AC Ladegerät Einstellungen",
"Configuration": "AC Ladegerät Konfiguration",
"EnableHuawei": "Huawei R4850G2 an CAN Bus Interface aktiv",
"VerboseLogging": "@:base.VerboseLogging",
"CanControllerFrequency": "Frequenz des Quarzes am CAN Controller",
"EnableAutoPower": "Automatische Leistungssteuerung",
"EnableBatterySoCLimits": "Ladezustand einer angeschlossenen Batterie berücksichtigen",
"Limits": "Limits",
"BatterySoCLimits": "Batterie SoC-Limits",
"VoltageLimit": "Ladespannungslimit",
"enableVoltageLimit": "Start Spannungslimit",
"stopVoltageLimitHint": "Maximal Spannung des Ladegeräts. Entspricht der geünschten Ladeschlussspannung der Batterie. Verwendet für die Automatische Leistungssteuerung und beim Notfallladen",
@ -845,6 +848,8 @@
"maxPowerLimitHint": "Maximale Ausgangsleistung. Verwendet für die Automatische Leistungssteuerung und beim Notfallladen",
"lowerPowerLimit": "Minimale Leistung",
"upperPowerLimit": "Maximale Leistung",
"StopBatterySoCThreshold": "Laden bei SoC beenden",
"StopBatterySoCThresholdHint": "Zur Verlängerung der Akku-Lebensdauer kann der Ladevorgang bei einem bestimmten SoC gestoppt werden.\nHinweis: Manche LiFePO-Akkus müssen gelegentlich voll geladen werden, um die SoC-Anzeige akkurat zu halten.",
"Seconds": "@:base.Seconds",
"EnableEmergencyCharge": "Notfallladen: Batterie wird mit maximaler Leistung geladen wenn durch das Batterie BMS angefordert"
},

View File

@ -842,9 +842,12 @@
"ChargerSettings": "AC Charger Settings",
"Configuration": "AC Charger Configuration",
"EnableHuawei": "Enable Huawei R4850G2 on CAN Bus Interface",
"VerboseLogging": "@:base.VerboseLogging",
"CanControllerFrequency": "CAN controller quarz frequency",
"EnableAutoPower": "Automatic power control",
"EnableBatterySoCLimits": "Use SoC data of a connected battery",
"Limits": "Limits",
"BatterySoCLimits": "Battery SoC Limits",
"VoltageLimit": "Charge Voltage limit",
"enableVoltageLimit": "Re-enable voltage limit",
"stopVoltageLimitHint": "Maximum charger voltage. Equals battery charge voltage limit. Used for automatic power control and when emergency charging",
@ -852,6 +855,8 @@
"maxPowerLimitHint": "Maximum output power. Used for automatic power control and when emergency charging",
"lowerPowerLimit": "Minimum output power",
"upperPowerLimit": "Maximum output power",
"StopBatterySoCThreshold": "Stop charging at SoC",
"StopBatterySoCThresholdHint": "To prolong the battery's lifespan, charging can be stopped at a certain SoC level.\nHint: In order to keep the SoC reading accurate, some LiFePO cells must be charged to full capacity regularly.",
"Seconds": "@:base.Seconds",
"EnableEmergencyCharge": "Emergency charge. Battery charged with maximum power if requested by Battery BMS"
},

View File

@ -833,9 +833,12 @@
"ChargerSettings": "AC Charger Settings",
"Configuration": "AC Charger Configuration",
"EnableHuawei": "Enable Huawei R4850G2 on CAN Bus Interface",
"VerboseLogging": "@:base.VerboseLogging",
"CanControllerFrequency": "CAN controller quarz frequency",
"EnableAutoPower": "Automatic power control",
"EnableBatterySoCLimits": "Use SoC data of a connected battery",
"Limits": "Limits",
"BatterySoCLimits": "Battery SoC Limits",
"VoltageLimit": "Charge Voltage limit",
"enableVoltageLimit": "Re-enable voltage limit",
"stopVoltageLimitHint": "Maximum charger voltage. Equals battery charge voltage limit. Used for automatic power control and when emergency charging",
@ -843,6 +846,8 @@
"maxPowerLimitHint": "Maximum output power. Used for automatic power control and when emergency charging",
"lowerPowerLimit": "Minimum output power",
"upperPowerLimit": "Maximum output power",
"StopBatterySoCThreshold": "Stop charging at SoC",
"StopBatterySoCThresholdHint": "To prolong the battery's lifespan, charging can be stopped at a certain SoC level.\nHint: In order to keep the SoC reading accurate, some LiFePO cells must be charged to full capacity regularly.",
"Seconds": "@:base.Seconds",
"EnableEmergencyCharge": "Emergency charge. Battery charged with maximum power if requested by Battery BMS"
},

View File

@ -1,10 +1,13 @@
export interface AcChargerConfig {
enabled: boolean;
verbose_logging: boolean;
can_controller_frequency: number;
auto_power_enabled: boolean;
auto_power_batterysoc_limits_enabled: boolean;
voltage_limit: number;
enable_voltage_limit: number;
lower_power_limit: number;
upper_power_limit: number;
emergency_charge_enabled: boolean;
stop_batterysoc_threshold: number;
}

View File

@ -23,11 +23,21 @@
</div>
</div>
<InputElement v-show="acChargerConfigList.enabled"
:label="$t('acchargeradmin.VerboseLogging')"
v-model="acChargerConfigList.verbose_logging"
type="checkbox" wide/>
<InputElement v-show="acChargerConfigList.enabled"
:label="$t('acchargeradmin.EnableAutoPower')"
v-model="acChargerConfigList.auto_power_enabled"
type="checkbox" wide/>
<InputElement v-show="acChargerConfigList.enabled && acChargerConfigList.auto_power_enabled"
:label="$t('acchargeradmin.EnableBatterySoCLimits')"
v-model="acChargerConfigList.auto_power_batterysoc_limits_enabled"
type="checkbox" wide />
<InputElement v-show="acChargerConfigList.enabled"
:label="$t('acchargeradmin.EnableEmergencyCharge')"
v-model="acChargerConfigList.emergency_charge_enabled"
@ -80,6 +90,22 @@
</div>
</div>
</CardElement>
<CardElement :text="$t('acchargeradmin.BatterySoCLimits')" textVariant="text-bg-primary" add-space
v-show="acChargerConfigList.auto_power_enabled && acChargerConfigList.auto_power_batterysoc_limits_enabled">
<div class="row mb-3">
<label for="stopBatterySoCThreshold" class="col-sm-2 col-form-label">{{ $t('acchargeradmin.StopBatterySoCThreshold') }}:
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.StopBatterySoCThresholdHint')" />
</label>
<div class="col-sm-10">
<div class="input-group">
<input type="number" class="form-control" id="stopBatterySoCThreshold"
placeholder="95" v-model="acChargerConfigList.stop_batterysoc_threshold"
aria-describedby="stopBatterySoCThresholdDescription" min="2" max="100" required/>
<span class="input-group-text" id="stopBatterySoCThresholdDescription">%</span>
</div>
</div>
</div>
</CardElement>
</CardElement>
<FormFooter @reload="getChargerConfig"/>