Skip to content

Commit 919817e

Browse files
authored
feat: optional device lifecycle management for Bender isoCHA425HV (EVerest#1811)
Summary: - Adds optional device lifecycle management for the Bender isoCHA425HV isolation monitor, allowing the device to be disabled when not in use and enabled only during active measurement periods. - Reduces other measurement errors when the isolation monitor is not actively measuring. New configuration option: - Added `disable_device_on_stop` configuration option (default: `false`). - When enabled, the device is only powered on during active measurement periods. - The device is disabled when measurements are stopped. Device lifecycle management (when `disable_device_on_stop` is enabled): - Configuration phase: the device is not automatically started during `configure_device()`. - Start measurements (`handle_start()`): the device is enabled before measurements begin. - Stop measurements (`handle_stop()`): the device is disabled after measurements stop. - Self-test (`handle_start_self_test()`): the device is enabled before self-test and disabled after completion. Incompatibility handling: - Detects incompatible configuration when both `disable_device_on_stop` and `selftest_enable_at_start` are enabled. - Logs a warning and automatically disables `selftest_enable_at_start` (since the device won't be started during configuration). Signed-off-by: Florin Mihut <florinmihut1@gmail.com>
1 parent b7e9c06 commit 919817e

File tree

3 files changed

+76
-13
lines changed

3 files changed

+76
-13
lines changed

modules/HardwareDrivers/IsolationMonitors/Bender_isoCHA425HV/main/isolation_monitorImpl.cpp

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
33

44
#include "isolation_monitorImpl.hpp"
5+
#include "everest/logging.hpp"
56
#include <chrono>
67
#include <fmt/core.h>
78
#include <thread>
@@ -16,6 +17,13 @@ void isolation_monitorImpl::init() {
1617
void isolation_monitorImpl::configure_device() {
1718
// Query device name and version
1819
bool successful = true;
20+
int selftest_enable_at_start_value = config.selftest_enable_at_start ? 1 : 0;
21+
if (config.disable_device_on_stop and config.selftest_enable_at_start) {
22+
EVLOG_warning << "disable_device_on_stop configuration option and "
23+
"selftest_enable_at_start are incompatible. Self test at "
24+
"start will be disabled.";
25+
selftest_enable_at_start_value = 0;
26+
}
1927
do {
2028
successful = true;
2129
successful &= send_to_imd(3000, (config.voltage_to_earth_monitoring_alarm_enable ? 1 : 0));
@@ -48,14 +56,16 @@ void isolation_monitorImpl::configure_device() {
4856
std::this_thread::sleep_for(std::chrono::milliseconds(20));
4957
successful &= send_to_imd(3024, (config.selftest_enable_gridconnection ? 1 : 0));
5058
std::this_thread::sleep_for(std::chrono::milliseconds(20));
51-
successful &= send_to_imd(3025, (config.selftest_enable_at_start ? 1 : 0));
59+
successful &= send_to_imd(3025, selftest_enable_at_start_value);
5260
std::this_thread::sleep_for(std::chrono::milliseconds(20));
5361
successful &= send_to_imd(3027, config.relay_k1_alarm_assignment);
5462
std::this_thread::sleep_for(std::chrono::milliseconds(20));
5563
successful &= send_to_imd(3028, config.relay_k2_alarm_assignment);
5664
std::this_thread::sleep_for(std::chrono::milliseconds(20));
57-
// start up
58-
successful &= send_to_imd(3026, 1);
65+
// start up enable the device if the configuration option is not set
66+
if (!config.disable_device_on_stop) {
67+
successful &= send_to_imd(3026, 1);
68+
}
5969
// Give device time to process startup command
6070
std::this_thread::sleep_for(std::chrono::milliseconds(50));
6171

@@ -68,9 +78,10 @@ void isolation_monitorImpl::configure_device() {
6878
enable_faster_cable_check_mode();
6979
std::this_thread::sleep_for(std::chrono::milliseconds(20));
7080
} else {
71-
EVLOG_info
72-
<< "Does not support faster cable check method, falling back to long self test. This may create "
73-
"timeouts with certain cars in CableCheck. Consider upgrading to at least firmware 5.00";
81+
EVLOG_info << "Does not support faster cable check method, falling "
82+
"back to long self test. This may create "
83+
"timeouts with certain cars in CableCheck. Consider "
84+
"upgrading to at least firmware 5.00";
7485
disable_faster_cable_check_mode();
7586
std::this_thread::sleep_for(std::chrono::milliseconds(20));
7687
}
@@ -83,8 +94,8 @@ void isolation_monitorImpl::configure_device() {
8394

8495
void isolation_monitorImpl::start_self_test() {
8596
if (last_test != TestType::ExternalTest) {
86-
// Wait a bit to ensure device is ready (not processing previous read operations)
87-
// This prevents conflicts with the regular reading loop
97+
// Wait a bit to ensure device is ready (not processing previous read
98+
// operations) This prevents conflicts with the regular reading loop
8899
std::this_thread::sleep_for(std::chrono::milliseconds(50));
89100

90101
if (mod->r_serial_comm_hub->call_modbus_write_multiple_registers(
@@ -139,6 +150,8 @@ bool isolation_monitorImpl::send_to_imd(const uint16_t& command, const uint16_t&
139150
void isolation_monitorImpl::ready() {
140151
this->configure_device();
141152
bool self_test_running = false;
153+
bool need_to_disable_device = false;
154+
int device_disabled_timeout_s = 10;
142155

143156
while (true) {
144157
read_imd_values();
@@ -148,6 +161,7 @@ void isolation_monitorImpl::ready() {
148161
if (self_test_timeout <= 0) {
149162
// a time out happend
150163
self_test_started = false;
164+
need_to_disable_device = true;
151165
// publish failed result
152166
EVLOG_warning << "Self test timed out";
153167
publish_self_test_result(false);
@@ -157,6 +171,7 @@ void isolation_monitorImpl::ready() {
157171
// Self test is done
158172
self_test_running = false;
159173
self_test_started = false;
174+
need_to_disable_device = true;
160175
// was it successfull? If there is no error, it was...
161176
bool result = true;
162177
if (last_alarm == AlarmType::DeviceError) {
@@ -173,6 +188,23 @@ void isolation_monitorImpl::ready() {
173188
}
174189
if (not error_state_monitor->is_error_active("isolation_monitor/DeviceFault", "")) {
175190
std::this_thread::sleep_for(std::chrono::seconds(1));
191+
if (need_to_disable_device) {
192+
device_disabled_timeout_s--;
193+
if (device_disabled_timeout_s <= 0) {
194+
need_to_disable_device = false;
195+
device_disabled_timeout_s = 10;
196+
// disable the device if the configuration option is set and we are not publishing
197+
// aka we are in a measuring cycle (start called)
198+
if (not enable_publishing && config.disable_device_on_stop) {
199+
if (not send_to_imd(3026, 0)) {
200+
EVLOG_error << "Can't disable the device: " << read_device_name();
201+
} else {
202+
EVLOG_info << "Device disabled after self test since we didn't start measuring cycle "
203+
"(timeout 10s)";
204+
}
205+
}
206+
}
207+
}
176208
} else {
177209
std::this_thread::sleep_for(std::chrono::seconds(10));
178210
}
@@ -181,14 +213,36 @@ void isolation_monitorImpl::ready() {
181213

182214
void isolation_monitorImpl::handle_start() {
183215
enable_publishing = true;
216+
if (config.disable_device_on_stop) {
217+
if (not send_to_imd(3026, 1)) {
218+
EVLOG_error << "Can't enable the device: " << read_device_name();
219+
} else {
220+
EVLOG_info << "Device enabled for measurements";
221+
}
222+
}
184223
}
185224

186225
void isolation_monitorImpl::handle_stop() {
187226
enable_publishing = false;
227+
if (config.disable_device_on_stop) {
228+
if (not send_to_imd(3026, 0)) {
229+
EVLOG_error << "Can't disable the device: " << read_device_name();
230+
} else {
231+
EVLOG_info << "Device disabled after measurements";
232+
}
233+
}
188234
}
189235

190236
void isolation_monitorImpl::handle_start_self_test(double& test_voltage_V) {
191237
EVLOG_info << "IMD Starting self-test...";
238+
// make sure that the device is on
239+
if (config.disable_device_on_stop) {
240+
if (not send_to_imd(3026, 1)) {
241+
EVLOG_error << "Can't enable the device: " << read_device_name();
242+
} else {
243+
EVLOG_info << "Device enabled for self test";
244+
}
245+
}
192246
start_self_test();
193247
}
194248

@@ -209,11 +263,13 @@ void isolation_monitorImpl::read_imd_values() {
209263

210264
isolation_monitorImpl::MeasurementValue voltage_to_earth_l1e;
211265
isolation_monitorImpl::MeasurementValue voltage_to_earth_l2e;
212-
// Read Voltage to Earth L1E and L2E only if the device is not in self test mode and only it
213-
// we are in a measuring cycle. We have seen that Bender sometimes is overwhelmed
266+
// Read Voltage to Earth L1E and L2E only if the device is not in self test
267+
// mode and only it we are in a measuring cycle. We have seen that Bender
268+
// sometimes is overwhelmed
214269
if ((last_test == TestType::NoTest) and (enable_publishing or config.always_publish_measurements)) {
215-
// VOLTAGE_U_L1E_V (1016) and VOLTAGE_U_L2E_V (1020) are consecutive (4 registers apart)
216-
// Read 8 registers starting from 1016 to get both measurements in a single operation
270+
// VOLTAGE_U_L1E_V (1016) and VOLTAGE_U_L2E_V (1020) are consecutive (4
271+
// registers apart) Read 8 registers starting from 1016 to get both
272+
// measurements in a single operation
217273
types::serial_comm_hub_requests::Result register_response =
218274
mod->r_serial_comm_hub->call_modbus_read_holding_registers(
219275
config.imd_device_id, static_cast<int>(ImdRegisters::VOLTAGE_U_L1E_V), 8);
@@ -271,7 +327,8 @@ void isolation_monitorImpl::read_imd_values() {
271327
valid_readings = false;
272328
}
273329

274-
// do not publish values if in error state or the device is in self test mode
330+
// do not publish values if in error state or the device is in self test
331+
// mode
275332
if (last_test == TestType::NoTest) {
276333
if (not error_state_monitor->is_error_active("isolation_monitor/DeviceFault", "")) {
277334
publish_isolation_measurement(m);

modules/HardwareDrivers/IsolationMonitors/Bender_isoCHA425HV/main/isolation_monitorImpl.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct Conf {
4242
bool voltage_to_earth_monitoring_alarm_enable;
4343
int relay_k1_alarm_assignment;
4444
int relay_k2_alarm_assignment;
45+
bool disable_device_on_stop;
4546
};
4647

4748
class isolation_monitorImpl : public isolation_monitorImplBase {

modules/HardwareDrivers/IsolationMonitors/Bender_isoCHA425HV/manifest.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ provides:
122122
3000 Enable over voltage to earth monitoring alarm
123123
type: boolean
124124
default: false
125+
disable_device_on_stop:
126+
description: >-
127+
Disable the device upon stop measurement
128+
type: boolean
129+
default: false
125130
requires:
126131
serial_comm_hub:
127132
interface: serial_communication_hub

0 commit comments

Comments
 (0)