From f645adc9368976493d2cdc7ffba8f1dcab4dd90a Mon Sep 17 00:00:00 2001 From: Bernhard Kirchen Date: Sun, 15 Oct 2023 19:34:05 +0200 Subject: [PATCH] AC charger: make CAN controller frequency configurable --- include/Configuration.h | 1 + include/Huawei_can.h | 3 ++- include/defaults.h | 1 + src/Configuration.cpp | 2 ++ src/Huawei_can.cpp | 13 ++++++++++--- src/WebApi_Huawei.cpp | 11 +++++++++++ webapp/src/locales/de.json | 1 + webapp/src/locales/en.json | 1 + webapp/src/locales/fr.json | 1 + webapp/src/types/AcChargerConfig.ts | 1 + webapp/src/views/AcChargerAdminView.vue | 18 ++++++++++++++++++ 11 files changed, 49 insertions(+), 4 deletions(-) diff --git a/include/Configuration.h b/include/Configuration.h index 8cb44caf8..55d31acd7 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -177,6 +177,7 @@ struct CONFIG_T { uint8_t Battery_JkBmsPollingInterval; bool Huawei_Enabled; + uint32_t Huawei_CAN_Controller_Frequency; bool Huawei_Auto_Power_Enabled; float Huawei_Auto_Power_Voltage_Limit; float Huawei_Auto_Power_Enable_Voltage_Limit; diff --git a/include/Huawei_can.h b/include/Huawei_can.h index 3b0634110..eb69c6c53 100644 --- a/include/Huawei_can.h +++ b/include/Huawei_can.h @@ -90,7 +90,8 @@ typedef struct RectifierParameters { class HuaweiCanCommClass { public: - bool init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huawei_clk, uint8_t huawei_irq, uint8_t huawei_cs); + bool init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huawei_clk, + uint8_t huawei_irq, uint8_t huawei_cs, uint32_t frequency); void loop(); bool gotNewRxDataFrame(bool clear); uint8_t getErrorCode(bool clear); diff --git a/include/defaults.h b/include/defaults.h index c02067411..47bea0255 100644 --- a/include/defaults.h +++ b/include/defaults.h @@ -137,6 +137,7 @@ #define BATTERY_JKBMS_POLLING_INTERVAL 5 #define HUAWEI_ENABLED false +#define HUAWEI_CAN_CONTROLLER_FREQUENCY 8000000UL #define HUAWEI_AUTO_POWER_VOLTAGE_LIMIT 42.0 #define HUAWEI_AUTO_POWER_ENABLE_VOLTAGE_LIMIT 42.0 #define HUAWEI_AUTO_POWER_LOWER_POWER_LIMIT 150 diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 74a126152..b223738c6 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -190,6 +190,7 @@ bool ConfigurationClass::write() JsonObject huawei = doc.createNestedObject("huawei"); huawei["enabled"] = config.Huawei_Enabled; + huawei["can_controller_frequency"] = config.Huawei_CAN_Controller_Frequency; huawei["auto_power_enabled"] = config.Huawei_Auto_Power_Enabled; huawei["voltage_limit"] = config.Huawei_Auto_Power_Voltage_Limit; huawei["enable_voltage_limit"] = config.Huawei_Auto_Power_Enable_Voltage_Limit; @@ -413,6 +414,7 @@ bool ConfigurationClass::read() JsonObject huawei = doc["huawei"]; config.Huawei_Enabled = huawei["enabled"] | HUAWEI_ENABLED; + 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_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; diff --git a/src/Huawei_can.cpp b/src/Huawei_can.cpp index 5a6341d19..ffc8929ef 100644 --- a/src/Huawei_can.cpp +++ b/src/Huawei_can.cpp @@ -30,7 +30,8 @@ void HuaweiCanCommunicationTask(void* parameter) { } } -bool HuaweiCanCommClass::init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huawei_clk, uint8_t huawei_irq, uint8_t huawei_cs) { +bool HuaweiCanCommClass::init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huawei_clk, + uint8_t huawei_irq, uint8_t huawei_cs, uint32_t frequency) { SPI = new SPIClass(HSPI); SPI->begin(huawei_clk, huawei_miso, huawei_mosi, huawei_cs); pinMode(huawei_cs, OUTPUT); @@ -39,8 +40,14 @@ bool HuaweiCanCommClass::init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t pinMode(huawei_irq, INPUT_PULLUP); _huaweiIrq = huawei_irq; + auto mcp_frequency = MCP_8MHZ; + if (16000000UL == frequency) { mcp_frequency = MCP_16MHZ; } + else if (8000000UL != frequency) { + MessageOutput.printf("Huawei CAN: unknown frequency %d Hz, using 8 MHz\r\n", mcp_frequency); + } + _CAN = new MCP_CAN(SPI, huawei_cs); - if (!_CAN->begin(MCP_STDEXT, CAN_125KBPS, MCP_8MHZ) == CAN_OK) { + if (!_CAN->begin(MCP_STDEXT, CAN_125KBPS, mcp_frequency) == CAN_OK) { return false; } @@ -198,7 +205,7 @@ void HuaweiCanClass::init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huaw return; } - if (!HuaweiCanComm.init(huawei_miso, huawei_mosi, huawei_clk, huawei_irq, huawei_cs)) { + if (!HuaweiCanComm.init(huawei_miso, huawei_mosi, huawei_clk, huawei_irq, huawei_cs, config.Huawei_CAN_Controller_Frequency)) { MessageOutput.println("[HuaweiCanClass::init] Error Initializing Huawei CAN communication..."); return; }; diff --git a/src/WebApi_Huawei.cpp b/src/WebApi_Huawei.cpp index f8f75e234..2a7689aee 100644 --- a/src/WebApi_Huawei.cpp +++ b/src/WebApi_Huawei.cpp @@ -190,6 +190,7 @@ void WebApiHuaweiClass::onAdminGet(AsyncWebServerRequest* request) const CONFIG_T& config = Configuration.get(); root[F("enabled")] = config.Huawei_Enabled; + root[F("can_controller_frequency")] = config.Huawei_CAN_Controller_Frequency; root[F("auto_power_enabled")] = config.Huawei_Auto_Power_Enabled; root[F("voltage_limit")] = static_cast(config.Huawei_Auto_Power_Voltage_Limit * 100) / 100.0; root[F("enable_voltage_limit")] = static_cast(config.Huawei_Auto_Power_Enable_Voltage_Limit * 100) / 100.0; @@ -240,6 +241,7 @@ void WebApiHuaweiClass::onAdminPost(AsyncWebServerRequest* request) } if (!(root.containsKey("enabled")) || + !(root.containsKey("can_controller_frequency")) || !(root.containsKey("auto_power_enabled")) || !(root.containsKey("voltage_limit")) || !(root.containsKey("lower_power_limit")) || @@ -253,6 +255,7 @@ void WebApiHuaweiClass::onAdminPost(AsyncWebServerRequest* request) CONFIG_T& config = Configuration.get(); config.Huawei_Enabled = root[F("enabled")].as(); + config.Huawei_CAN_Controller_Frequency = root[F("can_controller_frequency")].as(); config.Huawei_Auto_Power_Enabled = root[F("auto_power_enabled")].as(); config.Huawei_Auto_Power_Voltage_Limit = root[F("voltage_limit")].as(); config.Huawei_Auto_Power_Enable_Voltage_Limit = root[F("enable_voltage_limit")].as(); @@ -267,6 +270,14 @@ void WebApiHuaweiClass::onAdminPost(AsyncWebServerRequest* request) response->setLength(); request->send(response); + // TODO(schlimmchen): HuaweiCan has no real concept of the fact that the + // config might change. at least not regarding CAN parameters. until that + // changes, the ESP must restart for configuration changes to take effect. + yield(); + delay(1000); + yield(); + ESP.restart(); + const PinMapping_t& pin = PinMapping.get(); // Properly turn this on if (config.Huawei_Enabled) { diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index 3ee579527..4ef2655dc 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -777,6 +777,7 @@ "ChargerSettings": "AC Ladegerät Einstellungen", "Configuration": "AC Ladegerät Konfiguration", "EnableHuawei": "Huawei R4850G2 an CAN Bus Interface aktiv", + "CanControllerFrequency": "Frequenz des Quarzes am CAN Controller", "EnableAutoPower": "Automatische Leistungssteuerung", "Limits": "Limits", "VoltageLimit": "Ladespannungslimit", diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index 71a7d63b5..2da7e8d6f 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -787,6 +787,7 @@ "ChargerSettings": "AC Charger Settings", "Configuration": "AC Charger Configuration", "EnableHuawei": "Enable Huawei R4850G2 on CAN Bus Interface", + "CanControllerFrequency": "CAN controller quarz frequency", "EnableAutoPower": "Automatic power control", "Limits": "Limits", "VoltageLimit": "Charge Voltage limit", diff --git a/webapp/src/locales/fr.json b/webapp/src/locales/fr.json index 496022529..e33128690 100644 --- a/webapp/src/locales/fr.json +++ b/webapp/src/locales/fr.json @@ -743,6 +743,7 @@ "ChargerSettings": "AC Charger Settings", "Configuration": "AC Charger Configuration", "EnableHuawei": "Enable Huawei R4850G2 on CAN Bus Interface", + "CanControllerFrequency": "CAN controller quarz frequency", "EnableAutoPower": "Automatic power control", "Limits": "Limits", "VoltageLimit": "Charge Voltage limit", diff --git a/webapp/src/types/AcChargerConfig.ts b/webapp/src/types/AcChargerConfig.ts index e50dc7aae..2e1b9ca89 100644 --- a/webapp/src/types/AcChargerConfig.ts +++ b/webapp/src/types/AcChargerConfig.ts @@ -1,5 +1,6 @@ export interface AcChargerConfig { enabled: boolean; + can_controller_frequency: number; auto_power_enabled: boolean; voltage_limit: number; enable_voltage_limit: number; diff --git a/webapp/src/views/AcChargerAdminView.vue b/webapp/src/views/AcChargerAdminView.vue index d6473769c..09527d58d 100644 --- a/webapp/src/views/AcChargerAdminView.vue +++ b/webapp/src/views/AcChargerAdminView.vue @@ -9,6 +9,20 @@ + +
+ +
+ +
+
+