From dedb9fbe7be00e27870303232ad9d629e69d4473 Mon Sep 17 00:00:00 2001 From: Cornelius Claussen Date: Tue, 30 Jul 2024 12:54:30 +0200 Subject: [PATCH] DC Power supply: Add charging phase information Signed-off-by: Cornelius Claussen --- interfaces/ISO15118_charger.yaml | 3 + interfaces/power_supply_DC.yaml | 9 +- modules/DPM1000/main/power_supply_DCImpl.cpp | 5 +- modules/DPM1000/main/power_supply_DCImpl.hpp | 3 +- modules/EvseManager/EvseManager.cpp | 39 +++-- modules/EvseManager/EvseManager.hpp | 6 + modules/EvseV2G/din_server.cpp | 1 + modules/EvseV2G/iso_server.cpp | 1 + .../dc_supply/power_supply_DCImpl.cpp | 5 +- .../dc_supply/power_supply_DCImpl.hpp | 3 +- modules/simulation/CMakeLists.txt | 1 - .../main/power_supply_DCImpl.cpp | 16 +- .../main/power_supply_DCImpl.hpp | 3 +- .../JsDCSupplySimulator/CMakeLists.txt | 0 .../simulation/JsDCSupplySimulator/index.js | 165 ------------------ .../JsDCSupplySimulator/manifest.yaml | 38 ---- types/power_supply_DC.yaml | 15 +- 17 files changed, 81 insertions(+), 232 deletions(-) delete mode 100644 modules/simulation/JsDCSupplySimulator/CMakeLists.txt delete mode 100644 modules/simulation/JsDCSupplySimulator/index.js delete mode 100644 modules/simulation/JsDCSupplySimulator/manifest.yaml diff --git a/interfaces/ISO15118_charger.yaml b/interfaces/ISO15118_charger.yaml index 0f872ad21..8a3dff5b8 100644 --- a/interfaces/ISO15118_charger.yaml +++ b/interfaces/ISO15118_charger.yaml @@ -193,6 +193,9 @@ vars: start_cable_check: description: The charger should now start a cable check type: "null" + start_pre_charge: + description: The charger should now start the pre charge phase + type: "null" dc_open_contactor: description: The contactor should be opened type: "null" diff --git a/interfaces/power_supply_DC.yaml b/interfaces/power_supply_DC.yaml index 48a9c1739..6f2ba9717 100644 --- a/interfaces/power_supply_DC.yaml +++ b/interfaces/power_supply_DC.yaml @@ -18,10 +18,17 @@ cmds: setMode: description: Set operation mode of the bidirectional DC power supply arguments: - value: + mode: description: Operation mode of power supply type: string $ref: /power_supply_DC#/Mode + phase: + description: >- + Charging phase for this mode change. This information should normally not be needed by the power supply, + as it should always just operate in CCCV mode. Some special setups however are handling CableCheck/PreCharge/Charge + a little bit different internally. + type: string + $ref: /power_supply_DC#/ChargingPhase setExportVoltageCurrent: description: Set output target voltage limit. Must be within reported limits. arguments: diff --git a/modules/DPM1000/main/power_supply_DCImpl.cpp b/modules/DPM1000/main/power_supply_DCImpl.cpp index 7ef281d65..324731f17 100644 --- a/modules/DPM1000/main/power_supply_DCImpl.cpp +++ b/modules/DPM1000/main/power_supply_DCImpl.cpp @@ -268,8 +268,9 @@ void power_supply_DCImpl::ready() { } } -void power_supply_DCImpl::handle_setMode(types::power_supply_DC::Mode& value) { - if (value == types::power_supply_DC::Mode::Export) { +void power_supply_DCImpl::handle_setMode(types::power_supply_DC::Mode& mode, + types::power_supply_DC::ChargingPhase& phase) { + if (mode == types::power_supply_DC::Mode::Export) { can_broker->set_state(true); } else { can_broker->set_state(false); diff --git a/modules/DPM1000/main/power_supply_DCImpl.hpp b/modules/DPM1000/main/power_supply_DCImpl.hpp index 60e7f01c7..2ae059db7 100644 --- a/modules/DPM1000/main/power_supply_DCImpl.hpp +++ b/modules/DPM1000/main/power_supply_DCImpl.hpp @@ -35,7 +35,8 @@ class power_supply_DCImpl : public power_supply_DCImplBase { protected: // command handler functions (virtual) - virtual void handle_setMode(types::power_supply_DC::Mode& value) override; + virtual void handle_setMode(types::power_supply_DC::Mode& mode, + types::power_supply_DC::ChargingPhase& phase) override; virtual void handle_setExportVoltageCurrent(double& voltage, double& current) override; virtual void handle_setImportVoltageCurrent(double& voltage, double& current) override; diff --git a/modules/EvseManager/EvseManager.cpp b/modules/EvseManager/EvseManager.cpp index 733c823a2..ebea50a2a 100644 --- a/modules/EvseManager/EvseManager.cpp +++ b/modules/EvseManager/EvseManager.cpp @@ -257,12 +257,21 @@ void EvseManager::ready() { r_hlc[0]->call_update_dc_present_values(present_values); // Cable check for DC charging - r_hlc[0]->subscribe_start_cable_check([this] { cable_check(); }); + r_hlc[0]->subscribe_start_cable_check([this] { + power_supply_DC_charging_phase = types::power_supply_DC::ChargingPhase::CableCheck; + cable_check(); + }); + + // Cable check for DC charging + r_hlc[0]->subscribe_start_pre_charge( + [this] { power_supply_DC_charging_phase = types::power_supply_DC::ChargingPhase::PreCharge; }); // Notification that current demand has started r_hlc[0]->subscribe_current_demand_started([this] { - charger->notify_currentdemand_started(); + power_supply_DC_charging_phase = types::power_supply_DC::ChargingPhase::Charging; current_demand_active = true; + apply_new_target_voltage_current(); + charger->notify_currentdemand_started(); }); r_hlc[0]->subscribe_current_demand_finished([this] { @@ -1500,8 +1509,9 @@ void EvseManager::cable_check() { void EvseManager::powersupply_DC_on() { if (not powersupply_dc_is_on) { - session_log.evse(false, "DC power supply: switch ON called"); - r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Export); + session_log.evse(false, "DC power supply: switch ON called, ChargingPhase: " + + types::power_supply_DC::charging_phase_to_string(power_supply_DC_charging_phase)); + r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Export, power_supply_DC_charging_phase); powersupply_dc_is_on = true; } } @@ -1513,6 +1523,9 @@ bool EvseManager::powersupply_DC_set(double _voltage, double _current) { double current = _current; static bool last_is_actually_exporting_to_grid{false}; + const bool charging_phase_changed = last_power_supply_DC_charging_phase not_eq power_supply_DC_charging_phase; + last_power_supply_DC_charging_phase = power_supply_DC_charging_phase; + // Some cars always request integer ampere values, so if we offer 14.34A they will request 14.0A. // On low power DC charging this makes quite a difference // this option will deliver the offered ampere value in those cases @@ -1529,12 +1542,13 @@ bool EvseManager::powersupply_DC_set(double _voltage, double _current) { auto caps = get_powersupply_capabilities(); - if ((config.hack_allow_bpt_with_iso2 or config.sae_j2847_2_bpt_enabled) and current_demand_active and - is_actually_exporting_to_grid) { + if ((((config.hack_allow_bpt_with_iso2 or config.sae_j2847_2_bpt_enabled) and is_actually_exporting_to_grid) or + charging_phase_changed) and + current_demand_active) { if (not last_is_actually_exporting_to_grid) { // switching from import from grid to export to grid session_log.evse(false, "DC power supply: switch ON in import mode"); - r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Import); + r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Import, power_supply_DC_charging_phase); } last_is_actually_exporting_to_grid = is_actually_exporting_to_grid; // Hack: we are exporting to grid but are in ISO-2 mode @@ -1565,11 +1579,13 @@ bool EvseManager::powersupply_DC_set(double _voltage, double _current) { } else { - if ((config.hack_allow_bpt_with_iso2 or config.sae_j2847_2_bpt_enabled) and current_demand_active and - last_is_actually_exporting_to_grid) { + if ((((config.hack_allow_bpt_with_iso2 or config.sae_j2847_2_bpt_enabled) and + last_is_actually_exporting_to_grid) or + charging_phase_changed) and + current_demand_active) { // switching from export to grid to import from grid session_log.evse(false, "DC power supply: switch ON in export mode"); - r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Export); + r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Export, power_supply_DC_charging_phase); last_is_actually_exporting_to_grid = is_actually_exporting_to_grid; } @@ -1600,9 +1616,10 @@ bool EvseManager::powersupply_DC_set(double _voltage, double _current) { } void EvseManager::powersupply_DC_off() { + power_supply_DC_charging_phase = types::power_supply_DC::ChargingPhase::Other; if (powersupply_dc_is_on) { session_log.evse(false, "DC power supply OFF"); - r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Off); + r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Off, power_supply_DC_charging_phase); powersupply_dc_is_on = false; } } diff --git a/modules/EvseManager/EvseManager.hpp b/modules/EvseManager/EvseManager.hpp index 87193864f..70806e658 100644 --- a/modules/EvseManager/EvseManager.hpp +++ b/modules/EvseManager/EvseManager.hpp @@ -333,6 +333,12 @@ class EvseManager : public Everest::ModuleBase { std::mutex powermeter_mutex; std::condition_variable powermeter_cv; bool initial_powermeter_value_received{false}; + + std::atomic power_supply_DC_charging_phase{ + types::power_supply_DC::ChargingPhase::Other}; + + types::power_supply_DC::ChargingPhase last_power_supply_DC_charging_phase{ + types::power_supply_DC::ChargingPhase::Other}; // ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1 }; diff --git a/modules/EvseV2G/din_server.cpp b/modules/EvseV2G/din_server.cpp index 79266b237..aa10f7292 100644 --- a/modules/EvseV2G/din_server.cpp +++ b/modules/EvseV2G/din_server.cpp @@ -1008,6 +1008,7 @@ enum v2g_event din_handle_request(v2g_connection* conn) { dlog(DLOG_LEVEL_TRACE, "Handling PreChargeReq"); conn->ctx->current_v2g_msg = V2G_PRE_CHARGE_MSG; if (conn->ctx->last_v2g_msg == V2G_CABLE_CHECK_MSG) { + conn->ctx->p_charger->publish_start_pre_charge(nullptr); dlog(DLOG_LEVEL_INFO, "Precharge-phase started"); } exi_out->V2G_Message.Body.PreChargeRes_isUsed = 1u; diff --git a/modules/EvseV2G/iso_server.cpp b/modules/EvseV2G/iso_server.cpp index f4ec4e46c..9998fc102 100644 --- a/modules/EvseV2G/iso_server.cpp +++ b/modules/EvseV2G/iso_server.cpp @@ -2123,6 +2123,7 @@ enum v2g_event iso_handle_request(v2g_connection* conn) { conn->ctx->current_v2g_msg = V2G_PRE_CHARGE_MSG; /* At first send mqtt charging phase signal to the customer interface */ if (conn->ctx->last_v2g_msg == V2G_CABLE_CHECK_MSG) { + conn->ctx->p_charger->publish_start_pre_charge(nullptr); dlog(DLOG_LEVEL_INFO, "Precharge-phase started"); } diff --git a/modules/MicroMegaWattBSP/dc_supply/power_supply_DCImpl.cpp b/modules/MicroMegaWattBSP/dc_supply/power_supply_DCImpl.cpp index 98c253264..1b543320f 100644 --- a/modules/MicroMegaWattBSP/dc_supply/power_supply_DCImpl.cpp +++ b/modules/MicroMegaWattBSP/dc_supply/power_supply_DCImpl.cpp @@ -42,9 +42,10 @@ void power_supply_DCImpl::ready() { publish_capabilities(caps); } -void power_supply_DCImpl::handle_setMode(types::power_supply_DC::Mode& value) { +void power_supply_DCImpl::handle_setMode(types::power_supply_DC::Mode& mode, + types::power_supply_DC::ChargingPhase& phase) { // your code for cmd setMode goes here - if (value == types::power_supply_DC::Mode::Export) { + if (mode == types::power_supply_DC::Mode::Export) { mod->serial.setOutputVoltageCurrent(req_voltage, req_current); is_on = true; } else { diff --git a/modules/MicroMegaWattBSP/dc_supply/power_supply_DCImpl.hpp b/modules/MicroMegaWattBSP/dc_supply/power_supply_DCImpl.hpp index 820d81fe3..e89fdfe88 100644 --- a/modules/MicroMegaWattBSP/dc_supply/power_supply_DCImpl.hpp +++ b/modules/MicroMegaWattBSP/dc_supply/power_supply_DCImpl.hpp @@ -33,7 +33,8 @@ class power_supply_DCImpl : public power_supply_DCImplBase { protected: // command handler functions (virtual) - virtual void handle_setMode(types::power_supply_DC::Mode& value) override; + virtual void handle_setMode(types::power_supply_DC::Mode& mode, + types::power_supply_DC::ChargingPhase& phase) override; virtual void handle_setExportVoltageCurrent(double& voltage, double& current) override; virtual void handle_setImportVoltageCurrent(double& voltage, double& current) override; diff --git a/modules/simulation/CMakeLists.txt b/modules/simulation/CMakeLists.txt index 33103b2d0..937ec4e7a 100644 --- a/modules/simulation/CMakeLists.txt +++ b/modules/simulation/CMakeLists.txt @@ -1,6 +1,5 @@ ev_add_module(DCSupplySimulator) ev_add_module(IMDSimulator) ev_add_module(JsEvManager) -ev_add_module(JsDCSupplySimulator) ev_add_module(JsSlacSimulator) ev_add_module(JsYetiSimulator) diff --git a/modules/simulation/DCSupplySimulator/main/power_supply_DCImpl.cpp b/modules/simulation/DCSupplySimulator/main/power_supply_DCImpl.cpp index 90deae5e2..182aafdf5 100644 --- a/modules/simulation/DCSupplySimulator/main/power_supply_DCImpl.cpp +++ b/modules/simulation/DCSupplySimulator/main/power_supply_DCImpl.cpp @@ -45,22 +45,26 @@ void power_supply_DCImpl::ready() { publish_capabilities(get_capabilities_from_config(config)); } -void power_supply_DCImpl::handle_setMode(types::power_supply_DC::Mode& value) { - mode = value; +void power_supply_DCImpl::handle_setMode(types::power_supply_DC::Mode& _mode, + types::power_supply_DC::ChargingPhase& phase) { + mode = _mode; + + EVLOG_info << "Set mode: " << types::power_supply_DC::mode_to_string(mode) + << " ChargingPhase: " << types::power_supply_DC::charging_phase_to_string(phase); std::scoped_lock access_lock(power_supply_values_mutex); - if ((value == types::power_supply_DC::Mode::Off) || (value == types::power_supply_DC::Mode::Fault)) { + if ((mode == types::power_supply_DC::Mode::Off) || (mode == types::power_supply_DC::Mode::Fault)) { connector_voltage = 0.0; connector_current = 0.0; - } else if (value == types::power_supply_DC::Mode::Export) { + } else if (mode == types::power_supply_DC::Mode::Export) { connector_voltage = settings_connector_export_voltage; connector_current = settings_connector_max_export_current; - } else if (value == types::power_supply_DC::Mode::Import) { + } else if (mode == types::power_supply_DC::Mode::Import) { connector_voltage = settings_connector_import_voltage; connector_current = settings_connector_max_import_current; } - mod->p_main->publish_mode(value); + mod->p_main->publish_mode(mode); } void power_supply_DCImpl::clampVoltageCurrent(double& voltage, double& current) { diff --git a/modules/simulation/DCSupplySimulator/main/power_supply_DCImpl.hpp b/modules/simulation/DCSupplySimulator/main/power_supply_DCImpl.hpp index e966d6363..0f847b2de 100644 --- a/modules/simulation/DCSupplySimulator/main/power_supply_DCImpl.hpp +++ b/modules/simulation/DCSupplySimulator/main/power_supply_DCImpl.hpp @@ -43,7 +43,8 @@ class power_supply_DCImpl : public power_supply_DCImplBase { protected: // command handler functions (virtual) - virtual void handle_setMode(types::power_supply_DC::Mode& value) override; + virtual void handle_setMode(types::power_supply_DC::Mode& mode, + types::power_supply_DC::ChargingPhase& phase) override; virtual void handle_setExportVoltageCurrent(double& voltage, double& current) override; virtual void handle_setImportVoltageCurrent(double& voltage, double& current) override; diff --git a/modules/simulation/JsDCSupplySimulator/CMakeLists.txt b/modules/simulation/JsDCSupplySimulator/CMakeLists.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/modules/simulation/JsDCSupplySimulator/index.js b/modules/simulation/JsDCSupplySimulator/index.js deleted file mode 100644 index 2820cf706..000000000 --- a/modules/simulation/JsDCSupplySimulator/index.js +++ /dev/null @@ -1,165 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 - 2022 Pionix GmbH and Contributors to EVerest -const { boot_module } = require('everestjs'); -const { setInterval } = require('timers'); - -let config_min_voltage; -let config_max_voltage; -let config_min_current; -let config_max_current; -let config_bidirectional; -let config_max_power; - -let settings_connector_export_voltage = 0; -let settings_connector_import_voltage = 0; -let settings_connector_max_export_current = 0; -let settings_connector_max_import_current = 0; - -let connector_voltage = 0.0; -let connector_current = 0.0; -let mode; -let energy_import_total = 0.0; -let energy_export_total = 0.0; - -let voltage; -let current; - - -function power_meter_external() { - const date = new Date(); - return ({ - timestamp: date.toISOString(), - meter_id: 'DC_POWERMETER', - energy_Wh_import: { - total: energy_import_total, - }, - energy_Wh_export: { - total: energy_export_total, - }, - power_W: { - total: connector_voltage * connector_current, - }, - voltage_V: { - DC: connector_voltage, - }, - current_A: { - DC: connector_current, - } - }); -} - -boot_module(async ({ - setup, config, -}) => { - config_max_voltage = config.impl.main.max_voltage; - config_min_voltage = config.impl.main.min_voltage; - config_max_current = config.impl.main.max_current; - config_min_current = config.impl.main.min_current; - config_bidirectional = config.impl.main.bidirectional; - config_max_power = config.impl.main.max_power; - - connector_voltage = 0.0; - connector_current = 0.0; - mode = 'Off'; - voltage = 0.0; - current = 0.0; - - setup.provides.main.register.setMode((mod, args) => { - if (args.value === 'Off') { - mode = 'Off'; connector_voltage = 0.0; - connector_current = 0.0; - } else if (args.value === 'Export') { - mode = 'Export'; connector_voltage = settings_connector_export_voltage; - connector_current = settings_connector_max_export_current; - } else if (args.value === 'Import') { - mode = 'Import'; connector_voltage = settings_connector_import_voltage; - connector_current = -settings_connector_max_import_current; - } else if (args.value === 'Fault') { - mode = 'Fault'; connector_voltage = 0.0; - connector_current = 0.0; - } - mod.provides.main.publish.mode(args.value); - }); - - setup.provides.main.register.setExportVoltageCurrent((mod, args) => { - voltage = args.voltage; - current = args.current; - - if (voltage < config_min_voltage) voltage = config_min_voltage; - if (current < config_min_current) current = config_min_current; - if (voltage > config_max_voltage) voltage = config_max_voltage; - if (current > config_max_current) current = config_max_current; - - settings_connector_max_export_current = current; - settings_connector_export_voltage = voltage; - - if (mode === 'Export') { - connector_voltage = settings_connector_export_voltage; - connector_current = settings_connector_max_export_current; - } - }); - - setup.provides.main.register.setImportVoltageCurrent((mod, args) => { - voltage = args.voltage; - current = args.current; - - if (voltage < config_min_voltage) voltage = config_min_voltage; - if (current < config_min_current) current = config_min_current; - if (voltage > config_max_voltage) voltage = config_max_voltage; - if (current > config_max_current) current = config_max_current; - - settings_connector_import_voltage = voltage; - settings_connector_max_import_current = current; - - if (mode === 'Import') { - connector_voltage = settings_connector_import_voltage; - connector_current = -settings_connector_max_import_current; - } - }); - - setup.provides.powermeter.register.stop_transaction((mod, args) => ({ - status: 'NOT_SUPPORTED', - error: 'DcSupplySimulator does not support stop transaction request.', - })); - - setup.provides.powermeter.register.start_transaction((mod, args) => ({ - status: 'OK', - })); -}).then((mod) => { - - const Capabilities = { - bidirectional: config_bidirectional, - max_export_voltage_V: config_max_voltage, - min_export_voltage_V: config_min_voltage, - max_export_current_A: config_max_current, - min_export_current_A: config_min_current, - max_import_voltage_V: config_max_voltage, - min_import_voltage_V: config_min_voltage, - max_import_current_A: config_max_current, - min_import_current_A: config_min_current, - max_export_power_W: config_max_power, - max_import_power_W: config_max_power, - current_regulation_tolerance_A: 2, - peak_current_ripple_A: 2, - conversion_efficiency_export: 0.9, - conversion_efficiency_import: 0.85, - }; - - setInterval(() => { - mod.provides.main.publish.voltage_current({ - voltage_V: connector_voltage, - current_A: connector_current, - }); - - if (connector_current > 0) energy_import_total += (connector_voltage * connector_current * 0.5) / 3600; - if (connector_current < 0) energy_export_total += (connector_voltage * -connector_current * 0.5) / 3600; - - mod.provides.powermeter.publish.powermeter(power_meter_external()); - mod.provides.main.publish.capabilities(Capabilities); - }, 500, mod); -}); - - - - - diff --git a/modules/simulation/JsDCSupplySimulator/manifest.yaml b/modules/simulation/JsDCSupplySimulator/manifest.yaml deleted file mode 100644 index 15081ca8d..000000000 --- a/modules/simulation/JsDCSupplySimulator/manifest.yaml +++ /dev/null @@ -1,38 +0,0 @@ -description: SIL Implementation of a programmable power supply for DC charging -provides: - main: - interface: power_supply_DC - description: Main interface for the power supply - config: - bidirectional: - description: Set to true for bidirectional supply - type: boolean - default: true - max_power: - description: Max supported power in watt - type: number - default: 150000 - min_voltage: - description: Min supported voltage - type: number - default: 200.0 - max_voltage: - description: Max supported voltage - type: number - default: 900.0 - min_current: - description: Min supported current - type: number - default: 1.0 - max_current: - description: Max supported current - type: number - default: 200.0 - powermeter: - interface: powermeter - description: Power meter interface for simulation -enable_external_mqtt: true -metadata: - license: https://opensource.org/licenses/Apache-2.0 - authors: - - Cornelius Claussen (Pionix GmbH) diff --git a/types/power_supply_DC.yaml b/types/power_supply_DC.yaml index ebbf5a349..a27018694 100644 --- a/types/power_supply_DC.yaml +++ b/types/power_supply_DC.yaml @@ -7,9 +7,18 @@ types: type: string enum: - "Off" - - Export - - Import - - Fault + - "Export" + - "Import" + - "Fault" + ChargingPhase: + description: >- + Charging phase of the current mode change. Other is used for e.g. switching it off or any other internal testing not related to real charging. + type: string + enum: + - "Other" + - "CableCheck" + - "PreCharge" + - "Charging" VoltageCurrent: description: Voltage (V) and Current (A) at the input/output of the power supply type: object