From 027271ab7af962ba8ceb8b2a594d31f23a7e0ba1 Mon Sep 17 00:00:00 2001 From: dyldonahue <98500199+dyldonahue@users.noreply.github.com> Date: Sun, 9 Jun 2024 14:05:56 -0400 Subject: [PATCH] Miscellaneous FSAE changes (#104) * Clamping voltages within a non noisy range * Fixing DCL copy timer and clearing all faults every loop * Copying over other thermistors from last reading * Filtered mode works * Disabling thermistors * Printing cell temperatures * inverted ccl * Making Max Temp based on cell temps instead of thermistors * Using continuous CCL for max CCL * Disregarding therms if bad ADC reading * Adding in lower bound temperature clamp --------- Co-authored-by: nwdepatie --- Core/Inc/bmsConfig.h | 1 + Core/Inc/compute.h | 3 + Core/Inc/datastructs.h | 6 +- Core/Src/analyzer.c | 185 ++++++++++++++++++++++------------------ Core/Src/compute.c | 75 ++++++++++++++-- Core/Src/main.c | 45 +++++++--- Core/Src/segment.c | 147 +++++++++++++++++-------------- Core/Src/stateMachine.c | 15 +++- Drivers/Embedded-Base | 2 +- 9 files changed, 308 insertions(+), 171 deletions(-) diff --git a/Core/Inc/bmsConfig.h b/Core/Inc/bmsConfig.h index 6534d7b..b2b036f 100644 --- a/Core/Inc/bmsConfig.h +++ b/Core/Inc/bmsConfig.h @@ -26,6 +26,7 @@ #define MAX_DELTA_V 0.015 #define BAL_MIN_V 4.00 #define MAX_CELL_TEMP 55 +#define MIN_CELL_TEMP 15 #define MAX_CELL_CURR 500 // Amps per BMS cell #define MAX_CELL_TEMP_BAL 45 #define MAX_CHG_CELL_CURR 20 diff --git a/Core/Inc/compute.h b/Core/Inc/compute.h index 3f9bfdb..611305e 100644 --- a/Core/Inc/compute.h +++ b/Core/Inc/compute.h @@ -189,4 +189,7 @@ void compute_send_cell_temp_message(acc_data_t* bmsdata); */ void compute_send_segment_temp_message(acc_data_t* bmsdata); +void compute_send_fault_message(uint8_t status, int16_t curr, int16_t in_dcl); +void compute_send_voltage_noise_message(acc_data_t* bmsdata); + #endif // COMPUTE_H diff --git a/Core/Inc/datastructs.h b/Core/Inc/datastructs.h index 7352162..af344e8 100644 --- a/Core/Inc/datastructs.h +++ b/Core/Inc/datastructs.h @@ -12,7 +12,7 @@ */ typedef struct { /* These are retrieved from the initial LTC comms */ - uint16_t voltage_reading[NUM_CELLS_PER_CHIP]; /* store voltage readings from each chip */ + uint16_t voltage[NUM_CELLS_PER_CHIP]; /* store voltage readings from each chip */ int8_t thermistor_reading[NUM_THERMS_PER_CHIP]; /* store all therm readings from each chip */ int8_t thermistor_value[NUM_THERMS_PER_CHIP]; int error_reading; @@ -22,7 +22,8 @@ typedef struct { float cell_resistance[NUM_CELLS_PER_CHIP]; uint16_t open_cell_voltage[NUM_CELLS_PER_CHIP]; - uint8_t bad_volt_diff_count[NUM_CELLS_PER_CHIP]; + uint8_t noise_reading[NUM_CELLS_PER_CHIP]; /* bool representing noise ignored read */ + uint8_t consecutive_noise[NUM_CELLS_PER_CHIP]; /* count representing consecutive noisy reads */ } chipdata_t; /** @@ -92,6 +93,7 @@ typedef struct { uint8_t soc; int8_t segment_average_temps[NUM_SEGMENTS]; + uint8_t segment_noise_percentage[NUM_SEGMENTS]; /** * @brief Note that this is a 32 bit integer, so there are 32 max possible fault codes diff --git a/Core/Src/analyzer.c b/Core/Src/analyzer.c index 86b5d86..b495a5b 100644 --- a/Core/Src/analyzer.c +++ b/Core/Src/analyzer.c @@ -123,18 +123,18 @@ const uint8_t RELEVANT_THERM_MAP_L[NUM_CELLS_PER_CHIP][NUM_RELEVANT_THERMS] = uint8_t THERM_DISABLE[NUM_CHIPS][NUM_THERMS_PER_CHIP] = { - {1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0}, - {1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1}, - {1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0}, - {1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0}, - {1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, - {1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0}, - {1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0}, - {1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0}, - {1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, - {1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0}, - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, - {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + {1,0,1,0,0,1,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,0,0,1,1,1,0,0,0,0,1,0 }, + {1,0,1,0,0,1,0,0,1,0,1,1,0,1,1,0,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1 }, + {1,0,1,0,0,1,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0 }, + {1,0,1,0,0,1,0,0,1,1,0,1,0,0,1,0,0,0,0,0,1,1,1,0,1,0,0,1,0,0,0,0 }, + {1,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1 }, + {1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1,0,1,1,1,0,0,0 }, + {1,0,1,0,0,1,0,0,1,0,1,1,0,0,1,1,0,0,1,0,1,1,1,0,0,0,0,0,0,0,1,0 }, + {1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1,0,1,1,1,1,1,1 }, + {1,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0 }, + {1,0,1,0,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0 }, + {1,1,1,0,0,1,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0 }, + {1,1,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0 } }; /* @@ -193,56 +193,25 @@ void calc_state_of_charge(); void calc_cell_temps() { - static uint8_t num_samples = 7; /* Samples for LPF */ - for (uint8_t c = 0; c < NUM_CHIPS; c++) { - //const uint8_t (*therm_map)[NUM_RELEVANT_THERMS] = (c % 2 == 0) ? RELEVANT_THERM_MAP_L : RELEVANT_THERM_MAP_H; - int16_t therm_sum = 0; - uint8_t therm_count = 0; - - for (uint8_t therm = 0; therm < NUM_THERMS_PER_CHIP; therm++) { - - if (THERM_DISABLE[c][therm]) continue; - - therm_sum += bmsdata->chip_data[c].thermistor_value[therm]; - therm_count++; - } - - int8_t temp_avg = therm_sum / therm_count; - - for (uint8_t therm = 0; therm < NUM_THERMS_PER_CHIP; therm++) { - bmsdata->chip_data[c].thermistor_value[therm] = temp_avg; - bmsdata->chip_data[c].thermistor_value[therm] = (int8_t)((((int64_t)prevbmsdata->chip_data[c].thermistor_value[therm] * (num_samples - 5)) - + bmsdata->chip_data[c].thermistor_value[therm] * 5) / num_samples); - } - for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { - - /* Takes the average temperature of all the relevant thermistors */ - bmsdata->chip_data[c].cell_temp[cell] = bmsdata->chip_data[c].thermistor_value[0]; /* Note, all temp readings are the same at this point */ - - /* Low Pass Filter */ - - - /* Cleansing value */ - if (bmsdata->chip_data[c].cell_temp[cell] > MAX_TEMP) { - bmsdata->chip_data[c].cell_temp[cell] = MAX_TEMP; + const uint8_t (*therm_map)[NUM_RELEVANT_THERMS] = (c % 2 == 0) ? RELEVANT_THERM_MAP_L : RELEVANT_THERM_MAP_H; + uint8_t therm_count = 0; + int temp_sum = 0; + for (uint8_t therm = 0; therm < NUM_RELEVANT_THERMS; therm++) { + uint8_t thermNum = therm_map[cell][therm]; + + if (thermNum != NO_THERM) { + //printf("%d\t", bmsdata->chip_data[c].thermistor_value[therm]); + temp_sum += bmsdata->chip_data[c].thermistor_value[therm]; + therm_count++; + } } + //printf("\r\n"); + /* Takes the average temperature of all the relevant thermistors */ + bmsdata->chip_data[c].cell_temp[cell] = temp_sum / therm_count; + therm_count = 0; } - // uint8_t therm_count = 0; - // int temp_sum = 0; - // for (uint8_t therm = 0; therm < NUM_RELEVANT_THERMS; therm++) { - // uint8_t thermNum = therm_map[cell][therm]; - - // if (thermNum != NO_THERM) { - // temp_sum += bmsdata->chip_data[c].thermistor_value[thermNum]; - // therm_count++; - // } - // } - - // /* Takes the average temperature of all the relevant thermistors */ - // bmsdata->chip_data[c].cell_temp[cell] = temp_sum / therm_count; - // therm_count = 0; } } @@ -262,20 +231,20 @@ void calc_pack_temps() for (uint8_t therm = 0; therm < NUM_THERMS_PER_CHIP; therm++) { /* finds out the maximum cell temp and location */ - if (THERM_DISABLE[c][therm]) continue; + //if (THERM_DISABLE[c][therm]) continue; total_accepted++; - if (bmsdata->chip_data[c].thermistor_value[therm] > bmsdata->max_temp.val) { - bmsdata->max_temp.val = bmsdata->chip_data[c].thermistor_value[therm]; - bmsdata->max_temp.cellNum = c; - bmsdata->max_temp.chipIndex = therm; - } + //if (bmsdata->chip_data[c].thermistor_value[therm] > bmsdata->max_temp.val) { + // bmsdata->max_temp.val = bmsdata->chip_data[c].thermistor_value[therm]; + // bmsdata->max_temp.cellNum = c; + // bmsdata->max_temp.chipIndex = therm; + //} /* finds out the minimum cell temp and location */ - if (bmsdata->chip_data[c].thermistor_value[therm] < bmsdata->min_temp.val) { - bmsdata->min_temp.val = bmsdata->chip_data[c].thermistor_value[therm]; - bmsdata->min_temp.cellNum = c; - bmsdata->min_temp.chipIndex = therm; - } + //if (bmsdata->chip_data[c].thermistor_value[therm] < bmsdata->min_temp.val) { + // bmsdata->min_temp.val = bmsdata->chip_data[c].thermistor_value[therm]; + // bmsdata->min_temp.cellNum = c; + // bmsdata->min_temp.chipIndex = therm; + //} total_temp += bmsdata->chip_data[c].thermistor_value[therm]; total_seg_temp += bmsdata->chip_data[c].thermistor_value[therm]; @@ -288,6 +257,24 @@ void calc_pack_temps() } } + + for (uint8_t c = 0; c < NUM_CHIPS; c++) { + for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { + if (bmsdata->chip_data[c].cell_temp[cell] > bmsdata->max_temp.val) { + bmsdata->max_temp.val = bmsdata->chip_data[c].cell_temp[cell]; + bmsdata->max_temp.cellNum = cell; + bmsdata->max_temp.chipIndex = c; + } + + /* finds out the minimum cell temp and location */ + if (bmsdata->chip_data[c].cell_temp[cell] < bmsdata->min_temp.val) { + bmsdata->min_temp.val = bmsdata->chip_data[c].cell_temp[cell]; + bmsdata->min_temp.cellNum = cell; + bmsdata->min_temp.chipIndex = c; + } + } + } + /* takes the average of all the cell temperatures */ bmsdata->avg_temp = total_temp / (total_accepted); } @@ -317,8 +304,8 @@ void calc_pack_voltage_stats() for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { /* fings out the maximum cell voltage and location */ - if (bmsdata->chip_data[c].voltage_reading[cell] > bmsdata->max_voltage.val) { - bmsdata->max_voltage.val = bmsdata->chip_data[c].voltage_reading[cell]; + if (bmsdata->chip_data[c].voltage[cell] > bmsdata->max_voltage.val) { + bmsdata->max_voltage.val = bmsdata->chip_data[c].voltage[cell]; bmsdata->max_voltage.chipIndex = c; bmsdata->max_voltage.cellNum = cell; } @@ -330,8 +317,8 @@ void calc_pack_voltage_stats() } /* finds out the minimum cell voltage and location */ - if (bmsdata->chip_data[c].voltage_reading[cell] < bmsdata->min_voltage.val) { - bmsdata->min_voltage.val = bmsdata->chip_data[c].voltage_reading[cell]; + if (bmsdata->chip_data[c].voltage[cell] < bmsdata->min_voltage.val) { + bmsdata->min_voltage.val = bmsdata->chip_data[c].voltage[cell]; bmsdata->min_voltage.chipIndex = c; bmsdata->min_voltage.cellNum = cell; } @@ -342,7 +329,7 @@ void calc_pack_voltage_stats() bmsdata->min_ocv.cellNum = cell; } - total_volt += bmsdata->chip_data[c].voltage_reading[cell]; + total_volt += bmsdata->chip_data[c].voltage[cell]; total_ocv += bmsdata->chip_data[c].open_cell_voltage[cell]; } } @@ -382,7 +369,7 @@ void calc_cell_resistances() void calc_dcl() { - nertimer_t dcl_timer; + static nertimer_t dcl_timer; int16_t current_limit = 0x7FFF; @@ -411,6 +398,7 @@ void calc_dcl() bmsdata->discharge_limit = 0; } + /* State machine to prevent DCL from plummeting, copy over last DCL for 500ms */ else if (!is_timer_active(&dcl_timer) && current_limit < 5) { if (prevbmsdata == NULL) { bmsdata->discharge_limit = current_limit; @@ -501,6 +489,10 @@ void calc_cont_ccl() } else { bmsdata->cont_CCL = TEMP_TO_CCL[max_res_index]; } + + if (bmsdata->cont_CCL > MAX_CHG_CELL_CURR){ + bmsdata->cont_CCL = MAX_CHG_CELL_CURR; + } } void calc_open_cell_voltage() @@ -510,7 +502,7 @@ void calc_open_cell_voltage() for (uint8_t chip = 0; chip < NUM_CHIPS; chip++) { for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { bmsdata->chip_data[chip].open_cell_voltage[cell] - = bmsdata->chip_data[chip].voltage_reading[cell]; + = bmsdata->chip_data[chip].voltage[cell]; } } return; @@ -523,12 +515,12 @@ void calc_open_cell_voltage() for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { /* Sets open cell voltage to a moving average of OCV_AVG values */ bmsdata->chip_data[chip].open_cell_voltage[cell] - = ((uint32_t)(bmsdata->chip_data[chip].voltage_reading[cell]) + = ((uint32_t)(bmsdata->chip_data[chip].voltage[cell]) + ((uint32_t)(prevbmsdata->chip_data[chip].open_cell_voltage[cell]) * (OCV_AVG - 1))) / OCV_AVG; bmsdata->chip_data[chip].open_cell_voltage[cell] - = bmsdata->chip_data[chip].voltage_reading[cell]; + = bmsdata->chip_data[chip].voltage[cell]; if (bmsdata->chip_data[chip].open_cell_voltage[cell] > MAX_VOLT * 10000) { bmsdata->chip_data[chip].open_cell_voltage[cell] @@ -578,7 +570,7 @@ void analyzer_push(acc_data_t* data) prevbmsdata = bmsdata; bmsdata = data; - //disable_therms(); + disable_therms(); //high_curr_therm_check(); /* = prev if curr > 50 */ // diff_curr_therm_check(); /* = prev if curr - prevcurr > 10 */ @@ -593,25 +585,30 @@ void analyzer_push(acc_data_t* data) calc_cell_resistances(); calc_dcl(); calc_cont_dcl(); + //calcCCL(); calc_cont_ccl(); calc_state_of_charge(); + calc_noise_volt_percent(); + + data->charge_limit = data->cont_CCL; is_first_reading_ = false; } void disable_therms() { - int8_t temp_rep_1 = 25; /* Iniitalize to room temp (necessary to stabilize when the BMS first - boots up/has null values) */ - // if (!is_first_reading_) temp_rep_1 = prevbmsdata->avg_temp; /* Set to actual average temp of - // the pack */ + int8_t tmp_temp = 25; /* Iniitalize to room temp (necessary to stabilize when the BMS first boots up/has null values) */ + if (!is_first_reading_) tmp_temp = prevbmsdata->avg_temp; /* Set to actual average temp of the pack */ for (uint8_t c = 0; c < NUM_CHIPS; c++) { for (uint8_t therm = 0; therm < NUM_THERMS_PER_CHIP; therm++) { /* If 2D LUT shows therm should be disable */ if (THERM_DISABLE[c][therm]) { /* Nullify thermistor by setting to pack average */ - bmsdata->chip_data[c].thermistor_value[therm] = temp_rep_1; + bmsdata->chip_data[c].thermistor_value[therm] = tmp_temp; + } + else { + bmsdata->chip_data[c].thermistor_value[therm] = bmsdata->chip_data[c].thermistor_reading[therm]; } } } @@ -641,6 +638,26 @@ void calc_state_of_charge() } } +void calc_noise_volt_percent() +{ + int i = 0; + for (uint8_t seg = 0; seg < NUM_SEGMENTS; seg++) { + uint8_t count = 0; + /* merge results from each of the two chips ona given segment */ + for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { + count = bmsdata->chip_data[seg + i].noise_reading[cell]; + count += bmsdata->chip_data[seg + i + 1].noise_reading[cell]; + } + i++; + + /* turn into percentage */ + //printf("count: %d\r\n", count); + bmsdata->segment_noise_percentage[seg] = (uint8_t)(100 * (count) / (NUM_CELLS_PER_CHIP * 2.0f)); + + } +} + + void high_curr_therm_check() { if (prevbmsdata == NULL) diff --git a/Core/Src/compute.c b/Core/Src/compute.c index 93ad18e..9511632 100644 --- a/Core/Src/compute.c +++ b/Core/Src/compute.c @@ -264,11 +264,11 @@ void compute_send_mc_charge_message(acc_data_t* bmsdata) { struct __attribute__((__packed__)){ - uint16_t max_charge; + int16_t max_charge; } charge_data; /* scale to A * 10 */ - charge_data.max_charge = 10 * bmsdata->charge_limit; + charge_data.max_charge = -10 * bmsdata->charge_limit; /* convert to big endian */ endian_swap(&charge_data.max_charge, sizeof(charge_data.max_charge)); @@ -447,12 +447,12 @@ void compute_send_current_message(acc_data_t* bmsdata) { struct __attribute__((__packed__)){ uint16_t dcl; - uint16_t ccl; + int16_t ccl; uint16_t pack_curr; } current_status_msg_data; current_status_msg_data.dcl = bmsdata->discharge_limit; - current_status_msg_data.ccl = bmsdata->charge_limit; + current_status_msg_data.ccl = -1 * bmsdata->charge_limit; current_status_msg_data.pack_curr = bmsdata->pack_current; /* convert to big endian */ @@ -516,15 +516,17 @@ void compute_send_segment_temp_message(acc_data_t* bmsdata) int8_t segment2_average_temp; int8_t segment3_average_temp; int8_t segment4_average_temp; + int8_t segment5_average_temp; + int8_t segment6_average_temp; + } segment_temp_msg_data; segment_temp_msg_data.segment1_average_temp = bmsdata->segment_average_temps[0]; segment_temp_msg_data.segment2_average_temp = bmsdata->segment_average_temps[1]; segment_temp_msg_data.segment3_average_temp = bmsdata->segment_average_temps[2]; segment_temp_msg_data.segment4_average_temp = bmsdata->segment_average_temps[3]; - - uint8_t buff[4] = { 0 }; - memcpy(buff, &segment_temp_msg_data, sizeof(segment_temp_msg_data)); + segment_temp_msg_data.segment5_average_temp = bmsdata->segment_average_temps[4]; + segment_temp_msg_data.segment6_average_temp = bmsdata->segment_average_temps[5]; can_msg_t acc_msg; acc_msg.id = 0x85; @@ -539,7 +541,66 @@ void compute_send_segment_temp_message(acc_data_t* bmsdata) can_send_msg(line, &acc_msg); } +void compute_send_fault_message(uint8_t status, int16_t curr, int16_t in_dcl) +{ + struct __attribute__((__packed__)){ + uint8_t status; + int16_t pack_curr; + int16_t dcl; + } fault_msg_data; + + fault_msg_data.status = status; + fault_msg_data.pack_curr = curr; + fault_msg_data.dcl = in_dcl; + + endian_swap(&fault_msg_data.pack_curr, sizeof(fault_msg_data.pack_curr)); + endian_swap(&fault_msg_data.dcl, sizeof(fault_msg_data.dcl)); + + can_msg_t acc_msg; + acc_msg.id = 0x703; + acc_msg.len = 5; + memcpy(acc_msg.data, &fault_msg_data, sizeof(fault_msg_data)); + #ifdef CHARGING_ENABLED + can_t* line = &can2; + #else + can_t* line = &can1; + #endif + + can_send_msg(line, &acc_msg); +} + +void compute_send_voltage_noise_message(acc_data_t* bmsdata) +{ + struct __attribute__((__packed__)){ + uint8_t seg1_noise; + uint8_t seg2_noise; + uint8_t seg3_noise; + uint8_t seg4_noise; + uint8_t seg5_noise; + uint8_t seg6_noise; + } voltage_noise_msg_data; + + voltage_noise_msg_data.seg1_noise = bmsdata->segment_noise_percentage[0]; + voltage_noise_msg_data.seg2_noise = bmsdata->segment_noise_percentage[1]; + voltage_noise_msg_data.seg3_noise = bmsdata->segment_noise_percentage[2]; + voltage_noise_msg_data.seg4_noise = bmsdata->segment_noise_percentage[3]; + voltage_noise_msg_data.seg5_noise = bmsdata->segment_noise_percentage[4]; + voltage_noise_msg_data.seg6_noise = bmsdata->segment_noise_percentage[5]; + + can_msg_t acc_msg; + acc_msg.id = 0x88; + acc_msg.len = sizeof(voltage_noise_msg_data); + memcpy(acc_msg.data, &voltage_noise_msg_data, sizeof(voltage_noise_msg_data)); + + #ifdef CHARGING_ENABLED + can_t* line = &can2; + #else + can_t* line = &can1; + #endif + + can_send_msg(line, &acc_msg); +} void change_adc1_channel(uint8_t channel) { diff --git a/Core/Src/main.c b/Core/Src/main.c index 43525ce..97fa2b7 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -148,12 +148,21 @@ const void print_bms_stats(acc_data_t *acc_data) else if (current_state == 1) printf("READY\r\n"); else if (current_state == 2) printf("CHARGING\r\n"); else if (current_state == 3) printf("FAULTED: %X\r\n", acc_data->fault_code); + + printf("Voltage Noise Percent:\r\n"); + printf("Seg 1: %d\r\n", acc_data->segment_noise_percentage[0]); + printf("Seg 2: %d\r\n", acc_data->segment_noise_percentage[1]); + printf("Seg 3: %d\r\n", acc_data->segment_noise_percentage[2]); + printf("Seg 4: %d\r\n", acc_data->segment_noise_percentage[3]); + printf("Seg 5: %d\r\n", acc_data->segment_noise_percentage[4]); + printf("Seg 6: %d\r\n", acc_data->segment_noise_percentage[5]); + printf("Raw Cell Voltage:\r\n"); for(uint8_t c = 0; c < NUM_CHIPS; c++) { for(uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { - printf("%d\t", acc_data->chip_data[c].voltage_reading[cell]); + printf("%d\t", acc_data->chip_data[c].voltage[cell]); } printf("\r\n"); } @@ -168,22 +177,21 @@ const void print_bms_stats(acc_data_t *acc_data) printf("\r\n"); } - printf("Filtered Cell Temps:\r\n"); + printf("Thermistors with Disabling:\r\n"); for(uint8_t c = 0; c < NUM_CHIPS; c++) { - printf("Chip %d: ", c); + printf("Chip %d: ", c); - for (uint8_t cell = 0; cell < NUM_THERMS_PER_CHIP; cell++) { + for (uint8_t cell = 0; cell < NUM_THERMS_PER_CHIP; cell++) { - if (THERM_DISABLE[c][cell]) continue; + //if (THERM_DISABLE[c][cell]) continue; printf("%d ", acc_data->chip_data[c].thermistor_value[cell]); } printf("\r\n"); - } + } - - printf("UnFiltered Cell Temps:\r\n"); + printf("UnFiltered Thermistor Temps:\r\n"); for(uint8_t c = 0; c < NUM_CHIPS; c++) { printf("Chip %d: ", c); @@ -196,6 +204,19 @@ const void print_bms_stats(acc_data_t *acc_data) printf("\r\n"); } + printf("Cell Temps:\r\n"); + for(uint8_t c = 0; c < NUM_CHIPS; c++) + { + printf("Chip %d: ", c); + + for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { + + printf("%d ", acc_data->chip_data[c].cell_temp[cell]); + } + + printf("\r\n"); + } + start_timer(&debug_stat_timer, PRINT_STAT_WAIT); } @@ -226,7 +247,7 @@ int main(void) SystemClock_Config(); /* USER CODE BEGIN SysInit */ - + HAL_Delay(500); /* USER CODE END SysInit */ /* Initialize all configured peripherals */ @@ -259,10 +280,10 @@ int main(void) //} + HAL_Delay(500); //watchdog_init(); segment_init(); compute_init(); - /* USER CODE END 2 */ @@ -275,7 +296,7 @@ int main(void) acc_data_t *acc_data = malloc(sizeof(acc_data_t)); acc_data->is_charger_connected = false; - //acc_data->faultCode = FAULTS_CLEAR; + acc_data->fault_code = FAULTS_CLEAR; /* * Collect all the segment data needed to perform analysis @@ -292,7 +313,7 @@ int main(void) //get_can2_msg(); #ifdef DEBUG_STATS - //print_bms_stats(acc_data); + print_bms_stats(acc_data); #endif HAL_IWDG_Refresh(&hiwdg); diff --git a/Core/Src/segment.c b/Core/Src/segment.c index f54e52b..8ccebbd 100644 --- a/Core/Src/segment.c +++ b/Core/Src/segment.c @@ -9,7 +9,7 @@ #define VOLTAGE_WAIT_TIME 100 /* ms */ #define THERM_AVG 15 /* Number of values to average */ #define MAX_VOLT_DELTA 2500 -#define MAX_VOLT_DELTA_COUNT 10 +#define MAX_CONSEC_NOISE 10 #define GPIO_EXPANDER_ADDR 0x40 #define GPIO_REGISTER_ADDR 0x09 @@ -126,13 +126,13 @@ int pull_voltages() //int test_v[12] = {800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800}; if (!is_timer_expired(&voltage_reading_timer) && voltage_reading_timer.active) { for (uint8_t i = 0; i < NUM_CHIPS; i++) { - memcpy(segment_data[i].voltage_reading, previous_data[i].voltage_reading, - sizeof(segment_data[i].voltage_reading)); + memcpy(segment_data[i].voltage, previous_data[i].voltage, + sizeof(segment_data[i].voltage)); } return voltage_error; } - uint16_t segment_voltages[NUM_CHIPS][12]; + uint16_t raw_voltages[NUM_CHIPS][12]; push_chip_configuration(); LTC6804_adcv(ltc68041); @@ -141,10 +141,10 @@ int pull_voltages() * If we received an incorrect PEC indicating a bad read * copy over the data from the last good read and indicate an error */ - if (LTC6804_rdcv(ltc68041, 0, NUM_CHIPS, segment_voltages) == -1) { + if (LTC6804_rdcv(ltc68041, 0, NUM_CHIPS, raw_voltages) == -1) { for (uint8_t i = 0; i < NUM_CHIPS; i++) { - memcpy(segment_data[i].voltage_reading, previous_data[i].voltage_reading, - sizeof(segment_data[i].voltage_reading)); + memcpy(segment_data[i].voltage, previous_data[i].voltage, + sizeof(segment_data[i].voltage)); printf("Bad voltage read\n"); } @@ -164,24 +164,38 @@ int pull_voltages() /* cell 6 on every chip is not a real reading, we need to have the array skip this, and shift the remaining readings up one index*/ if (j == 5) continue; - if (NULL/*abs(segment_voltages[i][dest_index] - previous_data[i].voltage_reading[dest_index]) - > MAX_VOLT_DELTA*/) { - segment_data[corrected_index].voltage_reading[dest_index] = previous_data[i].voltage_reading[dest_index]; - segment_data[corrected_index].bad_volt_diff_count[dest_index]++; - - if (segment_data[corrected_index].bad_volt_diff_count[dest_index] > MAX_VOLT_DELTA_COUNT) { - segment_data[corrected_index].bad_volt_diff_count[dest_index] = 0; - segment_data[corrected_index].voltage_reading[dest_index] = segment_voltages[corrected_index][j]; - } + segment_data[corrected_index].noise_reading[dest_index] = 0; + + if (raw_voltages[i][j] > (int)(10000 * (MAX_VOLT + 0.5)) || raw_voltages[i][j] < (int)(10000 * (MIN_VOLT - 0.5))) { + //if (previous_data[corrected_index].voltage[dest_index] > 45000 || previous_data[corrected_index].voltage[dest_index] < 20000) printf("poop\r\n"); + segment_data[corrected_index].voltage[dest_index] = previous_data[corrected_index].voltage[dest_index]; + segment_data[corrected_index].noise_reading[dest_index] = 1; + segment_data[corrected_index].consecutive_noise[dest_index]++; + //printf("New data: %d\r\n", segment_data[corrected_index].voltage[dest_index]); + // if (segment_data[corrected_index].consecutive_noise[dest_index] > MAX_CONSEC_NOISE) { + // segment_data[corrected_index].noise_reading[dest_index] = 0; + // segment_data[corrected_index].consecutive_noise[dest_index] = 0; + // segment_data[corrected_index].voltage[dest_index] = raw_voltages[i][j]; + // } } else { - segment_data[corrected_index].bad_volt_diff_count[dest_index] = 0; - segment_data[corrected_index].voltage_reading[dest_index] = segment_voltages[corrected_index][j]; + //printf("previous: %d\r\n", previous_data[corrected_index].voltage[dest_index]); + //if (previous_data[corrected_index].voltage[dest_index] > 45000 || previous_data[corrected_index].voltage[dest_index] < 20000) printf("pee\r\n"); + //else printf("wiping\r\n"); + segment_data[corrected_index].consecutive_noise[dest_index] = 0; + segment_data[corrected_index].voltage[dest_index] = raw_voltages[i][j]; + + if (raw_voltages[i][j] < 45000 && raw_voltages[i][j] > 24000) { + previous_data[corrected_index].voltage[dest_index] = raw_voltages[i][j]; + //printf("previous: %d\r\n", previous_data[corrected_index].voltage[dest_index]); + //printf("raw: %d\r\n", segment_data[corrected_index].voltage[dest_index]); + } + } dest_index++; } } - + /* Start the timer between readings if successful */ start_timer(&voltage_reading_timer, VOLTAGE_WAIT_TIME); @@ -203,29 +217,21 @@ int pull_thermistors() uint16_t raw_temp_voltages[NUM_CHIPS][6]; - /* Set GPIO expander to output */ - uint8_t i2c_write_data[NUM_CHIPS][3]; - for(int chip = 0; chip < NUM_CHIPS; chip++) { - i2c_write_data[chip][0] = 0x40; // GPIO expander addr - i2c_write_data[chip][1] = 0x00; // GPIO direction addr - i2c_write_data[chip][2] = 0x00; // Set all to output + static uint8_t current_therm = 1; + if (current_therm > 16) { + current_therm = 1; } - uint8_t comm_reg_data[NUM_CHIPS][6]; - - serialize_i2c_msg(i2c_write_data, comm_reg_data); - LTC6804_wrcomm(ltc68041, NUM_CHIPS, comm_reg_data); - LTC6804_stcomm(ltc68041, 24); + /* Sets multiplexors to select thermistors */ + select_therm(current_therm); + HAL_Delay(200); + //push_chip_configuration(); + LTC6804_clraux(ltc68041); + LTC6804_adax(ltc68041); /* Run ADC for AUX (GPIOs and refs) */ + HAL_Delay(3); + LTC6804_rdaux(ltc68041, 0, NUM_CHIPS, raw_temp_voltages); /* Rotate through all thermistor pairs (we can poll two at once) */ - for (int therm = 1; therm <= 16; therm++) { - /* Sets multiplexors to select thermistors */ - select_therm(therm); - //HAL_Delay(15); - push_chip_configuration(); - LTC6804_adax(ltc68041); /* Run ADC for AUX (GPIOs and refs) */ - HAL_Delay(3); - LTC6804_rdaux(ltc68041, 0, NUM_CHIPS, raw_temp_voltages); /* Fetch ADC results from AUX registers */ - + for (uint8_t therm = 1; therm <= (NUM_THERMS_PER_CHIP / 2); therm++) { for (uint8_t c = 0; c < NUM_CHIPS; c++) { int corrected_index = mapping_correction[c]; @@ -233,31 +239,46 @@ int pull_thermistors() * Get current temperature LUT. Voltage is adjusted to account for 5V reg * fluctuations (index 2 is a reading of the ADC 5V ref) */ - - /* see "thermister decoding" in confluence in shepherd software 22A */ - uint16_t steinhart_input_low = 10000 * (float)( ((float)raw_temp_voltages[c][2])/ (raw_temp_voltages[c][0]) - 1 ); - uint16_t steinhart_input_high = 10000 * (float)( ((float)raw_temp_voltages[c][2])/ (raw_temp_voltages[c][1]) - 1 ); - - segment_data[corrected_index].thermistor_reading[therm - 1] = steinhart_est(steinhart_input_low); - segment_data[corrected_index].thermistor_reading[therm + 15] = steinhart_est(steinhart_input_high); - - /* Directly update for a set time from start up due to therm voltages - * needing to settle */ - segment_data[corrected_index].thermistor_value[therm - 1] - = segment_data[corrected_index].thermistor_reading[therm - 1]; - segment_data[corrected_index].thermistor_value[therm + 15] - = segment_data[corrected_index].thermistor_reading[therm + 15]; - - if (raw_temp_voltages[c][0] == LTC_BAD_READ - || raw_temp_voltages[c][1] == LTC_BAD_READ) { - memcpy(segment_data[corrected_index].thermistor_reading, previous_data[c].thermistor_reading, - sizeof(segment_data[corrected_index].thermistor_reading)); - memcpy(segment_data[corrected_index].thermistor_value, previous_data[c].thermistor_value, - sizeof(segment_data[corrected_index].thermistor_value)); + if (therm == current_therm) { + /* see "thermister decoding" in confluence in shepherd software 22A */ + uint16_t steinhart_input_low = 10000 * (float)( ((float)raw_temp_voltages[c][2])/ (raw_temp_voltages[c][0]) - 1 ); + uint16_t steinhart_input_high = 10000 * (float)( ((float)raw_temp_voltages[c][2])/ (raw_temp_voltages[c][1]) - 1 ); + + segment_data[corrected_index].thermistor_reading[therm - 1] = steinhart_est(steinhart_input_low); + segment_data[corrected_index].thermistor_reading[therm + 15] = steinhart_est(steinhart_input_high); + + /* Directly update for a set time from start up due to therm voltages + * needing to settle */ + segment_data[corrected_index].thermistor_value[therm - 1] + = segment_data[corrected_index].thermistor_reading[therm - 1]; + segment_data[corrected_index].thermistor_value[therm + 15] + = segment_data[corrected_index].thermistor_reading[therm + 15]; + + if (raw_temp_voltages[c][0] == LTC_BAD_READ + || raw_temp_voltages[c][1] == LTC_BAD_READ + || segment_data[corrected_index].thermistor_value[therm - 1] > (MAX_CELL_TEMP + 5) + || segment_data[corrected_index].thermistor_value[therm + 15] > (MAX_CELL_TEMP + 5 ) + || segment_data[corrected_index].thermistor_value[therm - 1] < (MIN_CELL_TEMP - 5) + || segment_data[corrected_index].thermistor_value[therm + 15] < (MIN_CELL_TEMP - 5 )) { + memcpy(segment_data[corrected_index].thermistor_reading, previous_data[c].thermistor_reading, + sizeof(segment_data[corrected_index].thermistor_reading)); + memcpy(segment_data[corrected_index].thermistor_value, previous_data[c].thermistor_value, + sizeof(segment_data[corrected_index].thermistor_value)); + } + } + else { + segment_data[corrected_index].thermistor_reading[therm - 1] = previous_data[corrected_index].thermistor_reading[therm - 1]; + segment_data[corrected_index].thermistor_reading[therm + 15] = previous_data[corrected_index].thermistor_reading[therm + 15]; + + segment_data[corrected_index].thermistor_value[therm - 1] + = segment_data[corrected_index].thermistor_reading[therm - 1]; + segment_data[corrected_index].thermistor_value[therm + 15] + = segment_data[corrected_index].thermistor_reading[therm + 15]; } } } - start_timer(&therm_timer, THERM_WAIT_TIME); /* Start timer for next reading */ + current_therm++; + start_timer(&therm_timer, 100/*THERM_WAIT_TIME*/); /* Start timer for next reading */ /* the following algorithms were used to eliminate noise on Car 17D - keep them off if possible */ //variance_therm_check(); @@ -272,7 +293,7 @@ void segment_retrieve_data(chipdata_t databuf[NUM_CHIPS]) { segment_data = databuf; - /* Pull voltages and thermistors and indiacte if there was a problem during + /* Pull voltages and thermistors and indiacate if there was a problem during * retrieval */ voltage_error = pull_voltages(); therm_error = pull_thermistors(); @@ -574,4 +595,4 @@ void discard_neutrals() } } } -} \ No newline at end of file +} diff --git a/Core/Src/stateMachine.c b/Core/Src/stateMachine.c index bd823ec..49f1e0b 100644 --- a/Core/Src/stateMachine.c +++ b/Core/Src/stateMachine.c @@ -270,7 +270,9 @@ uint32_t sm_fault_return(acc_data_t* accData) else { fault_table[0].data_1 = fault_data->pack_current; + fault_table[0].lim_1 = (fault_data->discharge_limit + DCDC_CURRENT_DRAW)*10 * CURR_ERR_MARG; fault_table[1].data_1 = fault_data->pack_current; + fault_table[1].lim_1 = (fault_data->charge_limit)*10; fault_table[2].data_1 = fault_data->min_voltage.val; fault_table[3].data_1 = fault_data->max_voltage.val; fault_table[4].data_1 = fault_data->max_voltage.val; @@ -278,13 +280,15 @@ uint32_t sm_fault_return(acc_data_t* accData) fault_table[5].data_1 = fault_data->max_temp.val; fault_table[6].data_1 = fault_data->min_voltage.val; } + static uint32_t fault_status = 0; int incr = 0; while (fault_table[incr].id != NULL) { fault_status |= sm_fault_eval(&fault_table[incr]); incr++; } - + //TODO: Remove This !!!! + fault_status &= ~DISCHARGE_LIMIT_ENFORCEMENT_FAULT; return fault_status; } @@ -337,17 +341,24 @@ uint32_t sm_fault_eval(fault_eval_t* index) if (is_timer_expired(&index->timer) && fault_present) { printf("\t\t\t*******Faulted: %s\r\n", index->id); + compute_send_fault_message(2, index->data_1, index->lim_1); return index->code; } + else return 0; } else if (!is_timer_active(&index->timer) && fault_present) { + printf("\t\t\t*******Starting fault timer: %s\r\n", index->id); start_timer(&index->timer, index->timeout); + if (index->code == DISCHARGE_LIMIT_ENFORCEMENT_FAULT) { + compute_send_fault_message(1, index->data_1, index->lim_1); + } + return 0; } /* if (index->code == CELL_VOLTAGE_TOO_LOW) { @@ -464,7 +475,7 @@ void sm_balance_cells(acc_data_t* bms_data) * in voltages */ for (uint8_t chip = 0; chip < NUM_CHIPS; chip++) { for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { - uint16_t delta = bms_data->chip_data[chip].voltage_reading[cell] + uint16_t delta = bms_data->chip_data[chip].voltage[cell] - (uint16_t)bms_data->min_voltage.val; if (delta > MAX_DELTA_V * 10000) balanceConfig[chip][cell] = true; diff --git a/Drivers/Embedded-Base b/Drivers/Embedded-Base index 2c8a6b9..ff34106 160000 --- a/Drivers/Embedded-Base +++ b/Drivers/Embedded-Base @@ -1 +1 @@ -Subproject commit 2c8a6b973a3e9ccc02f892fd27dc5330e9524e27 +Subproject commit ff34106b18e296434fc817d7a9c66efc28c07abe