Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
118169a
replaced magic numbers from charging request can message with enum.
advaitSurajVedant Oct 31, 2025
1e0d8e2
changed handshake names to be more accurate and removed extra value
advaitSurajVedant Oct 31, 2025
b9dacca
added loop function to generalize id looping functionality of CCUInte…
advaitSurajVedant Nov 2, 2025
1896db1
Merge branch 'main' into feature/updating_ccu_acu_handshake
advaitSurajVedant Nov 2, 2025
43ca9dd
merge clenaup
advaitSurajVedant Nov 2, 2025
8911749
fixed cell temp logic to send 2 groups of 2 temps per chip instead of…
advaitSurajVedant Nov 2, 2025
f3bbd89
updated CCUINterface to a be a template
advaitSurajVedant Nov 4, 2025
c9aa150
fixed magic number error
advaitSurajVedant Nov 4, 2025
7990f1f
removed templating for CCUInterface
advaitSurajVedant Nov 5, 2025
6f8e86c
got rid of ACUController template stuff and added new tests for acuco…
advaitSurajVedant Nov 5, 2025
35870c6
removed random 8 from BMSDriverGroup and make it in terms of the pack…
advaitSurajVedant Nov 5, 2025
1167818
exchanged valid packe data struct for an array
advaitSurajVedant Nov 5, 2025
4426c46
created a map for cmds to read group and changed store voltage and te…
advaitSurajVedant Nov 5, 2025
5e3bb2e
removed 2 const for size_of_packet_value_bytes
advaitSurajVedant Nov 6, 2025
1d632d8
added ChipSelectConfig as param to BMSDriverGroup and made user it pa…
advaitSurajVedant Nov 7, 2025
ecb4c91
removed some ACU Constants
advaitSurajVedant Nov 7, 2025
ae43b99
merged with temp2 branch to remove any excess other pr changes from m…
advaitSurajVedant Nov 16, 2025
b9a0d33
Merge branch 'main' into feature/moved_bms_chip_config_to_array
advaitSurajVedant Nov 16, 2025
a4127f5
debugged and fixed infinite loop issues
advaitSurajVedant Dec 1, 2025
67893f1
fixed error
advaitSurajVedant Dec 2, 2025
7f79d88
Merge branch 'main' into feature/moved_bms_chip_config_to_array
advaitSurajVedant Dec 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 165 additions & 7 deletions include/ACU_Constants.h

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions include/ACU_InterfaceTasks.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#include <chrono>

using chip_type = LTC6811_Type_e;
using BMSDriverInstance_t = BMSDriverInstance<ACUConstants::NUM_CHIPS, ACUConstants::NUM_CHIP_SELECTS, chip_type::LTC6811_1>;
using BMSFaultDataManagerInstance_t = BMSFaultDataManagerInstance<ACUConstants::NUM_CHIPS>;
using BMSDriverInstance_t = BMSDriverInstance<ACUConstants::NUM_CHIPS_PER_CHIP_SELECT, ACUConstants::NUM_CHIP_SELECTS, ACUConstants::NUM_VOLTAGE_CELLS, ACUConstants::NUM_TEMP_CELLS, ACUConstants::NUM_BOARD_TEMPS, chip_type::LTC6811_1>;
using BMSFaultDataManagerInstance_t = BMSFaultDataManagerInstance<ACUConstants::NUM_CHIPS_PER_CHIP_SELECT * ACUConstants::NUM_CHIP_SELECTS>;
/**
* Init Functions - to be called in setup
*/
Expand Down
4 changes: 2 additions & 2 deletions include/ACU_SystemTasks.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
#include <ht_task.hpp>

using chip_type = LTC6811_Type_e;
using BMSDriverInstance_t = BMSDriverInstance<ACUConstants::NUM_CHIPS, ACUConstants::NUM_CHIP_SELECTS, chip_type::LTC6811_1>;
using BMSFaultDataManagerInstance_t = BMSFaultDataManagerInstance<ACUConstants::NUM_CHIPS>;
using BMSDriverInstance_t = BMSDriverInstance<ACUConstants::NUM_CHIPS_PER_CHIP_SELECT, ACUConstants::NUM_CHIP_SELECTS, ACUConstants::NUM_VOLTAGE_CELLS, ACUConstants::NUM_TEMP_CELLS, ACUConstants::NUM_BOARD_TEMPS, chip_type::LTC6811_1>;
using BMSFaultDataManagerInstance_t = BMSFaultDataManagerInstance<ACUConstants::NUM_CHIPS_PER_CHIP_SELECT * ACUConstants::NUM_CHIP_SELECTS>;
bool initialize_all_systems();

/* Delegate Functions */
Expand Down
150 changes: 71 additions & 79 deletions lib/interfaces/include/BMSDriverGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ namespace bms_driver_defaults
constexpr const float CV_ADC_CONVERSION_TIME_MS = 1.2f;
constexpr const float GPIO_ADC_CONVERSION_TIME_MS = 1.2f;
constexpr const float CV_ADC_LSB_VOLTAGE = 0.0001f; // Cell voltage ADC resolution: 100μV per LSB (1/10000 V)
constexpr const size_t SIZE_OF_PACKET_VALUE_BYTES = 2;
}

namespace ref_max_min_defaults
{
constexpr const volt TOTAL_VOLTAGE = 0;
Expand All @@ -97,23 +97,15 @@ namespace ref_max_min_defaults
constexpr const celsius MAX_BOARD_TEMP = 0;
};

struct ValidPacketData_s
{
bool valid_read_cells_1_to_3 = true;
bool valid_read_cells_4_to_6 = true;
bool valid_read_cells_7_to_9 = true;
bool valid_read_cells_10_to_12 = true;
bool valid_read_gpios_1_to_3 = true;
bool valid_read_gpios_4_to_6 = true;
};

template <size_t num_chips, size_t num_cells, size_t num_board_thermistors>

template <size_t num_chips, size_t num_voltage_cells, size_t num_temp_cells, size_t num_board_temps>
struct BMSData_s
{
std::array<ValidPacketData_s, num_chips> valid_read_packets;
std::array<volt, num_cells> voltages;
std::array<celsius, 4 * num_chips> cell_temperatures;
std::array<celsius, num_board_thermistors> board_temperatures;
std::array<std::array<bool, ReadGroup_e::NUM_GROUPS>, num_chips> valid_read_packets;
std::array<volt, num_voltage_cells> voltages;
std::array<celsius, num_temp_cells> cell_temperatures;
std::array<celsius, num_board_temps> board_temperatures;
volt min_cell_voltage;
volt max_cell_voltage;
celsius max_cell_temp;
Expand Down Expand Up @@ -167,28 +159,49 @@ struct BMSDriverGroupConfig_s
* @param current The current read group state
* @return The next read group, wrapping from CURRENT_GROUP_AUX_B back to CURRENT_GROUP_A
*/
constexpr ReadGroup_e advance_read_group(ReadGroup_e current)
constexpr bool advance_read_group(ReadGroup_e* current)
{
return static_cast<ReadGroup_e>(
(static_cast<int>(current) + 1) % static_cast<int>(ReadGroup_e::NUM_GROUPS)
);
// Get current as int
int curr = static_cast<int>(*current);

// Compute next value with wrap-around
int next = (curr + 1) % static_cast<int>(ReadGroup_e::NUM_GROUPS);

// Detect wrap: we wrapped if next is 0
bool wrapped = (next == 0);

// Write back through the pointer
*current = static_cast<ReadGroup_e>(next);

return wrapped;
}

template <size_t num_chips, size_t num_chip_selects, LTC6811_Type_e chip_type>

template <size_t num_chips_per_chip_select, size_t num_chip_selects, size_t num_voltage_cells, size_t num_temp_cells, size_t num_board_temps, LTC6811_Type_e chip_type, size_t size_of_packet_value_bytes>
class BMSDriverGroup
{
public:
constexpr static size_t num_cells = (num_chips / 2) * 21;

constexpr static size_t num_cell_temps = (num_chips * 4);
constexpr static size_t num_board_temps = num_chips;

using BMSDriverData = BMSData_s<num_chips, num_cells, num_chips>;

static constexpr size_t _data_size_bytes = 6;
static constexpr size_t _pec_size_bytes = 2;
static constexpr size_t _total_packet_size_bytes = _data_size_bytes + _pec_size_bytes;
static constexpr std::array<CMD_CODES_e, ReadGroup_e::NUM_GROUPS> _read_group_to_cmd = {
CMD_CODES_e::READ_CELL_VOLTAGE_GROUP_A,
CMD_CODES_e::READ_CELL_VOLTAGE_GROUP_B,
CMD_CODES_e::READ_CELL_VOLTAGE_GROUP_C,
CMD_CODES_e::READ_CELL_VOLTAGE_GROUP_D,
CMD_CODES_e::READ_GPIO_VOLTAGE_GROUP_A,
CMD_CODES_e::READ_GPIO_VOLTAGE_GROUP_B
};

// constexpr static size_t num_cell_temps = (num_chips * 4);
// constexpr static size_t num_board_temps = num_chips;

using BMSDriverData_t = BMSData_s<num_chip_selects * num_chips_per_chip_select, num_voltage_cells, num_temp_cells, num_board_temps>;
using ChipSelectConfig_t = ChipSelectConfig<num_chip_selects, num_chips_per_chip_select, _data_size_bytes / size_of_packet_value_bytes>;
using ChipSelect_t = ChipSelect<num_chips_per_chip_select, _data_size_bytes / size_of_packet_value_bytes>;
using Chip_t = Chip<_data_size_bytes / size_of_packet_value_bytes>;
BMSDriverGroup(
const std::array<int, num_chip_selects>& cs,
const std::array<int, num_chips>& cs_per_chip,
const std::array<int, num_chips>& addr,
const ChipSelectConfig_t& chip_select_config,
const BMSDriverGroupConfig_s default_params
);

Expand All @@ -213,7 +226,7 @@ class BMSDriverGroup
* AND record the maximum value and locations
*/
// void read_thermistor_and_humidity();
BMSDriverData read_data();
BMSDriverData_t read_data();

/**
* Getter function to retrieve the ACUData structure
Expand All @@ -223,7 +236,7 @@ class BMSDriverGroup
/**
* Getter function to retrieve the BMSDriverData structure
*/
BMSDriverData get_bms_data();
BMSDriverData_t get_bms_data();

/* -------------------- WRITING DATA FUNCTIONS -------------------- */

Expand All @@ -232,12 +245,12 @@ class BMSDriverGroup
* @pre needs access to undervoltage, overvoltage, configuration MACROS, and discharge data
* @post sends packaged data over SPI
*/
void write_configuration(uint8_t dcto_mode, const std::array<uint16_t, num_chips> &cell_balance_statuses);
void write_configuration(uint8_t dcto_mode, const std::array<uint16_t, num_chip_selects * num_chips_per_chip_select> &cell_balance_statuses);

/**
* Alternative header for configuration function call
*/
void write_configuration(const std::array<bool, num_cells> &cell_balance_statuses);
void write_configuration(const bool* cell_balance_statuses, size_t cell_balance_statuses_size);

/* -------------------- OBSERVABILITY FUNCTIONS -------------------- */

Expand Down Expand Up @@ -272,7 +285,7 @@ class BMSDriverGroup
* @note Each chip has 6 validity flags (cells 1-3, 4-6, 7-9, 10-12, GPIO 1-3, 4-6)
* @note Useful for fault detection and EMI resilience monitoring
*/
const std::array<ValidPacketData_s, num_chips>& get_validity_data() {
const std::array<std::array<bool, ReadGroup_e::NUM_GROUPS>, num_chip_selects * num_chips_per_chip_select>& get_validity_data() {
return _bms_data.valid_read_packets;
}

Expand All @@ -296,8 +309,8 @@ class BMSDriverGroup
* @note Each bit represents one cell's balance enable status
* @note Useful for verifying write_configuration() worked correctly
*/
const std::array<uint16_t, num_chips>& get_cell_discharge_enable() {
return _cell_discharge_en;
const std::array<uint16_t, num_chip_selects * num_chips_per_chip_select>& get_cell_discharge_enable() {
return _cell_discharge_en;
}

/**
Expand All @@ -310,7 +323,6 @@ class BMSDriverGroup
}

private:

ReadGroup_e _current_read_group = ReadGroup_e::CV_GROUP_A;

/**
Expand All @@ -331,9 +343,9 @@ class BMSDriverGroup
*/
void _start_wakeup_protocol();

void _start_wakeup_protocol(size_t cs);
void _start_wakeup_protocol(size_t chip_select_pin);

BMSDriverData _read_data_through_broadcast();
BMSDriverData_t _read_data_through_broadcast();

/**
* REFERENCE ONLY: LTC6811-2 ADDRESS MODE IS BROKEN AND UNUSED
Expand All @@ -357,15 +369,15 @@ class BMSDriverGroup
* PRODUCTION: All production code uses LTC6811_1 (broadcast mode) exclusively.
* See ACU_InterfaceTasks.cpp lines 27-28.
*/
BMSDriverData _read_data_through_address();
BMSDriverData_t _read_data_through_address();

void _store_temperature_humidity_data(BMSDriverData &bms_data, ReferenceMaxMin_s &max_min_reference, const uint16_t &gpio_in, uint8_t gpio_index, uint8_t chip_index);
void _store_cell_temperature_data(BMSDriverData_t &bms_data, ReferenceMaxMin_s &max_min_reference, const uint16_t &temp_in, uint8_t cell_temp_index);
void _store_board_temperature_data(BMSDriverData_t &bms_data, ReferenceMaxMin_s &max_min_reference, const uint16_t &temp_in, uint8_t board_index);
void _store_voltage_data(BMSDriverData_t &bms_data, ReferenceMaxMin_s &max_min_reference, volt voltage_in, uint8_t cell_index);

void _store_voltage_data(BMSDriverData &bms_data, ReferenceMaxMin_s &max_min_reference, volt voltage_in, uint8_t cell_index);
void _write_config_through_broadcast(uint8_t dcto_mode, std::array<uint8_t, 6> buffer_format, const std::array<uint16_t, num_chip_selects * num_chips_per_chip_select> &cell_balance_statuses);

void _write_config_through_broadcast(uint8_t dcto_mode, std::array<uint8_t, 6> buffer_format, const std::array<uint16_t, num_chips> &cell_balance_statuses);

void _write_config_through_address(uint8_t dcto_mode, const std::array<uint8_t, 6>& buffer_format, const std::array<uint16_t, num_chips> &cell_balance_statuses);
// void _write_config_through_address(uint8_t dcto_mode, const std::array<uint8_t, 6>& buffer_format, const std::array<uint16_t, num_chip_selects * num_chips_per_chip_select> &cell_balance_statuses);

/**
* Writes command to start cell voltage ADC converion
Expand All @@ -382,21 +394,18 @@ class BMSDriverGroup

void _start_ADC_conversion_through_broadcast(const std::array<uint8_t, 2> &cmd_code);

void _start_ADC_conversion_through_address(const std::array<uint8_t, 2>& cmd_code);

void _load_cell_voltages(BMSDriverData &bms_data, ReferenceMaxMin_s &max_min_ref, const std::array<uint8_t, 6> &data_in_cv_group,
uint8_t chip_index, uint8_t start_cell_index);

void _load_auxillaries(BMSDriverData &bms_data, ReferenceMaxMin_s &max_min_ref, const std::array<uint8_t, 6> &data_in_gpio_group,
uint8_t chip_index, uint8_t start_gpio_index);
// void _start_ADC_conversion_through_address(const std::array<uint8_t, 2>& cmd_code);

void _load_cell_voltages(BMSDriverData_t &bms_data, ReferenceMaxMin_s &max_min_ref, const std::array<uint8_t, size_of_packet_value_bytes> &data_in_cell_voltage, uint8_t cell_index);
void _load_cell_temps(BMSDriverData_t &bms_data, ReferenceMaxMin_s &max_min_ref, const std::array<uint8_t, size_of_packet_value_bytes> &data_in_temp, uint8_t cell_index);
void _load_board_temps(BMSDriverData_t &bms_data, ReferenceMaxMin_s &max_min_ref, const std::array<uint8_t, size_of_packet_value_bytes> &data_in_temp, uint8_t board_index);
/* -------------------- GETTER FUNCTIONS -------------------- */

/**
* @brief When the inverters are idle, comms get funky from EMI. This function allows us to determine if the acu reads valid packets
* @return bool of whether the PEC correctly reflects the buffer being given. If no, then we know that EMI (likely) is causing invalid reads
*/
bool _check_if_valid_packet(const std::array<uint8_t, 8 * (num_chips / num_chip_selects)> &data, size_t param_iterator);
bool _check_if_valid_packet(const std::array<uint8_t, _total_packet_size_bytes * num_chips_per_chip_select> &data, size_t param_iterator);

/**
* Generates a Packet Error Code
Expand All @@ -412,21 +421,20 @@ class BMSDriverGroup
* Generates a formmatted 2 byte array for the Command bytes
* @return unsigned 8 bit array of length 2
*/
std::array<uint8_t, 2> _generate_formatted_CMD(CMD_CODES_e command, int ic_index);
std::array<uint8_t, 2> _generate_formatted_CMD(CMD_CODES_e command, size_t chip_addr);

/**
* Generates Command and PEC as one byte array of length 4: CMD0, CMD1, PEC0, PEC1
* @return unsigned 8 bit, length 4
*/
std::array<uint8_t, 4> _generate_CMD_PEC(CMD_CODES_e command, int ic_index);
std::array<uint8_t, 4> _generate_CMD_PEC(CMD_CODES_e command, size_t chip_addr);

/**
* @return usable command address for LTC6811_2
*/
uint8_t _get_cmd_address(int address) { return 0x80 | (address << 3); }

private:

/**
* initializes PEC table
* Made static so that it can be called in constructor -> _pec15table is made const
Expand All @@ -436,7 +444,7 @@ class BMSDriverGroup
constexpr std::array<uint16_t, 256> _initialize_Pec_Table();

/* MEMBER VARIABLES */
BMSDriverData _bms_data;
BMSDriverData_t _bms_data;

/**
* Tracks min/max/sum values across all 6 read groups within a single timestamp cycle.
Expand All @@ -450,25 +458,9 @@ class BMSDriverGroup
* It can only be 9 or 10
* NOTE: needs to be initialized
*/
const std::array<int, num_chip_selects> _chip_select;

/**
* We will need this for both models of the IC
* This determines where we get our signals from on the Arduino
* It can only be 9 or 10
* NOTE: needs to be initialized
*/
const std::array<int, num_chips> _chip_select_per_chip;
const ChipSelectConfig_t _chip_select_config;

/**
* We will only end up using the address if this is a LTC6811-2
* NOTE: But if we are, we need to call a setup function to instatiate each with the correct addresses
* EX) BMS Segments 1, 4, and 5 are on chip select 9
* BMS Segments 2, 3, and 6 are on chip select 10
* Those segments correspond to 2 ICs each, so the instance with chip_select 9
* Will have IC addresses: 0,1,6,7,8,9 | The rest are for chip_select 10
*/
const std::array<int, num_chips> _address; // constant


/**
* REPLACING SEPARATE CONFIGURATION FILE
Expand All @@ -487,11 +479,11 @@ class BMSDriverGroup
* We only use 12 bits to represent a 1 (discharge) or 0 (charge)
* out of the 16 bits
*/
std::array<uint16_t, num_chips> _cell_discharge_en = {}; // not const
std::array<uint16_t, num_chip_selects * num_chips_per_chip_select> _cell_discharge_en = {}; // not const
};

template <size_t num_chips, size_t num_chip_selects, LTC6811_Type_e chip_type>
using BMSDriverInstance = etl::singleton<BMSDriverGroup<num_chips, num_chip_selects, chip_type>>;
template <size_t num_chips_per_chip_select, size_t num_chip_selects, size_t num_voltage_cells, size_t num_temp_cells, size_t num_board_temps, LTC6811_Type_e chip_type>
using BMSDriverInstance = etl::singleton<BMSDriverGroup<num_chips_per_chip_select, num_chip_selects, num_voltage_cells, num_temp_cells, num_board_temps, chip_type, bms_driver_defaults::SIZE_OF_PACKET_VALUE_BYTES>>;

#include <BMSDriverGroup.tpp>

Expand Down
Loading