From cc9d12b1fa469ebc4994054518edd71084a615ae Mon Sep 17 00:00:00 2001 From: Kelm Date: Tue, 16 Jun 2026 08:21:30 -0700 Subject: [PATCH 01/18] fixes to therm lut and thermal broadcast --- .../BMS/src/app/segments/app_segments_calculation.cpp | 7 ++++++- firmware/shared/srcpp/app/app_thermistor.hpp | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp index 4c4f1f1c2a..efddca9257 100644 --- a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp +++ b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp @@ -130,7 +130,12 @@ Therms> const float voltage = reading.value(); const float resistance = R_SERIES * (voltage / (V_REF2 - voltage)); - out[seg][therm] = app::therm::adbms_ntc10k_lut.resistanceToTemp(resistance); + const float temp = app::therm::adbms_ntc10k_lut.resistanceToTemp(resistance); + // TODO: Do error reporting on this please + if (temp > std::numeric_limits::lowest() && temp < std::numeric_limits::max()) + { + out[seg][therm] = temp; + } } } return out; diff --git a/firmware/shared/srcpp/app/app_thermistor.hpp b/firmware/shared/srcpp/app/app_thermistor.hpp index 47187ad7ce..183e6d6b99 100644 --- a/firmware/shared/srcpp/app/app_thermistor.hpp +++ b/firmware/shared/srcpp/app/app_thermistor.hpp @@ -66,9 +66,13 @@ namespace therm } // Ensure resistance is within bounds: resistances[0] is highest, resistances[size-1] is lowest - if (!(thermistor_resistance <= resistances_[0] && thermistor_resistance >= resistances_[size_ - 1U])) + if ((thermistor_resistance < resistances_[0])) { - return -1.0f; + return std::numeric_limits::lowest(); + } + else if (thermistor_resistance > resistances_[size_ - 1U]) + { + return std::numeric_limits::max(); } // Binary search for insertion point From ab3fcea09340ca4027cfb8914312a3faa27280f3 Mon Sep 17 00:00:00 2001 From: Pranay Oza <105095960+pranay-o@users.noreply.github.com> Date: Tue, 16 Jun 2026 11:27:27 -0400 Subject: [PATCH 02/18] other issues --- firmware/cmake/embedded.cmake | 16 ++++++++-------- .../BMS/src/app/states/app_balancingState.cpp | 2 +- firmware/hexray/BMS/src/io/io_adbms.hpp | 2 +- firmware/hexray/BMS/src/jobs.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/firmware/cmake/embedded.cmake b/firmware/cmake/embedded.cmake index a9978782d4..3770e01b0d 100644 --- a/firmware/cmake/embedded.cmake +++ b/firmware/cmake/embedded.cmake @@ -149,14 +149,14 @@ function(embedded_binary else () target_compile_options(${ELF_NAME} PRIVATE -Os) endif () - IF (${CMAKE_BUILD_TYPE} STREQUAL "Debug" AND ${USE_UBSAN}) - target_compile_options(${ELF_NAME} PRIVATE -fsanitize=undefined) - set_property(SOURCE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp" APPEND PROPERTY COMPILE_OPTIONS - -fno-sanitize=undefined - -Wno-error=suggest-attribute=noreturn - -Wno-suggest-attribute=noreturn - ) - target_sources(${ELF_NAME} PRIVATE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp") + IF (${CMAKE_BUILD_TYPE} STREQUAL "Debug") +# target_compile_options(${ELF_NAME} PRIVATE -fsanitize=undefined) +# set_property(SOURCE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp" APPEND PROPERTY COMPILE_OPTIONS +# -fno-sanitize=undefined +# -Wno-error=suggest-attribute=noreturn +# -Wno-suggest-attribute=noreturn +# ) +# target_sources(${ELF_NAME} PRIVATE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp") ENDIF () target_link_options(${ELF_NAME} PRIVATE diff --git a/firmware/hexray/BMS/src/app/states/app_balancingState.cpp b/firmware/hexray/BMS/src/app/states/app_balancingState.cpp index d3985c89cd..d326bbbd71 100644 --- a/firmware/hexray/BMS/src/app/states/app_balancingState.cpp +++ b/firmware/hexray/BMS/src/app/states/app_balancingState.cpp @@ -23,7 +23,7 @@ namespace balancingState (io::irs::negativeState() == app::can_utils::ContactorState::CONTACTOR_STATE_OPEN); const bool balancing_enabled = app::can_rx::Debug_CellBalancing_Request_get(); - if (balancing_enabled && !ir_negative_open) + if (balancing_enabled && ir_negative_open) { app::segments::balancing::tick(); } diff --git a/firmware/hexray/BMS/src/io/io_adbms.hpp b/firmware/hexray/BMS/src/io/io_adbms.hpp index 49667fc32f..6788ad2947 100644 --- a/firmware/hexray/BMS/src/io/io_adbms.hpp +++ b/firmware/hexray/BMS/src/io/io_adbms.hpp @@ -12,7 +12,7 @@ #include // Physical daisy-chain dimensions for this ECU. -inline constexpr uint8_t NUM_SEGMENTS = 10; +inline constexpr uint8_t NUM_SEGMENTS = 1; inline constexpr uint8_t CELLS_PER_SEGMENT = 14; inline constexpr uint8_t THERMISTORS_PER_SEGMENT = 14; inline constexpr uint8_t THERM_GPIOS_PER_SEGMENT = 8; diff --git a/firmware/hexray/BMS/src/jobs.cpp b/firmware/hexray/BMS/src/jobs.cpp index a78c0bd923..aa61230e08 100644 --- a/firmware/hexray/BMS/src/jobs.cpp +++ b/firmware/hexray/BMS/src/jobs.cpp @@ -45,7 +45,7 @@ using io::adbms::Therms; static void vehicle_transmit_func(const JsonCanMsg &tx_msg) { const io::CanMsg msg = app::jsoncan::copyToCanMsg(tx_msg); - const auto res = vehicle_can_tx_queue.push(msg); + const auto res = can_tx_queue.push(msg); LOG_IF_ERR(res); if (not res) { From deb59776e618411134cbe31705b2663ab4429414 Mon Sep 17 00:00:00 2001 From: Pranay Oza <105095960+pranay-o@users.noreply.github.com> Date: Tue, 16 Jun 2026 11:42:34 -0400 Subject: [PATCH 03/18] done --- can_bus/hexray/shared_enum.json | 5 +++-- .../app/segments/app_segments_calculation.cpp | 16 ++++++++++------ firmware/hexray/BMS/src/jobs.cpp | 2 +- firmware/shared/srcpp/util/util_errorCodes.hpp | 3 +++ 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/can_bus/hexray/shared_enum.json b/can_bus/hexray/shared_enum.json index a2a892a174..29c732f26d 100644 --- a/can_bus/hexray/shared_enum.json +++ b/can_bus/hexray/shared_enum.json @@ -11,8 +11,9 @@ "INVALID_READING": 8, "ERROR_INDETERMINATE": 9, "POLL_INVALID": 10, - "NO_SEGMENT_DEFINED" : 11, - "NO_ERROR" : 12 + "THERM_OUT_OF_RANGE": 11, + "NO_SEGMENT_DEFINED" : 12, + "NO_ERROR" : 13 }, "SwitchState": { "OFF": 0, diff --git a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp index efddca9257..824d8c9552 100644 --- a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp +++ b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp @@ -104,9 +104,9 @@ Cells> cellOwcOk( return owc_cell; } -Therms> - thermTemps(const std::array>, static_cast(ThermistorMux::THERMISTOR_MUX_COUNT)> - &therm_voltages) +Therms> thermTemps( + const std::array>, static_cast(ThermistorMux::THERMISTOR_MUX_COUNT)> + &therm_voltages) { Therms> out; @@ -136,14 +136,18 @@ Therms> { out[seg][therm] = temp; } + else + { + out[seg][therm] = std::unexpected(ErrorCode::THERM_OUT_OF_RANGE); + } } } return out; } -Therms> - thermOwcOk(const std::array>, static_cast(ThermistorMux::THERMISTOR_MUX_COUNT)> - &therm_voltages) +Therms> thermOwcOk( + const std::array>, static_cast(ThermistorMux::THERMISTOR_MUX_COUNT)> + &therm_voltages) { Therms> out; diff --git a/firmware/hexray/BMS/src/jobs.cpp b/firmware/hexray/BMS/src/jobs.cpp index aa61230e08..a78c0bd923 100644 --- a/firmware/hexray/BMS/src/jobs.cpp +++ b/firmware/hexray/BMS/src/jobs.cpp @@ -45,7 +45,7 @@ using io::adbms::Therms; static void vehicle_transmit_func(const JsonCanMsg &tx_msg) { const io::CanMsg msg = app::jsoncan::copyToCanMsg(tx_msg); - const auto res = can_tx_queue.push(msg); + const auto res = vehicle_can_tx_queue.push(msg); LOG_IF_ERR(res); if (not res) { diff --git a/firmware/shared/srcpp/util/util_errorCodes.hpp b/firmware/shared/srcpp/util/util_errorCodes.hpp index f43f0838ca..095eb0bfbf 100644 --- a/firmware/shared/srcpp/util/util_errorCodes.hpp +++ b/firmware/shared/srcpp/util/util_errorCodes.hpp @@ -16,6 +16,7 @@ enum class ErrorCode INVALID_READING, ERROR_INDETERMINATE, POLL_INVALID, + THERM_OUT_OF_RANGE, NUM_EXIT_CODES, }; @@ -47,6 +48,8 @@ constexpr const char *error_code_to_string(const ErrorCode code) return "Indeterminate error"; case ErrorCode::POLL_INVALID: return "Poll invalid"; + case ErrorCode::THERM_OUT_OF_RANGE: + return "Therm out of range"; case ErrorCode::NUM_EXIT_CODES: default: return "Unknown error code"; From 85c7632c471978d64d04d48b73f10891b3c61510 Mon Sep 17 00:00:00 2001 From: Kelm Date: Tue, 16 Jun 2026 08:41:04 -0700 Subject: [PATCH 04/18] whoops --- firmware/shared/srcpp/app/app_thermistor.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/shared/srcpp/app/app_thermistor.hpp b/firmware/shared/srcpp/app/app_thermistor.hpp index 183e6d6b99..f446d7ccc2 100644 --- a/firmware/shared/srcpp/app/app_thermistor.hpp +++ b/firmware/shared/srcpp/app/app_thermistor.hpp @@ -66,11 +66,11 @@ namespace therm } // Ensure resistance is within bounds: resistances[0] is highest, resistances[size-1] is lowest - if ((thermistor_resistance < resistances_[0])) + if ((thermistor_resistance <= resistances_[0])) { return std::numeric_limits::lowest(); } - else if (thermistor_resistance > resistances_[size_ - 1U]) + else if (thermistor_resistance >= resistances_[size_ - 1U]) { return std::numeric_limits::max(); } From e08294f637f8069623b20b85e2d3fe83a5a553be Mon Sep 17 00:00:00 2001 From: AmirTajaddodi Date: Tue, 16 Jun 2026 09:05:01 -0700 Subject: [PATCH 05/18] bs --- firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp b/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp index cfb0ba2afd..bd44f6bdeb 100644 --- a/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp +++ b/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp @@ -21,6 +21,9 @@ namespace io::adbms result clear::flags() { Segments clr_regs{}; + for (size_t seg = 0U; seg < NUM_SEGMENTS; seg++) { + clr_regs[seg].fill(1); + } RETURN_IF_ERR(writeRegGroup(CLRFLAG, clr_regs)); RETURN_IF_ERR(writeRegGroup(CLOVUV, clr_regs)); return {}; From 3b8235b7458d6a7badee2d3c75b9c328b78042af Mon Sep 17 00:00:00 2001 From: Pranay Oza <105095960+pranay-o@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:09:26 -0400 Subject: [PATCH 06/18] done --- firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp b/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp index bd44f6bdeb..d6eb5dd705 100644 --- a/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp +++ b/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp @@ -22,7 +22,7 @@ result clear::flags() { Segments clr_regs{}; for (size_t seg = 0U; seg < NUM_SEGMENTS; seg++) { - clr_regs[seg].fill(1); + clr_regs[seg].fill(0xFF); } RETURN_IF_ERR(writeRegGroup(CLRFLAG, clr_regs)); RETURN_IF_ERR(writeRegGroup(CLOVUV, clr_regs)); From 7faa5fea77e933cbe7d9e7529f28d7cacdea1ecd Mon Sep 17 00:00:00 2001 From: AmirTajaddodi Date: Tue, 16 Jun 2026 09:27:17 -0700 Subject: [PATCH 07/18] blank shots --- firmware/shared/srcpp/app/app_thermistor.hpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/firmware/shared/srcpp/app/app_thermistor.hpp b/firmware/shared/srcpp/app/app_thermistor.hpp index f446d7ccc2..5fe2474545 100644 --- a/firmware/shared/srcpp/app/app_thermistor.hpp +++ b/firmware/shared/srcpp/app/app_thermistor.hpp @@ -53,20 +53,10 @@ namespace therm float resistanceToTemp(float thermistor_resistance) const noexcept { if (!valid_ || resistances_ == nullptr || size_ == 0U) - return -1.0f; - - // Guard against NaN/inf inputs - if (!std::isfinite(thermistor_resistance)) - return -1.0f; - - // Handle trivial single-entry LUT safely - if (size_ == 1U) - { - return APPROX_EQUAL_FLOAT(thermistor_resistance, resistances_[0], 0.0001f) ? starting_temp_ : -1.0f; - } + return std::numeric_limits::lowest(); // Ensure resistance is within bounds: resistances[0] is highest, resistances[size-1] is lowest - if ((thermistor_resistance <= resistances_[0])) + if ((thermistor_resistance <= resistances_[0]) || !std::isfinite(thermistor_resistance)) { return std::numeric_limits::lowest(); } @@ -75,6 +65,12 @@ namespace therm return std::numeric_limits::max(); } + // Handle trivial single-entry LUT safely + if (size_ == 1U) + { + return APPROX_EQUAL_FLOAT(thermistor_resistance, resistances_[0], 0.0001f) ? starting_temp_ : -1.0f; + } + // Binary search for insertion point uint16_t low_index = 0U; uint16_t high_index = static_cast(size_ - 1); From 6343e5ecd3276fcbd084de508a71f81e4236a1da Mon Sep 17 00:00:00 2001 From: Kelm Date: Tue, 16 Jun 2026 09:36:28 -0700 Subject: [PATCH 08/18] god I hope this works --- .../src/app/segments/app_segments_calculation.cpp | 15 ++++++++------- firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp | 3 ++- firmware/shared/srcpp/app/app_thermistor.hpp | 11 +++++++---- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp index 824d8c9552..43230f5eb2 100644 --- a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp +++ b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp @@ -104,9 +104,9 @@ Cells> cellOwcOk( return owc_cell; } -Therms> thermTemps( - const std::array>, static_cast(ThermistorMux::THERMISTOR_MUX_COUNT)> - &therm_voltages) +Therms> + thermTemps(const std::array>, static_cast(ThermistorMux::THERMISTOR_MUX_COUNT)> + &therm_voltages) { Therms> out; @@ -132,7 +132,8 @@ Therms> thermTemps( const float resistance = R_SERIES * (voltage / (V_REF2 - voltage)); const float temp = app::therm::adbms_ntc10k_lut.resistanceToTemp(resistance); // TODO: Do error reporting on this please - if (temp > std::numeric_limits::lowest() && temp < std::numeric_limits::max()) + if (std::abs(std::numeric_limits::lowest() - temp) > 1e-4f && + std::abs(temp - std::numeric_limits::max()) > 1e-4f) { out[seg][therm] = temp; } @@ -145,9 +146,9 @@ Therms> thermTemps( return out; } -Therms> thermOwcOk( - const std::array>, static_cast(ThermistorMux::THERMISTOR_MUX_COUNT)> - &therm_voltages) +Therms> + thermOwcOk(const std::array>, static_cast(ThermistorMux::THERMISTOR_MUX_COUNT)> + &therm_voltages) { Therms> out; diff --git a/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp b/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp index d6eb5dd705..b998d7032a 100644 --- a/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp +++ b/firmware/hexray/BMS/src/io/adbms/io_adbms_aux.cpp @@ -21,7 +21,8 @@ namespace io::adbms result clear::flags() { Segments clr_regs{}; - for (size_t seg = 0U; seg < NUM_SEGMENTS; seg++) { + for (size_t seg = 0U; seg < NUM_SEGMENTS; seg++) + { clr_regs[seg].fill(0xFF); } RETURN_IF_ERR(writeRegGroup(CLRFLAG, clr_regs)); diff --git a/firmware/shared/srcpp/app/app_thermistor.hpp b/firmware/shared/srcpp/app/app_thermistor.hpp index 5fe2474545..ce1834ed9d 100644 --- a/firmware/shared/srcpp/app/app_thermistor.hpp +++ b/firmware/shared/srcpp/app/app_thermistor.hpp @@ -48,7 +48,8 @@ namespace therm * Calculate temperature based on thermistor temperature and LUT * @param thermistor_resistance resistance of the thermistor * @param temp_resistance_lut reverse lookup table - * @return Thermistor temperature in degrees C or -1 if out of bounds or invalid LUT + * @return Thermistor temperature in degrees C or lowest float if out of bounds or invalid LUT. + * Special case for temperature too high, will return highest float instead of lowest. */ float resistanceToTemp(float thermistor_resistance) const noexcept { @@ -65,12 +66,14 @@ namespace therm return std::numeric_limits::max(); } - // Handle trivial single-entry LUT safely + // Handle trivial single-entry LUT safely if (size_ == 1U) { - return APPROX_EQUAL_FLOAT(thermistor_resistance, resistances_[0], 0.0001f) ? starting_temp_ : -1.0f; + return APPROX_EQUAL_FLOAT(thermistor_resistance, resistances_[0], 0.0001f) + ? starting_temp_ + : std::numeric_limits::lowest(); } - + // Binary search for insertion point uint16_t low_index = 0U; uint16_t high_index = static_cast(size_ - 1); From 51468cf0d2623349e87e92baaff61c93f830f915 Mon Sep 17 00:00:00 2001 From: Kelm Date: Tue, 16 Jun 2026 12:27:58 -0700 Subject: [PATCH 09/18] breaks test, hopefully fixes therns --- .../app/segments/app_segments_calculation.cpp | 14 ++++------- firmware/hexray/BMS/src/io/io_thermistors.cpp | 9 ++++++- firmware/shared/srcpp/app/app_thermistor.hpp | 25 +++++++++++++------ .../shared/srcpp/util/util_errorCodes.hpp | 3 +++ 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp index 43230f5eb2..e0204a94f2 100644 --- a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp +++ b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp @@ -130,17 +130,13 @@ Therms> const float voltage = reading.value(); const float resistance = R_SERIES * (voltage / (V_REF2 - voltage)); - const float temp = app::therm::adbms_ntc10k_lut.resistanceToTemp(resistance); - // TODO: Do error reporting on this please - if (std::abs(std::numeric_limits::lowest() - temp) > 1e-4f && - std::abs(temp - std::numeric_limits::max()) > 1e-4f) + const auto temp = app::therm::adbms_ntc10k_lut.resistanceToTemp(resistance); + if (!temp) { - out[seg][therm] = temp; - } - else - { - out[seg][therm] = std::unexpected(ErrorCode::THERM_OUT_OF_RANGE); + out[seg][therm] = std::unexpected(temp.error()); + continue; } + out[seg][therm] = temp.value(); } } return out; diff --git a/firmware/hexray/BMS/src/io/io_thermistors.cpp b/firmware/hexray/BMS/src/io/io_thermistors.cpp index c1b56afba9..748c141919 100644 --- a/firmware/hexray/BMS/src/io/io_thermistors.cpp +++ b/firmware/hexray/BMS/src/io/io_thermistors.cpp @@ -42,6 +42,13 @@ float readSelectedTemp() const float raw_voltage = aux_tsns.getVoltage(); const float thermistor_resistance = (raw_voltage * BIAS_RESISTOR_OHM) / (REFERENCE_VOLTAGE - raw_voltage); - return b57861s_lut.resistanceToTemp(thermistor_resistance); + const auto result = b57861s_lut.resistanceToTemp(thermistor_resistance); + if (!result) + { + LOG_ERROR("Thermistor LUT error: {}", static_cast(result.error())); + return std::numeric_limits::lowest(); + } + + return result.value(); } } // namespace io::therm \ No newline at end of file diff --git a/firmware/shared/srcpp/app/app_thermistor.hpp b/firmware/shared/srcpp/app/app_thermistor.hpp index ce1834ed9d..e329775325 100644 --- a/firmware/shared/srcpp/app/app_thermistor.hpp +++ b/firmware/shared/srcpp/app/app_thermistor.hpp @@ -1,5 +1,6 @@ #pragma once #include "app_math.hpp" +#include "util_errorCodes.hpp" #include #include @@ -51,27 +52,37 @@ namespace therm * @return Thermistor temperature in degrees C or lowest float if out of bounds or invalid LUT. * Special case for temperature too high, will return highest float instead of lowest. */ - float resistanceToTemp(float thermistor_resistance) const noexcept + std::expected resistanceToTemp(float thermistor_resistance) const noexcept { if (!valid_ || resistances_ == nullptr || size_ == 0U) - return std::numeric_limits::lowest(); + return std::unexpected(ErrorCode::LUT_INVALID); // Ensure resistance is within bounds: resistances[0] is highest, resistances[size-1] is lowest if ((thermistor_resistance <= resistances_[0]) || !std::isfinite(thermistor_resistance)) { - return std::numeric_limits::lowest(); + return std::unexpected(ErrorCode::LUT_UNDERSHOOT); } else if (thermistor_resistance >= resistances_[size_ - 1U]) { - return std::numeric_limits::max(); + return std::unexpected(ErrorCode::LUT_OVERSHOOT); } // Handle trivial single-entry LUT safely if (size_ == 1U) { - return APPROX_EQUAL_FLOAT(thermistor_resistance, resistances_[0], 0.0001f) - ? starting_temp_ - : std::numeric_limits::lowest(); + + if (!APPROX_EQUAL_FLOAT(thermistor_resistance, resistances_[0], 0.0001f)) + { + if (thermistor_resistance < resistances_[0]) + { + return std::unexpected(ErrorCode::LUT_UNDERSHOOT); + } + else + { + return std::unexpected(ErrorCode::LUT_OVERSHOOT); + } + } + return starting_temp_; } // Binary search for insertion point diff --git a/firmware/shared/srcpp/util/util_errorCodes.hpp b/firmware/shared/srcpp/util/util_errorCodes.hpp index 095eb0bfbf..c32051b3d0 100644 --- a/firmware/shared/srcpp/util/util_errorCodes.hpp +++ b/firmware/shared/srcpp/util/util_errorCodes.hpp @@ -18,6 +18,9 @@ enum class ErrorCode POLL_INVALID, THERM_OUT_OF_RANGE, NUM_EXIT_CODES, + LUT_INVALID, + LUT_OVERSHOOT, + LUT_UNDERSHOOT }; template using result = std::expected; From cb32e235c1ad19df33d6b8e9bae1540e3c5fbf67 Mon Sep 17 00:00:00 2001 From: Kelm Date: Tue, 16 Jun 2026 12:40:31 -0700 Subject: [PATCH 10/18] god please please pleaase fix --- .../BMS/src/app/segments/app_segments_calculation.cpp | 2 +- firmware/shared/srcpp/app/app_thermistor.hpp | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp index e0204a94f2..5edf5ac1f2 100644 --- a/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp +++ b/firmware/hexray/BMS/src/app/segments/app_segments_calculation.cpp @@ -130,7 +130,7 @@ Therms> const float voltage = reading.value(); const float resistance = R_SERIES * (voltage / (V_REF2 - voltage)); - const auto temp = app::therm::adbms_ntc10k_lut.resistanceToTemp(resistance); + const auto temp = app::therm::adbms_ntc10k_lut.resistanceToTemp(resistance); if (!temp) { out[seg][therm] = std::unexpected(temp.error()); diff --git a/firmware/shared/srcpp/app/app_thermistor.hpp b/firmware/shared/srcpp/app/app_thermistor.hpp index e329775325..9c182c161e 100644 --- a/firmware/shared/srcpp/app/app_thermistor.hpp +++ b/firmware/shared/srcpp/app/app_thermistor.hpp @@ -58,11 +58,11 @@ namespace therm return std::unexpected(ErrorCode::LUT_INVALID); // Ensure resistance is within bounds: resistances[0] is highest, resistances[size-1] is lowest - if ((thermistor_resistance <= resistances_[0]) || !std::isfinite(thermistor_resistance)) + if (!std::isfinite(thermistor_resistance) || thermistor_resistance >= resistances_[0]) { return std::unexpected(ErrorCode::LUT_UNDERSHOOT); } - else if (thermistor_resistance >= resistances_[size_ - 1U]) + else if (thermistor_resistance <= resistances_[size_ - 1U]) { return std::unexpected(ErrorCode::LUT_OVERSHOOT); } @@ -70,10 +70,9 @@ namespace therm // Handle trivial single-entry LUT safely if (size_ == 1U) { - if (!APPROX_EQUAL_FLOAT(thermistor_resistance, resistances_[0], 0.0001f)) { - if (thermistor_resistance < resistances_[0]) + if (thermistor_resistance > resistances_[0]) { return std::unexpected(ErrorCode::LUT_UNDERSHOOT); } From 51ec0e94de36e0d665fc37e74ce93e2182dff8e8 Mon Sep 17 00:00:00 2001 From: Pranay Oza <105095960+pranay-o@users.noreply.github.com> Date: Wed, 17 Jun 2026 00:30:40 -0400 Subject: [PATCH 11/18] serial number --- can_bus/hexray/BMS/BMS_tx.json | 60 +++++++++++++++++++ firmware/hexray/BMS/src/app/app_segments.hpp | 1 + .../app/segments/app_segments_broadcast.cpp | 27 +++++++++ .../BMS/src/io/adbms/io_adbms_configs.cpp | 24 ++++++++ .../BMS/src/io/adbms/io_adbms_internal.hpp | 3 + firmware/hexray/BMS/src/io/io_adbms.hpp | 2 +- firmware/hexray/BMS/src/jobs.cpp | 3 + 7 files changed, 119 insertions(+), 1 deletion(-) diff --git a/can_bus/hexray/BMS/BMS_tx.json b/can_bus/hexray/BMS/BMS_tx.json index ca5799b003..ed80da122c 100644 --- a/can_bus/hexray/BMS/BMS_tx.json +++ b/can_bus/hexray/BMS/BMS_tx.json @@ -8287,6 +8287,66 @@ } } }, + "SegmentSerialIds": { + "msg_id": 483, + "cycle_time": null, + "allowed_modes": [ + "DEBUG" + ], + "description": "Per-segment 48-bit ADBMS serial number (read from RDSID), split into three 16-bit words (word0 = bits 0-15, word1 = bits 16-31, word2 = bits 32-47)", + "signals": { + "Seg0_SerialIdWord0": { "bits": 16 }, + "Seg0_SerialIdWord1": { "bits": 16 }, + "Seg0_SerialIdWord2": { "bits": 16 }, + "Seg1_SerialIdWord0": { "bits": 16 }, + "Seg1_SerialIdWord1": { "bits": 16 }, + "Seg1_SerialIdWord2": { "bits": 16 }, + "Seg2_SerialIdWord0": { "bits": 16 }, + "Seg2_SerialIdWord1": { "bits": 16 }, + "Seg2_SerialIdWord2": { "bits": 16 }, + "Seg3_SerialIdWord0": { "bits": 16 }, + "Seg3_SerialIdWord1": { "bits": 16 }, + "Seg3_SerialIdWord2": { "bits": 16 }, + "Seg4_SerialIdWord0": { "bits": 16 }, + "Seg4_SerialIdWord1": { "bits": 16 }, + "Seg4_SerialIdWord2": { "bits": 16 }, + "Seg5_SerialIdWord0": { "bits": 16 }, + "Seg5_SerialIdWord1": { "bits": 16 }, + "Seg5_SerialIdWord2": { "bits": 16 }, + "Seg6_SerialIdWord0": { "bits": 16 }, + "Seg6_SerialIdWord1": { "bits": 16 }, + "Seg6_SerialIdWord2": { "bits": 16 }, + "Seg7_SerialIdWord0": { "bits": 16 }, + "Seg7_SerialIdWord1": { "bits": 16 }, + "Seg7_SerialIdWord2": { "bits": 16 }, + "Seg8_SerialIdWord0": { "bits": 16 }, + "Seg8_SerialIdWord1": { "bits": 16 }, + "Seg8_SerialIdWord2": { "bits": 16 }, + "Seg9_SerialIdWord0": { "bits": 16 }, + "Seg9_SerialIdWord1": { "bits": 16 }, + "Seg9_SerialIdWord2": { "bits": 16 } + } + }, + "SegmentSerialIdErrors": { + "msg_id": 484, + "cycle_time": null, + "allowed_modes": [ + "DEBUG" + ], + "description": "Per-segment error codes for segment serial number reads (NO_ERROR = no error)", + "signals": { + "Seg0_SerialIdError": { "enum": "ErrorCode" }, + "Seg1_SerialIdError": { "enum": "ErrorCode" }, + "Seg2_SerialIdError": { "enum": "ErrorCode" }, + "Seg3_SerialIdError": { "enum": "ErrorCode" }, + "Seg4_SerialIdError": { "enum": "ErrorCode" }, + "Seg5_SerialIdError": { "enum": "ErrorCode" }, + "Seg6_SerialIdError": { "enum": "ErrorCode" }, + "Seg7_SerialIdError": { "enum": "ErrorCode" }, + "Seg8_SerialIdError": { "enum": "ErrorCode" }, + "Seg9_SerialIdError": { "enum": "ErrorCode" } + } + }, "EvseCPStatus": { "msg_id": 482, "allowed_modes":[ diff --git a/firmware/hexray/BMS/src/app/app_segments.hpp b/firmware/hexray/BMS/src/app/app_segments.hpp index 9966a4e6f6..f50b6057df 100644 --- a/firmware/hexray/BMS/src/app/app_segments.hpp +++ b/firmware/hexray/BMS/src/app/app_segments.hpp @@ -110,6 +110,7 @@ namespace broadcast } // namespace debug void segmentHealthError(const health::Snapshot &health); + void serialNumbers(const io::adbms::Segments> &serial_nums); void cellVoltageStats(const CellParam &min, const CellParam &max); void cellTempStats(const CellParam &min, const CellParam &max); void segmentVoltageStats(const SegmentParam &min, const SegmentParam &max); diff --git a/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp b/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp index a2c691b482..d9c16fdfce 100644 --- a/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp +++ b/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp @@ -154,6 +154,11 @@ BroadcastBuffer segment_stat_d_error_buffer(app::can_tx::BMS_SegmentStatDErrors_getData()); +// Three consecutive 16-bit words per segment hold the 48-bit serial: [seg*3 + w] = bits [16*w, 16*w + 16). +BroadcastBuffer + segment_serial_id_buffer(app::can_tx::BMS_SegmentSerialIds_getData()); +BroadcastBuffer + segment_serial_id_error_buffer(app::can_tx::BMS_SegmentSerialIdErrors_getData()); } // namespace @@ -439,6 +444,28 @@ namespace debug } } // namespace debug +void serialNumbers(const Segments> &serial_nums) +{ + for (size_t seg = 0U; seg < NUM_SEGMENTS; seg++) + { + const auto &r = serial_nums[seg]; + const uint64_t serial = r.value_or(0U); + segment_serial_id_buffer[seg * 3U] = static_cast(serial & 0xFFFFU); + segment_serial_id_buffer[seg * 3U + 1U] = static_cast((serial >> 16U) & 0xFFFFU); + segment_serial_id_buffer[seg * 3U + 2U] = static_cast((serial >> 32U) & 0xFFFFU); + segment_serial_id_error_buffer[seg] = r ? app::can_utils::ErrorCode::NO_ERROR : toCanErr(r.error()); + } + for (size_t seg = NUM_SEGMENTS; seg < MAX_NUM_SEGMENTS; seg++) + { + segment_serial_id_buffer[seg * 3U] = 0U; + segment_serial_id_buffer[seg * 3U + 1U] = 0U; + segment_serial_id_buffer[seg * 3U + 2U] = 0U; + segment_serial_id_error_buffer[seg] = app::can_utils::ErrorCode::NO_SEGMENT_DEFINED; + } + segment_serial_id_buffer.send(); + segment_serial_id_error_buffer.send(); +} + // void cmdCountMismatch(const Segments &mismatches) // { // for (size_t seg = 0U; seg < NUM_SEGMENTS; seg++) diff --git a/firmware/hexray/BMS/src/io/adbms/io_adbms_configs.cpp b/firmware/hexray/BMS/src/io/adbms/io_adbms_configs.cpp index 65a3996dc3..8f24f87b61 100644 --- a/firmware/hexray/BMS/src/io/adbms/io_adbms_configs.cpp +++ b/firmware/hexray/BMS/src/io/adbms/io_adbms_configs.cpp @@ -90,4 +90,28 @@ Segments> read::pwmReg() } return pwm_configs; } + +Segments> read::serialNum() +{ + Segments> serial_nums{}; + + const Segments> raw_serial = readRegGroup(RDSID); + for (size_t seg = 0U; seg < NUM_SEGMENTS; ++seg) + { + if (!raw_serial[seg]) + { + serial_nums[seg] = unexpected(raw_serial[seg].error()); + continue; + } + + const RegBuffer &bytes = raw_serial[seg].value(); + uint64_t serial = 0U; + for (size_t i = 0U; i < REG_GROUP_SIZE; ++i) + { + serial |= static_cast(bytes[i]) << (8U * i); + } + serial_nums[seg] = serial; + } + return serial_nums; +} } // namespace io::adbms diff --git a/firmware/hexray/BMS/src/io/adbms/io_adbms_internal.hpp b/firmware/hexray/BMS/src/io/adbms/io_adbms_internal.hpp index b199dfce00..c9cc791a52 100644 --- a/firmware/hexray/BMS/src/io/adbms/io_adbms_internal.hpp +++ b/firmware/hexray/BMS/src/io/adbms/io_adbms_internal.hpp @@ -14,6 +14,9 @@ namespace io::adbms inline constexpr uint8_t CMD_BYTES = 2; inline constexpr uint8_t PEC_BYTES = 2; +// Serial Number +inline constexpr uint16_t RDSID = 0x002CU; + // Config inline constexpr uint16_t WRCFGA = 0x0001U; inline constexpr uint16_t WRCFGB = 0x0024U; diff --git a/firmware/hexray/BMS/src/io/io_adbms.hpp b/firmware/hexray/BMS/src/io/io_adbms.hpp index 6788ad2947..6a43b10095 100644 --- a/firmware/hexray/BMS/src/io/io_adbms.hpp +++ b/firmware/hexray/BMS/src/io/io_adbms.hpp @@ -238,6 +238,7 @@ namespace read [[nodiscard]] Segments> segVoltage(); [[nodiscard]] ThermGpios> thermGpioVoltage(); [[nodiscard]] Segments status(); + [[nodiscard]] Segments> serialNum(); } // namespace read namespace command @@ -267,7 +268,6 @@ namespace command [[nodiscard]] result pollAuxAdc(); [[nodiscard]] result startBalance(); [[nodiscard]] result stopBalance(); - [[nodiscard]] result owcCells(OpenWireSwitch owcSwitch); } // namespace command diff --git a/firmware/hexray/BMS/src/jobs.cpp b/firmware/hexray/BMS/src/jobs.cpp index a78c0bd923..84c3757916 100644 --- a/firmware/hexray/BMS/src/jobs.cpp +++ b/firmware/hexray/BMS/src/jobs.cpp @@ -188,12 +188,15 @@ void jobs_runAdbmsConfigs_tick() } } + const Segments> serial_numbers = io::adbms::read::serialNum(); + std::array, MAX_NUM_SEGMENTS> health; { const io::unique_semaphore h{ health_lock }; health = app::segments::health::getAll(); } + app::segments::broadcast::serialNumbers(serial_numbers); app::segments::broadcast::segmentHealthError(health); if (all_segments_ok) From b62d613e8c808e2a7fc290cfc78c68413e909203 Mon Sep 17 00:00:00 2001 From: Kelm Date: Tue, 16 Jun 2026 23:58:04 -0700 Subject: [PATCH 12/18] added bspdtest enable in jobs --- firmware/hexray/BMS/src/jobs.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/hexray/BMS/src/jobs.cpp b/firmware/hexray/BMS/src/jobs.cpp index 84c3757916..61ddf7bf7b 100644 --- a/firmware/hexray/BMS/src/jobs.cpp +++ b/firmware/hexray/BMS/src/jobs.cpp @@ -140,6 +140,7 @@ void jobs_run100Hz_tick() app::latches::broadcast(); app::can_tx::BMS_BSPDBrakePressureThresholdExceeded_set(io::bspdtest::isBrakePressureThresholdExceeded()); app::can_tx::BMS_BSPDAccelBrakeOk_set(io::bspdtest::isAccelBrakeOk()); + // io::bspdtest::enable(app::can_rx::Debug_BSPD_Test_get()); if (app::can_alerts::AnyBoardHasFault()) { From f524305ac02700577c8480dbff4aaa5b02d6fb88 Mon Sep 17 00:00:00 2001 From: Kelm Date: Tue, 16 Jun 2026 23:59:33 -0700 Subject: [PATCH 13/18] oops --- firmware/hexray/BMS/src/jobs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hexray/BMS/src/jobs.cpp b/firmware/hexray/BMS/src/jobs.cpp index 61ddf7bf7b..5a5d26bfdb 100644 --- a/firmware/hexray/BMS/src/jobs.cpp +++ b/firmware/hexray/BMS/src/jobs.cpp @@ -140,7 +140,7 @@ void jobs_run100Hz_tick() app::latches::broadcast(); app::can_tx::BMS_BSPDBrakePressureThresholdExceeded_set(io::bspdtest::isBrakePressureThresholdExceeded()); app::can_tx::BMS_BSPDAccelBrakeOk_set(io::bspdtest::isAccelBrakeOk()); - // io::bspdtest::enable(app::can_rx::Debug_BSPD_Test_get()); + io::bspdtest::enable(app::can_rx::Debug_EnableTestCurrent_get()); if (app::can_alerts::AnyBoardHasFault()) { From a8e1199efda6a40a00639154e36bd961c2d09633 Mon Sep 17 00:00:00 2001 From: Kelm Date: Thu, 18 Jun 2026 02:23:51 -0700 Subject: [PATCH 14/18] some reverts --- firmware/cmake/embedded.cmake | 14 +++++++------- firmware/hexray/BMS/src/io/io_adbms.hpp | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/cmake/embedded.cmake b/firmware/cmake/embedded.cmake index 3770e01b0d..5de9158870 100644 --- a/firmware/cmake/embedded.cmake +++ b/firmware/cmake/embedded.cmake @@ -150,13 +150,13 @@ function(embedded_binary target_compile_options(${ELF_NAME} PRIVATE -Os) endif () IF (${CMAKE_BUILD_TYPE} STREQUAL "Debug") -# target_compile_options(${ELF_NAME} PRIVATE -fsanitize=undefined) -# set_property(SOURCE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp" APPEND PROPERTY COMPILE_OPTIONS -# -fno-sanitize=undefined -# -Wno-error=suggest-attribute=noreturn -# -Wno-suggest-attribute=noreturn -# ) -# target_sources(${ELF_NAME} PRIVATE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp") + target_compile_options(${ELF_NAME} PRIVATE -fsanitize=undefined) + set_property(SOURCE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp" APPEND PROPERTY COMPILE_OPTIONS + -fno-sanitize=undefined + -Wno-error=suggest-attribute=noreturn + -Wno-suggest-attribute=noreturn + ) + target_sources(${ELF_NAME} PRIVATE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp") ENDIF () target_link_options(${ELF_NAME} PRIVATE diff --git a/firmware/hexray/BMS/src/io/io_adbms.hpp b/firmware/hexray/BMS/src/io/io_adbms.hpp index 6a43b10095..9d08b4a61d 100644 --- a/firmware/hexray/BMS/src/io/io_adbms.hpp +++ b/firmware/hexray/BMS/src/io/io_adbms.hpp @@ -12,7 +12,7 @@ #include // Physical daisy-chain dimensions for this ECU. -inline constexpr uint8_t NUM_SEGMENTS = 1; +inline constexpr uint8_t NUM_SEGMENTS = 10; inline constexpr uint8_t CELLS_PER_SEGMENT = 14; inline constexpr uint8_t THERMISTORS_PER_SEGMENT = 14; inline constexpr uint8_t THERM_GPIOS_PER_SEGMENT = 8; From 32bd18aa26ee7e6e0ed94ad4390de4ac9c01cb08 Mon Sep 17 00:00:00 2001 From: Kelm Date: Thu, 18 Jun 2026 02:34:34 -0700 Subject: [PATCH 15/18] beatiful morning, wet shoes --- firmware/cmake/embedded.cmake | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/cmake/embedded.cmake b/firmware/cmake/embedded.cmake index 5de9158870..a9978782d4 100644 --- a/firmware/cmake/embedded.cmake +++ b/firmware/cmake/embedded.cmake @@ -149,14 +149,14 @@ function(embedded_binary else () target_compile_options(${ELF_NAME} PRIVATE -Os) endif () - IF (${CMAKE_BUILD_TYPE} STREQUAL "Debug") - target_compile_options(${ELF_NAME} PRIVATE -fsanitize=undefined) - set_property(SOURCE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp" APPEND PROPERTY COMPILE_OPTIONS - -fno-sanitize=undefined - -Wno-error=suggest-attribute=noreturn - -Wno-suggest-attribute=noreturn - ) - target_sources(${ELF_NAME} PRIVATE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp") + IF (${CMAKE_BUILD_TYPE} STREQUAL "Debug" AND ${USE_UBSAN}) + target_compile_options(${ELF_NAME} PRIVATE -fsanitize=undefined) + set_property(SOURCE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp" APPEND PROPERTY COMPILE_OPTIONS + -fno-sanitize=undefined + -Wno-error=suggest-attribute=noreturn + -Wno-suggest-attribute=noreturn + ) + target_sources(${ELF_NAME} PRIVATE "${SHARED_LIB_INCLUDE_DIR_CPP}/lib_ubsan.cpp") ENDIF () target_link_options(${ELF_NAME} PRIVATE From e8e3504783b90c71cee3c40e4b1a7657a6e6c682 Mon Sep 17 00:00:00 2001 From: Kelm Date: Thu, 18 Jun 2026 02:40:50 -0700 Subject: [PATCH 16/18] pr comments --- can_bus/hexray/shared_enum.json | 7 ++++--- .../src/app/segments/app_segments_broadcast.cpp | 4 ++-- .../BMS/src/app/states/app_balancingState.cpp | 2 +- firmware/shared/srcpp/util/util_errorCodes.hpp | 14 +++++++++----- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/can_bus/hexray/shared_enum.json b/can_bus/hexray/shared_enum.json index 29c732f26d..ee8925d43f 100644 --- a/can_bus/hexray/shared_enum.json +++ b/can_bus/hexray/shared_enum.json @@ -11,9 +11,10 @@ "INVALID_READING": 8, "ERROR_INDETERMINATE": 9, "POLL_INVALID": 10, - "THERM_OUT_OF_RANGE": 11, - "NO_SEGMENT_DEFINED" : 12, - "NO_ERROR" : 13 + "LUT_UNDERSHOOT": 11, + "LUT_OVERSHOOT": 12, + "NO_SEGMENT_DEFINED" : 13, + "NO_ERROR" : 14 }, "SwitchState": { "OFF": 0, diff --git a/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp b/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp index d9c16fdfce..ae62d6db72 100644 --- a/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp +++ b/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp @@ -448,8 +448,8 @@ void serialNumbers(const Segments> &serial_nums) { for (size_t seg = 0U; seg < NUM_SEGMENTS; seg++) { - const auto &r = serial_nums[seg]; - const uint64_t serial = r.value_or(0U); + const auto &r = serial_nums[seg]; + const uint64_t serial = r.value_or(0U); segment_serial_id_buffer[seg * 3U] = static_cast(serial & 0xFFFFU); segment_serial_id_buffer[seg * 3U + 1U] = static_cast((serial >> 16U) & 0xFFFFU); segment_serial_id_buffer[seg * 3U + 2U] = static_cast((serial >> 32U) & 0xFFFFU); diff --git a/firmware/hexray/BMS/src/app/states/app_balancingState.cpp b/firmware/hexray/BMS/src/app/states/app_balancingState.cpp index d326bbbd71..d3985c89cd 100644 --- a/firmware/hexray/BMS/src/app/states/app_balancingState.cpp +++ b/firmware/hexray/BMS/src/app/states/app_balancingState.cpp @@ -23,7 +23,7 @@ namespace balancingState (io::irs::negativeState() == app::can_utils::ContactorState::CONTACTOR_STATE_OPEN); const bool balancing_enabled = app::can_rx::Debug_CellBalancing_Request_get(); - if (balancing_enabled && ir_negative_open) + if (balancing_enabled && !ir_negative_open) { app::segments::balancing::tick(); } diff --git a/firmware/shared/srcpp/util/util_errorCodes.hpp b/firmware/shared/srcpp/util/util_errorCodes.hpp index c32051b3d0..3306d8f9a0 100644 --- a/firmware/shared/srcpp/util/util_errorCodes.hpp +++ b/firmware/shared/srcpp/util/util_errorCodes.hpp @@ -16,11 +16,11 @@ enum class ErrorCode INVALID_READING, ERROR_INDETERMINATE, POLL_INVALID, - THERM_OUT_OF_RANGE, - NUM_EXIT_CODES, LUT_INVALID, LUT_OVERSHOOT, - LUT_UNDERSHOOT + LUT_UNDERSHOOT, + NO_SEGMENT_DEFINED, + NUM_EXIT_CODES }; template using result = std::expected; @@ -51,8 +51,12 @@ constexpr const char *error_code_to_string(const ErrorCode code) return "Indeterminate error"; case ErrorCode::POLL_INVALID: return "Poll invalid"; - case ErrorCode::THERM_OUT_OF_RANGE: - return "Therm out of range"; + case ErrorCode::LUT_UNDERSHOOT: + return "LUT undershoot"; + case ErrorCode::LUT_OVERSHOOT: + return "LUT overshoot"; + case ErrorCode::NO_SEGMENT_DEFINED: + return "No segment defined for this index"; case ErrorCode::NUM_EXIT_CODES: default: return "Unknown error code"; From 594bb48e83de676170c6076c6a3c6a8eb8501eb5 Mon Sep 17 00:00:00 2001 From: Pranay Oza <105095960+pranay-o@users.noreply.github.com> Date: Thu, 18 Jun 2026 09:16:00 -0400 Subject: [PATCH 17/18] removingh shi --- can_bus/hexray/BMS/BMS_tx.json | 2 +- firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/can_bus/hexray/BMS/BMS_tx.json b/can_bus/hexray/BMS/BMS_tx.json index ed80da122c..7c30f24182 100644 --- a/can_bus/hexray/BMS/BMS_tx.json +++ b/can_bus/hexray/BMS/BMS_tx.json @@ -8293,7 +8293,7 @@ "allowed_modes": [ "DEBUG" ], - "description": "Per-segment 48-bit ADBMS serial number (read from RDSID), split into three 16-bit words (word0 = bits 0-15, word1 = bits 16-31, word2 = bits 32-47)", + "description": "Per-segment 48-bit ADBMS serial number", "signals": { "Seg0_SerialIdWord0": { "bits": 16 }, "Seg0_SerialIdWord1": { "bits": 16 }, diff --git a/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp b/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp index ae62d6db72..b850acd1cb 100644 --- a/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp +++ b/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp @@ -154,7 +154,6 @@ BroadcastBuffer segment_stat_d_error_buffer(app::can_tx::BMS_SegmentStatDErrors_getData()); -// Three consecutive 16-bit words per segment hold the 48-bit serial: [seg*3 + w] = bits [16*w, 16*w + 16). BroadcastBuffer segment_serial_id_buffer(app::can_tx::BMS_SegmentSerialIds_getData()); BroadcastBuffer From 9d2fe4e96ba258eec01c5f9d04d13b8d2100a2c0 Mon Sep 17 00:00:00 2001 From: Pranay Oza <105095960+pranay-o@users.noreply.github.com> Date: Thu, 18 Jun 2026 09:17:44 -0400 Subject: [PATCH 18/18] remove --- .../src/app/segments/app_segments_broadcast.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp b/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp index b850acd1cb..d1a70f50c8 100644 --- a/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp +++ b/firmware/hexray/BMS/src/app/segments/app_segments_broadcast.cpp @@ -465,22 +465,6 @@ void serialNumbers(const Segments> &serial_nums) segment_serial_id_error_buffer.send(); } -// void cmdCountMismatch(const Segments &mismatches) -// { -// for (size_t seg = 0U; seg < NUM_SEGMENTS; seg++) -// { -// segment_cmdcnt_buffer[seg] = mismatches[seg]; -// } -// segment_cmdcnt_buffer.send(); -// } - -// void spiLinkStats(const io::adbms::SpiBusReach &reach) -// { -// can_tx::BMS_LowSideSegmentReach_set(reach.ls_reach); -// can_tx::BMS_HighSideSegmentReach_set(reach.hs_reach); -// io::can_tx::BMS_SpiLinkStatus_sendAperiodic(); -// } - void segmentHealthError(const health::Snapshot &health) { for (size_t seg = 0U; seg < MAX_NUM_SEGMENTS; seg++)