Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DC Powersupply: allow runtime update of max current/watt caps #646

Merged
merged 2 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion interfaces/power_supply_DC.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
description: Interface for power supplies used for DC charging
cmds:
getCapabilities:
description: Get capabilities of power supply
description: >-
Get maximum capabilities of power supply. It should report the maximum possible values under best conditions, even if it
is e.g. derated at this moment due to high temperature.
result:
description: Capabilities
type: object
Expand Down Expand Up @@ -46,3 +48,7 @@ vars:
description: Fault code. Published when fault happens.
type: string
$ref: /power_supply_DC#/FaultCode
update_capabilities:
description: Update some capability values at run-time. This can be used to e.g. report lower limits due to temperature de-rating of the PSU.
type: object
$ref: /power_supply_DC#/UpdateCapabilities
45 changes: 24 additions & 21 deletions modules/EvseManager/EvseManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ void EvseManager::ready() {

powersupply_capabilities = r_powersupply_DC[0]->call_getCapabilities();

// subscribe to run time updates e.g. due to de-rating
r_powersupply_DC[0]->subscribe_update_capabilities(
[this](auto caps) { update_powersupply_capabilities(caps); });

updateLocalMaxWattLimit(powersupply_capabilities.max_export_power_W);

setup_physical_values.dc_current_regulation_tolerance =
Expand Down Expand Up @@ -1033,7 +1037,7 @@ bool EvseManager::updateLocalEnergyLimit(types::energy::ExternalLimits l) {
// by default we import energy
updateLocalMaxCurrentLimit(hw_capabilities.max_current_A_import);
} else {
updateLocalMaxWattLimit(powersupply_capabilities.max_export_power_W);
updateLocalMaxWattLimit(get_powersupply_capabilities().max_export_power_W);
}
} else {
// apply external limits if they are lower
Expand Down Expand Up @@ -1242,6 +1246,7 @@ void EvseManager::cable_check() {
ok = false;
imd_stop();
} else {
auto caps = get_powersupply_capabilities();
// read out one new isolation resistance
isolation_measurement.clear();
types::isolation_monitor::IsolationMeasurement m;
Expand All @@ -1252,9 +1257,9 @@ void EvseManager::cable_check() {
fail_session();
} else {
// wait until the voltage is back to safe level
float minvoltage = (config.switch_to_minimum_voltage_after_cable_check
? powersupply_capabilities.min_export_voltage_V
: config.dc_isolation_voltage_V);
float minvoltage =
(config.switch_to_minimum_voltage_after_cable_check ? caps.min_export_voltage_V
: config.dc_isolation_voltage_V);

// We do not want to shut down power supply
if (minvoltage < 60) {
Expand All @@ -1269,8 +1274,8 @@ void EvseManager::cable_check() {
} else {
// verify it is within ranges. Warning level is <500 Ohm/V_max_output_rating, Fault
// is <100
const double min_resistance_ok = 500. * powersupply_capabilities.max_export_voltage_V;
const double min_resistance_warning = 100. * powersupply_capabilities.max_export_voltage_V;
const double min_resistance_ok = 500. * caps.max_export_voltage_V;
const double min_resistance_warning = 100. * caps.max_export_voltage_V;

if (m.resistance_F_Ohm < min_resistance_warning) {
session_log.evse(
Expand Down Expand Up @@ -1350,6 +1355,8 @@ bool EvseManager::powersupply_DC_set(double _voltage, double _current) {
current = std::abs(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 (not last_is_actually_exporting_to_grid) {
Expand All @@ -1360,17 +1367,14 @@ bool EvseManager::powersupply_DC_set(double _voltage, double _current) {
last_is_actually_exporting_to_grid = is_actually_exporting_to_grid;
// Hack: we are exporting to grid but are in ISO-2 mode
// check limits of supply
if (powersupply_capabilities.min_import_voltage_V.has_value() and
voltage >= powersupply_capabilities.min_import_voltage_V.value() and
voltage <= powersupply_capabilities.max_import_voltage_V.value()) {
if (caps.min_import_voltage_V.has_value() and voltage >= caps.min_import_voltage_V.value() and
voltage <= caps.max_import_voltage_V.value()) {

if (powersupply_capabilities.max_import_current_A.has_value() and
current > powersupply_capabilities.max_import_current_A.value())
current = powersupply_capabilities.max_import_current_A.value();
if (caps.max_import_current_A.has_value() and current > caps.max_import_current_A.value())
current = caps.max_import_current_A.value();

if (powersupply_capabilities.min_import_current_A.has_value() and
current < powersupply_capabilities.min_import_current_A.value())
current = powersupply_capabilities.min_import_current_A.value();
if (caps.min_import_current_A.has_value() and current < caps.min_import_current_A.value())
current = caps.min_import_current_A.value();

// Now it is within limits of DC power supply.
// now also limit with the limits given by the energymanager.
Expand Down Expand Up @@ -1398,14 +1402,13 @@ bool EvseManager::powersupply_DC_set(double _voltage, double _current) {
}

// check limits of supply
if (voltage >= powersupply_capabilities.min_export_voltage_V and
voltage <= powersupply_capabilities.max_export_voltage_V) {
if (voltage >= caps.min_export_voltage_V and voltage <= caps.max_export_voltage_V) {

if (current > powersupply_capabilities.max_export_current_A)
current = powersupply_capabilities.max_export_current_A;
if (current > caps.max_export_current_A)
current = caps.max_export_current_A;

if (current < powersupply_capabilities.min_export_current_A)
current = powersupply_capabilities.min_export_current_A;
if (current < caps.min_export_current_A)
current = caps.min_export_current_A;

// Now it is within limits of DC power supply.
// now also limit with the limits given by the energymanager.
Expand Down
19 changes: 18 additions & 1 deletion modules/EvseManager/EvseManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ class EvseManager : public Everest::ModuleBase {
void charger_was_authorized();

const std::vector<std::unique_ptr<powermeterIntf>>& r_powermeter_billing();
types::power_supply_DC::Capabilities powersupply_capabilities;

// FIXME: this will be removed with proper intergration of BPT on ISO-20
// on DIN SPEC and -2 we claim a positive charging current on ISO protocol,
Expand All @@ -191,6 +190,21 @@ class EvseManager : public Everest::ModuleBase {
std::chrono::time_point<date::utc_clock> random_delay_start_time;
std::atomic<std::chrono::seconds> random_delay_max_duration;
std::atomic<std::chrono::time_point<std::chrono::steady_clock>> timepoint_ready_for_charging;

types::power_supply_DC::Capabilities get_powersupply_capabilities() {
std::scoped_lock lock(powersupply_capabilities_mutex);
return powersupply_capabilities;
}

void update_powersupply_capabilities(types::power_supply_DC::UpdateCapabilities caps) {
std::scoped_lock lock(powersupply_capabilities_mutex);
powersupply_capabilities.max_export_current_A = caps.max_export_current_A;
powersupply_capabilities.max_export_power_W = caps.max_export_power_W;

powersupply_capabilities.max_import_current_A = caps.max_import_current_A;
powersupply_capabilities.max_import_power_W = caps.max_import_power_W;
}

// ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1

protected:
Expand All @@ -205,6 +219,9 @@ class EvseManager : public Everest::ModuleBase {

// ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1
// insert your private definitions here
std::mutex powersupply_capabilities_mutex;
types::power_supply_DC::Capabilities powersupply_capabilities;

Everest::timed_mutex_traceable power_mutex;
types::powermeter::Powermeter latest_powermeter_data_billing;

Expand Down
32 changes: 16 additions & 16 deletions modules/EvseManager/energy_grid/energyImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void energyImpl::clear_import_request_schedule() {
entry_import.limits_to_root.ac_min_current_A = hw_caps.min_current_A_import;
entry_import.limits_to_root.ac_supports_changing_phases_during_charging =
hw_caps.supports_changing_phases_during_charging;
entry_import.conversion_efficiency = mod->powersupply_capabilities.conversion_efficiency_export;
entry_import.conversion_efficiency = mod->get_powersupply_capabilities().conversion_efficiency_export;
energy_flow_request.schedule_import.emplace(std::vector<types::energy::ScheduleReqEntry>({entry_import}));
}

Expand All @@ -80,7 +80,7 @@ void energyImpl::clear_export_request_schedule() {
entry_export.limits_to_root.ac_min_current_A = hw_caps.min_current_A_export;
entry_export.limits_to_root.ac_supports_changing_phases_during_charging =
hw_caps.supports_changing_phases_during_charging;
entry_export.conversion_efficiency = mod->powersupply_capabilities.conversion_efficiency_import;
entry_export.conversion_efficiency = mod->get_powersupply_capabilities().conversion_efficiency_import;
energy_flow_request.schedule_export.emplace(std::vector<types::energy::ScheduleReqEntry>({entry_export}));
}

Expand Down Expand Up @@ -387,6 +387,8 @@ void energyImpl::handle_enforce_limits(types::energy::EnforcedLimits& value) {
last_target_voltage = target_voltage;
last_actual_voltage = actual_voltage;

auto powersupply_capabilities = mod->get_powersupply_capabilities();

// tell car our new limits
types::iso15118_charger::DC_EVSEMaximumLimits evseMaxLimits;

Expand All @@ -403,33 +405,31 @@ void energyImpl::handle_enforce_limits(types::energy::EnforcedLimits& value) {
value.limits_root_side.value().total_power_W.value() / target_voltage;
}
} else {
evseMaxLimits.EVSEMaximumCurrentLimit = mod->powersupply_capabilities.max_export_current_A;
evseMaxLimits.EVSEMaximumCurrentLimit = powersupply_capabilities.max_export_current_A;
}

if (evseMaxLimits.EVSEMaximumCurrentLimit > mod->powersupply_capabilities.max_export_current_A)
evseMaxLimits.EVSEMaximumCurrentLimit = mod->powersupply_capabilities.max_export_current_A;
if (evseMaxLimits.EVSEMaximumCurrentLimit > powersupply_capabilities.max_export_current_A)
evseMaxLimits.EVSEMaximumCurrentLimit = powersupply_capabilities.max_export_current_A;

if (mod->powersupply_capabilities.max_import_current_A.has_value() &&
evseMaxLimits.EVSEMaximumCurrentLimit <
-mod->powersupply_capabilities.max_import_current_A.value())
evseMaxLimits.EVSEMaximumCurrentLimit =
-mod->powersupply_capabilities.max_import_current_A.value();
if (powersupply_capabilities.max_import_current_A.has_value() &&
evseMaxLimits.EVSEMaximumCurrentLimit < -powersupply_capabilities.max_import_current_A.value())
evseMaxLimits.EVSEMaximumCurrentLimit = -powersupply_capabilities.max_import_current_A.value();

// now evseMaxLimits.EVSEMaximumCurrentLimit is between
// -max_import_current_A ... +max_export_current_A

evseMaxLimits.EVSEMaximumPowerLimit = value.limits_root_side.value().total_power_W.value();
if (evseMaxLimits.EVSEMaximumPowerLimit > mod->powersupply_capabilities.max_export_power_W)
evseMaxLimits.EVSEMaximumPowerLimit = mod->powersupply_capabilities.max_export_power_W;
if (evseMaxLimits.EVSEMaximumPowerLimit > powersupply_capabilities.max_export_power_W)
evseMaxLimits.EVSEMaximumPowerLimit = powersupply_capabilities.max_export_power_W;

if (mod->powersupply_capabilities.max_import_power_W.has_value() &&
evseMaxLimits.EVSEMaximumPowerLimit < -mod->powersupply_capabilities.max_import_power_W.value())
evseMaxLimits.EVSEMaximumPowerLimit = -mod->powersupply_capabilities.max_import_power_W.value();
if (powersupply_capabilities.max_import_power_W.has_value() &&
evseMaxLimits.EVSEMaximumPowerLimit < -powersupply_capabilities.max_import_power_W.value())
evseMaxLimits.EVSEMaximumPowerLimit = -powersupply_capabilities.max_import_power_W.value();

// now evseMaxLimits.EVSEMaximumPowerLimit is between
// -max_import_power_W ... +max_export_power_W

evseMaxLimits.EVSEMaximumVoltageLimit = mod->powersupply_capabilities.max_export_voltage_V;
evseMaxLimits.EVSEMaximumVoltageLimit = powersupply_capabilities.max_export_voltage_V;

// FIXME: we tell the ISO stack positive numbers for DIN spec and ISO-2 here in case of exporting to
// grid. This needs to be fixed in the transition to -20 for BPT.
Expand Down
20 changes: 20 additions & 0 deletions types/power_supply_DC.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ types:
type: number
minimum: 0.0
maximum: 1.0
UpdateCapabilities:
description: Runtime update of some of the capabilities values. Can be used to e.g. inform about throttling of a power supply due to temperature de-rating.
type: object
additionalProperties: false
required:
- max_export_current_A
- max_export_power_W
properties:
max_export_current_A:
description: Maximum current that the power supply can output in Ampere
type: number
max_import_current_A:
description: Maximum current that the power supply can output in Ampere
type: number
max_export_power_W:
description: Maximum export power that the power supply can output in Watt
type: number
max_import_power_W:
description: Maximum import power that the power supply can sink in Watt
type: number
FaultCode:
description: Fault codes
type: string
Expand Down
Loading