Skip to content

Commit

Permalink
Adding D20 dynamic mode support
Browse files Browse the repository at this point in the history
D20 dynamic mode works now for IsoMux

Signed-off-by: Sebastian Lukas <sebastian.lukas@pionix.de>
  • Loading branch information
SebaLukas authored and corneliusclaussen committed Oct 25, 2024
1 parent 61bfbd6 commit e9c7992
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 5 deletions.
4 changes: 2 additions & 2 deletions dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ libfsm:
# libiso15118
libiso15118:
git: https://github.com/EVerest/libiso15118.git
git_tag: v0.2.0
git_tag: a135d7d3cc62a2206b1128b267a388e209b3cd2c
cmake_condition: "EVEREST_DEPENDENCY_ENABLED_LIBISO15118"

# LEM DCBM 400/600 module
Expand All @@ -71,7 +71,7 @@ libocpp:
# Josev
Josev:
git: https://github.com/EVerest/ext-switchev-iso15118.git
git_tag: 2024.9.0
git_tag: 4abfad56331332d56a87e40cc361744f87e65c39
cmake_condition: "EVEREST_ENABLE_PY_SUPPORT AND EVEREST_DEPENDENCY_ENABLED_JOSEV"
# libcbv2g
libcbv2g:
Expand Down
11 changes: 11 additions & 0 deletions interfaces/ISO15118_charger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,14 @@ vars:
Parameters that may be displayed on the EVSE (Soc, battery capacity)
type: object
$ref: /iso15118_charger#/DisplayParameters
d20_dc_dynamic_charge_mode:
description: >-
The parameters the EVCC offers and sets for dynamic control mode
type: object
$ref: /iso15118_charger#/DcChargeDynamicModeValues
dc_ev_present_voltage:
description: Present Voltage measured from the EV
type: number
meter_info_requested:
description: The EV requested meter infos from the EVSE
type: "null"
3 changes: 3 additions & 0 deletions modules/Evse15118D20/Evse15118D20.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ struct Conf {
bool enable_ssl_logging;
bool enable_tls_key_logging;
bool enable_sdp_server;
bool supported_dynamic_mode;

Check notice on line 31 in modules/Evse15118D20/Evse15118D20.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/Evse15118D20/Evse15118D20.hpp#L31

struct member 'Conf::supported_dynamic_mode' is never used.
bool supported_mobility_needs_mode_provided_by_secc;

Check notice on line 32 in modules/Evse15118D20/Evse15118D20.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/Evse15118D20/Evse15118D20.hpp#L32

struct member 'Conf::supported_mobility_needs_mode_provided_by_secc' is never used.
bool supported_scheduled_mode;

Check notice on line 33 in modules/Evse15118D20/Evse15118D20.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/Evse15118D20/Evse15118D20.hpp#L33

struct member 'Conf::supported_scheduled_mode' is never used.
};

class Evse15118D20 : public Everest::ModuleBase {
Expand Down
74 changes: 71 additions & 3 deletions modules/Evse15118D20/charger/ISO15118_chargerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,30 @@ convert_display_parameters(const iso15118::session::feedback::DisplayParameters&
in.inlet_hot};
}

types::iso15118_charger::DcChargeDynamicModeValues
convert_dynamic_values(const iso15118::session::feedback::DcChargeDynamicMode& in) {

std::optional<float> departure_time{std::nullopt};
if (in.departure_time.has_value()) {
departure_time = static_cast<float>(*in.departure_time);
}

return {in.target_energy_request,
in.max_energy_request,
in.min_energy_request,
in.max_charge_power,
in.min_charge_power,
in.max_charge_current,
in.max_voltage,
in.min_voltage,
departure_time,
in.max_discharge_power,
in.min_discharge_power,
in.max_discharge_current,
in.max_v2x_energy_request,
in.min_v2x_energy_request};
}

} // namespace

void ISO15118_chargerImpl::init() {
Expand Down Expand Up @@ -112,17 +136,52 @@ void ISO15118_chargerImpl::ready() {
};
const auto callbacks = create_callbacks();

if (mod->config.supported_dynamic_mode) {
setup_config.control_mobility_modes.push_back(
{iso15118::message_20::ControlMode::Dynamic, iso15118::message_20::MobilityNeedsMode::ProvidedByEvcc});
if (mod->config.supported_mobility_needs_mode_provided_by_secc) {
setup_config.control_mobility_modes.push_back(
{iso15118::message_20::ControlMode::Dynamic, iso15118::message_20::MobilityNeedsMode::ProvidedBySecc});
}
}

if (mod->config.supported_scheduled_mode) {
setup_config.control_mobility_modes.push_back(
{iso15118::message_20::ControlMode::Scheduled, iso15118::message_20::MobilityNeedsMode::ProvidedByEvcc});
}

if (setup_config.control_mobility_modes.empty()) {
EVLOG_warning << "Control mobility modes are empty! Setting dynamic mode as default!";
setup_config.control_mobility_modes.push_back(
{iso15118::message_20::ControlMode::Dynamic, iso15118::message_20::MobilityNeedsMode::ProvidedByEvcc});
}

controller = std::make_unique<iso15118::TbdController>(tbd_config, callbacks, setup_config);
controller->loop();

try {
controller->loop();
} catch (const std::exception& e) {
EVLOG_error << e.what();
}
}

iso15118::session::feedback::Callbacks ISO15118_chargerImpl::create_callbacks() {
iso15118::session::feedback::Callbacks callbacks;

callbacks.dc_charge_target = [this](const iso15118::session::feedback::DcChargeTarget& charge_target) {
publish_dc_ev_target_voltage_current({charge_target.voltage, charge_target.current});
callbacks.dc_pre_charge_target_voltage = [this](float target_voltage) {
publish_dc_ev_target_voltage_current({target_voltage, 0});
};

callbacks.dc_charge_scheduled_mode = [this](const iso15118::session::feedback::DcChargeScheduledMode&
dc_charge_schedule) {
publish_dc_ev_target_voltage_current({dc_charge_schedule.target_voltage, dc_charge_schedule.target_current});
};

callbacks.dc_charge_dynamic_mode =
[this](const iso15118::session::feedback::DcChargeDynamicMode& dc_charge_dynamic) {
publish_d20_dc_dynamic_charge_mode(convert_dynamic_values(dc_charge_dynamic));
};

callbacks.dc_max_limits = [this](const iso15118::session::feedback::DcMaximumLimits& max_limits) {
publish_dc_ev_maximum_limits({max_limits.current, max_limits.power, max_limits.voltage});
};
Expand Down Expand Up @@ -173,6 +232,15 @@ iso15118::session::feedback::Callbacks ISO15118_chargerImpl::create_callbacks()
publish_display_parameters(convert_display_parameters(parameters));
};

callbacks.dc_present_voltage = [this](float present_voltage) { publish_dc_ev_present_voltage(present_voltage); };

callbacks.meter_info_requested = [this](bool meter_info_requested) {
if (meter_info_requested) {
EVLOG_info << "Meter info is requested from EV";
publish_meter_info_requested(nullptr);
}
};

return callbacks;
}

Expand Down
14 changes: 14 additions & 0 deletions modules/Evse15118D20/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,20 @@ config:
Enable the built-in SDP server
type: boolean
default: true
supported_dynamic_mode:
description: The EVSE should support dynamic mode
type: boolean
default: true
supported_mobility_needs_mode_provided_by_secc:
description: >-
The EVSE should support the mobility needs mode provided by the SECC.
Mobility needs mode provided by the EVCC is always provided.
type: boolean
default: false
supported_scheduled_mode:
description: The EVSE should support scheduled mode
type: boolean
default: false
provides:
charger:
interface: ISO15118_charger
Expand Down
42 changes: 42 additions & 0 deletions modules/EvseManager/EvseManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,48 @@ void EvseManager::ready() {
}
});

r_hlc[0]->subscribe_d20_dc_dynamic_charge_mode(
[this](types::iso15118_charger::DcChargeDynamicModeValues values) {
constexpr auto PRE_CHARGE_MAX_POWER = 800.0f;

bool target_changed{false};

if (values.min_voltage > latest_target_voltage) {
latest_target_voltage = values.min_voltage + 10; // TODO(sl): Check if okay
target_changed = true;
}
if (values.max_voltage < latest_target_voltage) {
latest_target_voltage = values.max_voltage - 10; // TODO(sl): Check if okay
target_changed = true;
}

const double latest_target_power = latest_target_voltage * latest_target_current;

if (latest_target_power <= PRE_CHARGE_MAX_POWER or values.min_charge_power > latest_target_power or
values.max_charge_power < latest_target_power) {
latest_target_current = static_cast<double>(values.max_charge_power) / latest_target_voltage;
if (values.max_charge_current < latest_target_current) {
latest_target_current = values.max_charge_current;
}
target_changed = true;
}

if (target_changed) {
apply_new_target_voltage_current();
if (not contactor_open) {
powersupply_DC_on();
}

{
Everest::scoped_lock_timeout lock(ev_info_mutex,
Everest::MutexDescription::EVSE_publish_ev_info);
ev_info.target_voltage = latest_target_voltage;
ev_info.target_current = latest_target_current;
p_evse->publish_ev_info(ev_info);
}
}
});

// Car requests DC contactor open. We don't actually open but switch off DC supply.
// opening will be done by Charger on C->B CP event.
r_hlc[0]->subscribe_dc_open_contactor([this] {
Expand Down
30 changes: 30 additions & 0 deletions modules/IsoMux/charger/ISO15118_chargerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,36 @@ void ISO15118_chargerImpl::init() {
publish_display_parameters(o);
}
});

mod->r_iso20->subscribe_d20_dc_dynamic_charge_mode([this](const auto o) {
if (mod->selected_iso20()) {
publish_d20_dc_dynamic_charge_mode(o);
}
});

mod->r_iso2->subscribe_dc_ev_present_voltage([this](const auto o) {
if (not mod->selected_iso20()) {
publish_dc_ev_present_voltage(o);
}
});

mod->r_iso20->subscribe_dc_ev_present_voltage([this](const auto o) {
if (mod->selected_iso20()) {
publish_dc_ev_present_voltage(o);
}
});

mod->r_iso2->subscribe_meter_info_requested([this]() {
if (not mod->selected_iso20()) {
publish_meter_info_requested(nullptr);
}
});

mod->r_iso20->subscribe_meter_info_requested([this]() {
if (mod->selected_iso20()) {
publish_meter_info_requested(nullptr);
}
});
}

void ISO15118_chargerImpl::ready() {
Expand Down
74 changes: 74 additions & 0 deletions types/iso15118_charger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -586,3 +586,77 @@ types:
inlet_hot:
description: Inlet temperature is too high
type: boolean
DcChargeDynamicModeValues:
description: Parameters for dynamic control mode
type: object
additionalProperties: false
required:
- target_energy_request
- max_energy_request
- min_energy_request
- max_charge_power
- min_charge_power
- max_charge_current
- max_voltage
- min_voltage
properties:
departure_time:
description: The time when the EV wants to finish charging
type: number
minimum: 0
target_energy_request:
description: Energy request to fulfil the target SoC
type: number
minimum: 0
max_energy_request:
description: Maximum acceptable energy level of the EV
type: number
minimum: 0
min_energy_request:
description: Energy request to fulfil the minimum SoC
type: number
minimum: 0
max_charge_power:
description: Maximum charge power allowed by the EV
type: number
minimum: 0
min_charge_power:
description: Minimum charge power allowed by the EV
type: number
minimum: 0
max_charge_current:
description: Maximum charge current allowed by the EV
type: number
minimum: 0
max_voltage:
description: Maximum voltage allowed by the EV
type: number
minimum: 0
min_voltage:
description: Minimum voltage allowd by the EV
type: number
minimum: 0
max_discharge_power:
description: Maximum discharge current allowed by the EV
type: number
minimum: 0
min_discharge_power:
description: Minimum discharge current allowed by the EVodo
type: number
minimum: 0
max_discharge_current:
description: Maximum discharge current allowed by the EV
type: number
minimum: 0
max_v2x_energy_request:
description: >-
Energy which may be charged until the PresentSOC has left the range
dedicated for cycling activity.
type: number
minimum: 0
min_v2x_energy_request:
description: >-
Energy which needs to be charged until the PresentSOC has left the
range dedicated for cycling activity.
type: number
minimum: 0

0 comments on commit e9c7992

Please sign in to comment.