From 6960c176b847b2a68f90c5ecc7c71f647395ce51 Mon Sep 17 00:00:00 2001 From: TanishM Date: Wed, 28 Jan 2026 20:37:21 -0500 Subject: [PATCH 1/9] initial precharge (WRONG) --- include/ACU_Constants.h | 4 +++- include/ACU_SystemTasks.h | 2 ++ lib/systems/include/ACUController.h | 13 ++++++++++--- lib/systems/src/ACUController.cpp | 5 +++-- src/ACU_SystemTasks.cpp | 3 ++- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/include/ACU_Constants.h b/include/ACU_Constants.h index a54b3b8..7988bc6 100644 --- a/include/ACU_Constants.h +++ b/include/ACU_Constants.h @@ -24,6 +24,7 @@ namespace ACUSystems constexpr const volt VOLTAGE_DIFF_TO_INIT_CB = 0.02; // differential with lowest cell voltage to enable cell balancing for a cell constexpr const celsius BALANCE_TEMP_LIMIT_C = 50.0; constexpr const celsius BALANCE_ENABLE_TEMP_THRESH_C = 35.0; // Celsius + constexpr const volt TS_ISOLATION_VOLTAGE = 0.2; // Voltas } namespace ACUInterfaces { @@ -32,7 +33,8 @@ namespace ACUInterfaces { const size_t SERIAL_BAUDRATE = 115200; constexpr const size_t TEENSY_OK_PIN = 3; // > Needs to stay HIGH while wd_kick_pin flips to keep BMS_OK high - constexpr const size_t WD_KICK_PIN = 4; // > Needs to flip at 100 Hz to keep BMS_OK high + constexpr const size_t WD_KICK_PIN = 4; // > Needs to flip at 100 Hz to keep BMS_OK high + constexpr const size_t SW_NOT_OK_PIN = 5; constexpr const size_t N_LATCH_EN_PIN = 6; // > Input to Safety Light, true when teensy is not in FAULT state constexpr const size_t TS_OUT_FILTERED_PIN = 17; constexpr const size_t PACK_OUT_FILTERED_PIN = 18; diff --git a/include/ACU_SystemTasks.h b/include/ACU_SystemTasks.h index 5a0f535..33ba1d8 100644 --- a/include/ACU_SystemTasks.h +++ b/include/ACU_SystemTasks.h @@ -39,4 +39,6 @@ ::HT_TASK::TaskResponse evaluate_accumulator(const unsigned long &sysMicros, con ::HT_TASK::TaskResponse tick_state_machine(const unsigned long &sysMicros, const HT_TASK::TaskInfo &taskInfo); + + #endif \ No newline at end of file diff --git a/lib/systems/include/ACUController.h b/lib/systems/include/ACUController.h index 7efc94d..a80d039 100644 --- a/lib/systems/include/ACUController.h +++ b/lib/systems/include/ACUController.h @@ -20,6 +20,8 @@ namespace acu_controller_default_parameters constexpr const float PACK_MAX_VOLTAGE = 529.2; // from data sheet https://wiki.hytechracing.org/books/ht09-design/page/molicel-pack-investigation constexpr const float PACK_MIN_VOLTAGE = 378.0; // from data sheet^ but just assume 126 * 3.0V constexpr const float PACK_INTERNAL_RESISTANCE = 0.246; // Ohms (measured) + + } struct ACUControllerData_s { @@ -37,6 +39,7 @@ struct ACUControllerData_s uint32_t last_bms_not_ok_eval; bool charging_enabled; bool balancing_enabled; + bool sw_not_ok; }; struct ACUControllerThresholds_s @@ -73,6 +76,7 @@ struct ACUControllerParameters_s size_t invalid_packet_count_thresh = 0; ACUControllerFaultDurations_s fault_durations; ACUControllerPackSpecs_s pack_specs; + float ts_isolation_voltage; }; class ACUController { @@ -99,8 +103,10 @@ class ACUController .pack_nominal_capacity = acu_controller_default_parameters::PACK_NOMINAL_CAPACITY_AH, .pack_max_voltage = acu_controller_default_parameters::PACK_MAX_VOLTAGE, .pack_min_voltage = acu_controller_default_parameters::PACK_MIN_VOLTAGE, - .pack_internal_resistance = acu_controller_default_parameters::PACK_INTERNAL_RESISTANCE - }) : _acu_parameters{thresholds, invalid_packet_count_thresh, fault_durations, pack_specs} {}; + .pack_internal_resistance = acu_controller_default_parameters::PACK_INTERNAL_RESISTANCE} + + + ) : _acu_parameters{thresholds, invalid_packet_count_thresh, fault_durations, pack_specs} {}; /** * @brief Initialize the status time stamps because we don't want accidental sudden faults @@ -112,12 +118,13 @@ class ACUController * @post updates configuration bytes and sends configuration command * @param pack_current current flowing from the pack in amps (negative during discharge, positive during charge) */ - ACUControllerData_s evaluate_accumulator(time_ms current_millis, const BMSCoreData_s &bms_core_data, size_t max_consecutive_invalid_packet_count, float em_current, size_t num_of_voltage_cells); + ACUControllerData_s evaluate_accumulator(time_ms current_millis, const BMSCoreData_s &bms_core_data, size_t max_consecutive_invalid_packet_count, float em_current, size_t num_of_voltage_cells, float pack_voltage_adc, float ts_voltage_adc, float ts_isolation_voltage); /** * Calculate Cell Balancing values * @pre cell charging is enabled * @post output will have the new values + * check TS isolation */ void calculate_cell_balance_statuses(bool* output, const volt* voltages, size_t num_of_voltage_cells, volt min_voltage); diff --git a/lib/systems/src/ACUController.cpp b/lib/systems/src/ACUController.cpp index d3eda66..acd283c 100644 --- a/lib/systems/src/ACUController.cpp +++ b/lib/systems/src/ACUController.cpp @@ -1,4 +1,5 @@ #include "ACUController.h" +#include "ACU_Constants.h" void ACUController::init(time_ms system_start_time, volt pack_voltage) @@ -17,7 +18,7 @@ void ACUController::init(time_ms system_start_time, volt pack_voltage) -ACUControllerData_s ACUController::evaluate_accumulator(time_ms current_millis, const BMSCoreData_s &input_state, size_t max_consecutive_invalid_packet_count, float em_current, size_t num_of_voltage_cells) +ACUControllerData_s ACUController::evaluate_accumulator(time_ms current_millis, const BMSCoreData_s &input_state, size_t max_consecutive_invalid_packet_count, float em_current, size_t num_of_voltage_cells, float pack_voltage_adc, float ts_voltage_adc, float ts_isolation_voltage) { // _acu_state.charging_enabled = input_state.charging_enabled; @@ -100,7 +101,7 @@ ACUControllerData_s ACUController::evaluate_accumulator(time_ms current_millis, // Determine if bms is ok _acu_state.bms_ok = _check_bms_ok(current_millis); - + _acu_state.sw_not_ok = !((pack_voltage_adc < ts_isolation_voltage) && (ts_voltage_adc < ts_isolation_voltage)); return _acu_state; } diff --git a/src/ACU_SystemTasks.cpp b/src/ACU_SystemTasks.cpp index 70c9112..67e5b3b 100644 --- a/src/ACU_SystemTasks.cpp +++ b/src/ACU_SystemTasks.cpp @@ -62,7 +62,8 @@ HT_TASK::TaskResponse evaluate_accumulator(const unsigned long &sysMicros, const BMSDriverInstance_t::instance().get_bms_core_data(), BMSFaultDataManagerInstance_t::instance().get_fault_data().max_consecutive_invalid_packet_count, EMInterfaceInstance::instance().get_latest_data(sys_time::hal_millis()).em_current, - ACUConstants::NUM_CELLS + ACUConstants::NUM_CELLS, + ACUSystems::TS_ISOLATION_VOLTAGE ); return HT_TASK::TaskResponse::YIELD; } From 1e07b586ad90c2711db21549825a38f0c4c4b013 Mon Sep 17 00:00:00 2001 From: TanishM Date: Thu, 29 Jan 2026 02:21:48 -0500 Subject: [PATCH 2/9] precharge_sw_check added --- include/ACU_Constants.h | 2 +- include/ACU_SystemTasks.h | 1 + lib/interfaces/src/WatchdogInterface.cpp | 1 + lib/state_machine/include/ACUStateMachine.h | 6 +++++- lib/state_machine/src/ACUStateMachine.cpp | 9 ++++++++- lib/systems/include/ACUController.h | 18 +++++++++++++----- lib/systems/src/ACUController.cpp | 19 ++++++++++++++++--- src/ACU_InterfaceTasks.cpp | 6 +++++- src/ACU_SystemTasks.cpp | 16 ++++++++++++---- 9 files changed, 62 insertions(+), 16 deletions(-) diff --git a/include/ACU_Constants.h b/include/ACU_Constants.h index 7988bc6..6ab5231 100644 --- a/include/ACU_Constants.h +++ b/include/ACU_Constants.h @@ -24,7 +24,7 @@ namespace ACUSystems constexpr const volt VOLTAGE_DIFF_TO_INIT_CB = 0.02; // differential with lowest cell voltage to enable cell balancing for a cell constexpr const celsius BALANCE_TEMP_LIMIT_C = 50.0; constexpr const celsius BALANCE_ENABLE_TEMP_THRESH_C = 35.0; // Celsius - constexpr const volt TS_ISOLATION_VOLTAGE = 0.2; // Voltas + constexpr const volt TS_ISOLATION_VOLTAGE = 0.2; // Volts } namespace ACUInterfaces { diff --git a/include/ACU_SystemTasks.h b/include/ACU_SystemTasks.h index 33ba1d8..d2eab69 100644 --- a/include/ACU_SystemTasks.h +++ b/include/ACU_SystemTasks.h @@ -30,6 +30,7 @@ extern ::etl::delegate has_imd_fault; extern ::etl::delegate received_valid_shdn_out; extern ::etl::delegate enable_cell_balancing; extern ::etl::delegate disable_cell_balancing; +extern ::etl::delegate weld_check; extern ::etl::delegate disable_watchdog; extern ::etl::delegate reinitialize_watchdog; extern ::etl::delegate disable_n_latch_en; diff --git a/lib/interfaces/src/WatchdogInterface.cpp b/lib/interfaces/src/WatchdogInterface.cpp index ef190c9..0edd011 100644 --- a/lib/interfaces/src/WatchdogInterface.cpp +++ b/lib/interfaces/src/WatchdogInterface.cpp @@ -5,6 +5,7 @@ void WatchdogInterface::init() { pinMode(_watchdog_parameters.pinout.teensy_ok_pin, OUTPUT); pinMode(_watchdog_parameters.pinout.teensy_wd_kick_pin, OUTPUT); pinMode(_watchdog_parameters.pinout.teensy_n_latch_en_pin, OUTPUT); + // Initial Pin States for OUTPUT pins digitalWrite(_watchdog_parameters.pinout.teensy_ok_pin, HIGH); diff --git a/lib/state_machine/include/ACUStateMachine.h b/lib/state_machine/include/ACUStateMachine.h index 4672e85..5ad50d7 100644 --- a/lib/state_machine/include/ACUStateMachine.h +++ b/lib/state_machine/include/ACUStateMachine.h @@ -13,7 +13,8 @@ enum class ACUState_e STARTUP = 0, ACTIVE = 1, CHARGING = 2, - FAULTED = 3, + FAULTED = 3, + WELDED = 4, }; class ACUStateMachine @@ -23,6 +24,7 @@ class ACUStateMachine etl::delegate charge_state_requested, etl::delegate has_bms_fault, etl::delegate has_imd_fault, + etl::delegate weld_check, etl::delegate received_valid_shdn_out, etl::delegate enable_cell_balancing, etl::delegate disable_cell_balancing, @@ -35,6 +37,7 @@ class ACUStateMachine _charge_state_requested(charge_state_requested), _has_bms_fault(has_bms_fault), _has_imd_fault(has_imd_fault), + _weld_check(weld_check), _received_valid_shdn_out(received_valid_shdn_out), _enable_cell_balancing(enable_cell_balancing), _disable_cell_balancing(disable_cell_balancing), @@ -77,6 +80,7 @@ class ACUStateMachine etl::delegate _charge_state_requested; etl::delegate _has_bms_fault; etl::delegate _has_imd_fault; + etl::delegate _weld_check; etl::delegate _received_valid_shdn_out; /// @brief setters etl::delegate _enable_cell_balancing; diff --git a/lib/state_machine/src/ACUStateMachine.cpp b/lib/state_machine/src/ACUStateMachine.cpp index c1e3536..a8bd104 100644 --- a/lib/state_machine/src/ACUStateMachine.cpp +++ b/lib/state_machine/src/ACUStateMachine.cpp @@ -4,7 +4,7 @@ void ACUStateMachine::tick_state_machine(unsigned long current_millis) { switch(_current_state) { case ACUState_e::STARTUP: { - if (_received_valid_shdn_out()) { + if (_received_valid_shdn_out()) { // is there a race condition between voltage reading and shdn_out? _set_state(ACUState_e::ACTIVE, current_millis); break; } @@ -12,8 +12,15 @@ void ACUStateMachine::tick_state_machine(unsigned long current_millis) { _set_state(ACUState_e::FAULTED, current_millis); break; } + if (_weld_check()) { + _set_state(ACUState_e::WELDED, current_millis); + } break; } + case ACUState_e::WELDED: + { + //do smth + } case ACUState_e::ACTIVE: { if (_charge_state_requested()) { diff --git a/lib/systems/include/ACUController.h b/lib/systems/include/ACUController.h index a80d039..1cac005 100644 --- a/lib/systems/include/ACUController.h +++ b/lib/systems/include/ACUController.h @@ -1,6 +1,7 @@ #ifndef ACUCONTROLLER_H #define ACUCONTROLLER_H +#include #include #include #include @@ -39,7 +40,9 @@ struct ACUControllerData_s uint32_t last_bms_not_ok_eval; bool charging_enabled; bool balancing_enabled; - bool sw_not_ok; + bool air_plus_welded; + bool air_minus_welded; + }; struct ACUControllerThresholds_s @@ -53,6 +56,7 @@ struct ACUControllerThresholds_s volt v_diff_to_init_cb = 0; celsius balance_temp_limit_c = 0; celsius balance_enable_temp_c = 0; + volt ts_isolation_voltage = 0; }; struct ACUControllerFaultDurations_s @@ -73,10 +77,10 @@ struct ACUControllerPackSpecs_s struct ACUControllerParameters_s { ACUControllerThresholds_s thresholds; + size_t weld_check_pin; size_t invalid_packet_count_thresh = 0; ACUControllerFaultDurations_s fault_durations; ACUControllerPackSpecs_s pack_specs; - float ts_isolation_voltage; }; class ACUController { @@ -94,6 +98,7 @@ class ACUController * @param max_temp_fault_dur max number of temp faults allowed */ ACUController(ACUControllerThresholds_s thresholds, + size_t weld_check_pin, size_t invalid_packet_count_thresh = acu_controller_default_parameters::MAX_INVALID_PACKET_FAULT_COUNT, ACUControllerFaultDurations_s fault_durations = { .max_allowed_voltage_fault_dur = acu_controller_default_parameters::MAX_VOLTAGE_FAULT_DUR, @@ -104,9 +109,9 @@ class ACUController .pack_max_voltage = acu_controller_default_parameters::PACK_MAX_VOLTAGE, .pack_min_voltage = acu_controller_default_parameters::PACK_MIN_VOLTAGE, .pack_internal_resistance = acu_controller_default_parameters::PACK_INTERNAL_RESISTANCE} + - - ) : _acu_parameters{thresholds, invalid_packet_count_thresh, fault_durations, pack_specs} {}; + ) : _acu_parameters{thresholds, weld_check_pin, invalid_packet_count_thresh, fault_durations, pack_specs} {}; /** * @brief Initialize the status time stamps because we don't want accidental sudden faults @@ -118,7 +123,7 @@ class ACUController * @post updates configuration bytes and sends configuration command * @param pack_current current flowing from the pack in amps (negative during discharge, positive during charge) */ - ACUControllerData_s evaluate_accumulator(time_ms current_millis, const BMSCoreData_s &bms_core_data, size_t max_consecutive_invalid_packet_count, float em_current, size_t num_of_voltage_cells, float pack_voltage_adc, float ts_voltage_adc, float ts_isolation_voltage); + ACUControllerData_s evaluate_accumulator(time_ms current_millis, const BMSCoreData_s &bms_core_data, size_t max_consecutive_invalid_packet_count, float em_current, size_t num_of_voltage_cells); /** * Calculate Cell Balancing values @@ -143,6 +148,9 @@ class ACUController { _acu_state.charging_enabled = false; } + + bool check_ts_isolation(volt pack_voltage_adc, volt ts_voltage_adc); + private: diff --git a/lib/systems/src/ACUController.cpp b/lib/systems/src/ACUController.cpp index acd283c..cdcd4a1 100644 --- a/lib/systems/src/ACUController.cpp +++ b/lib/systems/src/ACUController.cpp @@ -1,5 +1,5 @@ #include "ACUController.h" -#include "ACU_Constants.h" + void ACUController::init(time_ms system_start_time, volt pack_voltage) @@ -13,12 +13,17 @@ void ACUController::init(time_ms system_start_time, volt pack_voltage) _acu_state.prev_bms_time_stamp = system_start_time; _acu_state.SoC = (pack_voltage <= _acu_parameters.pack_specs.pack_min_voltage) ? 0.0f : ((pack_voltage - _acu_parameters.pack_specs.pack_min_voltage) / (_acu_parameters.pack_specs.pack_max_voltage - _acu_parameters.pack_specs.pack_min_voltage)); _acu_state.balancing_enabled = false; + _acu_state.air_minus_welded = false; + _acu_state.air_plus_welded = false; + + pinMode(_acu_parameters.weld_check_pin, OUTPUT); + digitalWrite(_acu_parameters.weld_check_pin, HIGH); } -ACUControllerData_s ACUController::evaluate_accumulator(time_ms current_millis, const BMSCoreData_s &input_state, size_t max_consecutive_invalid_packet_count, float em_current, size_t num_of_voltage_cells, float pack_voltage_adc, float ts_voltage_adc, float ts_isolation_voltage) +ACUControllerData_s ACUController::evaluate_accumulator(time_ms current_millis, const BMSCoreData_s &input_state, size_t max_consecutive_invalid_packet_count, float em_current, size_t num_of_voltage_cells) { // _acu_state.charging_enabled = input_state.charging_enabled; @@ -101,7 +106,6 @@ ACUControllerData_s ACUController::evaluate_accumulator(time_ms current_millis, // Determine if bms is ok _acu_state.bms_ok = _check_bms_ok(current_millis); - _acu_state.sw_not_ok = !((pack_voltage_adc < ts_isolation_voltage) && (ts_voltage_adc < ts_isolation_voltage)); return _acu_state; } @@ -174,4 +178,13 @@ bool ACUController::_check_invalid_packet_faults(time_ms current_millis) { bool invalid_packet_fault = (current_millis - _acu_state.last_time_invalid_packet_present) > _acu_parameters.fault_durations.max_allowed_invalid_packet_fault_dur; return invalid_packet_fault; +} + +bool ACUController::check_ts_isolation(volt pack_voltage_adc, volt ts_voltage_adc) +{ + bool sw_not_ok = !((pack_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage) && (ts_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage)); + digitalWrite(_acu_parameters.weld_check_pin, sw_not_ok); + _acu_state.air_minus_welded = (pack_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); + _acu_state.air_plus_welded = (ts_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); + return sw_not_ok; } \ No newline at end of file diff --git a/src/ACU_InterfaceTasks.cpp b/src/ACU_InterfaceTasks.cpp index 33e7594..9aff363 100644 --- a/src/ACU_InterfaceTasks.cpp +++ b/src/ACU_InterfaceTasks.cpp @@ -44,7 +44,11 @@ static ACUAllDataType_s make_acu_all_data() out.core_data.min_measured_ts_out_voltage = watchdog.min_measured_ts_out_voltage; out.core_data.min_shdn_out_voltage = watchdog.min_shdn_out_voltage; // SoC/SoH placeholders (leave unchanged here) - out.SoC = ACUControllerInstance::instance().get_status().SoC; + auto ACU = ACUControllerInstance::instance().get_status(); + + out.SoC = ACU.SoC; + out.core_data.air_plus_welded = ACU.air_plus_welded; + out.core_data.air_minus_welded = ACU.air_minus_welded; return out; } diff --git a/src/ACU_SystemTasks.cpp b/src/ACU_SystemTasks.cpp index 67e5b3b..2b994f8 100644 --- a/src/ACU_SystemTasks.cpp +++ b/src/ACU_SystemTasks.cpp @@ -11,7 +11,9 @@ bool initialize_all_systems() ACUSystems::MIN_PACK_TOTAL_VOLTAGE, ACUSystems::VOLTAGE_DIFF_TO_INIT_CB, ACUSystems::BALANCE_TEMP_LIMIT_C, - ACUSystems::BALANCE_ENABLE_TEMP_THRESH_C}); + ACUSystems::BALANCE_ENABLE_TEMP_THRESH_C, + ACUSystems::TS_ISOLATION_VOLTAGE}, + ACUInterfaces::SW_NOT_OK_PIN); ACUControllerInstance::instance().init(sys_time::hal_millis(), BMSDriverInstance_t::instance().get_bms_data().total_voltage); /* State Machine Initialization */ @@ -25,14 +27,19 @@ bool initialize_all_systems() etl::delegate has_imd_fault = etl::delegate::create([]() -> bool { return !ADCInterfaceInstance::instance().read_imd_ok(sys_time::hal_millis()); }); + etl::delegate weld_check = etl::delegate::create([]() -> bool + { ACUControllerInstance::instance().check_ts_isolation(ADCInterfaceInstance::instance().read_pack_out_filtered(), ADCInterfaceInstance::instance().read_ts_out_filtered()); }); + + etl::delegate disable_watchdog = etl::delegate::create(WatchdogInstance::instance()); + etl::delegate received_valid_shdn_out = etl::delegate::create(ADCInterfaceInstance::instance()); + etl::delegate enable_cell_balancing = etl::delegate::create([]() -> void { ACUControllerInstance::instance().enableCharging(); }); etl::delegate disable_cell_balancing = etl::delegate::create([]() -> void { ACUControllerInstance::instance().disableCharging(); }); - etl::delegate disable_watchdog = etl::delegate::create(WatchdogInstance::instance()); etl::delegate reinitialize_watchdog = etl::delegate::create(WatchdogInstance::instance()); @@ -40,9 +47,11 @@ bool initialize_all_systems() etl::delegate reset_latch = etl::delegate::create(WatchdogInstance::instance()); + ACUStateMachineInstance::create(charge_state_request, has_bms_fault, has_imd_fault, + weld_check, received_valid_shdn_out, enable_cell_balancing, disable_cell_balancing, @@ -62,8 +71,7 @@ HT_TASK::TaskResponse evaluate_accumulator(const unsigned long &sysMicros, const BMSDriverInstance_t::instance().get_bms_core_data(), BMSFaultDataManagerInstance_t::instance().get_fault_data().max_consecutive_invalid_packet_count, EMInterfaceInstance::instance().get_latest_data(sys_time::hal_millis()).em_current, - ACUConstants::NUM_CELLS, - ACUSystems::TS_ISOLATION_VOLTAGE + ACUConstants::NUM_CELLS ); return HT_TASK::TaskResponse::YIELD; } From a1a2f5ea1ca307ac58dd01b8438ff434046c6737 Mon Sep 17 00:00:00 2001 From: TanishM Date: Fri, 30 Jan 2026 21:07:24 -0500 Subject: [PATCH 3/9] fixed var names --- lib/interfaces/src/ACUEthernetInterface.cpp | 1 + lib/state_machine/src/ACUStateMachine.cpp | 2 +- lib/systems/include/ACUController.h | 4 ++-- lib/systems/src/ACUController.cpp | 8 ++++---- src/ACU_InterfaceTasks.cpp | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/interfaces/src/ACUEthernetInterface.cpp b/lib/interfaces/src/ACUEthernetInterface.cpp index 28614be..d592f80 100644 --- a/lib/interfaces/src/ACUEthernetInterface.cpp +++ b/lib/interfaces/src/ACUEthernetInterface.cpp @@ -45,6 +45,7 @@ hytech_msgs_ACUCoreData ACUEthernetInterface::make_acu_core_data_msg(const ACUCo out.min_measured_pack_voltage = shared_state.min_measured_pack_out_voltage; out.min_measured_tractive_system_voltage = shared_state.min_measured_ts_out_voltage; out.min_measured_shdn_out_voltage = shared_state.min_shdn_out_voltage; + return out; } diff --git a/lib/state_machine/src/ACUStateMachine.cpp b/lib/state_machine/src/ACUStateMachine.cpp index a8bd104..3b11289 100644 --- a/lib/state_machine/src/ACUStateMachine.cpp +++ b/lib/state_machine/src/ACUStateMachine.cpp @@ -19,7 +19,7 @@ void ACUStateMachine::tick_state_machine(unsigned long current_millis) { } case ACUState_e::WELDED: { - //do smth + } case ACUState_e::ACTIVE: { diff --git a/lib/systems/include/ACUController.h b/lib/systems/include/ACUController.h index 1cac005..b2bfdac 100644 --- a/lib/systems/include/ACUController.h +++ b/lib/systems/include/ACUController.h @@ -40,8 +40,8 @@ struct ACUControllerData_s uint32_t last_bms_not_ok_eval; bool charging_enabled; bool balancing_enabled; - bool air_plus_welded; - bool air_minus_welded; + bool high_side_contactor_welded; + bool low_side_contactor_welded; }; diff --git a/lib/systems/src/ACUController.cpp b/lib/systems/src/ACUController.cpp index cdcd4a1..0fb19f9 100644 --- a/lib/systems/src/ACUController.cpp +++ b/lib/systems/src/ACUController.cpp @@ -13,8 +13,8 @@ void ACUController::init(time_ms system_start_time, volt pack_voltage) _acu_state.prev_bms_time_stamp = system_start_time; _acu_state.SoC = (pack_voltage <= _acu_parameters.pack_specs.pack_min_voltage) ? 0.0f : ((pack_voltage - _acu_parameters.pack_specs.pack_min_voltage) / (_acu_parameters.pack_specs.pack_max_voltage - _acu_parameters.pack_specs.pack_min_voltage)); _acu_state.balancing_enabled = false; - _acu_state.air_minus_welded = false; - _acu_state.air_plus_welded = false; + _acu_state.high_side_contactor_welded = false; + _acu_state.low_side_contactor_welded = false; pinMode(_acu_parameters.weld_check_pin, OUTPUT); digitalWrite(_acu_parameters.weld_check_pin, HIGH); @@ -184,7 +184,7 @@ bool ACUController::check_ts_isolation(volt pack_voltage_adc, volt ts_voltage_ad { bool sw_not_ok = !((pack_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage) && (ts_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage)); digitalWrite(_acu_parameters.weld_check_pin, sw_not_ok); - _acu_state.air_minus_welded = (pack_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); - _acu_state.air_plus_welded = (ts_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); + _acu_state.low_side_contactor_welded = !(pack_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); + _acu_state.high_side_contactor_welded = !(ts_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); return sw_not_ok; } \ No newline at end of file diff --git a/src/ACU_InterfaceTasks.cpp b/src/ACU_InterfaceTasks.cpp index 9aff363..e90f16c 100644 --- a/src/ACU_InterfaceTasks.cpp +++ b/src/ACU_InterfaceTasks.cpp @@ -47,8 +47,8 @@ static ACUAllDataType_s make_acu_all_data() auto ACU = ACUControllerInstance::instance().get_status(); out.SoC = ACU.SoC; - out.core_data.air_plus_welded = ACU.air_plus_welded; - out.core_data.air_minus_welded = ACU.air_minus_welded; + out.core_data.high_side_contactor_welded = ACU.high_side_contactor_welded; + out.core_data.low_side_contactor_welded = ACU.low_side_contactor_welded; return out; } From 36bcb89cc77d463b4104ddf357f74da55d137816 Mon Sep 17 00:00:00 2001 From: TanishM Date: Fri, 30 Jan 2026 21:15:26 -0500 Subject: [PATCH 4/9] fixed platformio with new firmware types --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index bb64b60..aa28dfb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,7 +1,7 @@ [common] lib_deps_shared = https://github.com/hytech-racing/shared_firmware_systems.git - https://github.com/hytech-racing/shared_firmware_types.git#9525cc8b5778567afee9d9121f8f8933367e13b3 + https://github.com/hytech-racing/shared_firmware_types.git7a3684f9501d672b8229476644b8ee5556f0adb5 Embedded Template Library@^20.39.4 ; Teensy41 Environment. This environment is the primary environment for uploading code to the car. From 69d2566c1f7eec236d925d7068dc37c12ad4761e Mon Sep 17 00:00:00 2001 From: TanishM Date: Fri, 30 Jan 2026 21:18:09 -0500 Subject: [PATCH 5/9] small fix --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index aa28dfb..f200209 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,7 +1,7 @@ [common] lib_deps_shared = https://github.com/hytech-racing/shared_firmware_systems.git - https://github.com/hytech-racing/shared_firmware_types.git7a3684f9501d672b8229476644b8ee5556f0adb5 + https://github.com/hytech-racing/shared_firmware_types.git#7a3684f9501d672b8229476644b8ee5556f0adb5 Embedded Template Library@^20.39.4 ; Teensy41 Environment. This environment is the primary environment for uploading code to the car. From 1b853170a9feddd26bf25a705cb05fb3d3f412f9 Mon Sep 17 00:00:00 2001 From: TanishM Date: Fri, 30 Jan 2026 21:56:43 -0500 Subject: [PATCH 6/9] attempt to fix tests and changed variable names to be better --- include/ACU_SystemTasks.h | 2 +- lib/state_machine/include/ACUStateMachine.h | 6 +++--- lib/state_machine/src/ACUStateMachine.cpp | 2 +- src/ACU_SystemTasks.cpp | 4 ++-- test/test_systems/test_acu_controller.h | 18 +++++++++--------- test/test_systems/test_acu_state_machine.h | 9 +++++++++ 6 files changed, 25 insertions(+), 16 deletions(-) diff --git a/include/ACU_SystemTasks.h b/include/ACU_SystemTasks.h index d2eab69..2f3dcdd 100644 --- a/include/ACU_SystemTasks.h +++ b/include/ACU_SystemTasks.h @@ -30,7 +30,7 @@ extern ::etl::delegate has_imd_fault; extern ::etl::delegate received_valid_shdn_out; extern ::etl::delegate enable_cell_balancing; extern ::etl::delegate disable_cell_balancing; -extern ::etl::delegate weld_check; +extern ::etl::delegate contactor_welded; extern ::etl::delegate disable_watchdog; extern ::etl::delegate reinitialize_watchdog; extern ::etl::delegate disable_n_latch_en; diff --git a/lib/state_machine/include/ACUStateMachine.h b/lib/state_machine/include/ACUStateMachine.h index 5ad50d7..bf64120 100644 --- a/lib/state_machine/include/ACUStateMachine.h +++ b/lib/state_machine/include/ACUStateMachine.h @@ -24,7 +24,7 @@ class ACUStateMachine etl::delegate charge_state_requested, etl::delegate has_bms_fault, etl::delegate has_imd_fault, - etl::delegate weld_check, + etl::delegate contactor_welded, etl::delegate received_valid_shdn_out, etl::delegate enable_cell_balancing, etl::delegate disable_cell_balancing, @@ -37,7 +37,7 @@ class ACUStateMachine _charge_state_requested(charge_state_requested), _has_bms_fault(has_bms_fault), _has_imd_fault(has_imd_fault), - _weld_check(weld_check), + _contactor_welded(contactor_welded), _received_valid_shdn_out(received_valid_shdn_out), _enable_cell_balancing(enable_cell_balancing), _disable_cell_balancing(disable_cell_balancing), @@ -80,7 +80,7 @@ class ACUStateMachine etl::delegate _charge_state_requested; etl::delegate _has_bms_fault; etl::delegate _has_imd_fault; - etl::delegate _weld_check; + etl::delegate _contactor_welded; etl::delegate _received_valid_shdn_out; /// @brief setters etl::delegate _enable_cell_balancing; diff --git a/lib/state_machine/src/ACUStateMachine.cpp b/lib/state_machine/src/ACUStateMachine.cpp index 3b11289..2ac0d70 100644 --- a/lib/state_machine/src/ACUStateMachine.cpp +++ b/lib/state_machine/src/ACUStateMachine.cpp @@ -12,7 +12,7 @@ void ACUStateMachine::tick_state_machine(unsigned long current_millis) { _set_state(ACUState_e::FAULTED, current_millis); break; } - if (_weld_check()) { + if (_contactor_welded()) { _set_state(ACUState_e::WELDED, current_millis); } break; diff --git a/src/ACU_SystemTasks.cpp b/src/ACU_SystemTasks.cpp index 2b994f8..466c6d0 100644 --- a/src/ACU_SystemTasks.cpp +++ b/src/ACU_SystemTasks.cpp @@ -27,7 +27,7 @@ bool initialize_all_systems() etl::delegate has_imd_fault = etl::delegate::create([]() -> bool { return !ADCInterfaceInstance::instance().read_imd_ok(sys_time::hal_millis()); }); - etl::delegate weld_check = etl::delegate::create([]() -> bool + etl::delegate contactor_welded = etl::delegate::create([]() -> bool { ACUControllerInstance::instance().check_ts_isolation(ADCInterfaceInstance::instance().read_pack_out_filtered(), ADCInterfaceInstance::instance().read_ts_out_filtered()); }); etl::delegate disable_watchdog = etl::delegate::create(WatchdogInstance::instance()); @@ -51,7 +51,7 @@ bool initialize_all_systems() ACUStateMachineInstance::create(charge_state_request, has_bms_fault, has_imd_fault, - weld_check, + contactor_welded, received_valid_shdn_out, enable_cell_balancing, disable_cell_balancing, diff --git a/test/test_systems/test_acu_controller.h b/test/test_systems/test_acu_controller.h index 95b7538..187f049 100644 --- a/test/test_systems/test_acu_controller.h +++ b/test/test_systems/test_acu_controller.h @@ -19,12 +19,12 @@ ACUControllerThresholds_s thresholds = {ACUSystems::MIN_DISCHARGE_VOLTAGE_THRESH ACUSystems::MIN_PACK_TOTAL_VOLTAGE, ACUSystems::VOLTAGE_DIFF_TO_INIT_CB, ACUSystems::BALANCE_TEMP_LIMIT_C, - ACUSystems::BALANCE_ENABLE_TEMP_THRESH_C - }; + ACUSystems::BALANCE_ENABLE_TEMP_THRESH_C, + ACUSystems::TS_ISOLATION_VOLTAGE}; TEST(ACUControllerTesting, initial_state) { - ACUControllerInstance::create(thresholds); + ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; uint32_t start_time = 0; @@ -46,7 +46,7 @@ TEST(ACUControllerTesting, initial_state) TEST(ACUControllerTesting, charging_state) { - ACUControllerInstance::create(thresholds); + ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); ACUController controller = ACUControllerInstance::instance(); charging_enabled = true; @@ -91,7 +91,7 @@ TEST(ACUControllerTesting, charging_state) TEST(ACUControllerTesting, faulted_state) { - ACUControllerInstance::create(thresholds); + ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; // or true doesn't matter @@ -128,7 +128,7 @@ TEST(ACUControllerTesting, faulted_state) TEST(ACUControllerTesting, ir_compensation_discharge) { - ACUControllerInstance::create(thresholds); + ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; @@ -173,7 +173,7 @@ TEST(ACUControllerTesting, ir_compensation_discharge) TEST(ACUControllerTesting, ir_compensation_charge) { - ACUControllerInstance::create(thresholds); + ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; // Disable balancing to focus on IR compensation test @@ -219,7 +219,7 @@ TEST(ACUControllerTesting, ir_compensation_charge) // Tests that OV faults require 1000ms persistence before triggering TEST(ACUControllerTesting, cell_overvoltage_fault_persistence) { - ACUControllerInstance::create(thresholds); + ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; @@ -260,7 +260,7 @@ TEST(ACUControllerTesting, cell_overvoltage_fault_persistence) // Tests that UV faults require 1000ms persistence before triggering TEST(ACUControllerTesting, cell_undervoltage_fault_persistence) { - ACUControllerInstance::create(thresholds); + ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; diff --git a/test/test_systems/test_acu_state_machine.h b/test/test_systems/test_acu_state_machine.h index 3e839a6..69df725 100644 --- a/test/test_systems/test_acu_state_machine.h +++ b/test/test_systems/test_acu_state_machine.h @@ -10,6 +10,7 @@ bool received_CCU_msg_var; bool has_bms_fault_var; bool has_imd_fault_var; bool received_valid_shdn_out_var; +bool is_contactor_welded; bool charging_en = false; bool watchdog_en = true; @@ -27,6 +28,10 @@ etl::delegate has_imd_fault = etl::delegate::create([]() -> bool return has_imd_fault_var; }); +etl::delegate contactor_welded = etl::delegate::create([]() -> bool { + return contactor_welded; +}); + etl::delegate received_valid_shdn_out = etl::delegate::create([]() -> bool { return received_valid_shdn_out_var; }); @@ -59,6 +64,7 @@ ACUStateMachine state_machine = ACUStateMachine( received_CCU_message, has_bms_fault, has_imd_fault, + contactor_welded, received_valid_shdn_out, enable_cell_balancing, disable_cell_balancing, @@ -74,6 +80,7 @@ TEST (ACUStateMachineTesting, initial_state) { has_bms_fault_var = false; has_imd_fault_var = false; received_valid_shdn_out_var = false; + is_contactor_welded = false; ASSERT_EQ(state_machine.get_state(), ACUState_e::STARTUP); // initial state_machine.tick_state_machine(0); @@ -89,6 +96,7 @@ TEST (ACUStateMachineTesting, CCU_msg_state) { has_bms_fault_var = false; has_imd_fault_var = false; received_valid_shdn_out_var = false; + is_contactor_welded = false; ASSERT_EQ(state_machine.get_state(), ACUState_e::ACTIVE); // initial @@ -110,6 +118,7 @@ TEST (ACUStateMachineTesting, fault_states) { has_bms_fault_var = false; has_imd_fault_var = false; received_valid_shdn_out_var = true; + is_contactor_welded = false; ASSERT_EQ(state_machine.get_state(), ACUState_e::ACTIVE); // initial From b34b8ada24b17e27265ab73a327b7f123e17186c Mon Sep 17 00:00:00 2001 From: TanishM Date: Fri, 30 Jan 2026 22:11:22 -0500 Subject: [PATCH 7/9] see if it works (stone) --- test/test_systems/test_acu_state_machine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_systems/test_acu_state_machine.h b/test/test_systems/test_acu_state_machine.h index 69df725..7665c30 100644 --- a/test/test_systems/test_acu_state_machine.h +++ b/test/test_systems/test_acu_state_machine.h @@ -29,7 +29,7 @@ etl::delegate has_imd_fault = etl::delegate::create([]() -> bool }); etl::delegate contactor_welded = etl::delegate::create([]() -> bool { - return contactor_welded; + return is_contactor_welded; }); etl::delegate received_valid_shdn_out = etl::delegate::create([]() -> bool { From 9f0f880f2f0922d8b92cb3c72b63ffa66aa9cfd4 Mon Sep 17 00:00:00 2001 From: TanishM Date: Sat, 31 Jan 2026 16:25:10 -0500 Subject: [PATCH 8/9] moved writing pin to ADCInterface --- lib/interfaces/include/ADCInterface.h | 5 +++ lib/interfaces/src/ADCInterface.cpp | 9 ++++++ lib/state_machine/include/ACUStateMachine.h | 6 ++++ lib/state_machine/src/ACUStateMachine.cpp | 12 +++++-- lib/systems/include/ACUController.h | 4 +-- lib/systems/src/ACUController.cpp | 5 +-- src/ACU_InterfaceTasks.cpp | 3 +- src/ACU_SystemTasks.cpp | 15 +++++++-- test/test_systems/test_acu_controller.h | 35 +++++++++++---------- test/test_systems/test_acu_state_machine.h | 8 +++++ 10 files changed, 72 insertions(+), 30 deletions(-) diff --git a/lib/interfaces/include/ADCInterface.h b/lib/interfaces/include/ADCInterface.h index c9bc494..7181b94 100644 --- a/lib/interfaces/include/ADCInterface.h +++ b/lib/interfaces/include/ADCInterface.h @@ -25,6 +25,7 @@ struct ADCPinout_s pin teensy_pack_out_filtered_pin; pin teensy_bspd_current_pin; pin teensy_scaled_24V_pin; + pin teensy_sw_not_ok_pin; }; struct ADCConversions_s @@ -155,6 +156,10 @@ class ADCInterface */ bool is_in_imd_startup_period() const; + void set_sw_not_ok_pin_high(); + + void set_sw_not_ok_pin_low(); + private: const ADCInterfaceParams_s _adc_parameters = {}; diff --git a/lib/interfaces/src/ADCInterface.cpp b/lib/interfaces/src/ADCInterface.cpp index 81450fe..f7850b9 100644 --- a/lib/interfaces/src/ADCInterface.cpp +++ b/lib/interfaces/src/ADCInterface.cpp @@ -9,6 +9,7 @@ void ADCInterface::init(uint32_t init_millis) { pinMode(_adc_parameters.pinout.teensy_pack_out_filtered_pin, INPUT); pinMode(_adc_parameters.pinout.teensy_bspd_current_pin, INPUT); pinMode(_adc_parameters.pinout.teensy_scaled_24V_pin, INPUT); + pinMode(_adc_parameters.pinout.teensy_sw_not_ok_pin, OUTPUT); _init_millis = init_millis; _in_imd_startup_period = true; @@ -80,4 +81,12 @@ const ADCInterfaceParams_s& ADCInterface::get_adc_params() const { bool ADCInterface::is_in_imd_startup_period() const { return _in_imd_startup_period; +} + +void ADCInterface::set_sw_not_ok_pin_high() { + digitalWrite(_adc_parameters.pinout.teensy_sw_not_ok_pin, HIGH); +} + +void ADCInterface::set_sw_not_ok_pin_low() { + digitalWrite(_adc_parameters.pinout.teensy_sw_not_ok_pin, LOW); } \ No newline at end of file diff --git a/lib/state_machine/include/ACUStateMachine.h b/lib/state_machine/include/ACUStateMachine.h index bf64120..73812b3 100644 --- a/lib/state_machine/include/ACUStateMachine.h +++ b/lib/state_machine/include/ACUStateMachine.h @@ -25,6 +25,8 @@ class ACUStateMachine etl::delegate has_bms_fault, etl::delegate has_imd_fault, etl::delegate contactor_welded, + etl::delegate set_sw_not_ok_pin_high, + etl::delegate set_sw_not_ok_pin_low, etl::delegate received_valid_shdn_out, etl::delegate enable_cell_balancing, etl::delegate disable_cell_balancing, @@ -38,6 +40,8 @@ class ACUStateMachine _has_bms_fault(has_bms_fault), _has_imd_fault(has_imd_fault), _contactor_welded(contactor_welded), + _set_sw_not_ok_pin_high(set_sw_not_ok_pin_high), + _set_sw_not_ok_pin_low(set_sw_not_ok_pin_low), _received_valid_shdn_out(received_valid_shdn_out), _enable_cell_balancing(enable_cell_balancing), _disable_cell_balancing(disable_cell_balancing), @@ -81,6 +85,8 @@ class ACUStateMachine etl::delegate _has_bms_fault; etl::delegate _has_imd_fault; etl::delegate _contactor_welded; + etl::delegate _set_sw_not_ok_pin_high; + etl::delegate _set_sw_not_ok_pin_low; etl::delegate _received_valid_shdn_out; /// @brief setters etl::delegate _enable_cell_balancing; diff --git a/lib/state_machine/src/ACUStateMachine.cpp b/lib/state_machine/src/ACUStateMachine.cpp index 2ac0d70..5223a79 100644 --- a/lib/state_machine/src/ACUStateMachine.cpp +++ b/lib/state_machine/src/ACUStateMachine.cpp @@ -4,6 +4,14 @@ void ACUStateMachine::tick_state_machine(unsigned long current_millis) { switch(_current_state) { case ACUState_e::STARTUP: { + if (_contactor_welded()) { + _set_sw_not_ok_pin_high(); + _set_state(ACUState_e::WELDED, current_millis); + } + else { + _set_sw_not_ok_pin_low(); + } + if (_received_valid_shdn_out()) { // is there a race condition between voltage reading and shdn_out? _set_state(ACUState_e::ACTIVE, current_millis); break; @@ -12,9 +20,7 @@ void ACUStateMachine::tick_state_machine(unsigned long current_millis) { _set_state(ACUState_e::FAULTED, current_millis); break; } - if (_contactor_welded()) { - _set_state(ACUState_e::WELDED, current_millis); - } + break; } case ACUState_e::WELDED: diff --git a/lib/systems/include/ACUController.h b/lib/systems/include/ACUController.h index b2bfdac..a679883 100644 --- a/lib/systems/include/ACUController.h +++ b/lib/systems/include/ACUController.h @@ -77,7 +77,6 @@ struct ACUControllerPackSpecs_s struct ACUControllerParameters_s { ACUControllerThresholds_s thresholds; - size_t weld_check_pin; size_t invalid_packet_count_thresh = 0; ACUControllerFaultDurations_s fault_durations; ACUControllerPackSpecs_s pack_specs; @@ -98,7 +97,6 @@ class ACUController * @param max_temp_fault_dur max number of temp faults allowed */ ACUController(ACUControllerThresholds_s thresholds, - size_t weld_check_pin, size_t invalid_packet_count_thresh = acu_controller_default_parameters::MAX_INVALID_PACKET_FAULT_COUNT, ACUControllerFaultDurations_s fault_durations = { .max_allowed_voltage_fault_dur = acu_controller_default_parameters::MAX_VOLTAGE_FAULT_DUR, @@ -111,7 +109,7 @@ class ACUController .pack_internal_resistance = acu_controller_default_parameters::PACK_INTERNAL_RESISTANCE} - ) : _acu_parameters{thresholds, weld_check_pin, invalid_packet_count_thresh, fault_durations, pack_specs} {}; + ) : _acu_parameters{thresholds, invalid_packet_count_thresh, fault_durations, pack_specs} {}; /** * @brief Initialize the status time stamps because we don't want accidental sudden faults diff --git a/lib/systems/src/ACUController.cpp b/lib/systems/src/ACUController.cpp index 0fb19f9..164d5ae 100644 --- a/lib/systems/src/ACUController.cpp +++ b/lib/systems/src/ACUController.cpp @@ -15,9 +15,6 @@ void ACUController::init(time_ms system_start_time, volt pack_voltage) _acu_state.balancing_enabled = false; _acu_state.high_side_contactor_welded = false; _acu_state.low_side_contactor_welded = false; - - pinMode(_acu_parameters.weld_check_pin, OUTPUT); - digitalWrite(_acu_parameters.weld_check_pin, HIGH); } @@ -183,7 +180,7 @@ bool ACUController::_check_invalid_packet_faults(time_ms current_millis) bool ACUController::check_ts_isolation(volt pack_voltage_adc, volt ts_voltage_adc) { bool sw_not_ok = !((pack_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage) && (ts_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage)); - digitalWrite(_acu_parameters.weld_check_pin, sw_not_ok); + _acu_state.low_side_contactor_welded = !(pack_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); _acu_state.high_side_contactor_welded = !(ts_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); return sw_not_ok; diff --git a/src/ACU_InterfaceTasks.cpp b/src/ACU_InterfaceTasks.cpp index e90f16c..cbb69a7 100644 --- a/src/ACU_InterfaceTasks.cpp +++ b/src/ACU_InterfaceTasks.cpp @@ -98,7 +98,8 @@ void initialize_all_interfaces() ACUInterfaces::TS_OUT_FILTERED_PIN, ACUInterfaces::PACK_OUT_FILTERED_PIN, ACUInterfaces::BSPD_CURRENT_PIN, - ACUInterfaces::SCALED_24V_PIN}, + ACUInterfaces::SCALED_24V_PIN, + ACUInterfaces::SW_NOT_OK_PIN}, ADCConversions_s {ACUInterfaces::SHUTDOWN_CONV_FACTOR, ACUInterfaces::PRECHARGE_CONV_FACTOR, ACUInterfaces::PACK_AND_TS_OUT_CONV_FACTOR, diff --git a/src/ACU_SystemTasks.cpp b/src/ACU_SystemTasks.cpp index 466c6d0..7686bf8 100644 --- a/src/ACU_SystemTasks.cpp +++ b/src/ACU_SystemTasks.cpp @@ -12,8 +12,7 @@ bool initialize_all_systems() ACUSystems::VOLTAGE_DIFF_TO_INIT_CB, ACUSystems::BALANCE_TEMP_LIMIT_C, ACUSystems::BALANCE_ENABLE_TEMP_THRESH_C, - ACUSystems::TS_ISOLATION_VOLTAGE}, - ACUInterfaces::SW_NOT_OK_PIN); + ACUSystems::TS_ISOLATION_VOLTAGE} ); ACUControllerInstance::instance().init(sys_time::hal_millis(), BMSDriverInstance_t::instance().get_bms_data().total_voltage); /* State Machine Initialization */ @@ -29,7 +28,13 @@ bool initialize_all_systems() etl::delegate contactor_welded = etl::delegate::create([]() -> bool { ACUControllerInstance::instance().check_ts_isolation(ADCInterfaceInstance::instance().read_pack_out_filtered(), ADCInterfaceInstance::instance().read_ts_out_filtered()); }); - + + etl::delegate set_sw_not_ok_pin_high = etl::delegate::create([]() -> void + { ADCInterfaceInstance::instance().set_sw_not_ok_pin_high(); }); + + etl::delegate set_sw_not_ok_pin_low = etl::delegate::create([]() -> void + { ADCInterfaceInstance::instance().set_sw_not_ok_pin_low(); }); + etl::delegate disable_watchdog = etl::delegate::create(WatchdogInstance::instance()); etl::delegate received_valid_shdn_out = etl::delegate::create(ADCInterfaceInstance::instance()); @@ -52,6 +57,8 @@ bool initialize_all_systems() has_bms_fault, has_imd_fault, contactor_welded, + set_sw_not_ok_pin_high, + set_sw_not_ok_pin_low, received_valid_shdn_out, enable_cell_balancing, disable_cell_balancing, @@ -61,6 +68,8 @@ bool initialize_all_systems() disable_n_latch_en, sys_time::hal_millis()); + ADCInterfaceInstance::instance().set_sw_not_ok_pin_high(); + return true; } diff --git a/test/test_systems/test_acu_controller.h b/test/test_systems/test_acu_controller.h index 187f049..c4d8d49 100644 --- a/test/test_systems/test_acu_controller.h +++ b/test/test_systems/test_acu_controller.h @@ -24,29 +24,32 @@ ACUControllerThresholds_s thresholds = {ACUSystems::MIN_DISCHARGE_VOLTAGE_THRESH TEST(ACUControllerTesting, initial_state) { - ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); + ACUControllerInstance::create(thresholds); ACUController controller = ACUControllerInstance::instance(); + charging_enabled = false; uint32_t start_time = 0; - + controller.init(start_time, 420.0f); + + ASSERT_EQ(false, false); - BMSCoreData_s data{}; // zeros - auto status = controller.evaluate_accumulator(start_time, data, 0, ZERO_PACK_CURRENT, num_cells); + // BMSCoreData_s data{}; // zeros + // auto status = controller.evaluate_accumulator(start_time, data, 0, ZERO_PACK_CURRENT, num_cells); - ASSERT_EQ(status.has_fault, false); - ASSERT_EQ(status.charging_enabled, false); + // ASSERT_EQ(status.has_fault, false); + // ASSERT_EQ(status.charging_enabled, false); - ASSERT_EQ(status.last_time_ov_fault_not_present, 0); - ASSERT_EQ(status.last_time_uv_fault_not_present, 0); - ASSERT_EQ(status.last_time_cell_ot_fault_not_present, 0); - ASSERT_EQ(status.last_time_board_ot_fault_not_present, 0); - ASSERT_EQ(status.last_time_pack_uv_fault_not_present, 0); + // ASSERT_EQ(status.last_time_ov_fault_not_present, 0); + // ASSERT_EQ(status.last_time_uv_fault_not_present, 0); + // ASSERT_EQ(status.last_time_cell_ot_fault_not_present, 0); + // ASSERT_EQ(status.last_time_board_ot_fault_not_present, 0); + // ASSERT_EQ(status.last_time_pack_uv_fault_not_present, 0); } TEST(ACUControllerTesting, charging_state) { - ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); + ACUControllerInstance::create(thresholds); ACUController controller = ACUControllerInstance::instance(); charging_enabled = true; @@ -91,7 +94,7 @@ TEST(ACUControllerTesting, charging_state) TEST(ACUControllerTesting, faulted_state) { - ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); + ACUControllerInstance::create(thresholds); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; // or true doesn't matter @@ -128,7 +131,7 @@ TEST(ACUControllerTesting, faulted_state) TEST(ACUControllerTesting, ir_compensation_discharge) { - ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); + ACUControllerInstance::create(thresholds); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; @@ -173,7 +176,7 @@ TEST(ACUControllerTesting, ir_compensation_discharge) TEST(ACUControllerTesting, ir_compensation_charge) { - ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); + ACUControllerInstance::create(thresholds); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; // Disable balancing to focus on IR compensation test @@ -219,7 +222,7 @@ TEST(ACUControllerTesting, ir_compensation_charge) // Tests that OV faults require 1000ms persistence before triggering TEST(ACUControllerTesting, cell_overvoltage_fault_persistence) { - ACUControllerInstance::create(thresholds, ACUInterfaces::SW_NOT_OK_PIN); + ACUControllerInstance::create(thresholds); ACUController controller = ACUControllerInstance::instance(); charging_enabled = false; diff --git a/test/test_systems/test_acu_state_machine.h b/test/test_systems/test_acu_state_machine.h index 7665c30..697752b 100644 --- a/test/test_systems/test_acu_state_machine.h +++ b/test/test_systems/test_acu_state_machine.h @@ -32,6 +32,12 @@ etl::delegate contactor_welded = etl::delegate::create([]() -> b return is_contactor_welded; }); +etl::delegate set_sw_not_ok_pin_high = etl::delegate::create([]() -> void { +}); + +etl::delegate set_sw_not_ok_pin_low = etl::delegate::create([]() -> void { +}); + etl::delegate received_valid_shdn_out = etl::delegate::create([]() -> bool { return received_valid_shdn_out_var; }); @@ -65,6 +71,8 @@ ACUStateMachine state_machine = ACUStateMachine( has_bms_fault, has_imd_fault, contactor_welded, + set_sw_not_ok_pin_high, + set_sw_not_ok_pin_low, received_valid_shdn_out, enable_cell_balancing, disable_cell_balancing, From f42c2d3ae6ca6055a1d682824b9b754b9e8038f2 Mon Sep 17 00:00:00 2001 From: TanishM Date: Sat, 7 Feb 2026 19:00:57 -0500 Subject: [PATCH 9/9] changed state machine design and updated tests --- lib/state_machine/include/ACUStateMachine.h | 8 +++- lib/state_machine/src/ACUStateMachine.cpp | 49 ++++++++++++++------- lib/systems/src/ACUController.cpp | 4 +- src/ACU_InterfaceTasks.cpp | 8 ++-- test/test_systems/test_acu_controller.h | 19 ++++---- test/test_systems/test_acu_state_machine.h | 37 +++++++++++----- 6 files changed, 82 insertions(+), 43 deletions(-) diff --git a/lib/state_machine/include/ACUStateMachine.h b/lib/state_machine/include/ACUStateMachine.h index 73812b3..dada732 100644 --- a/lib/state_machine/include/ACUStateMachine.h +++ b/lib/state_machine/include/ACUStateMachine.h @@ -14,7 +14,8 @@ enum class ACUState_e ACTIVE = 1, CHARGING = 2, FAULTED = 3, - WELDED = 4, + WELDED = 4, + WELDPASSED = 5 }; class ACUStateMachine @@ -61,6 +62,8 @@ class ACUStateMachine */ ACUState_e get_state() { return _current_state; } + + private: void _set_state(ACUState_e new_state, unsigned long curr_millis); @@ -79,7 +82,8 @@ class ACUStateMachine ACUState_e _current_state; unsigned long _last_state_changed_time; // time of last state change - + + // Lamdas for state machine abstraction, functions defined in main etl::delegate _charge_state_requested; etl::delegate _has_bms_fault; diff --git a/lib/state_machine/src/ACUStateMachine.cpp b/lib/state_machine/src/ACUStateMachine.cpp index 5223a79..8c72f05 100644 --- a/lib/state_machine/src/ACUStateMachine.cpp +++ b/lib/state_machine/src/ACUStateMachine.cpp @@ -1,32 +1,37 @@ #include "ACUStateMachine.h" +#include +using namespace std; + void ACUStateMachine::tick_state_machine(unsigned long current_millis) { switch(_current_state) { case ACUState_e::STARTUP: { - if (_contactor_welded()) { - _set_sw_not_ok_pin_high(); - _set_state(ACUState_e::WELDED, current_millis); - } - else { - _set_sw_not_ok_pin_low(); + if (current_millis - _last_state_changed_time >= 1000) { + if (_contactor_welded()) { + _set_state(ACUState_e::WELDED, current_millis); + break; + } + else { + _set_state(ACUState_e::WELDPASSED, current_millis); + break; + } } - - if (_received_valid_shdn_out()) { // is there a race condition between voltage reading and shdn_out? + + break; + } + case ACUState_e::WELDPASSED: + { + if (_received_valid_shdn_out()) { _set_state(ACUState_e::ACTIVE, current_millis); break; } - if ((current_millis - _last_state_changed_time > 2000) && (_has_bms_fault() || _has_imd_fault())) { - _set_state(ACUState_e::FAULTED, current_millis); - break; - } - - break; } case ACUState_e::WELDED: { } + case ACUState_e::ACTIVE: { if (_charge_state_requested()) { @@ -97,6 +102,8 @@ void ACUStateMachine::_handle_exit_logic(ACUState_e prev_state, unsigned long cu } case ACUState_e::STARTUP: case ACUState_e::ACTIVE: + case ACUState_e::WELDPASSED: + case ACUState_e::WELDED: default: break; } @@ -107,9 +114,20 @@ void ACUStateMachine::_handle_entry_logic(ACUState_e new_state, unsigned long cu switch(new_state) { case ACUState_e::STARTUP: { + _last_state_changed_time = curr_millis; _reinitialize_watchdog(); break; } + case ACUState_e::WELDPASSED: + { + _set_sw_not_ok_pin_low(); + break; + } + case ACUState_e::WELDED: + { + _set_sw_not_ok_pin_high(); + break; + } case ACUState_e::CHARGING: { _enable_cell_balancing(); @@ -126,4 +144,5 @@ void ACUStateMachine::_handle_entry_logic(ACUState_e new_state, unsigned long cu default: break; } -} \ No newline at end of file +} + diff --git a/lib/systems/src/ACUController.cpp b/lib/systems/src/ACUController.cpp index 164d5ae..10bd2a8 100644 --- a/lib/systems/src/ACUController.cpp +++ b/lib/systems/src/ACUController.cpp @@ -179,9 +179,11 @@ bool ACUController::_check_invalid_packet_faults(time_ms current_millis) bool ACUController::check_ts_isolation(volt pack_voltage_adc, volt ts_voltage_adc) { - bool sw_not_ok = !((pack_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage) && (ts_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage)); + _acu_state.low_side_contactor_welded = !(pack_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); _acu_state.high_side_contactor_welded = !(ts_voltage_adc < _acu_parameters.thresholds.ts_isolation_voltage); + + bool sw_not_ok = _acu_state.low_side_contactor_welded || _acu_state.high_side_contactor_welded; return sw_not_ok; } \ No newline at end of file diff --git a/src/ACU_InterfaceTasks.cpp b/src/ACU_InterfaceTasks.cpp index cbb69a7..aa40923 100644 --- a/src/ACU_InterfaceTasks.cpp +++ b/src/ACU_InterfaceTasks.cpp @@ -44,11 +44,11 @@ static ACUAllDataType_s make_acu_all_data() out.core_data.min_measured_ts_out_voltage = watchdog.min_measured_ts_out_voltage; out.core_data.min_shdn_out_voltage = watchdog.min_shdn_out_voltage; // SoC/SoH placeholders (leave unchanged here) - auto ACU = ACUControllerInstance::instance().get_status(); + auto ACUStatus = ACUControllerInstance::instance().get_status(); - out.SoC = ACU.SoC; - out.core_data.high_side_contactor_welded = ACU.high_side_contactor_welded; - out.core_data.low_side_contactor_welded = ACU.low_side_contactor_welded; + out.SoC = ACUStatus.SoC; + out.core_data.high_side_contactor_welded = ACUStatus.high_side_contactor_welded; + out.core_data.low_side_contactor_welded = ACUStatus.low_side_contactor_welded; return out; } diff --git a/test/test_systems/test_acu_controller.h b/test/test_systems/test_acu_controller.h index c4d8d49..bf076b6 100644 --- a/test/test_systems/test_acu_controller.h +++ b/test/test_systems/test_acu_controller.h @@ -32,19 +32,18 @@ TEST(ACUControllerTesting, initial_state) controller.init(start_time, 420.0f); - ASSERT_EQ(false, false); - // BMSCoreData_s data{}; // zeros - // auto status = controller.evaluate_accumulator(start_time, data, 0, ZERO_PACK_CURRENT, num_cells); + BMSCoreData_s data{}; // zeros + auto status = controller.evaluate_accumulator(start_time, data, 0, ZERO_PACK_CURRENT, num_cells); - // ASSERT_EQ(status.has_fault, false); - // ASSERT_EQ(status.charging_enabled, false); + ASSERT_EQ(status.has_fault, false); + ASSERT_EQ(status.charging_enabled, false); - // ASSERT_EQ(status.last_time_ov_fault_not_present, 0); - // ASSERT_EQ(status.last_time_uv_fault_not_present, 0); - // ASSERT_EQ(status.last_time_cell_ot_fault_not_present, 0); - // ASSERT_EQ(status.last_time_board_ot_fault_not_present, 0); - // ASSERT_EQ(status.last_time_pack_uv_fault_not_present, 0); + ASSERT_EQ(status.last_time_ov_fault_not_present, 0); + ASSERT_EQ(status.last_time_uv_fault_not_present, 0); + ASSERT_EQ(status.last_time_cell_ot_fault_not_present, 0); + ASSERT_EQ(status.last_time_board_ot_fault_not_present, 0); + ASSERT_EQ(status.last_time_pack_uv_fault_not_present, 0); } TEST(ACUControllerTesting, charging_state) diff --git a/test/test_systems/test_acu_state_machine.h b/test/test_systems/test_acu_state_machine.h index 697752b..9b1b943 100644 --- a/test/test_systems/test_acu_state_machine.h +++ b/test/test_systems/test_acu_state_machine.h @@ -6,7 +6,7 @@ #include "ACUStateMachine.h" -bool received_CCU_msg_var; +bool request_charge_state; bool has_bms_fault_var; bool has_imd_fault_var; bool received_valid_shdn_out_var; @@ -16,8 +16,8 @@ bool charging_en = false; bool watchdog_en = true; bool n_latch_en = true; -etl::delegate received_CCU_message = etl::delegate::create([]() -> bool { - return received_CCU_msg_var; +etl::delegate charge_state_requested = etl::delegate::create([]() -> bool { + return request_charge_state; }); etl::delegate has_bms_fault = etl::delegate::create([]() -> bool { @@ -67,7 +67,7 @@ etl::delegate reset_latch = etl::delegate::create([]() -> void { }); ACUStateMachine state_machine = ACUStateMachine( - received_CCU_message, + charge_state_requested, has_bms_fault, has_imd_fault, contactor_welded, @@ -84,7 +84,7 @@ ACUStateMachine state_machine = ACUStateMachine( ); TEST (ACUStateMachineTesting, initial_state) { - received_CCU_msg_var = false; + request_charge_state = false; has_bms_fault_var = false; has_imd_fault_var = false; received_valid_shdn_out_var = false; @@ -94,13 +94,18 @@ TEST (ACUStateMachineTesting, initial_state) { state_machine.tick_state_machine(0); ASSERT_EQ(state_machine.get_state(), ACUState_e::STARTUP); + state_machine.tick_state_machine(1001); + ASSERT_EQ(state_machine.get_state(), ACUState_e::WELDPASSED); + received_valid_shdn_out_var = true; state_machine.tick_state_machine(0); ASSERT_EQ(state_machine.get_state(), ACUState_e::ACTIVE); + + } -TEST (ACUStateMachineTesting, CCU_msg_state) { - received_CCU_msg_var = false; +TEST (ACUStateMachineTesting, charge_state) { + request_charge_state = false; has_bms_fault_var = false; has_imd_fault_var = false; received_valid_shdn_out_var = false; @@ -108,21 +113,22 @@ TEST (ACUStateMachineTesting, CCU_msg_state) { ASSERT_EQ(state_machine.get_state(), ACUState_e::ACTIVE); // initial - received_CCU_msg_var = true; + request_charge_state = true; + ASSERT_EQ(state_machine.get_state(), ACUState_e::ACTIVE); ASSERT_EQ(charging_en, false); state_machine.tick_state_machine(0); ASSERT_EQ(state_machine.get_state(), ACUState_e::CHARGING); ASSERT_EQ(charging_en, true); - received_CCU_msg_var = false; + request_charge_state = false; state_machine.tick_state_machine(0); ASSERT_EQ(state_machine.get_state(), ACUState_e::ACTIVE); ASSERT_EQ(charging_en, false); } TEST (ACUStateMachineTesting, fault_states) { - received_CCU_msg_var = false; + request_charge_state = false; has_bms_fault_var = false; has_imd_fault_var = false; received_valid_shdn_out_var = true; @@ -158,9 +164,18 @@ TEST (ACUStateMachineTesting, fault_states) { has_bms_fault_var = false; state_machine.tick_state_machine(0); ASSERT_EQ(state_machine.get_state(), ACUState_e::STARTUP); + + is_contactor_welded = true; + state_machine.tick_state_machine(0); + ASSERT_EQ(state_machine.get_state(), ACUState_e::STARTUP); + + state_machine.tick_state_machine(1000); + ASSERT_EQ(state_machine.get_state(), ACUState_e::WELDED); + is_contactor_welded = false; state_machine.tick_state_machine(0); - ASSERT_EQ(state_machine.get_state(), ACUState_e::ACTIVE); + ASSERT_EQ(state_machine.get_state(), ACUState_e::WELDED); + }