Feature: Huawei: add SoC stop threshold and verbose logging switch
This commit is contained in:
parent
b9ad1e3054
commit
0ed09aeb4c
@ -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;
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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"
|
||||
},
|
||||
|
||||
@ -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"
|
||||
},
|
||||
|
||||
@ -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"
|
||||
},
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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"/>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user