From 15d4c7c3c3cec95eadf168b1630f70dbe4d6c93d Mon Sep 17 00:00:00 2001 From: dyldonahue Date: Fri, 20 Sep 2024 12:20:42 -0400 Subject: [PATCH 1/5] done --- Core/Inc/stateMachine.h | 3 +++ Core/Src/compute.c | 26 ++++++++++++++++++++++++++ Core/Src/segment.c | 2 ++ Core/Src/stateMachine.c | 4 ++++ 4 files changed, 35 insertions(+) diff --git a/Core/Inc/stateMachine.h b/Core/Inc/stateMachine.h index d68e73e..987aa1a 100644 --- a/Core/Inc/stateMachine.h +++ b/Core/Inc/stateMachine.h @@ -10,6 +10,9 @@ /* global that can be read for debugging in main */ extern BMSState_t current_state; +/* global defined in segment.c that keeps an eye on the number of crc errors */ +extern uint16_t crc_error_check; + #define NUM_FAULTS 8 /** diff --git a/Core/Src/compute.c b/Core/Src/compute.c index 7ba5999..40e3030 100644 --- a/Core/Src/compute.c +++ b/Core/Src/compute.c @@ -666,6 +666,32 @@ void compute_send_voltage_noise_message(acc_data_t *bmsdata) can_send_msg(line, &acc_msg); } + +void compute_send_debug_message(uint8_t *data, uint8_t len) +{ + can_msg_t debug_msg; + debug_msg.id = 0x702; + debug_msg.len = len; + + if (len > 8) { + len = 8; + } + + if (len > 1) { + endian_swap(data, len); + } + + memcpy(debug_msg.data, data, len); + +#ifdef CHARGING_ENABLED + can_t *line = &can2; +#else + can_t *line = &can1; +#endif + + can_send_msg(line, &debug_msg); +} + void change_adc1_channel(uint8_t channel) { ADC_ChannelConfTypeDef sConfig = { 0 }; diff --git a/Core/Src/segment.c b/Core/Src/segment.c index 921edf7..728b44a 100644 --- a/Core/Src/segment.c +++ b/Core/Src/segment.c @@ -30,6 +30,7 @@ nertimer_t variance_timer; int voltage_error = 0; //not faulted int therm_error = 0; //not faulted +uint16_t crc_error_check = 0; /* our segments are mapped backwards and in pairs, so they are read in 1,0 then 3,2, etc*/ const int mapping_correction[12] = { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10 }; @@ -162,6 +163,7 @@ int pull_voltages() previous_data[i].voltage, sizeof(segment_data[i].voltage)); + crc_error_check++; printf("Bad voltage read\n"); } return 1; diff --git a/Core/Src/stateMachine.c b/Core/Src/stateMachine.c index 45ae75f..312b5da 100644 --- a/Core/Src/stateMachine.c +++ b/Core/Src/stateMachine.c @@ -177,6 +177,7 @@ void sm_handle_state(acc_data_t *bmsdata) SEGMENT_TEMP, MC_DISCHARGE, MC_CHARGE, + CAN_DEBUG, MAX_MSGS }; @@ -224,6 +225,9 @@ void sm_handle_state(acc_data_t *bmsdata) case MC_CHARGE: compute_send_mc_charge_message(bmsdata); break; + + case CAN_DEBUG: + compute_send_debug_message(&crc_error_check, 2); default: break; From 344f283a3c3594da4db96ca63056c881e5306001 Mon Sep 17 00:00:00 2001 From: dyldonahue Date: Fri, 20 Sep 2024 12:26:13 -0400 Subject: [PATCH 2/5] clang --- Core/Inc/stateMachine.h | 70 +-- Core/Src/compute.c | 1080 ++++++++++++++++++------------------ Core/Src/segment.c | 1168 ++++++++++++++++++--------------------- Core/Src/stateMachine.c | 785 +++++++++++++------------- 4 files changed, 1474 insertions(+), 1629 deletions(-) diff --git a/Core/Inc/stateMachine.h b/Core/Inc/stateMachine.h index 987aa1a..9e20cda 100644 --- a/Core/Inc/stateMachine.h +++ b/Core/Inc/stateMachine.h @@ -1,10 +1,10 @@ #ifndef BMS_STATES_H #define BMS_STATES_H +#include "analyzer.h" +#include "compute.h" #include "datastructs.h" #include "segment.h" -#include "compute.h" -#include "analyzer.h" #include "timer.h" /* global that can be read for debugging in main */ @@ -16,62 +16,64 @@ extern uint16_t crc_error_check; #define NUM_FAULTS 8 /** -* @brief Returns if we want to balance cells during a particular frame -* -* @param bmsdata -* @return true -* @return false -*/ + * @brief Returns if we want to balance cells during a particular frame + * + * @param bmsdata + * @return true + * @return false + */ bool sm_balancing_check(acc_data_t *bmsdata); /** -* @brief Returns if we want to charge cells during a particular frame -* -* @param bmsdata -* @return true -* @return false -*/ + * @brief Returns if we want to charge cells during a particular frame + * + * @param bmsdata + * @return true + * @return false + */ bool sm_charging_check(acc_data_t *bmsdata); /** -* @brief Returns any new faults or current faults that have come up -* @note Should be bitwise OR'ed with the current fault status -* -* @param accData -* @return uint32_t -*/ + * @brief Returns any new faults or current faults that have come up + * @note Should be bitwise OR'ed with the current fault status + * + * @param accData + * @return uint32_t + */ uint32_t sm_fault_return(acc_data_t *accData); /** - * @brief Used in parellel to faultReturn(), calculates each fault to append the fault status - * + * @brief Used in parellel to faultReturn(), calculates each fault to append the + * fault status + * * @param index * @return fault_code */ uint32_t sm_fault_eval(fault_eval_t *index); /** - * @brief handles the state machine, calls the appropriate handler function and runs every loop functions - * - * @param bmsdata + * @brief handles the state machine, calls the appropriate handler function and + * runs every loop functions + * + * @param bmsdata */ void sm_handle_state(acc_data_t *bmsdata); /** -* @brief Algorithm behind determining which cells we want to balance -* @note Directly interfaces with the segments -* -* @param bms_data -*/ + * @brief Algorithm behind determining which cells we want to balance + * @note Directly interfaces with the segments + * + * @param bms_data + */ void sm_balance_cells(acc_data_t *bms_data); void sm_broadcast_current_limit(acc_data_t *bmsdata); /** * @brief algorithm to calculate and set fan speed based on temperature - * - * @param bmsdata * -*/ + * @param bmsdata + * + */ void calculate_pwm(acc_data_t *bmsdata); -#endif //BMS_STATES_H \ No newline at end of file +#endif // BMS_STATES_H \ No newline at end of file diff --git a/Core/Src/compute.c b/Core/Src/compute.c index 40e3030..a6b0cd8 100644 --- a/Core/Src/compute.c +++ b/Core/Src/compute.c @@ -1,20 +1,20 @@ #include "compute.h" -#include "can_handler.h" -#include "can.h" #include "c_utils.h" +#include "can.h" +#include "can_handler.h" #include "main.h" -#include #include "stm32f405xx.h" -#include +#include #include +#include #define MAX_CAN1_STORAGE 10 #define MAX_CAN2_STORAGE 10 -#define REF_CHANNEL 0 +#define REF_CHANNEL 0 #define VOUT_CHANNEL 1 -//#define CHARGING_ENABLED +// #define CHARGING_ENABLED uint8_t fan_speed; bool is_charging_enabled; @@ -32,678 +32,644 @@ extern ADC_HandleTypeDef hadc2; TIM_OC_InitTypeDef pwm_config; ADC_ChannelConfTypeDef adc_config; -const uint32_t fan_channels[6] = { TIM_CHANNEL_3, TIM_CHANNEL_1, TIM_CHANNEL_4, - TIM_CHANNEL_3, TIM_CHANNEL_2, TIM_CHANNEL_1 }; +const uint32_t fan_channels[6] = {TIM_CHANNEL_3, TIM_CHANNEL_1, TIM_CHANNEL_4, + TIM_CHANNEL_3, TIM_CHANNEL_2, TIM_CHANNEL_1}; can_t can1; // main can bus, used by most peripherals can_t can2; // p2p can bus with charger -uint32_t adc_values[2] = { 0 }; +uint32_t adc_values[2] = {0}; /* private function defintions */ float read_ref_voltage(); float read_vout(); -uint8_t compute_init() -{ - // TODO throw all of these objects into a compute struct - can1.hcan = &hcan1; - can1.id_list = can1_id_list; - can1.id_list_len = sizeof(can1_id_list) / sizeof(can1_id_list[0]); - //can1.callback = can_receive_callback; - can1_rx_queue = ringbuffer_create(MAX_CAN1_STORAGE, sizeof(can_msg_t)); - can_init(&can1); - - can2.hcan = &hcan2; - can2.id_list = can2_id_list; - can2.id_list_len = sizeof(can2_id_list) / sizeof(can2_id_list[0]); - //can2.callback = can_receive_callback; - can2_rx_queue = ringbuffer_create(MAX_CAN2_STORAGE, sizeof(can_msg_t)); - can_init(&can2); - - pwm_config.OCMode = TIM_OCMODE_PWM1; - pwm_config.Pulse = 0; - pwm_config.OCPolarity = TIM_OCPOLARITY_HIGH; - pwm_config.OCFastMode = TIM_OCFAST_DISABLE; - - if (HAL_TIM_PWM_ConfigChannel(&htim1, &pwm_config, - fan_channels[FAN1]) != HAL_OK) - return -1; - if (HAL_TIM_PWM_ConfigChannel(&htim8, &pwm_config, - fan_channels[FAN2]) != HAL_OK) - return -1; - - // HAL_TIM_PWM_Start(&htim1, fan_channels[FAN1]); - // HAL_TIM_PWM_Start(&htim1, fan_channels[FAN2]); - // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN3]); - // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN4]); - // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN5]); - // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN6]); - bmsdata->is_charger_connected = false; - - HAL_ADC_Start(&hadc2); - - return 0; +uint8_t compute_init() { + // TODO throw all of these objects into a compute struct + can1.hcan = &hcan1; + can1.id_list = can1_id_list; + can1.id_list_len = sizeof(can1_id_list) / sizeof(can1_id_list[0]); + // can1.callback = can_receive_callback; + can1_rx_queue = ringbuffer_create(MAX_CAN1_STORAGE, sizeof(can_msg_t)); + can_init(&can1); + + can2.hcan = &hcan2; + can2.id_list = can2_id_list; + can2.id_list_len = sizeof(can2_id_list) / sizeof(can2_id_list[0]); + // can2.callback = can_receive_callback; + can2_rx_queue = ringbuffer_create(MAX_CAN2_STORAGE, sizeof(can_msg_t)); + can_init(&can2); + + pwm_config.OCMode = TIM_OCMODE_PWM1; + pwm_config.Pulse = 0; + pwm_config.OCPolarity = TIM_OCPOLARITY_HIGH; + pwm_config.OCFastMode = TIM_OCFAST_DISABLE; + + if (HAL_TIM_PWM_ConfigChannel(&htim1, &pwm_config, fan_channels[FAN1]) != + HAL_OK) + return -1; + if (HAL_TIM_PWM_ConfigChannel(&htim8, &pwm_config, fan_channels[FAN2]) != + HAL_OK) + return -1; + + // HAL_TIM_PWM_Start(&htim1, fan_channels[FAN1]); + // HAL_TIM_PWM_Start(&htim1, fan_channels[FAN2]); + // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN3]); + // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN4]); + // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN5]); + // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN6]); + bmsdata->is_charger_connected = false; + + HAL_ADC_Start(&hadc2); + + return 0; } -void compute_enable_charging(bool enable_charging) -{ - is_charging_enabled = enable_charging; +void compute_enable_charging(bool enable_charging) { + is_charging_enabled = enable_charging; } int compute_send_charging_message(uint16_t voltage_to_set, - uint16_t current_to_set, acc_data_t *bms_data) -{ - struct __attribute__((__packed__)) { - uint16_t charger_voltage; // Note the charger voltage sent over should be 10*desired voltage - uint16_t charger_current; // Note the charge current sent over should be 10*desired current - uint8_t charger_control; - uint8_t reserved_1; - uint16_t reserved_23; - } charger_msg_data; - - charger_msg_data.charger_voltage = voltage_to_set * 10; - charger_msg_data.charger_current = current_to_set * 10; - - if (is_charging_enabled) { - charger_msg_data.charger_control = 0x00; //0:Start charging. - } else { - charger_msg_data.charger_control = - 0xFF; // 1:battery protection, stop charging - } - - charger_msg_data.reserved_1 = 0x00; - charger_msg_data.reserved_23 = 0x0000; - - can_msg_t charger_msg; - charger_msg.id = 0x1806E5F4; - charger_msg.len = 8; - memcpy(charger_msg.data, &charger_msg_data, sizeof(charger_msg_data)); - - uint8_t temp = charger_msg.data[0]; - charger_msg.data[0] = charger_msg.data[1]; - charger_msg.data[1] = temp; - temp = charger_msg.data[2]; - charger_msg.data[2] = charger_msg.data[3]; - charger_msg.data[3] = temp; + uint16_t current_to_set, + acc_data_t *bms_data) { + struct __attribute__((__packed__)) { + uint16_t charger_voltage; // Note the charger voltage sent over should be + // 10*desired voltage + uint16_t charger_current; // Note the charge current sent over should be + // 10*desired current + uint8_t charger_control; + uint8_t reserved_1; + uint16_t reserved_23; + } charger_msg_data; + + charger_msg_data.charger_voltage = voltage_to_set * 10; + charger_msg_data.charger_current = current_to_set * 10; + + if (is_charging_enabled) { + charger_msg_data.charger_control = 0x00; // 0:Start charging. + } else { + charger_msg_data.charger_control = + 0xFF; // 1:battery protection, stop charging + } + + charger_msg_data.reserved_1 = 0x00; + charger_msg_data.reserved_23 = 0x0000; + + can_msg_t charger_msg; + charger_msg.id = 0x1806E5F4; + charger_msg.len = 8; + memcpy(charger_msg.data, &charger_msg_data, sizeof(charger_msg_data)); + + uint8_t temp = charger_msg.data[0]; + charger_msg.data[0] = charger_msg.data[1]; + charger_msg.data[1] = temp; + temp = charger_msg.data[2]; + charger_msg.data[2] = charger_msg.data[3]; + charger_msg.data[3] = temp; #ifdef CHARGING_ENABLED - HAL_StatusTypeDef res = can_send_extended_msg(&can2, &charger_msg); - if (res != HAL_OK) { - printf("CAN ERROR CODE %X", res); - } + HAL_StatusTypeDef res = can_send_extended_msg(&can2, &charger_msg); + if (res != HAL_OK) { + printf("CAN ERROR CODE %X", res); + } #endif - return 0; + return 0; } -bool compute_charger_connected() -{ - //TODO need to set up CAN msg that actually toggles this bool - return false; //bmsdata->is_charger_connected; +bool compute_charger_connected() { + // TODO need to set up CAN msg that actually toggles this bool + return false; // bmsdata->is_charger_connected; } -//TODO add this back -// void compute_charger_callback(const CAN_message_t& msg) -// { -// return; -// } +// TODO add this back +// void compute_charger_callback(const CAN_message_t& msg) +// { +// return; +// } uint8_t compute_set_fan_speed(TIM_HandleTypeDef *pwmhandle, - fan_select_t fan_select, uint8_t duty_cycle) -{ - if (!pwmhandle) - return -1; - if (fan_select >= FANMAX) - return -1; - if (duty_cycle > 100) - return -1; - - uint32_t CCR_value = 0; - uint32_t channel = fan_channels[fan_select]; - - CCR_value = (pwmhandle->Instance->ARR * duty_cycle) / 100; - __HAL_TIM_SET_COMPARE(pwmhandle, channel, CCR_value); - - return 0; + fan_select_t fan_select, uint8_t duty_cycle) { + if (!pwmhandle) + return -1; + if (fan_select >= FANMAX) + return -1; + if (duty_cycle > 100) + return -1; + + uint32_t CCR_value = 0; + uint32_t channel = fan_channels[fan_select]; + + CCR_value = (pwmhandle->Instance->ARR * duty_cycle) / 100; + __HAL_TIM_SET_COMPARE(pwmhandle, channel, CCR_value); + + return 0; } -void compute_set_fault(int fault_state) -{ - //TODO work with charger fw on this - HAL_GPIO_WritePin(GPIOA, Fault_Output_Pin, !fault_state); - //if (true) digitalWrite(CHARGE_SAFETY_RELAY, 1); +void compute_set_fault(int fault_state) { + // TODO work with charger fw on this + HAL_GPIO_WritePin(GPIOA, Fault_Output_Pin, !fault_state); + // if (true) digitalWrite(CHARGE_SAFETY_RELAY, 1); } -int16_t compute_get_pack_current() -{ - // static const float GAIN = 5.00; // mV/A - // static const float OFFSET = 0.0; // mV - // static const uint8_t num_samples = 10; - // static int16_t current_accumulator = 0.0; // A - - // /* starting equation : Vout = Vref + Voffset + (Gain * Ip) */ - // float ref_voltage = read_ref_voltage(); - // float vout = read_vout(); - - // ref_voltage *= 1000;// convert to mV - // vout *= 1000; - - // int16_t current = (vout - ref_voltage - OFFSET) / (GAIN); // convert to V - - // /* Low Pass Filter of Current*/ - // current = ((current_accumulator * (num_samples - 1)) + current) / num_samples; - // current_accumulator = current; - - // return current; - - static const float CURRENT_LOWCHANNEL_MAX = 75.0; //Amps - static const float CURRENT_LOWCHANNEL_MIN = -75.0; //Amps - // static const float CURRENT_SUPPLY_VOLTAGE = 5.038; - static const float CURRENT_ADC_RESOLUTION = 5.0 / MAX_ADC_RESOLUTION; - - static const float CURRENT_LOWCHANNEL_OFFSET = - 2.500; // Calibrated with current = 0A - static const float CURRENT_HIGHCHANNEL_OFFSET = - 2.500; // Calibrated with current = 0A - - static const float HIGHCHANNEL_GAIN = - 1 / 0.0041; // Calibrated with current = 5A, 10A, 20A - static const float LOWCHANNEL_GAIN = 1 / 0.0267; - - // Change ADC channel to read the high current sensor - change_adc1_channel(VOUT_CHANNEL); - HAL_ADC_Start(&hadc1); - HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); - int raw_low_current = HAL_ADC_GetValue(&hadc1); - - HAL_ADC_Start(&hadc2); - HAL_ADC_PollForConversion(&hadc2, HAL_MAX_DELAY); - int raw_high_current = HAL_ADC_GetValue(&hadc2); - - change_adc1_channel(REF_CHANNEL); - HAL_ADC_Start(&hadc1); - HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); - int ref_5V = HAL_ADC_GetValue(&hadc1); - - int16_t ref_voltage_raw = - (int16_t)(1000.0f * ((float)ref_5V * CURRENT_ADC_RESOLUTION)); - - int16_t high_current_voltage_raw = - (int16_t)(1000.0f * - ((float)raw_high_current * CURRENT_ADC_RESOLUTION)); - high_current_voltage_raw = - (int16_t)(5000.0f * high_current_voltage_raw / - (float)ref_voltage_raw); - - int16_t high_current = (high_current_voltage_raw - - (1000 * CURRENT_HIGHCHANNEL_OFFSET)) * - (1 / 4.0f); //* (HIGHCHANNEL_GAIN/100.0f))/1000; - - int16_t low_current_voltage_raw = - (int16_t)(1000.0f * - ((float)raw_low_current * CURRENT_ADC_RESOLUTION)); - low_current_voltage_raw = (int16_t)(5000.0f * low_current_voltage_raw / - (float)ref_voltage_raw); - - int16_t low_current = (float)(low_current_voltage_raw - - (1000 * CURRENT_LOWCHANNEL_OFFSET)) * - (1 / 26.7); //* (LOWCHANNEL_GAIN/100.0f))/1000; - - // If the current is scoped within the range of the low channel, use the low channel - - if ((low_current < CURRENT_LOWCHANNEL_MAX - 5.0 && low_current >= 0) || - (low_current > CURRENT_LOWCHANNEL_MIN + 5.0 && low_current < 0)) { - //printf("\rLow Current: %d\n", -low_current); - return -low_current; - } - - //printf("\rHigh Current: %d\n", -high_current); - return -high_current; +int16_t compute_get_pack_current() { + // static const float GAIN = 5.00; // mV/A + // static const float OFFSET = 0.0; // mV + // static const uint8_t num_samples = 10; + // static int16_t current_accumulator = 0.0; // A + + // /* starting equation : Vout = Vref + Voffset + (Gain * Ip) */ + // float ref_voltage = read_ref_voltage(); + // float vout = read_vout(); + + // ref_voltage *= 1000;// convert to mV + // vout *= 1000; + + // int16_t current = (vout - ref_voltage - OFFSET) / (GAIN); // convert to V + + // /* Low Pass Filter of Current*/ + // current = ((current_accumulator * (num_samples - 1)) + current) / + // num_samples; current_accumulator = current; + + // return current; + + static const float CURRENT_LOWCHANNEL_MAX = 75.0; // Amps + static const float CURRENT_LOWCHANNEL_MIN = -75.0; // Amps + // static const float CURRENT_SUPPLY_VOLTAGE = 5.038; + static const float CURRENT_ADC_RESOLUTION = 5.0 / MAX_ADC_RESOLUTION; + + static const float CURRENT_LOWCHANNEL_OFFSET = + 2.500; // Calibrated with current = 0A + static const float CURRENT_HIGHCHANNEL_OFFSET = + 2.500; // Calibrated with current = 0A + + static const float HIGHCHANNEL_GAIN = + 1 / 0.0041; // Calibrated with current = 5A, 10A, 20A + static const float LOWCHANNEL_GAIN = 1 / 0.0267; + + // Change ADC channel to read the high current sensor + change_adc1_channel(VOUT_CHANNEL); + HAL_ADC_Start(&hadc1); + HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); + int raw_low_current = HAL_ADC_GetValue(&hadc1); + + HAL_ADC_Start(&hadc2); + HAL_ADC_PollForConversion(&hadc2, HAL_MAX_DELAY); + int raw_high_current = HAL_ADC_GetValue(&hadc2); + + change_adc1_channel(REF_CHANNEL); + HAL_ADC_Start(&hadc1); + HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); + int ref_5V = HAL_ADC_GetValue(&hadc1); + + int16_t ref_voltage_raw = + (int16_t)(1000.0f * ((float)ref_5V * CURRENT_ADC_RESOLUTION)); + + int16_t high_current_voltage_raw = + (int16_t)(1000.0f * ((float)raw_high_current * CURRENT_ADC_RESOLUTION)); + high_current_voltage_raw = + (int16_t)(5000.0f * high_current_voltage_raw / (float)ref_voltage_raw); + + int16_t high_current = + (high_current_voltage_raw - (1000 * CURRENT_HIGHCHANNEL_OFFSET)) * + (1 / 4.0f); //* (HIGHCHANNEL_GAIN/100.0f))/1000; + + int16_t low_current_voltage_raw = + (int16_t)(1000.0f * ((float)raw_low_current * CURRENT_ADC_RESOLUTION)); + low_current_voltage_raw = + (int16_t)(5000.0f * low_current_voltage_raw / (float)ref_voltage_raw); + + int16_t low_current = + (float)(low_current_voltage_raw - (1000 * CURRENT_LOWCHANNEL_OFFSET)) * + (1 / 26.7); //* (LOWCHANNEL_GAIN/100.0f))/1000; + + // If the current is scoped within the range of the low channel, use the low + // channel + + if ((low_current < CURRENT_LOWCHANNEL_MAX - 5.0 && low_current >= 0) || + (low_current > CURRENT_LOWCHANNEL_MIN + 5.0 && low_current < 0)) { + // printf("\rLow Current: %d\n", -low_current); + return -low_current; + } + + // printf("\rHigh Current: %d\n", -high_current); + return -high_current; } -void compute_send_mc_discharge_message(acc_data_t *bmsdata) -{ - struct __attribute__((__packed__)) { - uint16_t max_discharge; - } discharge_data; +void compute_send_mc_discharge_message(acc_data_t *bmsdata) { + struct __attribute__((__packed__)) { + uint16_t max_discharge; + } discharge_data; - /* scale to A * 10 */ - discharge_data.max_discharge = 10 * bmsdata->discharge_limit; + /* scale to A * 10 */ + discharge_data.max_discharge = 10 * bmsdata->discharge_limit; - /* convert to big endian */ - endian_swap(&discharge_data.max_discharge, - sizeof(discharge_data.max_discharge)); + /* convert to big endian */ + endian_swap(&discharge_data.max_discharge, + sizeof(discharge_data.max_discharge)); - can_msg_t mc_msg = { 0 }; - mc_msg.id = - 0x156; // 0x0A is the dcl id, 0x22 is the device id set by us - mc_msg.len = 8; - memcpy(mc_msg.data, &discharge_data, sizeof(discharge_data)); + can_msg_t mc_msg = {0}; + mc_msg.id = 0x156; // 0x0A is the dcl id, 0x22 is the device id set by us + mc_msg.len = 8; + memcpy(mc_msg.data, &discharge_data, sizeof(discharge_data)); - can_send_msg(&can1, &mc_msg); + can_send_msg(&can1, &mc_msg); } -void compute_send_mc_charge_message(acc_data_t *bmsdata) -{ - struct __attribute__((__packed__)) { - int16_t max_charge; - } charge_data; +void compute_send_mc_charge_message(acc_data_t *bmsdata) { + struct __attribute__((__packed__)) { + int16_t max_charge; + } charge_data; - /* scale to A * 10 */ - charge_data.max_charge = -10 * bmsdata->charge_limit; + /* scale to A * 10 */ + charge_data.max_charge = -10 * bmsdata->charge_limit; - /* convert to big endian */ - endian_swap(&charge_data.max_charge, sizeof(charge_data.max_charge)); + /* convert to big endian */ + endian_swap(&charge_data.max_charge, sizeof(charge_data.max_charge)); - can_msg_t mc_msg = { 0 }; - mc_msg.id = - 0x176; // 0x0A is the dcl id, 0x157 is the device id set by us - mc_msg.len = 8; - memcpy(mc_msg.data, &charge_data, sizeof(charge_data)); + can_msg_t mc_msg = {0}; + mc_msg.id = 0x176; // 0x0A is the dcl id, 0x157 is the device id set by us + mc_msg.len = 8; + memcpy(mc_msg.data, &charge_data, sizeof(charge_data)); - can_send_msg(&can1, &mc_msg); + can_send_msg(&can1, &mc_msg); } -void compute_send_acc_status_message(acc_data_t *bmsdata) -{ - struct __attribute__((__packed__)) { - uint16_t packVolt; - uint16_t pack_current; - uint16_t pack_ah; - uint8_t pack_soc; - uint8_t pack_health; - } acc_status_msg_data; - - acc_status_msg_data.packVolt = bmsdata->pack_voltage; - acc_status_msg_data.pack_current = - (uint16_t)(bmsdata->pack_current); // convert with 2s complement - acc_status_msg_data.pack_ah = 0; - acc_status_msg_data.pack_soc = bmsdata->soc; - acc_status_msg_data.pack_health = 0; - - /* convert to big endian */ - endian_swap(&acc_status_msg_data.packVolt, - sizeof(acc_status_msg_data.packVolt)); - endian_swap(&acc_status_msg_data.pack_current, - sizeof(acc_status_msg_data.pack_current)); - endian_swap(&acc_status_msg_data.pack_ah, - sizeof(acc_status_msg_data.pack_ah)); - - can_msg_t acc_msg; - acc_msg.id = 0x80; - acc_msg.len = sizeof(acc_status_msg_data); - memcpy(acc_msg.data, &acc_status_msg_data, sizeof(acc_status_msg_data)); +void compute_send_acc_status_message(acc_data_t *bmsdata) { + struct __attribute__((__packed__)) { + uint16_t packVolt; + uint16_t pack_current; + uint16_t pack_ah; + uint8_t pack_soc; + uint8_t pack_health; + } acc_status_msg_data; + + acc_status_msg_data.packVolt = bmsdata->pack_voltage; + acc_status_msg_data.pack_current = + (uint16_t)(bmsdata->pack_current); // convert with 2s complement + acc_status_msg_data.pack_ah = 0; + acc_status_msg_data.pack_soc = bmsdata->soc; + acc_status_msg_data.pack_health = 0; + + /* convert to big endian */ + endian_swap(&acc_status_msg_data.packVolt, + sizeof(acc_status_msg_data.packVolt)); + endian_swap(&acc_status_msg_data.pack_current, + sizeof(acc_status_msg_data.pack_current)); + endian_swap(&acc_status_msg_data.pack_ah, + sizeof(acc_status_msg_data.pack_ah)); + + can_msg_t acc_msg; + acc_msg.id = 0x80; + acc_msg.len = sizeof(acc_status_msg_data); + memcpy(acc_msg.data, &acc_status_msg_data, sizeof(acc_status_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } void compute_send_bms_status_message(acc_data_t *bmsdata, int bms_state, - bool balance) -{ - struct __attribute__((__packed__)) { - uint8_t state; - uint32_t fault; - int8_t temp_avg; - uint8_t temp_internal; - uint8_t balance; - } bms_status_msg_data; - - bms_status_msg_data.temp_avg = (int8_t)(bmsdata->avg_temp); - bms_status_msg_data.state = (uint8_t)(bms_state); - bms_status_msg_data.fault = bmsdata->fault_code; - bms_status_msg_data.temp_internal = (uint8_t)(0); - bms_status_msg_data.balance = (uint8_t)(balance); - - /* convert to big endian */ - endian_swap(&bms_status_msg_data.fault, - sizeof(bms_status_msg_data.fault)); - - can_msg_t acc_msg; - acc_msg.id = 0x81; - acc_msg.len = sizeof(bms_status_msg_data); - memcpy(acc_msg.data, &bms_status_msg_data, sizeof(bms_status_msg_data)); + bool balance) { + struct __attribute__((__packed__)) { + uint8_t state; + uint32_t fault; + int8_t temp_avg; + uint8_t temp_internal; + uint8_t balance; + } bms_status_msg_data; + + bms_status_msg_data.temp_avg = (int8_t)(bmsdata->avg_temp); + bms_status_msg_data.state = (uint8_t)(bms_state); + bms_status_msg_data.fault = bmsdata->fault_code; + bms_status_msg_data.temp_internal = (uint8_t)(0); + bms_status_msg_data.balance = (uint8_t)(balance); + + /* convert to big endian */ + endian_swap(&bms_status_msg_data.fault, sizeof(bms_status_msg_data.fault)); + + can_msg_t acc_msg; + acc_msg.id = 0x81; + acc_msg.len = sizeof(bms_status_msg_data); + memcpy(acc_msg.data, &bms_status_msg_data, sizeof(bms_status_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_shutdown_ctrl_message(uint8_t mpe_state) -{ - struct __attribute__((__packed__)) { - uint8_t mpeState; - } shutdown_control_msg_data; +void compute_send_shutdown_ctrl_message(uint8_t mpe_state) { + struct __attribute__((__packed__)) { + uint8_t mpeState; + } shutdown_control_msg_data; - shutdown_control_msg_data.mpeState = mpe_state; + shutdown_control_msg_data.mpeState = mpe_state; - can_msg_t acc_msg; - acc_msg.id = 0x82; - acc_msg.len = sizeof(shutdown_control_msg_data); - memcpy(acc_msg.data, &shutdown_control_msg_data, - sizeof(shutdown_control_msg_data)); + can_msg_t acc_msg; + acc_msg.id = 0x82; + acc_msg.len = sizeof(shutdown_control_msg_data); + memcpy(acc_msg.data, &shutdown_control_msg_data, + sizeof(shutdown_control_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_cell_data_message(acc_data_t *bmsdata) -{ - struct __attribute__((__packed__)) { - uint16_t high_cell_voltage; - uint8_t high_cell_id; - uint16_t low_cell_voltage; - uint8_t low_cell_id; - uint16_t volt_avg; - } cell_data_msg_data; - - cell_data_msg_data.high_cell_voltage = bmsdata->max_voltage.val; - cell_data_msg_data.high_cell_id = - (bmsdata->max_voltage.chipIndex << 4) | - bmsdata->max_voltage.cellNum; - cell_data_msg_data.low_cell_voltage = bmsdata->min_voltage.val; - cell_data_msg_data.low_cell_id = (bmsdata->min_voltage.chipIndex << 4) | - bmsdata->min_voltage.cellNum; - cell_data_msg_data.volt_avg = bmsdata->avg_voltage; - - /* convert to big endian */ - endian_swap(&cell_data_msg_data.high_cell_voltage, - sizeof(cell_data_msg_data.high_cell_voltage)); - endian_swap(&cell_data_msg_data.low_cell_voltage, - sizeof(cell_data_msg_data.low_cell_voltage)); - endian_swap(&cell_data_msg_data.volt_avg, - sizeof(cell_data_msg_data.volt_avg)); - - can_msg_t acc_msg; - acc_msg.id = 0x83; - acc_msg.len = sizeof(cell_data_msg_data); - memcpy(acc_msg.data, &cell_data_msg_data, sizeof(cell_data_msg_data)); +void compute_send_cell_data_message(acc_data_t *bmsdata) { + struct __attribute__((__packed__)) { + uint16_t high_cell_voltage; + uint8_t high_cell_id; + uint16_t low_cell_voltage; + uint8_t low_cell_id; + uint16_t volt_avg; + } cell_data_msg_data; + + cell_data_msg_data.high_cell_voltage = bmsdata->max_voltage.val; + cell_data_msg_data.high_cell_id = + (bmsdata->max_voltage.chipIndex << 4) | bmsdata->max_voltage.cellNum; + cell_data_msg_data.low_cell_voltage = bmsdata->min_voltage.val; + cell_data_msg_data.low_cell_id = + (bmsdata->min_voltage.chipIndex << 4) | bmsdata->min_voltage.cellNum; + cell_data_msg_data.volt_avg = bmsdata->avg_voltage; + + /* convert to big endian */ + endian_swap(&cell_data_msg_data.high_cell_voltage, + sizeof(cell_data_msg_data.high_cell_voltage)); + endian_swap(&cell_data_msg_data.low_cell_voltage, + sizeof(cell_data_msg_data.low_cell_voltage)); + endian_swap(&cell_data_msg_data.volt_avg, + sizeof(cell_data_msg_data.volt_avg)); + + can_msg_t acc_msg; + acc_msg.id = 0x83; + acc_msg.len = sizeof(cell_data_msg_data); + memcpy(acc_msg.data, &cell_data_msg_data, sizeof(cell_data_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } void compute_send_cell_voltage_message(uint8_t cell_id, - uint16_t instant_voltage, - uint16_t internal_Res, uint8_t shunted, - uint16_t open_voltage) -{ - struct __attribute__((__packed__)) { - uint8_t cellID; - uint16_t instantVoltage; - uint16_t internalResistance; - uint8_t shunted; - uint16_t openVoltage; - } cell_voltage_msg_data; - - cell_voltage_msg_data.cellID = cell_id; - cell_voltage_msg_data.instantVoltage = instant_voltage; - cell_voltage_msg_data.internalResistance = internal_Res; - cell_voltage_msg_data.shunted = shunted; - cell_voltage_msg_data.openVoltage = open_voltage; - - /* convert to big endian */ - endian_swap(&cell_voltage_msg_data.instantVoltage, - sizeof(cell_voltage_msg_data.instantVoltage)); - endian_swap(&cell_voltage_msg_data.internalResistance, - sizeof(cell_voltage_msg_data.internalResistance)); - endian_swap(&cell_voltage_msg_data.openVoltage, - sizeof(cell_voltage_msg_data.openVoltage)); - - can_msg_t acc_msg; - acc_msg.id = 0x87; - acc_msg.len = sizeof(cell_voltage_msg_data); - memcpy(acc_msg.data, &cell_voltage_msg_data, - sizeof(cell_voltage_msg_data)); + uint16_t instant_voltage, + uint16_t internal_Res, uint8_t shunted, + uint16_t open_voltage) { + struct __attribute__((__packed__)) { + uint8_t cellID; + uint16_t instantVoltage; + uint16_t internalResistance; + uint8_t shunted; + uint16_t openVoltage; + } cell_voltage_msg_data; + + cell_voltage_msg_data.cellID = cell_id; + cell_voltage_msg_data.instantVoltage = instant_voltage; + cell_voltage_msg_data.internalResistance = internal_Res; + cell_voltage_msg_data.shunted = shunted; + cell_voltage_msg_data.openVoltage = open_voltage; + + /* convert to big endian */ + endian_swap(&cell_voltage_msg_data.instantVoltage, + sizeof(cell_voltage_msg_data.instantVoltage)); + endian_swap(&cell_voltage_msg_data.internalResistance, + sizeof(cell_voltage_msg_data.internalResistance)); + endian_swap(&cell_voltage_msg_data.openVoltage, + sizeof(cell_voltage_msg_data.openVoltage)); + + can_msg_t acc_msg; + acc_msg.id = 0x87; + acc_msg.len = sizeof(cell_voltage_msg_data); + memcpy(acc_msg.data, &cell_voltage_msg_data, sizeof(cell_voltage_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_current_message(acc_data_t *bmsdata) -{ - struct __attribute__((__packed__)) { - uint16_t dcl; - int16_t ccl; - uint16_t pack_curr; - } current_status_msg_data; - - current_status_msg_data.dcl = bmsdata->discharge_limit; - current_status_msg_data.ccl = -1 * bmsdata->charge_limit; - current_status_msg_data.pack_curr = bmsdata->pack_current; - - /* convert to big endian */ - endian_swap(¤t_status_msg_data.dcl, - sizeof(current_status_msg_data.dcl)); - endian_swap(¤t_status_msg_data.ccl, - sizeof(current_status_msg_data.ccl)); - endian_swap(¤t_status_msg_data.pack_curr, - sizeof(current_status_msg_data.pack_curr)); - - can_msg_t acc_msg; - acc_msg.id = 0x86; - acc_msg.len = sizeof(current_status_msg_data); - memcpy(acc_msg.data, ¤t_status_msg_data, - sizeof(current_status_msg_data)); +void compute_send_current_message(acc_data_t *bmsdata) { + struct __attribute__((__packed__)) { + uint16_t dcl; + int16_t ccl; + uint16_t pack_curr; + } current_status_msg_data; + + current_status_msg_data.dcl = bmsdata->discharge_limit; + current_status_msg_data.ccl = -1 * bmsdata->charge_limit; + current_status_msg_data.pack_curr = bmsdata->pack_current; + + /* convert to big endian */ + endian_swap(¤t_status_msg_data.dcl, + sizeof(current_status_msg_data.dcl)); + endian_swap(¤t_status_msg_data.ccl, + sizeof(current_status_msg_data.ccl)); + endian_swap(¤t_status_msg_data.pack_curr, + sizeof(current_status_msg_data.pack_curr)); + + can_msg_t acc_msg; + acc_msg.id = 0x86; + acc_msg.len = sizeof(current_status_msg_data); + memcpy(acc_msg.data, ¤t_status_msg_data, + sizeof(current_status_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_cell_temp_message(acc_data_t *bmsdata) -{ - struct __attribute__((__packed__)) { - uint16_t max_cell_temp; - uint8_t max_cell_id; - uint16_t min_cell_temp; - uint8_t min_cell_id; - uint16_t average_temp; - } cell_temp_msg_data; - - cell_temp_msg_data.max_cell_temp = bmsdata->max_temp.val; - cell_temp_msg_data.max_cell_id = (bmsdata->max_temp.chipIndex << 4) | - (bmsdata->max_temp.cellNum - 17); - cell_temp_msg_data.min_cell_temp = bmsdata->min_temp.val; - cell_temp_msg_data.min_cell_id = (bmsdata->min_temp.chipIndex << 4) | - (bmsdata->min_temp.cellNum - 17); - cell_temp_msg_data.average_temp = bmsdata->avg_temp; - - /* convert to big endian */ - endian_swap(&cell_temp_msg_data.max_cell_temp, - sizeof(cell_temp_msg_data.max_cell_temp)); - endian_swap(&cell_temp_msg_data.min_cell_temp, - sizeof(cell_temp_msg_data.min_cell_temp)); - endian_swap(&cell_temp_msg_data.average_temp, - sizeof(cell_temp_msg_data.average_temp)); - - can_msg_t acc_msg; - acc_msg.id = 0x84; - acc_msg.len = sizeof(cell_temp_msg_data); - memcpy(acc_msg.data, &cell_temp_msg_data, sizeof(cell_temp_msg_data)); +void compute_send_cell_temp_message(acc_data_t *bmsdata) { + struct __attribute__((__packed__)) { + uint16_t max_cell_temp; + uint8_t max_cell_id; + uint16_t min_cell_temp; + uint8_t min_cell_id; + uint16_t average_temp; + } cell_temp_msg_data; + + cell_temp_msg_data.max_cell_temp = bmsdata->max_temp.val; + cell_temp_msg_data.max_cell_id = + (bmsdata->max_temp.chipIndex << 4) | (bmsdata->max_temp.cellNum - 17); + cell_temp_msg_data.min_cell_temp = bmsdata->min_temp.val; + cell_temp_msg_data.min_cell_id = + (bmsdata->min_temp.chipIndex << 4) | (bmsdata->min_temp.cellNum - 17); + cell_temp_msg_data.average_temp = bmsdata->avg_temp; + + /* convert to big endian */ + endian_swap(&cell_temp_msg_data.max_cell_temp, + sizeof(cell_temp_msg_data.max_cell_temp)); + endian_swap(&cell_temp_msg_data.min_cell_temp, + sizeof(cell_temp_msg_data.min_cell_temp)); + endian_swap(&cell_temp_msg_data.average_temp, + sizeof(cell_temp_msg_data.average_temp)); + + can_msg_t acc_msg; + acc_msg.id = 0x84; + acc_msg.len = sizeof(cell_temp_msg_data); + memcpy(acc_msg.data, &cell_temp_msg_data, sizeof(cell_temp_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_segment_temp_message(acc_data_t *bmsdata) -{ - struct __attribute__((__packed__)) { - int8_t segment1_average_temp; - 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]; - 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; - acc_msg.len = sizeof(segment_temp_msg_data); - memcpy(acc_msg.data, &segment_temp_msg_data, - sizeof(segment_temp_msg_data)); +void compute_send_segment_temp_message(acc_data_t *bmsdata) { + struct __attribute__((__packed__)) { + int8_t segment1_average_temp; + 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]; + 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; + acc_msg.len = sizeof(segment_temp_msg_data); + memcpy(acc_msg.data, &segment_temp_msg_data, sizeof(segment_temp_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + 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)); +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; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + 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)); +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; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_debug_message(uint8_t *data, uint8_t len) -{ - can_msg_t debug_msg; - debug_msg.id = 0x702; - debug_msg.len = len; +void compute_send_debug_message(uint8_t *data, uint8_t len) { + can_msg_t debug_msg; + debug_msg.id = 0x702; + debug_msg.len = len; - if (len > 8) { - len = 8; - } + if (len > 8) { + len = 8; + } - if (len > 1) { - endian_swap(data, len); - } + if (len > 1) { + endian_swap(data, len); + } - memcpy(debug_msg.data, data, len); + memcpy(debug_msg.data, data, len); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &debug_msg); + can_send_msg(line, &debug_msg); } - -void change_adc1_channel(uint8_t channel) -{ - ADC_ChannelConfTypeDef sConfig = { 0 }; - - if (channel == REF_CHANNEL) - sConfig.Channel = ADC_CHANNEL_9; - else if (channel == VOUT_CHANNEL) - sConfig.Channel = ADC_CHANNEL_15; - - sConfig.Rank = 1; - sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; - if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { - Error_Handler(); - } + +void change_adc1_channel(uint8_t channel) { + ADC_ChannelConfTypeDef sConfig = {0}; + + if (channel == REF_CHANNEL) + sConfig.Channel = ADC_CHANNEL_9; + else if (channel == VOUT_CHANNEL) + sConfig.Channel = ADC_CHANNEL_15; + + sConfig.Rank = 1; + sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; + if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { + Error_Handler(); + } } diff --git a/Core/Src/segment.c b/Core/Src/segment.c index 728b44a..6dd8607 100644 --- a/Core/Src/segment.c +++ b/Core/Src/segment.c @@ -1,19 +1,19 @@ #include "segment.h" -#include -#include -#include #include "main.h" #include +#include +#include +#include -#define THERM_WAIT_TIME 500 /* ms */ -#define VOLTAGE_WAIT_TIME 100 /* ms */ -#define THERM_AVG 15 /* Number of values to average */ -#define MAX_VOLT_DELTA 2500 -#define MAX_CONSEC_NOISE 10 +#define THERM_WAIT_TIME 500 /* ms */ +#define VOLTAGE_WAIT_TIME 100 /* ms */ +#define THERM_AVG 15 /* Number of values to average */ +#define MAX_VOLT_DELTA 2500 +#define MAX_CONSEC_NOISE 10 #define GPIO_EXPANDER_ADDR 0x40 #define GPIO_REGISTER_ADDR 0x09 -//TODO ensure spi 1 is correct for talking to segs +// TODO ensure spi 1 is correct for talking to segs extern SPI_HandleTypeDef hspi1; ltc_config *ltc68041; @@ -28,29 +28,29 @@ nertimer_t therm_timer; nertimer_t voltage_reading_timer; nertimer_t variance_timer; -int voltage_error = 0; //not faulted -int therm_error = 0; //not faulted +int voltage_error = 0; // not faulted +int therm_error = 0; // not faulted uint16_t crc_error_check = 0; -/* our segments are mapped backwards and in pairs, so they are read in 1,0 then 3,2, etc*/ -const int mapping_correction[12] = { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10 }; +/* our segments are mapped backwards and in pairs, so they are read in 1,0 then + * 3,2, etc*/ +const int mapping_correction[12] = {1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10}; uint16_t therm_settle_time_ = 0; const uint32_t VOLT_TEMP_CONV[106] = { - 157300, 148800, 140300, 131800, 123300, 114800, 108772, 102744, 96716, - 90688, 84660, 80328, 75996, 71664, 67332, 63000, 59860, 56720, - 53580, 50440, 47300, 45004, 42708, 40412, 38116, 35820, 34124, - 32428, 30732, 29036, 27340, 26076, 24812, 23548, 22284, 21020, - 20074, 19128, 18182, 17236, 16290, 15576, 14862, 14148, 13434, - 12720, 12176, 11632, 11088, 10544, 10000, 9584, 9168, 8753, - 8337, 7921, 7600, 7279, 6957, 6636, 6315, 6065, 5816, - 5566, 5317, 5067, 4872, 4676, 4481, 4285, 4090, 3936, - 3782, 3627, 3473, 3319, 3197, 3075, 2953, 2831, 2709, - 2612, 2514, 2417, 2319, 2222, 2144, 2066, 1988, 1910, - 1832, 1769, 1706, 1644, 1581, 1518, 1467, 1416, 1366, - 1315, 1264, 1223, 1181, 1140, 1098, 1057 -}; + 157300, 148800, 140300, 131800, 123300, 114800, 108772, 102744, 96716, + 90688, 84660, 80328, 75996, 71664, 67332, 63000, 59860, 56720, + 53580, 50440, 47300, 45004, 42708, 40412, 38116, 35820, 34124, + 32428, 30732, 29036, 27340, 26076, 24812, 23548, 22284, 21020, + 20074, 19128, 18182, 17236, 16290, 15576, 14862, 14148, 13434, + 12720, 12176, 11632, 11088, 10544, 10000, 9584, 9168, 8753, + 8337, 7921, 7600, 7279, 6957, 6636, 6315, 6065, 5816, + 5566, 5317, 5067, 4872, 4676, 4481, 4285, 4090, 3936, + 3782, 3627, 3473, 3319, 3197, 3075, 2953, 2831, 2709, + 2612, 2514, 2417, 2319, 2222, 2144, 2066, 1988, 1910, + 1832, 1769, 1706, 1644, 1581, 1518, 1467, 1416, 1366, + 1315, 1264, 1223, 1181, 1140, 1098, 1057}; const int32_t VOLT_TEMP_CALIB_OFFSET = 0; @@ -63,662 +63,566 @@ void pull_chip_configuration(void); int16_t calc_average(void); int8_t calc_therm_standard_dev(int16_t avg_temp); -void push_chip_configuration() -{ - LTC6804_wrcfg(ltc68041, NUM_CHIPS, local_config); +void push_chip_configuration() { + LTC6804_wrcfg(ltc68041, NUM_CHIPS, local_config); } -void segment_init() -{ - printf("Initializing Segments..."); - - ltc68041 = malloc(sizeof(ltc_config)); - LTC6804_initialize(ltc68041, &hspi1, GPIOA, SPI_1_CS_Pin); - - pull_chip_configuration(); - - for (int c = 0; c < NUM_CHIPS; c++) { - local_config[c][0] = 0xF8; - local_config[c][1] = 0x19; /* VUV = 0x619 = 1561 -> 2.4992V */ - local_config[c][2] = 0x06; /* VOV = 0xA60 = 2656 -> 4.2496V */ - local_config[c][3] = 0xA6; - local_config[c][4] = 0x00; - local_config[c][5] = 0x00; - } - push_chip_configuration(); - - start_timer(&voltage_reading_timer, VOLTAGE_WAIT_TIME); - start_timer(&therm_timer, THERM_WAIT_TIME); - - uint8_t i2c_write_data[NUM_CHIPS][3]; - - // Set GPIO expander to output - 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 - } - 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); +void segment_init() { + printf("Initializing Segments..."); + + ltc68041 = malloc(sizeof(ltc_config)); + LTC6804_initialize(ltc68041, &hspi1, GPIOA, SPI_1_CS_Pin); + + pull_chip_configuration(); + + for (int c = 0; c < NUM_CHIPS; c++) { + local_config[c][0] = 0xF8; + local_config[c][1] = 0x19; /* VUV = 0x619 = 1561 -> 2.4992V */ + local_config[c][2] = 0x06; /* VOV = 0xA60 = 2656 -> 4.2496V */ + local_config[c][3] = 0xA6; + local_config[c][4] = 0x00; + local_config[c][5] = 0x00; + } + push_chip_configuration(); + + start_timer(&voltage_reading_timer, VOLTAGE_WAIT_TIME); + start_timer(&therm_timer, THERM_WAIT_TIME); + + uint8_t i2c_write_data[NUM_CHIPS][3]; + + // Set GPIO expander to output + 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 + } + 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); } -void select_therm(uint8_t therm) -{ - /* Exit if out of range values */ - if (therm < 1 || therm > 16) { - return; - } - - uint8_t i2c_write_data[NUM_CHIPS][3]; - uint8_t comm_reg_data[NUM_CHIPS][6]; - - // select 0-16 on GPIO expander - for (int chip = 0; chip < NUM_CHIPS; chip++) { - i2c_write_data[chip][0] = GPIO_EXPANDER_ADDR; - i2c_write_data[chip][1] = GPIO_REGISTER_ADDR; - i2c_write_data[chip][2] = - (therm - - 1); // 0-15, will change multiplexer to select thermistor - } - serialize_i2c_msg(i2c_write_data, comm_reg_data); - push_chip_configuration(); - LTC6804_wrcomm(ltc68041, NUM_CHIPS, comm_reg_data); - LTC6804_stcomm(ltc68041, 24); +void select_therm(uint8_t therm) { + /* Exit if out of range values */ + if (therm < 1 || therm > 16) { + return; + } + + uint8_t i2c_write_data[NUM_CHIPS][3]; + uint8_t comm_reg_data[NUM_CHIPS][6]; + + // select 0-16 on GPIO expander + for (int chip = 0; chip < NUM_CHIPS; chip++) { + i2c_write_data[chip][0] = GPIO_EXPANDER_ADDR; + i2c_write_data[chip][1] = GPIO_REGISTER_ADDR; + i2c_write_data[chip][2] = + (therm - 1); // 0-15, will change multiplexer to select thermistor + } + serialize_i2c_msg(i2c_write_data, comm_reg_data); + push_chip_configuration(); + LTC6804_wrcomm(ltc68041, NUM_CHIPS, comm_reg_data); + LTC6804_stcomm(ltc68041, 24); } -int pull_voltages() -{ - /** - * If we haven't waited long enough between pulling voltage data - * just copy over the contents of the last good reading and the fault status - * from the most recent attempt - */ - - //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, - previous_data[i].voltage, - sizeof(segment_data[i].voltage)); - } - return voltage_error; - } - - uint16_t raw_voltages[NUM_CHIPS][12]; - - push_chip_configuration(); - LTC6804_adcv(ltc68041); - - /** - * 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, raw_voltages) == -1) { - for (uint8_t i = 0; i < NUM_CHIPS; i++) { - memcpy(segment_data[i].voltage, - previous_data[i].voltage, - sizeof(segment_data[i].voltage)); - - crc_error_check++; - printf("Bad voltage read\n"); - } - return 1; - } - - /* If the read was successful, copy the voltage data */ - for (uint8_t i = 0; i < NUM_CHIPS; i++) { - int corrected_index = mapping_correction[i]; - - /* correction to account for missing index, see more info below */ - int dest_index = 0; - - for (uint8_t j = 0; j < NUM_CELLS_PER_CHIP + 1; j++) { - /* 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; - - 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 { - //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); - - return 0; +int pull_voltages() { + /** + * If we haven't waited long enough between pulling voltage data + * just copy over the contents of the last good reading and the fault status + * from the most recent attempt + */ + + // 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, previous_data[i].voltage, + sizeof(segment_data[i].voltage)); + } + return voltage_error; + } + + uint16_t raw_voltages[NUM_CHIPS][12]; + + push_chip_configuration(); + LTC6804_adcv(ltc68041); + + /** + * 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, raw_voltages) == -1) { + for (uint8_t i = 0; i < NUM_CHIPS; i++) { + memcpy(segment_data[i].voltage, previous_data[i].voltage, + sizeof(segment_data[i].voltage)); + + crc_error_check++; + printf("Bad voltage read\n"); + } + return 1; + } + + /* If the read was successful, copy the voltage data */ + for (uint8_t i = 0; i < NUM_CHIPS; i++) { + int corrected_index = mapping_correction[i]; + + /* correction to account for missing index, see more info below */ + int dest_index = 0; + + for (uint8_t j = 0; j < NUM_CELLS_PER_CHIP + 1; j++) { + /* 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; + + 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 { + // 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); + + return 0; } -int pull_thermistors() -{ - /* If polled too soon, just copy existing values from memory */ - if (!is_timer_expired(&therm_timer)) { - for (uint8_t i = 0; i < NUM_CHIPS; i++) { - memcpy(segment_data[i].thermistor_reading, - previous_data[i].thermistor_reading, - sizeof(segment_data[i].thermistor_reading)); - memcpy(segment_data[i].thermistor_value, - previous_data[i].thermistor_value, - sizeof(segment_data[i].thermistor_value)); - } - return voltage_error; - } - - uint16_t raw_temp_voltages[NUM_CHIPS][6]; - - static uint8_t current_therm = 1; - if (current_therm > 16) { - current_therm = 1; - } - - /* 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 (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]; - /* - * Get current temperature LUT. Voltage is adjusted to account for 5V reg - * fluctuations (index 2 is a reading of the ADC 5V ref) - */ - 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]; - } - } - } - 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(); - //standard_dev_therm_check(); - //averaging_therm_check(); - //discard_neutrals(); - - return 0; /* Read successfully */ +int pull_thermistors() { + /* If polled too soon, just copy existing values from memory */ + if (!is_timer_expired(&therm_timer)) { + for (uint8_t i = 0; i < NUM_CHIPS; i++) { + memcpy(segment_data[i].thermistor_reading, + previous_data[i].thermistor_reading, + sizeof(segment_data[i].thermistor_reading)); + memcpy(segment_data[i].thermistor_value, + previous_data[i].thermistor_value, + sizeof(segment_data[i].thermistor_value)); + } + return voltage_error; + } + + uint16_t raw_temp_voltages[NUM_CHIPS][6]; + + static uint8_t current_therm = 1; + if (current_therm > 16) { + current_therm = 1; + } + + /* 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 (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]; + /* + * Get current temperature LUT. Voltage is adjusted to account for 5V reg + * fluctuations (index 2 is a reading of the ADC 5V ref) + */ + 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]; + } + } + } + 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(); + // standard_dev_therm_check(); + // averaging_therm_check(); + // discard_neutrals(); + + return 0; /* Read successfully */ } -void segment_retrieve_data(chipdata_t databuf[NUM_CHIPS]) -{ - segment_data = databuf; +void segment_retrieve_data(chipdata_t databuf[NUM_CHIPS]) { + segment_data = databuf; - /* Pull voltages and thermistors and indiacate if there was a problem during - * retrieval */ - voltage_error = pull_voltages(); - therm_error = pull_thermistors(); + /* Pull voltages and thermistors and indiacate if there was a problem during + * retrieval */ + voltage_error = pull_voltages(); + therm_error = pull_thermistors(); - /* Save the contents of the reading so that we can use it to fill in missing - * data */ - memcpy(previous_data, segment_data, sizeof(chipdata_t) * NUM_CHIPS); + /* Save the contents of the reading so that we can use it to fill in missing + * data */ + memcpy(previous_data, segment_data, sizeof(chipdata_t) * NUM_CHIPS); - segment_data = NULL; + segment_data = NULL; } -void configure_discharge(uint8_t chip, uint16_t cells) -{ - /* - * chipConfigurations[chip][4] == chipConfigurations[Literally what chip you - * want][register] 4 and 5 are registers to discharge chips - */ - local_config[chip][4] = (uint8_t)(cells & 0x00FF); - - /* - * Register 5 is split in half, so we maintain the upper half and add in the - * bottom half to discharge cells - */ - local_config[chip][5] = - (local_config[chip][5] & 0xF0) + (uint8_t)(cells >> 8); +void configure_discharge(uint8_t chip, uint16_t cells) { + /* + * chipConfigurations[chip][4] == chipConfigurations[Literally what chip you + * want][register] 4 and 5 are registers to discharge chips + */ + local_config[chip][4] = (uint8_t)(cells & 0x00FF); + + /* + * Register 5 is split in half, so we maintain the upper half and add in the + * bottom half to discharge cells + */ + local_config[chip][5] = + (local_config[chip][5] & 0xF0) + (uint8_t)(cells >> 8); } -void segment_enable_balancing(bool balance_enable) -{ - /* - * Discharging all cells in series - * Making the discharge command all 1's for all cells per chip - */ - static const uint16_t DICHARGE_ALL_COMMAND = 0xFFFF >> - (16 - NUM_CELLS_PER_CHIP); - - if (balance_enable) { - for (int c = 0; c < NUM_CHIPS; c++) { - configure_discharge(c, DICHARGE_ALL_COMMAND); - discharge_commands[c] = DICHARGE_ALL_COMMAND; - } - push_chip_configuration(); - } else { - for (int c = 0; c < NUM_CHIPS; c++) { - configure_discharge(c, 0); - discharge_commands[c] = 0; - } - push_chip_configuration(); - } +void segment_enable_balancing(bool balance_enable) { + /* + * Discharging all cells in series + * Making the discharge command all 1's for all cells per chip + */ + static const uint16_t DICHARGE_ALL_COMMAND = + 0xFFFF >> (16 - NUM_CELLS_PER_CHIP); + + if (balance_enable) { + for (int c = 0; c < NUM_CHIPS; c++) { + configure_discharge(c, DICHARGE_ALL_COMMAND); + discharge_commands[c] = DICHARGE_ALL_COMMAND; + } + push_chip_configuration(); + } else { + for (int c = 0; c < NUM_CHIPS; c++) { + configure_discharge(c, 0); + discharge_commands[c] = 0; + } + push_chip_configuration(); + } } // @todo Revisit after testing void cell_enable_balancing(uint8_t chip_num, uint8_t cell_num, - bool balance_enable) -{ - pull_chip_configuration(); + bool balance_enable) { + pull_chip_configuration(); - if (balance_enable) - discharge_commands[chip_num] |= (1 << cell_num); - else - discharge_commands[chip_num] &= ~(1 << cell_num); + if (balance_enable) + discharge_commands[chip_num] |= (1 << cell_num); + else + discharge_commands[chip_num] &= ~(1 << cell_num); - configure_discharge(chip_num, discharge_commands[chip_num]); + configure_discharge(chip_num, discharge_commands[chip_num]); - push_chip_configuration(); + push_chip_configuration(); } void segment_configure_balancing( - bool discharge_config[NUM_CHIPS][NUM_CELLS_PER_CHIP]) -{ - for (int c = 0; c < NUM_CHIPS; c++) { - for (int cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { - if (discharge_config[mapping_correction[c]][cell]) - discharge_commands[mapping_correction[c]] |= - 1 << cell; - else - discharge_commands[mapping_correction[c]] &= - ~(1 << cell); - } - - configure_discharge(c, discharge_commands[c]); - } - push_chip_configuration(); + bool discharge_config[NUM_CHIPS][NUM_CELLS_PER_CHIP]) { + for (int c = 0; c < NUM_CHIPS; c++) { + for (int cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { + if (discharge_config[mapping_correction[c]][cell]) + discharge_commands[mapping_correction[c]] |= 1 << cell; + else + discharge_commands[mapping_correction[c]] &= ~(1 << cell); + } + + configure_discharge(c, discharge_commands[c]); + } + push_chip_configuration(); } -bool cell_is_balancing(uint8_t chip_num, uint8_t cell_num) -{ - /* If the cell is one of the first 8, check the 4th register */ - if (cell_num < 8) { - return local_config[chip_num][4] & (1 << cell_num); - } - /* If the cell number is greater than 8, check the 5th register */ - else { - return local_config[chip_num][5] & (1 << (cell_num - 8)); - } - - return false; /* default case */ +bool cell_is_balancing(uint8_t chip_num, uint8_t cell_num) { + /* If the cell is one of the first 8, check the 4th register */ + if (cell_num < 8) { + return local_config[chip_num][4] & (1 << cell_num); + } + /* If the cell number is greater than 8, check the 5th register */ + else { + return local_config[chip_num][5] & (1 << (cell_num - 8)); + } + + return false; /* default case */ } -bool segment_is_balancing() -{ - for (int c = 0; c < NUM_CHIPS; c++) { - /* Reading from the 4th config register */ - for (int cell = 0; cell < 8; cell++) { - if (local_config[c][4] & (1 << cell)) - return true; - } - - /* Reading from the 5th config register */ - for (int cell = 0; cell < 4; cell++) { - if (local_config[c][5] & (1 << (cell))) - return true; - } - } - - return false; +bool segment_is_balancing() { + for (int c = 0; c < NUM_CHIPS; c++) { + /* Reading from the 4th config register */ + for (int cell = 0; cell < 8; cell++) { + if (local_config[c][4] & (1 << cell)) + return true; + } + + /* Reading from the 5th config register */ + for (int cell = 0; cell < 4; cell++) { + if (local_config[c][5] & (1 << (cell))) + return true; + } + } + + return false; } -void pull_chip_configuration() -{ - uint8_t remote_config[NUM_CHIPS][8]; - LTC6804_rdcfg(ltc68041, NUM_CHIPS, remote_config); +void pull_chip_configuration() { + uint8_t remote_config[NUM_CHIPS][8]; + LTC6804_rdcfg(ltc68041, NUM_CHIPS, remote_config); - for (int chip = 0; chip < NUM_CHIPS; chip++) { - for (int index = 0; index < 6; index++) { - local_config[chip][index] = remote_config[chip][index]; - } - } + for (int chip = 0; chip < NUM_CHIPS; chip++) { + for (int index = 0; index < 6; index++) { + local_config[chip][index] = remote_config[chip][index]; + } + } } -int8_t steinhart_est(uint16_t V) -{ - /* min temp - max temp with buffer on both */ - for (int i = -25; i < 80; i++) { - if (V > VOLT_TEMP_CONV[i + 25]) { - return i; - } - } +int8_t steinhart_est(uint16_t V) { + /* min temp - max temp with buffer on both */ + for (int i = -25; i < 80; i++) { + if (V > VOLT_TEMP_CONV[i + 25]) { + return i; + } + } - return 80; + return 80; } -void disable_gpio_pulldowns() -{ - HAL_Delay(1000); - /* Turn OFF GPIO 1 & 2 pull downs */ - pull_chip_configuration(); - for (int c = 0; c < NUM_CHIPS; c++) { - local_config[c][0] |= 0x18; - } - push_chip_configuration(); - - pull_chip_configuration(); - printf("Chip CFG:\n"); - for (int c = 0; c < NUM_CHIPS; c++) { - for (int byte = 0; byte < 6; byte++) { - printf("%x", local_config[c][byte]); - printf("\t"); - } - printf("\n"); - } - printf("Done\n"); +void disable_gpio_pulldowns() { + HAL_Delay(1000); + /* Turn OFF GPIO 1 & 2 pull downs */ + pull_chip_configuration(); + for (int c = 0; c < NUM_CHIPS; c++) { + local_config[c][0] |= 0x18; + } + push_chip_configuration(); + + pull_chip_configuration(); + printf("Chip CFG:\n"); + for (int c = 0; c < NUM_CHIPS; c++) { + for (int byte = 0; byte < 6; byte++) { + printf("%x", local_config[c][byte]); + printf("\t"); + } + printf("\n"); + } + printf("Done\n"); } -void serialize_i2c_msg(uint8_t data_to_write[][3], uint8_t comm_output[][6]) -{ - for (int chip = 0; chip < NUM_CHIPS; chip++) { - comm_output[chip][0] = 0x60 | (data_to_write[chip][0] >> - 4); /* START + high side of B0 */ - comm_output[chip][1] = (data_to_write[chip][0] << 4) | - 0x00; /* low side of B0 + ACK */ - comm_output[chip][2] = 0x00 | (data_to_write[chip][1] >> - 4); /* BLANK + high side of B1 */ - comm_output[chip][3] = (data_to_write[chip][1] << 4) | - 0x00; /* low side of B1 + ACK */ - comm_output[chip][4] = 0x00 | (data_to_write[chip][2] >> - 4); /* BLANK + high side of B2 */ - comm_output[chip][5] = (data_to_write[chip][2] << 4) | - 0x09; /* low side of B2 + STOP & NACK */ - } +void serialize_i2c_msg(uint8_t data_to_write[][3], uint8_t comm_output[][6]) { + for (int chip = 0; chip < NUM_CHIPS; chip++) { + comm_output[chip][0] = + 0x60 | (data_to_write[chip][0] >> 4); /* START + high side of B0 */ + comm_output[chip][1] = + (data_to_write[chip][0] << 4) | 0x00; /* low side of B0 + ACK */ + comm_output[chip][2] = + 0x00 | (data_to_write[chip][1] >> 4); /* BLANK + high side of B1 */ + comm_output[chip][3] = + (data_to_write[chip][1] << 4) | 0x00; /* low side of B1 + ACK */ + comm_output[chip][4] = + 0x00 | (data_to_write[chip][2] >> 4); /* BLANK + high side of B2 */ + comm_output[chip][5] = + (data_to_write[chip][2] << 4) | 0x09; /* low side of B2 + STOP & NACK */ + } } -void averaging_therm_check() -{ - for (int therm = 1; therm <= 16; therm++) { - for (int c = 0; c < NUM_CHIPS; c++) { - /* Directly update for a set time from start up due to therm voltages - * needing to settle */ - if (therm_avg_counter < THERM_AVG * 10) { - segment_data[c].thermistor_value[therm - 1] = - segment_data[c] - .thermistor_reading[therm - 1]; - segment_data[c].thermistor_value[therm + 15] = - segment_data[c] - .thermistor_reading[therm + 15]; - therm_avg_counter++; - } else { - /* We need to investigate this. Very sloppy */ - /* Discard if reading is 33C */ - if (segment_data[c] - .thermistor_reading[therm - 1] != - 33) { - /* If measured value is larger than current "averaged" value, - * increment value */ - if (segment_data[c] - .thermistor_reading[therm - - 1] > - segment_data[c] - .thermistor_value[therm - - 1]) { - segment_data[c] - .thermistor_value[therm - - 1]++; - /* If measured value is smaller than current "averaged" value, - * decrement value */ - } else if (segment_data[c] - .thermistor_reading - [therm - 1] < - segment_data[c] - .thermistor_value - [therm - 1]) { - segment_data[c] - .thermistor_value[therm - - 1]--; - } - } - - /* See comments above. Identical but for the upper 16 therms */ - if (segment_data[c] - .thermistor_reading[therm + 15] != - 33) { - if (segment_data[c] - .thermistor_reading[therm + - 15] > - segment_data[c] - .thermistor_value[therm + - 15]) { - segment_data[c] - .thermistor_value[therm + - 15]++; - } else if (segment_data[c] - .thermistor_reading - [therm + 15] < - segment_data[c].thermistor_value - [therm + 15]) { - segment_data[c] - .thermistor_value[therm + - 15]--; - } - } - } - } - } +void averaging_therm_check() { + for (int therm = 1; therm <= 16; therm++) { + for (int c = 0; c < NUM_CHIPS; c++) { + /* Directly update for a set time from start up due to therm voltages + * needing to settle */ + if (therm_avg_counter < THERM_AVG * 10) { + segment_data[c].thermistor_value[therm - 1] = + segment_data[c].thermistor_reading[therm - 1]; + segment_data[c].thermistor_value[therm + 15] = + segment_data[c].thermistor_reading[therm + 15]; + therm_avg_counter++; + } else { + /* We need to investigate this. Very sloppy */ + /* Discard if reading is 33C */ + if (segment_data[c].thermistor_reading[therm - 1] != 33) { + /* If measured value is larger than current "averaged" value, + * increment value */ + if (segment_data[c].thermistor_reading[therm - 1] > + segment_data[c].thermistor_value[therm - 1]) { + segment_data[c].thermistor_value[therm - 1]++; + /* If measured value is smaller than current "averaged" value, + * decrement value */ + } else if (segment_data[c].thermistor_reading[therm - 1] < + segment_data[c].thermistor_value[therm - 1]) { + segment_data[c].thermistor_value[therm - 1]--; + } + } + + /* See comments above. Identical but for the upper 16 therms */ + if (segment_data[c].thermistor_reading[therm + 15] != 33) { + if (segment_data[c].thermistor_reading[therm + 15] > + segment_data[c].thermistor_value[therm + 15]) { + segment_data[c].thermistor_value[therm + 15]++; + } else if (segment_data[c].thermistor_reading[therm + 15] < + segment_data[c].thermistor_value[therm + 15]) { + segment_data[c].thermistor_value[therm + 15]--; + } + } + } + } + } } -void standard_dev_therm_check() -{ - if (previous_data == NULL) - return; - int16_t avg_temp = calc_average(); - uint8_t standard_dev = calc_therm_standard_dev(avg_temp); - for (uint8_t c = 0; c < NUM_CHIPS; c++) { - for (uint8_t therm = 17; therm < 28; therm++) { - /* - * If difference between thermistor and average is more than - * MAX_STANDARD_DEV set the therm to pack average - */ - if (abs(segment_data[c].thermistor_value[therm] - - avg_temp) > (MAX_STANDARD_DEV * standard_dev)) { - /* Nullify thermistor by setting to pack average */ - segment_data[c].thermistor_value[therm] = - previous_data[c].thermistor_value[therm]; - } - } - } +void standard_dev_therm_check() { + if (previous_data == NULL) + return; + int16_t avg_temp = calc_average(); + uint8_t standard_dev = calc_therm_standard_dev(avg_temp); + for (uint8_t c = 0; c < NUM_CHIPS; c++) { + for (uint8_t therm = 17; therm < 28; therm++) { + /* + * If difference between thermistor and average is more than + * MAX_STANDARD_DEV set the therm to pack average + */ + if (abs(segment_data[c].thermistor_value[therm] - avg_temp) > + (MAX_STANDARD_DEV * standard_dev)) { + /* Nullify thermistor by setting to pack average */ + segment_data[c].thermistor_value[therm] = + previous_data[c].thermistor_value[therm]; + } + } + } } -int8_t calc_therm_standard_dev(int16_t avg_temp) -{ - uint16_t sum_diff_sqrd = 0; - for (uint8_t chip = 0; chip < NUM_CHIPS; chip++) { - for (uint8_t therm = 17; therm < 28; therm++) { - uint16_t sum_diff = - abs(segment_data[chip].thermistor_value[therm] - - avg_temp); - sum_diff_sqrd += sum_diff * sum_diff; - } - } - - uint8_t standard_dev = sqrt(sum_diff_sqrd / 88); - if (standard_dev < 8) { - standard_dev = 8; - } - return standard_dev; +int8_t calc_therm_standard_dev(int16_t avg_temp) { + uint16_t sum_diff_sqrd = 0; + for (uint8_t chip = 0; chip < NUM_CHIPS; chip++) { + for (uint8_t therm = 17; therm < 28; therm++) { + uint16_t sum_diff = + abs(segment_data[chip].thermistor_value[therm] - avg_temp); + sum_diff_sqrd += sum_diff * sum_diff; + } + } + + uint8_t standard_dev = sqrt(sum_diff_sqrd / 88); + if (standard_dev < 8) { + standard_dev = 8; + } + return standard_dev; } -int16_t calc_average() -{ - int16_t avg = 0; - for (int chip = 0; chip < NUM_CHIPS; chip++) { - for (int therm = 17; therm < 28; therm++) { - avg += segment_data[chip].thermistor_value[therm]; - } - } - - avg = avg / (NUM_CHIPS * 11); - return avg; +int16_t calc_average() { + int16_t avg = 0; + for (int chip = 0; chip < NUM_CHIPS; chip++) { + for (int therm = 17; therm < 28; therm++) { + avg += segment_data[chip].thermistor_value[therm]; + } + } + + avg = avg / (NUM_CHIPS * 11); + return avg; } -void variance_therm_check() -{ - if (previous_data == NULL) { - start_timer(&variance_timer, 1000); - return; - } - - if (is_timer_expired(&variance_timer)) { - for (uint8_t c = 0; c < NUM_CHIPS; c++) { - for (uint8_t therm = 17; therm < 28; therm++) { - if (abs(segment_data[c] - .thermistor_reading[therm] - - previous_data[c] - .thermistor_reading[therm]) > - 5 && - (segment_data[c].thermistor_reading[therm] < - 10 || - segment_data[c].thermistor_reading[therm] > - 30)) { - segment_data[c] - .thermistor_reading[therm] = - previous_data[c] - .thermistor_reading - [therm]; - segment_data[c].thermistor_value[therm] = - previous_data[c] - .thermistor_value[therm]; - } - } - } - } +void variance_therm_check() { + if (previous_data == NULL) { + start_timer(&variance_timer, 1000); + return; + } + + if (is_timer_expired(&variance_timer)) { + for (uint8_t c = 0; c < NUM_CHIPS; c++) { + for (uint8_t therm = 17; therm < 28; therm++) { + if (abs(segment_data[c].thermistor_reading[therm] - + previous_data[c].thermistor_reading[therm]) > 5 && + (segment_data[c].thermistor_reading[therm] < 10 || + segment_data[c].thermistor_reading[therm] > 30)) { + segment_data[c].thermistor_reading[therm] = + previous_data[c].thermistor_reading[therm]; + segment_data[c].thermistor_value[therm] = + previous_data[c].thermistor_value[therm]; + } + } + } + } } -void discard_neutrals() -{ - for (uint8_t c = 0; c < NUM_CHIPS; c++) { - for (uint8_t therm = 17; therm < 28; therm++) { - if (segment_data[c].thermistor_reading[therm] == 33) { - segment_data[c].thermistor_reading[therm] = 25; - segment_data[c].thermistor_value[therm] = 25; - } - } - } +void discard_neutrals() { + for (uint8_t c = 0; c < NUM_CHIPS; c++) { + for (uint8_t therm = 17; therm < 28; therm++) { + if (segment_data[c].thermistor_reading[therm] == 33) { + segment_data[c].thermistor_reading[therm] = 25; + segment_data[c].thermistor_value[therm] = 25; + } + } + } } diff --git a/Core/Src/stateMachine.c b/Core/Src/stateMachine.c index 312b5da..4bdb8ca 100644 --- a/Core/Src/stateMachine.c +++ b/Core/Src/stateMachine.c @@ -1,6 +1,6 @@ #include "stateMachine.h" -#include #include +#include #define MIN(a, b) (((a) < (b)) ? (a) : (b)) extern UART_HandleTypeDef huart4; @@ -11,11 +11,11 @@ uint32_t bms_fault = FAULTS_CLEAR; BMSState_t current_state = BOOT_STATE; uint32_t previousFault = 0; -nertimer_t charger_settle_countup = { .active = false }; -nertimer_t charger_max_volt_timer = { .active = false }; -nertimer_t charger_settle_countdown = { .active = false }; +nertimer_t charger_settle_countup = {.active = false}; +nertimer_t charger_max_volt_timer = {.active = false}; +nertimer_t charger_settle_countdown = {.active = false}; -nertimer_t can_msg_timer = { .active = false }; +nertimer_t can_msg_timer = {.active = false}; extern TIM_HandleTypeDef htim1; extern TIM_HandleTypeDef htim8; @@ -28,11 +28,11 @@ nertimer_t bootup_timer; static const uint16_t CHARGE_MESSAGE_WAIT = 250; /* ms */ const bool valid_transition_from_to[NUM_STATES][NUM_STATES] = { - /* BOOT, READY, CHARGING, FAULTED */ - { true, true, false, true }, /* BOOT */ - { false, true, true, true }, /* READY */ - { false, true, true, true }, /* CHARGING */ - { true, false, false, true } /* FAULTED */ + /* BOOT, READY, CHARGING, FAULTED */ + {true, true, false, true}, /* BOOT */ + {false, true, true, true}, /* READY */ + {false, true, true, true}, /* CHARGING */ + {true, false, false, true} /* FAULTED */ }; /* private function prototypes */ @@ -49,155 +49,140 @@ void request_transition(BMSState_t next_state); typedef void (*HandlerFunction_t)(acc_data_t *bmsdata); typedef void (*InitFunction_t)(); -const InitFunction_t init_LUT[NUM_STATES] = { &init_boot, &init_ready, - &init_charging, &init_faulted }; +const InitFunction_t init_LUT[NUM_STATES] = {&init_boot, &init_ready, + &init_charging, &init_faulted}; -const HandlerFunction_t handler_LUT[NUM_STATES] = { &handle_boot, &handle_ready, - &handle_charging, - &handle_faulted }; +const HandlerFunction_t handler_LUT[NUM_STATES] = { + &handle_boot, &handle_ready, &handle_charging, &handle_faulted}; -void init_boot() -{ - return; -} +void init_boot() { return; } -void handle_boot(acc_data_t *bmsdata) -{ - prevAccData = NULL; - segment_enable_balancing(false); - compute_enable_charging(false); - start_timer(&bootup_timer, 10000); - printf("Bootup timer started\r\n"); +void handle_boot(acc_data_t *bmsdata) { + prevAccData = NULL; + segment_enable_balancing(false); + compute_enable_charging(false); + start_timer(&bootup_timer, 10000); + printf("Bootup timer started\r\n"); - compute_set_fault(1); - // bmsdata->fault_code = FAULTS_CLEAR; + compute_set_fault(1); + // bmsdata->fault_code = FAULTS_CLEAR; - request_transition(READY_STATE); - return; + request_transition(READY_STATE); + return; } -void init_ready() -{ - segment_enable_balancing(false); - compute_enable_charging(false); - return; +void init_ready() { + segment_enable_balancing(false); + compute_enable_charging(false); + return; } -void handle_ready(acc_data_t *bmsdata) -{ - /* check for charger connection */ - if (compute_charger_connected() && - is_timer_expired(&bootup_timer)) { //TODO Fix once charger works - request_transition(READY_STATE); - } else { - sm_broadcast_current_limit(bmsdata); - return; - } +void handle_ready(acc_data_t *bmsdata) { + /* check for charger connection */ + if (compute_charger_connected() && + is_timer_expired(&bootup_timer)) { // TODO Fix once charger works + request_transition(READY_STATE); + } else { + sm_broadcast_current_limit(bmsdata); + return; + } } -void init_charging() -{ - cancel_timer(&charger_settle_countup); - return; +void init_charging() { + cancel_timer(&charger_settle_countup); + return; } -void handle_charging(acc_data_t *bmsdata) -{ - if (!compute_charger_connected()) { - request_transition(READY_STATE); - return; - - } else { - /* Check if we should charge */ - if (sm_charging_check(bmsdata)) - compute_enable_charging(true); - else { - compute_enable_charging(false); - compute_send_charging_message(0, 0, bmsdata); - } +void handle_charging(acc_data_t *bmsdata) { + if (!compute_charger_connected()) { + request_transition(READY_STATE); + return; + + } else { + /* Check if we should charge */ + if (sm_charging_check(bmsdata)) + compute_enable_charging(true); + else { + compute_enable_charging(false); + compute_send_charging_message(0, 0, bmsdata); + } - /* Check if we should balance */ - if (sm_balancing_check(bmsdata)) - sm_balance_cells(bmsdata); - else - segment_enable_balancing(false); - - /* Send CAN message, but not too often */ - if (is_timer_expired(&charger_message_timer) || - !is_timer_active(&charger_message_timer)) { - compute_send_charging_message((MAX_CHARGE_VOLT * - NUM_CELLS_PER_CHIP * - NUM_CHIPS), - 5, bmsdata); - start_timer(&charger_message_timer, - CHARGE_MESSAGE_WAIT); - } - } + /* Check if we should balance */ + if (sm_balancing_check(bmsdata)) + sm_balance_cells(bmsdata); + else + segment_enable_balancing(false); + + /* Send CAN message, but not too often */ + if (is_timer_expired(&charger_message_timer) || + !is_timer_active(&charger_message_timer)) { + compute_send_charging_message( + (MAX_CHARGE_VOLT * NUM_CELLS_PER_CHIP * NUM_CHIPS), 5, bmsdata); + start_timer(&charger_message_timer, CHARGE_MESSAGE_WAIT); + } + } } -void init_faulted() -{ - segment_enable_balancing(false); - compute_enable_charging(false); - entered_faulted = true; - return; +void init_faulted() { + segment_enable_balancing(false); + compute_enable_charging(false); + entered_faulted = true; + return; } -void handle_faulted(acc_data_t *bmsdata) -{ - if (entered_faulted) { - entered_faulted = false; - previousFault = sm_fault_return(bmsdata); - } - - if (bmsdata->fault_code == FAULTS_CLEAR) { - compute_set_fault(1); - request_transition(BOOT_STATE); - return; - } - - else { - compute_set_fault(0); - - //TODO update to HAL - //digitalWrite(CHARGE_SAFETY_RELAY, 0); - } - return; +void handle_faulted(acc_data_t *bmsdata) { + if (entered_faulted) { + entered_faulted = false; + previousFault = sm_fault_return(bmsdata); + } + + if (bmsdata->fault_code == FAULTS_CLEAR) { + compute_set_fault(1); + request_transition(BOOT_STATE); + return; + } + + else { + compute_set_fault(0); + + // TODO update to HAL + // digitalWrite(CHARGE_SAFETY_RELAY, 0); + } + return; } -void sm_handle_state(acc_data_t *bmsdata) -{ - static uint8_t can_msg_to_send = 0; - enum { - ACC_STATUS, - CURRENT, - BMS_STATUS, - CELL_TEMP, - CELL_DATA, - SEGMENT_TEMP, - MC_DISCHARGE, - MC_CHARGE, - CAN_DEBUG, - MAX_MSGS - }; - - bmsdata->fault_code = sm_fault_return(bmsdata); - - //calculate_pwm(bmsdata); - - if (bmsdata->fault_code != FAULTS_CLEAR) { - bmsdata->discharge_limit = 0; - request_transition(FAULTED_STATE); - } - // TODO needs testing - (update, seems to work fine) - handler_LUT[current_state](bmsdata); - - bmsdata->is_charger_connected = compute_charger_connected(); - - sm_broadcast_current_limit(bmsdata); - - /* send relevant CAN msgs */ - // clang-format off +void sm_handle_state(acc_data_t *bmsdata) { + static uint8_t can_msg_to_send = 0; + enum { + ACC_STATUS, + CURRENT, + BMS_STATUS, + CELL_TEMP, + CELL_DATA, + SEGMENT_TEMP, + MC_DISCHARGE, + MC_CHARGE, + CAN_DEBUG, + MAX_MSGS + }; + + bmsdata->fault_code = sm_fault_return(bmsdata); + + // calculate_pwm(bmsdata); + + if (bmsdata->fault_code != FAULTS_CLEAR) { + bmsdata->discharge_limit = 0; + request_transition(FAULTED_STATE); + } + // TODO needs testing - (update, seems to work fine) + handler_LUT[current_state](bmsdata); + + bmsdata->is_charger_connected = compute_charger_connected(); + + sm_broadcast_current_limit(bmsdata); + + /* send relevant CAN msgs */ + // clang-format off if (is_timer_expired(&can_msg_timer) || !is_timer_active(&can_msg_timer)) { switch (can_msg_to_send) { @@ -236,41 +221,39 @@ void sm_handle_state(acc_data_t *bmsdata) start_timer(&can_msg_timer, CAN_MESSAGE_WAIT); can_msg_to_send = (can_msg_to_send + 1) % MAX_MSGS; } - // clang-format on + // clang-format on } -void request_transition(BMSState_t next_state) -{ - if (current_state == next_state) - return; - if (!valid_transition_from_to[current_state][next_state]) - return; +void request_transition(BMSState_t next_state) { + if (current_state == next_state) + return; + if (!valid_transition_from_to[current_state][next_state]) + return; - init_LUT[next_state](); - current_state = next_state; + init_LUT[next_state](); + current_state = next_state; } -uint32_t sm_fault_return(acc_data_t *accData) -{ - /* FAULT CHECK (Check for fuckies) */ - - static nertimer_t ovr_curr_timer = { 0 }; - static nertimer_t ovr_chgcurr_timer = { 0 }; - static nertimer_t undr_volt_timer = { 0 }; - static nertimer_t ovr_chgvolt_timer = { 0 }; - static nertimer_t ovr_volt_timer = { 0 }; - static nertimer_t low_cell_timer = { 0 }; - static nertimer_t high_temp_timer = { 0 }; - static fault_eval_t *fault_table = NULL; - static acc_data_t *fault_data = NULL; - - fault_data = accData; - - if (!fault_table) { - /* Note that we are only allocating this table once at runtime, so there is no need to free it */ - fault_table = (fault_eval_t *)malloc(NUM_FAULTS * - sizeof(fault_eval_t)); - // clang-format off +uint32_t sm_fault_return(acc_data_t *accData) { + /* FAULT CHECK (Check for fuckies) */ + + static nertimer_t ovr_curr_timer = {0}; + static nertimer_t ovr_chgcurr_timer = {0}; + static nertimer_t undr_volt_timer = {0}; + static nertimer_t ovr_chgvolt_timer = {0}; + static nertimer_t ovr_volt_timer = {0}; + static nertimer_t low_cell_timer = {0}; + static nertimer_t high_temp_timer = {0}; + static fault_eval_t *fault_table = NULL; + static acc_data_t *fault_data = NULL; + + fault_data = accData; + + if (!fault_table) { + /* Note that we are only allocating this table once at runtime, so there is + * no need to free it */ + fault_table = (fault_eval_t *)malloc(NUM_FAULTS * sizeof(fault_eval_t)); + // clang-format off // ___________FAULT ID____________ __________TIMER___________ _____________DATA________________ __OPERATOR__ __________________________THRESHOLD____________________________ _______TIMER LENGTH_________ _____________FAULT CODE_________________ ___OPERATOR 2__ _______________DATA 2______________ __THRESHOLD 2__ fault_table[0] = (fault_eval_t) {.id = "Discharge Current Limit", .timer = ovr_curr_timer, .data_1 = fault_data->pack_current, .optype_1 = GT, .lim_1 = (fault_data->discharge_limit + DCDC_CURRENT_DRAW)*10 * CURR_ERR_MARG, .timeout = OVER_CURR_TIME, .code = DISCHARGE_LIMIT_ENFORCEMENT_FAULT, .optype_2 = NOP/* ---------------------------UNUSED------------------- */ }; fault_table[1] = (fault_eval_t) {.id = "Charge Current Limit", .timer = ovr_chgcurr_timer, .data_1 = fault_data->pack_current, .optype_1 = GT, .lim_1 = (fault_data->charge_limit)*10, .timeout = OVER_CHG_CURR_TIME, .code = CHARGE_LIMIT_ENFORCEMENT_FAULT, .optype_2 = LT, .data_2 = fault_data->pack_current, .lim_2 = 0 }; @@ -288,41 +271,39 @@ uint32_t sm_fault_return(acc_data_t *accData) cancel_timer(&ovr_volt_timer); cancel_timer(&low_cell_timer); cancel_timer(&high_temp_timer); - // clang-format on - } - - 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; - fault_table[4].data_2 = fault_data->is_charger_connected; - 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; + // clang-format on + } + + 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; + fault_table[4].data_2 = fault_data->is_charger_connected; + 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; } -uint32_t sm_fault_eval(fault_eval_t *index) -{ - bool condition1; - bool condition2; +uint32_t sm_fault_eval(fault_eval_t *index) { + bool condition1; + bool condition2; - // clang-format off + // clang-format off switch (index->optype_1) { case GT: condition1 = index->data_1 > index->lim_1; break; @@ -346,230 +327,222 @@ uint32_t sm_fault_eval(fault_eval_t *index) case NOP: condition2 = false; default: condition2 = false; } - // clang-format on - - bool fault_present = ((condition1 && condition2) || - (condition1 && (index->optype_2 == NOP))); - if ((!(is_timer_active(&index->timer))) && !fault_present) { - return 0; - } - - if (is_timer_active(&index->timer)) { - if (!fault_present) { - printf("\t\t\t*******Fault cleared: %s\r\n", index->id); - cancel_timer(&index->timer); - return 0; - } + // clang-format on + + bool fault_present = + ((condition1 && condition2) || (condition1 && (index->optype_2 == NOP))); + if ((!(is_timer_active(&index->timer))) && !fault_present) { + return 0; + } + + if (is_timer_active(&index->timer)) { + if (!fault_present) { + printf("\t\t\t*******Fault cleared: %s\r\n", index->id); + cancel_timer(&index->timer); + return 0; + } - 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; - } + 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 + 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); - } + 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) { - printf("\t\t\t*******Not fautled!!!!!\t%d\r\n", !is_timer_active(&index->timer) && condition1 && condition2); - printf("More stats...\t:%d\t%d\r\n", is_timer_expired(&index->timer), index->timer.active); - } */ - printf("err should not get here"); - return 0; + return 0; + } + /* if (index->code == CELL_VOLTAGE_TOO_LOW) { + printf("\t\t\t*******Not fautled!!!!!\t%d\r\n", + !is_timer_active(&index->timer) && condition1 && condition2); printf("More + stats...\t:%d\t%d\r\n", is_timer_expired(&index->timer), index->timer.active); + } */ + printf("err should not get here"); + return 0; } -/* charger settle countup = 1 minute pause to let readings settle and get good OCV */ -/* charger settle countdown = 5 minute interval between 1 minute settle pauses */ -/* charger_max_volt_timer = interval of time when voltage is too high before trying to start again */ -bool sm_charging_check(acc_data_t *bmsdata) -{ - if (!compute_charger_connected()) { - printf("Charger not connected\r\n"); - return false; - } - - if (!is_timer_expired(&charger_settle_countup) && - is_timer_active(&charger_settle_countup)) { - printf("Charger settle countup active\r\n"); - return false; - } - - if (!is_timer_expired(&charger_max_volt_timer) && - is_timer_active(&charger_max_volt_timer)) { - printf("Charger max volt timer active\r\n"); - return false; - } - - if (bmsdata->max_voltage.val > MAX_CHARGE_VOLT * 10000) { - start_timer(&charger_max_volt_timer, CHARGE_VOLT_TIMEOUT); - printf("Charger max volt timer started\r\n"); - printf("Max voltage: %d\r\n", bmsdata->max_voltage.val); - return false; - } - - if (is_timer_active(&charger_settle_countdown)) { - if (is_timer_expired(&charger_settle_countdown)) { - start_timer(&charger_settle_countup, - CHARGE_SETL_TIMEOUT); - return false; - } +/* charger settle countup = 1 minute pause to let readings settle and get good + * OCV */ +/* charger settle countdown = 5 minute interval between 1 minute settle pauses + */ +/* charger_max_volt_timer = interval of time when voltage is too high before + * trying to start again */ +bool sm_charging_check(acc_data_t *bmsdata) { + if (!compute_charger_connected()) { + printf("Charger not connected\r\n"); + return false; + } + + if (!is_timer_expired(&charger_settle_countup) && + is_timer_active(&charger_settle_countup)) { + printf("Charger settle countup active\r\n"); + return false; + } + + if (!is_timer_expired(&charger_max_volt_timer) && + is_timer_active(&charger_max_volt_timer)) { + printf("Charger max volt timer active\r\n"); + return false; + } + + if (bmsdata->max_voltage.val > MAX_CHARGE_VOLT * 10000) { + start_timer(&charger_max_volt_timer, CHARGE_VOLT_TIMEOUT); + printf("Charger max volt timer started\r\n"); + printf("Max voltage: %d\r\n", bmsdata->max_voltage.val); + return false; + } + + if (is_timer_active(&charger_settle_countdown)) { + if (is_timer_expired(&charger_settle_countdown)) { + start_timer(&charger_settle_countup, CHARGE_SETL_TIMEOUT); + return false; + } - else - return true; - } + else + return true; + } - else { - start_timer(&charger_settle_countdown, CHARGE_SETL_TIMEUP); - return true; - } + else { + start_timer(&charger_settle_countdown, CHARGE_SETL_TIMEUP); + return true; + } } -bool sm_balancing_check(acc_data_t *bmsdata) -{ - if (!compute_charger_connected()) - return false; - if (bmsdata->max_temp.val > MAX_CELL_TEMP_BAL) - return false; - if (bmsdata->max_voltage.val <= (BAL_MIN_V * 10000)) - return false; - if (bmsdata->delt_voltage <= (MAX_DELTA_V * 10000)) - return false; - - if (is_timer_active(&charger_settle_countup) && - !is_timer_expired(&charger_settle_countup)) - return false; - - return true; +bool sm_balancing_check(acc_data_t *bmsdata) { + if (!compute_charger_connected()) + return false; + if (bmsdata->max_temp.val > MAX_CELL_TEMP_BAL) + return false; + if (bmsdata->max_voltage.val <= (BAL_MIN_V * 10000)) + return false; + if (bmsdata->delt_voltage <= (MAX_DELTA_V * 10000)) + return false; + + if (is_timer_active(&charger_settle_countup) && + !is_timer_expired(&charger_settle_countup)) + return false; + + return true; } -void sm_broadcast_current_limit(acc_data_t *bmsdata) -{ - // States for Boosting State Machine - static enum { BOOST_STANDBY, BOOSTING, BOOST_RECHARGE } BoostState; - - static nertimer_t boost_timer; - static nertimer_t boost_recharge_timer; - - /* Transitioning out of boost */ - if (is_timer_expired(&boost_timer) && BoostState == BOOSTING) { - BoostState = BOOST_RECHARGE; - start_timer(&boost_recharge_timer, BOOST_RECHARGE_TIME); - } - /* Transition out of boost recharge */ - if (is_timer_expired(&boost_recharge_timer) && - BoostState == BOOST_RECHARGE) { - BoostState = BOOST_STANDBY; - } - /* Transition to boosting */ - if ((bmsdata->pack_current) > ((bmsdata->cont_DCL) * 10) && - BoostState == BOOST_STANDBY) { - BoostState = BOOSTING; - start_timer(&boost_timer, BOOST_TIME); - } - - /* Currently boosting */ - if (BoostState == BOOSTING || BoostState == BOOST_STANDBY) { - bmsdata->boost_setting = - MIN(bmsdata->discharge_limit, - bmsdata->cont_DCL * CONTDCL_MULTIPLIER); - } - - /* Currently recharging boost */ - else { - bmsdata->boost_setting = - MIN(bmsdata->cont_DCL, bmsdata->discharge_limit); - } +void sm_broadcast_current_limit(acc_data_t *bmsdata) { + // States for Boosting State Machine + static enum { BOOST_STANDBY, BOOSTING, BOOST_RECHARGE } BoostState; + + static nertimer_t boost_timer; + static nertimer_t boost_recharge_timer; + + /* Transitioning out of boost */ + if (is_timer_expired(&boost_timer) && BoostState == BOOSTING) { + BoostState = BOOST_RECHARGE; + start_timer(&boost_recharge_timer, BOOST_RECHARGE_TIME); + } + /* Transition out of boost recharge */ + if (is_timer_expired(&boost_recharge_timer) && BoostState == BOOST_RECHARGE) { + BoostState = BOOST_STANDBY; + } + /* Transition to boosting */ + if ((bmsdata->pack_current) > ((bmsdata->cont_DCL) * 10) && + BoostState == BOOST_STANDBY) { + BoostState = BOOSTING; + start_timer(&boost_timer, BOOST_TIME); + } + + /* Currently boosting */ + if (BoostState == BOOSTING || BoostState == BOOST_STANDBY) { + bmsdata->boost_setting = + MIN(bmsdata->discharge_limit, bmsdata->cont_DCL * CONTDCL_MULTIPLIER); + } + + /* Currently recharging boost */ + else { + bmsdata->boost_setting = MIN(bmsdata->cont_DCL, bmsdata->discharge_limit); + } } -void sm_balance_cells(acc_data_t *bms_data) -{ - bool balanceConfig[NUM_CHIPS][NUM_CELLS_PER_CHIP]; - - /* For all cells of all the chips, figure out if we need to balance by comparing the difference - * 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[cell] - - (uint16_t)bms_data->min_voltage.val; - if (delta > MAX_DELTA_V * 10000) - balanceConfig[chip][cell] = true; - else - balanceConfig[chip][cell] = false; - } - } +void sm_balance_cells(acc_data_t *bms_data) { + bool balanceConfig[NUM_CHIPS][NUM_CELLS_PER_CHIP]; + + /* For all cells of all the chips, figure out if we need to balance by + * comparing the difference 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[cell] - + (uint16_t)bms_data->min_voltage.val; + if (delta > MAX_DELTA_V * 10000) + balanceConfig[chip][cell] = true; + else + balanceConfig[chip][cell] = false; + } + } #ifdef DEBUG_CHARGING - printf("Cell Balancing:"); - for (uint8_t c = 0; c < NUM_CHIPS; c++) { - for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { - printf(balanceConfig[c][cell]); - printf("\t"); - } - printf("\n"); - } + printf("Cell Balancing:"); + for (uint8_t c = 0; c < NUM_CHIPS; c++) { + for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { + printf(balanceConfig[c][cell]); + printf("\t"); + } + printf("\n"); + } #endif - segment_configure_balancing(balanceConfig); + segment_configure_balancing(balanceConfig); } -void calculate_pwm(acc_data_t *bmsdata) -{ - // todo actually implement algorithm - // this should include: - // 1. set PWM based on temp of "nearby" cells - // 2. automate seleciton of htim rather than hardcode - - if (bmsdata->max_temp.val > 50) { - compute_set_fan_speed(&htim1, FAN1, 100); - compute_set_fan_speed(&htim1, FAN2, 100); - compute_set_fan_speed(&htim8, FAN3, 100); - compute_set_fan_speed(&htim8, FAN4, 100); - compute_set_fan_speed(&htim8, FAN5, 100); - compute_set_fan_speed(&htim8, FAN6, 100); - return; - } - - else if (bmsdata->max_temp.val > 40) { - compute_set_fan_speed(&htim1, FAN1, 50); - compute_set_fan_speed(&htim1, FAN2, 50); - compute_set_fan_speed(&htim8, FAN3, 50); - compute_set_fan_speed(&htim8, FAN4, 50); - compute_set_fan_speed(&htim8, FAN5, 50); - compute_set_fan_speed(&htim8, FAN6, 50); - return; - } - - else if (bmsdata->max_temp.val > 30) { - compute_set_fan_speed(&htim1, FAN1, 25); - compute_set_fan_speed(&htim1, FAN2, 25); - compute_set_fan_speed(&htim8, FAN3, 25); - compute_set_fan_speed(&htim8, FAN4, 25); - compute_set_fan_speed(&htim8, FAN5, 25); - compute_set_fan_speed(&htim8, FAN6, 25); - return; - } - - else { - compute_set_fan_speed(&htim1, FAN1, 0); - compute_set_fan_speed(&htim1, FAN2, 0); - compute_set_fan_speed(&htim8, FAN3, 0); - compute_set_fan_speed(&htim8, FAN4, 0); - compute_set_fan_speed(&htim8, FAN5, 0); - compute_set_fan_speed(&htim8, FAN6, 0); - return; - } +void calculate_pwm(acc_data_t *bmsdata) { + // todo actually implement algorithm + // this should include: + // 1. set PWM based on temp of "nearby" cells + // 2. automate seleciton of htim rather than hardcode + + if (bmsdata->max_temp.val > 50) { + compute_set_fan_speed(&htim1, FAN1, 100); + compute_set_fan_speed(&htim1, FAN2, 100); + compute_set_fan_speed(&htim8, FAN3, 100); + compute_set_fan_speed(&htim8, FAN4, 100); + compute_set_fan_speed(&htim8, FAN5, 100); + compute_set_fan_speed(&htim8, FAN6, 100); + return; + } + + else if (bmsdata->max_temp.val > 40) { + compute_set_fan_speed(&htim1, FAN1, 50); + compute_set_fan_speed(&htim1, FAN2, 50); + compute_set_fan_speed(&htim8, FAN3, 50); + compute_set_fan_speed(&htim8, FAN4, 50); + compute_set_fan_speed(&htim8, FAN5, 50); + compute_set_fan_speed(&htim8, FAN6, 50); + return; + } + + else if (bmsdata->max_temp.val > 30) { + compute_set_fan_speed(&htim1, FAN1, 25); + compute_set_fan_speed(&htim1, FAN2, 25); + compute_set_fan_speed(&htim8, FAN3, 25); + compute_set_fan_speed(&htim8, FAN4, 25); + compute_set_fan_speed(&htim8, FAN5, 25); + compute_set_fan_speed(&htim8, FAN6, 25); + return; + } + + else { + compute_set_fan_speed(&htim1, FAN1, 0); + compute_set_fan_speed(&htim1, FAN2, 0); + compute_set_fan_speed(&htim8, FAN3, 0); + compute_set_fan_speed(&htim8, FAN4, 0); + compute_set_fan_speed(&htim8, FAN5, 0); + compute_set_fan_speed(&htim8, FAN6, 0); + return; + } } From 09750a5d18111584e157bf6cf63211ed4156e93c Mon Sep 17 00:00:00 2001 From: dyldonahue Date: Fri, 20 Sep 2024 12:31:19 -0400 Subject: [PATCH 3/5] actual clang --- Core/Src/compute.c | 1057 +++++++++++++++++++------------------ Core/Src/segment.c | 1094 +++++++++++++++++++++------------------ Core/Src/stateMachine.c | 756 ++++++++++++++------------- 3 files changed, 1542 insertions(+), 1365 deletions(-) diff --git a/Core/Src/compute.c b/Core/Src/compute.c index a6b0cd8..77208d9 100644 --- a/Core/Src/compute.c +++ b/Core/Src/compute.c @@ -11,7 +11,7 @@ #define MAX_CAN1_STORAGE 10 #define MAX_CAN2_STORAGE 10 -#define REF_CHANNEL 0 +#define REF_CHANNEL 0 #define VOUT_CHANNEL 1 // #define CHARGING_ENABLED @@ -32,114 +32,117 @@ extern ADC_HandleTypeDef hadc2; TIM_OC_InitTypeDef pwm_config; ADC_ChannelConfTypeDef adc_config; -const uint32_t fan_channels[6] = {TIM_CHANNEL_3, TIM_CHANNEL_1, TIM_CHANNEL_4, - TIM_CHANNEL_3, TIM_CHANNEL_2, TIM_CHANNEL_1}; +const uint32_t fan_channels[6] = { TIM_CHANNEL_3, TIM_CHANNEL_1, TIM_CHANNEL_4, + TIM_CHANNEL_3, TIM_CHANNEL_2, TIM_CHANNEL_1 }; can_t can1; // main can bus, used by most peripherals can_t can2; // p2p can bus with charger -uint32_t adc_values[2] = {0}; +uint32_t adc_values[2] = { 0 }; /* private function defintions */ float read_ref_voltage(); float read_vout(); -uint8_t compute_init() { - // TODO throw all of these objects into a compute struct - can1.hcan = &hcan1; - can1.id_list = can1_id_list; - can1.id_list_len = sizeof(can1_id_list) / sizeof(can1_id_list[0]); - // can1.callback = can_receive_callback; - can1_rx_queue = ringbuffer_create(MAX_CAN1_STORAGE, sizeof(can_msg_t)); - can_init(&can1); - - can2.hcan = &hcan2; - can2.id_list = can2_id_list; - can2.id_list_len = sizeof(can2_id_list) / sizeof(can2_id_list[0]); - // can2.callback = can_receive_callback; - can2_rx_queue = ringbuffer_create(MAX_CAN2_STORAGE, sizeof(can_msg_t)); - can_init(&can2); - - pwm_config.OCMode = TIM_OCMODE_PWM1; - pwm_config.Pulse = 0; - pwm_config.OCPolarity = TIM_OCPOLARITY_HIGH; - pwm_config.OCFastMode = TIM_OCFAST_DISABLE; - - if (HAL_TIM_PWM_ConfigChannel(&htim1, &pwm_config, fan_channels[FAN1]) != - HAL_OK) - return -1; - if (HAL_TIM_PWM_ConfigChannel(&htim8, &pwm_config, fan_channels[FAN2]) != - HAL_OK) - return -1; - - // HAL_TIM_PWM_Start(&htim1, fan_channels[FAN1]); - // HAL_TIM_PWM_Start(&htim1, fan_channels[FAN2]); - // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN3]); - // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN4]); - // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN5]); - // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN6]); - bmsdata->is_charger_connected = false; - - HAL_ADC_Start(&hadc2); - - return 0; +uint8_t compute_init() +{ + // TODO throw all of these objects into a compute struct + can1.hcan = &hcan1; + can1.id_list = can1_id_list; + can1.id_list_len = sizeof(can1_id_list) / sizeof(can1_id_list[0]); + // can1.callback = can_receive_callback; + can1_rx_queue = ringbuffer_create(MAX_CAN1_STORAGE, sizeof(can_msg_t)); + can_init(&can1); + + can2.hcan = &hcan2; + can2.id_list = can2_id_list; + can2.id_list_len = sizeof(can2_id_list) / sizeof(can2_id_list[0]); + // can2.callback = can_receive_callback; + can2_rx_queue = ringbuffer_create(MAX_CAN2_STORAGE, sizeof(can_msg_t)); + can_init(&can2); + + pwm_config.OCMode = TIM_OCMODE_PWM1; + pwm_config.Pulse = 0; + pwm_config.OCPolarity = TIM_OCPOLARITY_HIGH; + pwm_config.OCFastMode = TIM_OCFAST_DISABLE; + + if (HAL_TIM_PWM_ConfigChannel(&htim1, &pwm_config, + fan_channels[FAN1]) != HAL_OK) + return -1; + if (HAL_TIM_PWM_ConfigChannel(&htim8, &pwm_config, + fan_channels[FAN2]) != HAL_OK) + return -1; + + // HAL_TIM_PWM_Start(&htim1, fan_channels[FAN1]); + // HAL_TIM_PWM_Start(&htim1, fan_channels[FAN2]); + // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN3]); + // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN4]); + // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN5]); + // HAL_TIM_PWM_Start(&htim8, fan_channels[FAN6]); + bmsdata->is_charger_connected = false; + + HAL_ADC_Start(&hadc2); + + return 0; } -void compute_enable_charging(bool enable_charging) { - is_charging_enabled = enable_charging; +void compute_enable_charging(bool enable_charging) +{ + is_charging_enabled = enable_charging; } int compute_send_charging_message(uint16_t voltage_to_set, - uint16_t current_to_set, - acc_data_t *bms_data) { - struct __attribute__((__packed__)) { - uint16_t charger_voltage; // Note the charger voltage sent over should be - // 10*desired voltage - uint16_t charger_current; // Note the charge current sent over should be - // 10*desired current - uint8_t charger_control; - uint8_t reserved_1; - uint16_t reserved_23; - } charger_msg_data; - - charger_msg_data.charger_voltage = voltage_to_set * 10; - charger_msg_data.charger_current = current_to_set * 10; - - if (is_charging_enabled) { - charger_msg_data.charger_control = 0x00; // 0:Start charging. - } else { - charger_msg_data.charger_control = - 0xFF; // 1:battery protection, stop charging - } - - charger_msg_data.reserved_1 = 0x00; - charger_msg_data.reserved_23 = 0x0000; - - can_msg_t charger_msg; - charger_msg.id = 0x1806E5F4; - charger_msg.len = 8; - memcpy(charger_msg.data, &charger_msg_data, sizeof(charger_msg_data)); - - uint8_t temp = charger_msg.data[0]; - charger_msg.data[0] = charger_msg.data[1]; - charger_msg.data[1] = temp; - temp = charger_msg.data[2]; - charger_msg.data[2] = charger_msg.data[3]; - charger_msg.data[3] = temp; + uint16_t current_to_set, acc_data_t *bms_data) +{ + struct __attribute__((__packed__)) { + uint16_t charger_voltage; // Note the charger voltage sent over should be + // 10*desired voltage + uint16_t charger_current; // Note the charge current sent over should be + // 10*desired current + uint8_t charger_control; + uint8_t reserved_1; + uint16_t reserved_23; + } charger_msg_data; + + charger_msg_data.charger_voltage = voltage_to_set * 10; + charger_msg_data.charger_current = current_to_set * 10; + + if (is_charging_enabled) { + charger_msg_data.charger_control = 0x00; // 0:Start charging. + } else { + charger_msg_data.charger_control = + 0xFF; // 1:battery protection, stop charging + } + + charger_msg_data.reserved_1 = 0x00; + charger_msg_data.reserved_23 = 0x0000; + + can_msg_t charger_msg; + charger_msg.id = 0x1806E5F4; + charger_msg.len = 8; + memcpy(charger_msg.data, &charger_msg_data, sizeof(charger_msg_data)); + + uint8_t temp = charger_msg.data[0]; + charger_msg.data[0] = charger_msg.data[1]; + charger_msg.data[1] = temp; + temp = charger_msg.data[2]; + charger_msg.data[2] = charger_msg.data[3]; + charger_msg.data[3] = temp; #ifdef CHARGING_ENABLED - HAL_StatusTypeDef res = can_send_extended_msg(&can2, &charger_msg); - if (res != HAL_OK) { - printf("CAN ERROR CODE %X", res); - } + HAL_StatusTypeDef res = can_send_extended_msg(&can2, &charger_msg); + if (res != HAL_OK) { + printf("CAN ERROR CODE %X", res); + } #endif - return 0; + return 0; } -bool compute_charger_connected() { - // TODO need to set up CAN msg that actually toggles this bool - return false; // bmsdata->is_charger_connected; +bool compute_charger_connected() +{ + // TODO need to set up CAN msg that actually toggles this bool + return false; // bmsdata->is_charger_connected; } // TODO add this back @@ -149,527 +152,561 @@ bool compute_charger_connected() { // } uint8_t compute_set_fan_speed(TIM_HandleTypeDef *pwmhandle, - fan_select_t fan_select, uint8_t duty_cycle) { - if (!pwmhandle) - return -1; - if (fan_select >= FANMAX) - return -1; - if (duty_cycle > 100) - return -1; - - uint32_t CCR_value = 0; - uint32_t channel = fan_channels[fan_select]; - - CCR_value = (pwmhandle->Instance->ARR * duty_cycle) / 100; - __HAL_TIM_SET_COMPARE(pwmhandle, channel, CCR_value); - - return 0; + fan_select_t fan_select, uint8_t duty_cycle) +{ + if (!pwmhandle) + return -1; + if (fan_select >= FANMAX) + return -1; + if (duty_cycle > 100) + return -1; + + uint32_t CCR_value = 0; + uint32_t channel = fan_channels[fan_select]; + + CCR_value = (pwmhandle->Instance->ARR * duty_cycle) / 100; + __HAL_TIM_SET_COMPARE(pwmhandle, channel, CCR_value); + + return 0; } -void compute_set_fault(int fault_state) { - // TODO work with charger fw on this - HAL_GPIO_WritePin(GPIOA, Fault_Output_Pin, !fault_state); - // if (true) digitalWrite(CHARGE_SAFETY_RELAY, 1); +void compute_set_fault(int fault_state) +{ + // TODO work with charger fw on this + HAL_GPIO_WritePin(GPIOA, Fault_Output_Pin, !fault_state); + // if (true) digitalWrite(CHARGE_SAFETY_RELAY, 1); } -int16_t compute_get_pack_current() { - // static const float GAIN = 5.00; // mV/A - // static const float OFFSET = 0.0; // mV - // static const uint8_t num_samples = 10; - // static int16_t current_accumulator = 0.0; // A - - // /* starting equation : Vout = Vref + Voffset + (Gain * Ip) */ - // float ref_voltage = read_ref_voltage(); - // float vout = read_vout(); - - // ref_voltage *= 1000;// convert to mV - // vout *= 1000; - - // int16_t current = (vout - ref_voltage - OFFSET) / (GAIN); // convert to V - - // /* Low Pass Filter of Current*/ - // current = ((current_accumulator * (num_samples - 1)) + current) / - // num_samples; current_accumulator = current; - - // return current; - - static const float CURRENT_LOWCHANNEL_MAX = 75.0; // Amps - static const float CURRENT_LOWCHANNEL_MIN = -75.0; // Amps - // static const float CURRENT_SUPPLY_VOLTAGE = 5.038; - static const float CURRENT_ADC_RESOLUTION = 5.0 / MAX_ADC_RESOLUTION; - - static const float CURRENT_LOWCHANNEL_OFFSET = - 2.500; // Calibrated with current = 0A - static const float CURRENT_HIGHCHANNEL_OFFSET = - 2.500; // Calibrated with current = 0A - - static const float HIGHCHANNEL_GAIN = - 1 / 0.0041; // Calibrated with current = 5A, 10A, 20A - static const float LOWCHANNEL_GAIN = 1 / 0.0267; - - // Change ADC channel to read the high current sensor - change_adc1_channel(VOUT_CHANNEL); - HAL_ADC_Start(&hadc1); - HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); - int raw_low_current = HAL_ADC_GetValue(&hadc1); - - HAL_ADC_Start(&hadc2); - HAL_ADC_PollForConversion(&hadc2, HAL_MAX_DELAY); - int raw_high_current = HAL_ADC_GetValue(&hadc2); - - change_adc1_channel(REF_CHANNEL); - HAL_ADC_Start(&hadc1); - HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); - int ref_5V = HAL_ADC_GetValue(&hadc1); - - int16_t ref_voltage_raw = - (int16_t)(1000.0f * ((float)ref_5V * CURRENT_ADC_RESOLUTION)); - - int16_t high_current_voltage_raw = - (int16_t)(1000.0f * ((float)raw_high_current * CURRENT_ADC_RESOLUTION)); - high_current_voltage_raw = - (int16_t)(5000.0f * high_current_voltage_raw / (float)ref_voltage_raw); - - int16_t high_current = - (high_current_voltage_raw - (1000 * CURRENT_HIGHCHANNEL_OFFSET)) * - (1 / 4.0f); //* (HIGHCHANNEL_GAIN/100.0f))/1000; - - int16_t low_current_voltage_raw = - (int16_t)(1000.0f * ((float)raw_low_current * CURRENT_ADC_RESOLUTION)); - low_current_voltage_raw = - (int16_t)(5000.0f * low_current_voltage_raw / (float)ref_voltage_raw); - - int16_t low_current = - (float)(low_current_voltage_raw - (1000 * CURRENT_LOWCHANNEL_OFFSET)) * - (1 / 26.7); //* (LOWCHANNEL_GAIN/100.0f))/1000; - - // If the current is scoped within the range of the low channel, use the low - // channel - - if ((low_current < CURRENT_LOWCHANNEL_MAX - 5.0 && low_current >= 0) || - (low_current > CURRENT_LOWCHANNEL_MIN + 5.0 && low_current < 0)) { - // printf("\rLow Current: %d\n", -low_current); - return -low_current; - } - - // printf("\rHigh Current: %d\n", -high_current); - return -high_current; +int16_t compute_get_pack_current() +{ + // static const float GAIN = 5.00; // mV/A + // static const float OFFSET = 0.0; // mV + // static const uint8_t num_samples = 10; + // static int16_t current_accumulator = 0.0; // A + + // /* starting equation : Vout = Vref + Voffset + (Gain * Ip) */ + // float ref_voltage = read_ref_voltage(); + // float vout = read_vout(); + + // ref_voltage *= 1000;// convert to mV + // vout *= 1000; + + // int16_t current = (vout - ref_voltage - OFFSET) / (GAIN); // convert to V + + // /* Low Pass Filter of Current*/ + // current = ((current_accumulator * (num_samples - 1)) + current) / + // num_samples; current_accumulator = current; + + // return current; + + static const float CURRENT_LOWCHANNEL_MAX = 75.0; // Amps + static const float CURRENT_LOWCHANNEL_MIN = -75.0; // Amps + // static const float CURRENT_SUPPLY_VOLTAGE = 5.038; + static const float CURRENT_ADC_RESOLUTION = 5.0 / MAX_ADC_RESOLUTION; + + static const float CURRENT_LOWCHANNEL_OFFSET = + 2.500; // Calibrated with current = 0A + static const float CURRENT_HIGHCHANNEL_OFFSET = + 2.500; // Calibrated with current = 0A + + static const float HIGHCHANNEL_GAIN = + 1 / 0.0041; // Calibrated with current = 5A, 10A, 20A + static const float LOWCHANNEL_GAIN = 1 / 0.0267; + + // Change ADC channel to read the high current sensor + change_adc1_channel(VOUT_CHANNEL); + HAL_ADC_Start(&hadc1); + HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); + int raw_low_current = HAL_ADC_GetValue(&hadc1); + + HAL_ADC_Start(&hadc2); + HAL_ADC_PollForConversion(&hadc2, HAL_MAX_DELAY); + int raw_high_current = HAL_ADC_GetValue(&hadc2); + + change_adc1_channel(REF_CHANNEL); + HAL_ADC_Start(&hadc1); + HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); + int ref_5V = HAL_ADC_GetValue(&hadc1); + + int16_t ref_voltage_raw = + (int16_t)(1000.0f * ((float)ref_5V * CURRENT_ADC_RESOLUTION)); + + int16_t high_current_voltage_raw = + (int16_t)(1000.0f * + ((float)raw_high_current * CURRENT_ADC_RESOLUTION)); + high_current_voltage_raw = + (int16_t)(5000.0f * high_current_voltage_raw / + (float)ref_voltage_raw); + + int16_t high_current = (high_current_voltage_raw - + (1000 * CURRENT_HIGHCHANNEL_OFFSET)) * + (1 / 4.0f); //* (HIGHCHANNEL_GAIN/100.0f))/1000; + + int16_t low_current_voltage_raw = + (int16_t)(1000.0f * + ((float)raw_low_current * CURRENT_ADC_RESOLUTION)); + low_current_voltage_raw = (int16_t)(5000.0f * low_current_voltage_raw / + (float)ref_voltage_raw); + + int16_t low_current = (float)(low_current_voltage_raw - + (1000 * CURRENT_LOWCHANNEL_OFFSET)) * + (1 / 26.7); //* (LOWCHANNEL_GAIN/100.0f))/1000; + + // If the current is scoped within the range of the low channel, use the low + // channel + + if ((low_current < CURRENT_LOWCHANNEL_MAX - 5.0 && low_current >= 0) || + (low_current > CURRENT_LOWCHANNEL_MIN + 5.0 && low_current < 0)) { + // printf("\rLow Current: %d\n", -low_current); + return -low_current; + } + + // printf("\rHigh Current: %d\n", -high_current); + return -high_current; } -void compute_send_mc_discharge_message(acc_data_t *bmsdata) { - struct __attribute__((__packed__)) { - uint16_t max_discharge; - } discharge_data; +void compute_send_mc_discharge_message(acc_data_t *bmsdata) +{ + struct __attribute__((__packed__)) { + uint16_t max_discharge; + } discharge_data; - /* scale to A * 10 */ - discharge_data.max_discharge = 10 * bmsdata->discharge_limit; + /* scale to A * 10 */ + discharge_data.max_discharge = 10 * bmsdata->discharge_limit; - /* convert to big endian */ - endian_swap(&discharge_data.max_discharge, - sizeof(discharge_data.max_discharge)); + /* convert to big endian */ + endian_swap(&discharge_data.max_discharge, + sizeof(discharge_data.max_discharge)); - can_msg_t mc_msg = {0}; - mc_msg.id = 0x156; // 0x0A is the dcl id, 0x22 is the device id set by us - mc_msg.len = 8; - memcpy(mc_msg.data, &discharge_data, sizeof(discharge_data)); + can_msg_t mc_msg = { 0 }; + mc_msg.id = + 0x156; // 0x0A is the dcl id, 0x22 is the device id set by us + mc_msg.len = 8; + memcpy(mc_msg.data, &discharge_data, sizeof(discharge_data)); - can_send_msg(&can1, &mc_msg); + can_send_msg(&can1, &mc_msg); } -void compute_send_mc_charge_message(acc_data_t *bmsdata) { - struct __attribute__((__packed__)) { - int16_t max_charge; - } charge_data; +void compute_send_mc_charge_message(acc_data_t *bmsdata) +{ + struct __attribute__((__packed__)) { + int16_t max_charge; + } charge_data; - /* scale to A * 10 */ - charge_data.max_charge = -10 * bmsdata->charge_limit; + /* scale to A * 10 */ + charge_data.max_charge = -10 * bmsdata->charge_limit; - /* convert to big endian */ - endian_swap(&charge_data.max_charge, sizeof(charge_data.max_charge)); + /* convert to big endian */ + endian_swap(&charge_data.max_charge, sizeof(charge_data.max_charge)); - can_msg_t mc_msg = {0}; - mc_msg.id = 0x176; // 0x0A is the dcl id, 0x157 is the device id set by us - mc_msg.len = 8; - memcpy(mc_msg.data, &charge_data, sizeof(charge_data)); + can_msg_t mc_msg = { 0 }; + mc_msg.id = + 0x176; // 0x0A is the dcl id, 0x157 is the device id set by us + mc_msg.len = 8; + memcpy(mc_msg.data, &charge_data, sizeof(charge_data)); - can_send_msg(&can1, &mc_msg); + can_send_msg(&can1, &mc_msg); } -void compute_send_acc_status_message(acc_data_t *bmsdata) { - struct __attribute__((__packed__)) { - uint16_t packVolt; - uint16_t pack_current; - uint16_t pack_ah; - uint8_t pack_soc; - uint8_t pack_health; - } acc_status_msg_data; - - acc_status_msg_data.packVolt = bmsdata->pack_voltage; - acc_status_msg_data.pack_current = - (uint16_t)(bmsdata->pack_current); // convert with 2s complement - acc_status_msg_data.pack_ah = 0; - acc_status_msg_data.pack_soc = bmsdata->soc; - acc_status_msg_data.pack_health = 0; - - /* convert to big endian */ - endian_swap(&acc_status_msg_data.packVolt, - sizeof(acc_status_msg_data.packVolt)); - endian_swap(&acc_status_msg_data.pack_current, - sizeof(acc_status_msg_data.pack_current)); - endian_swap(&acc_status_msg_data.pack_ah, - sizeof(acc_status_msg_data.pack_ah)); - - can_msg_t acc_msg; - acc_msg.id = 0x80; - acc_msg.len = sizeof(acc_status_msg_data); - memcpy(acc_msg.data, &acc_status_msg_data, sizeof(acc_status_msg_data)); +void compute_send_acc_status_message(acc_data_t *bmsdata) +{ + struct __attribute__((__packed__)) { + uint16_t packVolt; + uint16_t pack_current; + uint16_t pack_ah; + uint8_t pack_soc; + uint8_t pack_health; + } acc_status_msg_data; + + acc_status_msg_data.packVolt = bmsdata->pack_voltage; + acc_status_msg_data.pack_current = + (uint16_t)(bmsdata->pack_current); // convert with 2s complement + acc_status_msg_data.pack_ah = 0; + acc_status_msg_data.pack_soc = bmsdata->soc; + acc_status_msg_data.pack_health = 0; + + /* convert to big endian */ + endian_swap(&acc_status_msg_data.packVolt, + sizeof(acc_status_msg_data.packVolt)); + endian_swap(&acc_status_msg_data.pack_current, + sizeof(acc_status_msg_data.pack_current)); + endian_swap(&acc_status_msg_data.pack_ah, + sizeof(acc_status_msg_data.pack_ah)); + + can_msg_t acc_msg; + acc_msg.id = 0x80; + acc_msg.len = sizeof(acc_status_msg_data); + memcpy(acc_msg.data, &acc_status_msg_data, sizeof(acc_status_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } void compute_send_bms_status_message(acc_data_t *bmsdata, int bms_state, - bool balance) { - struct __attribute__((__packed__)) { - uint8_t state; - uint32_t fault; - int8_t temp_avg; - uint8_t temp_internal; - uint8_t balance; - } bms_status_msg_data; - - bms_status_msg_data.temp_avg = (int8_t)(bmsdata->avg_temp); - bms_status_msg_data.state = (uint8_t)(bms_state); - bms_status_msg_data.fault = bmsdata->fault_code; - bms_status_msg_data.temp_internal = (uint8_t)(0); - bms_status_msg_data.balance = (uint8_t)(balance); - - /* convert to big endian */ - endian_swap(&bms_status_msg_data.fault, sizeof(bms_status_msg_data.fault)); - - can_msg_t acc_msg; - acc_msg.id = 0x81; - acc_msg.len = sizeof(bms_status_msg_data); - memcpy(acc_msg.data, &bms_status_msg_data, sizeof(bms_status_msg_data)); + bool balance) +{ + struct __attribute__((__packed__)) { + uint8_t state; + uint32_t fault; + int8_t temp_avg; + uint8_t temp_internal; + uint8_t balance; + } bms_status_msg_data; + + bms_status_msg_data.temp_avg = (int8_t)(bmsdata->avg_temp); + bms_status_msg_data.state = (uint8_t)(bms_state); + bms_status_msg_data.fault = bmsdata->fault_code; + bms_status_msg_data.temp_internal = (uint8_t)(0); + bms_status_msg_data.balance = (uint8_t)(balance); + + /* convert to big endian */ + endian_swap(&bms_status_msg_data.fault, + sizeof(bms_status_msg_data.fault)); + + can_msg_t acc_msg; + acc_msg.id = 0x81; + acc_msg.len = sizeof(bms_status_msg_data); + memcpy(acc_msg.data, &bms_status_msg_data, sizeof(bms_status_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_shutdown_ctrl_message(uint8_t mpe_state) { - struct __attribute__((__packed__)) { - uint8_t mpeState; - } shutdown_control_msg_data; +void compute_send_shutdown_ctrl_message(uint8_t mpe_state) +{ + struct __attribute__((__packed__)) { + uint8_t mpeState; + } shutdown_control_msg_data; - shutdown_control_msg_data.mpeState = mpe_state; + shutdown_control_msg_data.mpeState = mpe_state; - can_msg_t acc_msg; - acc_msg.id = 0x82; - acc_msg.len = sizeof(shutdown_control_msg_data); - memcpy(acc_msg.data, &shutdown_control_msg_data, - sizeof(shutdown_control_msg_data)); + can_msg_t acc_msg; + acc_msg.id = 0x82; + acc_msg.len = sizeof(shutdown_control_msg_data); + memcpy(acc_msg.data, &shutdown_control_msg_data, + sizeof(shutdown_control_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_cell_data_message(acc_data_t *bmsdata) { - struct __attribute__((__packed__)) { - uint16_t high_cell_voltage; - uint8_t high_cell_id; - uint16_t low_cell_voltage; - uint8_t low_cell_id; - uint16_t volt_avg; - } cell_data_msg_data; - - cell_data_msg_data.high_cell_voltage = bmsdata->max_voltage.val; - cell_data_msg_data.high_cell_id = - (bmsdata->max_voltage.chipIndex << 4) | bmsdata->max_voltage.cellNum; - cell_data_msg_data.low_cell_voltage = bmsdata->min_voltage.val; - cell_data_msg_data.low_cell_id = - (bmsdata->min_voltage.chipIndex << 4) | bmsdata->min_voltage.cellNum; - cell_data_msg_data.volt_avg = bmsdata->avg_voltage; - - /* convert to big endian */ - endian_swap(&cell_data_msg_data.high_cell_voltage, - sizeof(cell_data_msg_data.high_cell_voltage)); - endian_swap(&cell_data_msg_data.low_cell_voltage, - sizeof(cell_data_msg_data.low_cell_voltage)); - endian_swap(&cell_data_msg_data.volt_avg, - sizeof(cell_data_msg_data.volt_avg)); - - can_msg_t acc_msg; - acc_msg.id = 0x83; - acc_msg.len = sizeof(cell_data_msg_data); - memcpy(acc_msg.data, &cell_data_msg_data, sizeof(cell_data_msg_data)); +void compute_send_cell_data_message(acc_data_t *bmsdata) +{ + struct __attribute__((__packed__)) { + uint16_t high_cell_voltage; + uint8_t high_cell_id; + uint16_t low_cell_voltage; + uint8_t low_cell_id; + uint16_t volt_avg; + } cell_data_msg_data; + + cell_data_msg_data.high_cell_voltage = bmsdata->max_voltage.val; + cell_data_msg_data.high_cell_id = + (bmsdata->max_voltage.chipIndex << 4) | + bmsdata->max_voltage.cellNum; + cell_data_msg_data.low_cell_voltage = bmsdata->min_voltage.val; + cell_data_msg_data.low_cell_id = (bmsdata->min_voltage.chipIndex << 4) | + bmsdata->min_voltage.cellNum; + cell_data_msg_data.volt_avg = bmsdata->avg_voltage; + + /* convert to big endian */ + endian_swap(&cell_data_msg_data.high_cell_voltage, + sizeof(cell_data_msg_data.high_cell_voltage)); + endian_swap(&cell_data_msg_data.low_cell_voltage, + sizeof(cell_data_msg_data.low_cell_voltage)); + endian_swap(&cell_data_msg_data.volt_avg, + sizeof(cell_data_msg_data.volt_avg)); + + can_msg_t acc_msg; + acc_msg.id = 0x83; + acc_msg.len = sizeof(cell_data_msg_data); + memcpy(acc_msg.data, &cell_data_msg_data, sizeof(cell_data_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } void compute_send_cell_voltage_message(uint8_t cell_id, - uint16_t instant_voltage, - uint16_t internal_Res, uint8_t shunted, - uint16_t open_voltage) { - struct __attribute__((__packed__)) { - uint8_t cellID; - uint16_t instantVoltage; - uint16_t internalResistance; - uint8_t shunted; - uint16_t openVoltage; - } cell_voltage_msg_data; - - cell_voltage_msg_data.cellID = cell_id; - cell_voltage_msg_data.instantVoltage = instant_voltage; - cell_voltage_msg_data.internalResistance = internal_Res; - cell_voltage_msg_data.shunted = shunted; - cell_voltage_msg_data.openVoltage = open_voltage; - - /* convert to big endian */ - endian_swap(&cell_voltage_msg_data.instantVoltage, - sizeof(cell_voltage_msg_data.instantVoltage)); - endian_swap(&cell_voltage_msg_data.internalResistance, - sizeof(cell_voltage_msg_data.internalResistance)); - endian_swap(&cell_voltage_msg_data.openVoltage, - sizeof(cell_voltage_msg_data.openVoltage)); - - can_msg_t acc_msg; - acc_msg.id = 0x87; - acc_msg.len = sizeof(cell_voltage_msg_data); - memcpy(acc_msg.data, &cell_voltage_msg_data, sizeof(cell_voltage_msg_data)); + uint16_t instant_voltage, + uint16_t internal_Res, uint8_t shunted, + uint16_t open_voltage) +{ + struct __attribute__((__packed__)) { + uint8_t cellID; + uint16_t instantVoltage; + uint16_t internalResistance; + uint8_t shunted; + uint16_t openVoltage; + } cell_voltage_msg_data; + + cell_voltage_msg_data.cellID = cell_id; + cell_voltage_msg_data.instantVoltage = instant_voltage; + cell_voltage_msg_data.internalResistance = internal_Res; + cell_voltage_msg_data.shunted = shunted; + cell_voltage_msg_data.openVoltage = open_voltage; + + /* convert to big endian */ + endian_swap(&cell_voltage_msg_data.instantVoltage, + sizeof(cell_voltage_msg_data.instantVoltage)); + endian_swap(&cell_voltage_msg_data.internalResistance, + sizeof(cell_voltage_msg_data.internalResistance)); + endian_swap(&cell_voltage_msg_data.openVoltage, + sizeof(cell_voltage_msg_data.openVoltage)); + + can_msg_t acc_msg; + acc_msg.id = 0x87; + acc_msg.len = sizeof(cell_voltage_msg_data); + memcpy(acc_msg.data, &cell_voltage_msg_data, + sizeof(cell_voltage_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_current_message(acc_data_t *bmsdata) { - struct __attribute__((__packed__)) { - uint16_t dcl; - int16_t ccl; - uint16_t pack_curr; - } current_status_msg_data; - - current_status_msg_data.dcl = bmsdata->discharge_limit; - current_status_msg_data.ccl = -1 * bmsdata->charge_limit; - current_status_msg_data.pack_curr = bmsdata->pack_current; - - /* convert to big endian */ - endian_swap(¤t_status_msg_data.dcl, - sizeof(current_status_msg_data.dcl)); - endian_swap(¤t_status_msg_data.ccl, - sizeof(current_status_msg_data.ccl)); - endian_swap(¤t_status_msg_data.pack_curr, - sizeof(current_status_msg_data.pack_curr)); - - can_msg_t acc_msg; - acc_msg.id = 0x86; - acc_msg.len = sizeof(current_status_msg_data); - memcpy(acc_msg.data, ¤t_status_msg_data, - sizeof(current_status_msg_data)); +void compute_send_current_message(acc_data_t *bmsdata) +{ + struct __attribute__((__packed__)) { + uint16_t dcl; + int16_t ccl; + uint16_t pack_curr; + } current_status_msg_data; + + current_status_msg_data.dcl = bmsdata->discharge_limit; + current_status_msg_data.ccl = -1 * bmsdata->charge_limit; + current_status_msg_data.pack_curr = bmsdata->pack_current; + + /* convert to big endian */ + endian_swap(¤t_status_msg_data.dcl, + sizeof(current_status_msg_data.dcl)); + endian_swap(¤t_status_msg_data.ccl, + sizeof(current_status_msg_data.ccl)); + endian_swap(¤t_status_msg_data.pack_curr, + sizeof(current_status_msg_data.pack_curr)); + + can_msg_t acc_msg; + acc_msg.id = 0x86; + acc_msg.len = sizeof(current_status_msg_data); + memcpy(acc_msg.data, ¤t_status_msg_data, + sizeof(current_status_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_cell_temp_message(acc_data_t *bmsdata) { - struct __attribute__((__packed__)) { - uint16_t max_cell_temp; - uint8_t max_cell_id; - uint16_t min_cell_temp; - uint8_t min_cell_id; - uint16_t average_temp; - } cell_temp_msg_data; - - cell_temp_msg_data.max_cell_temp = bmsdata->max_temp.val; - cell_temp_msg_data.max_cell_id = - (bmsdata->max_temp.chipIndex << 4) | (bmsdata->max_temp.cellNum - 17); - cell_temp_msg_data.min_cell_temp = bmsdata->min_temp.val; - cell_temp_msg_data.min_cell_id = - (bmsdata->min_temp.chipIndex << 4) | (bmsdata->min_temp.cellNum - 17); - cell_temp_msg_data.average_temp = bmsdata->avg_temp; - - /* convert to big endian */ - endian_swap(&cell_temp_msg_data.max_cell_temp, - sizeof(cell_temp_msg_data.max_cell_temp)); - endian_swap(&cell_temp_msg_data.min_cell_temp, - sizeof(cell_temp_msg_data.min_cell_temp)); - endian_swap(&cell_temp_msg_data.average_temp, - sizeof(cell_temp_msg_data.average_temp)); - - can_msg_t acc_msg; - acc_msg.id = 0x84; - acc_msg.len = sizeof(cell_temp_msg_data); - memcpy(acc_msg.data, &cell_temp_msg_data, sizeof(cell_temp_msg_data)); +void compute_send_cell_temp_message(acc_data_t *bmsdata) +{ + struct __attribute__((__packed__)) { + uint16_t max_cell_temp; + uint8_t max_cell_id; + uint16_t min_cell_temp; + uint8_t min_cell_id; + uint16_t average_temp; + } cell_temp_msg_data; + + cell_temp_msg_data.max_cell_temp = bmsdata->max_temp.val; + cell_temp_msg_data.max_cell_id = (bmsdata->max_temp.chipIndex << 4) | + (bmsdata->max_temp.cellNum - 17); + cell_temp_msg_data.min_cell_temp = bmsdata->min_temp.val; + cell_temp_msg_data.min_cell_id = (bmsdata->min_temp.chipIndex << 4) | + (bmsdata->min_temp.cellNum - 17); + cell_temp_msg_data.average_temp = bmsdata->avg_temp; + + /* convert to big endian */ + endian_swap(&cell_temp_msg_data.max_cell_temp, + sizeof(cell_temp_msg_data.max_cell_temp)); + endian_swap(&cell_temp_msg_data.min_cell_temp, + sizeof(cell_temp_msg_data.min_cell_temp)); + endian_swap(&cell_temp_msg_data.average_temp, + sizeof(cell_temp_msg_data.average_temp)); + + can_msg_t acc_msg; + acc_msg.id = 0x84; + acc_msg.len = sizeof(cell_temp_msg_data); + memcpy(acc_msg.data, &cell_temp_msg_data, sizeof(cell_temp_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_segment_temp_message(acc_data_t *bmsdata) { - struct __attribute__((__packed__)) { - int8_t segment1_average_temp; - 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]; - 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; - acc_msg.len = sizeof(segment_temp_msg_data); - memcpy(acc_msg.data, &segment_temp_msg_data, sizeof(segment_temp_msg_data)); +void compute_send_segment_temp_message(acc_data_t *bmsdata) +{ + struct __attribute__((__packed__)) { + int8_t segment1_average_temp; + 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]; + 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; + acc_msg.len = sizeof(segment_temp_msg_data); + memcpy(acc_msg.data, &segment_temp_msg_data, + sizeof(segment_temp_msg_data)); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + 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)); +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; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + 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)); +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; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &acc_msg); + can_send_msg(line, &acc_msg); } -void compute_send_debug_message(uint8_t *data, uint8_t len) { - can_msg_t debug_msg; - debug_msg.id = 0x702; - debug_msg.len = len; +void compute_send_debug_message(uint8_t *data, uint8_t len) +{ + can_msg_t debug_msg; + debug_msg.id = 0x702; + debug_msg.len = len; - if (len > 8) { - len = 8; - } + if (len > 8) { + len = 8; + } - if (len > 1) { - endian_swap(data, len); - } + if (len > 1) { + endian_swap(data, len); + } - memcpy(debug_msg.data, data, len); + memcpy(debug_msg.data, data, len); #ifdef CHARGING_ENABLED - can_t *line = &can2; + can_t *line = &can2; #else - can_t *line = &can1; + can_t *line = &can1; #endif - can_send_msg(line, &debug_msg); + can_send_msg(line, &debug_msg); } -void change_adc1_channel(uint8_t channel) { - ADC_ChannelConfTypeDef sConfig = {0}; +void change_adc1_channel(uint8_t channel) +{ + ADC_ChannelConfTypeDef sConfig = { 0 }; - if (channel == REF_CHANNEL) - sConfig.Channel = ADC_CHANNEL_9; - else if (channel == VOUT_CHANNEL) - sConfig.Channel = ADC_CHANNEL_15; + if (channel == REF_CHANNEL) + sConfig.Channel = ADC_CHANNEL_9; + else if (channel == VOUT_CHANNEL) + sConfig.Channel = ADC_CHANNEL_15; - sConfig.Rank = 1; - sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; - if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { - Error_Handler(); - } + sConfig.Rank = 1; + sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; + if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { + Error_Handler(); + } } diff --git a/Core/Src/segment.c b/Core/Src/segment.c index 6dd8607..7faf314 100644 --- a/Core/Src/segment.c +++ b/Core/Src/segment.c @@ -5,11 +5,11 @@ #include #include -#define THERM_WAIT_TIME 500 /* ms */ -#define VOLTAGE_WAIT_TIME 100 /* ms */ -#define THERM_AVG 15 /* Number of values to average */ -#define MAX_VOLT_DELTA 2500 -#define MAX_CONSEC_NOISE 10 +#define THERM_WAIT_TIME 500 /* ms */ +#define VOLTAGE_WAIT_TIME 100 /* ms */ +#define THERM_AVG 15 /* Number of values to average */ +#define MAX_VOLT_DELTA 2500 +#define MAX_CONSEC_NOISE 10 #define GPIO_EXPANDER_ADDR 0x40 #define GPIO_REGISTER_ADDR 0x09 @@ -29,28 +29,29 @@ nertimer_t voltage_reading_timer; nertimer_t variance_timer; int voltage_error = 0; // not faulted -int therm_error = 0; // not faulted +int therm_error = 0; // not faulted uint16_t crc_error_check = 0; /* our segments are mapped backwards and in pairs, so they are read in 1,0 then * 3,2, etc*/ -const int mapping_correction[12] = {1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10}; +const int mapping_correction[12] = { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10 }; uint16_t therm_settle_time_ = 0; const uint32_t VOLT_TEMP_CONV[106] = { - 157300, 148800, 140300, 131800, 123300, 114800, 108772, 102744, 96716, - 90688, 84660, 80328, 75996, 71664, 67332, 63000, 59860, 56720, - 53580, 50440, 47300, 45004, 42708, 40412, 38116, 35820, 34124, - 32428, 30732, 29036, 27340, 26076, 24812, 23548, 22284, 21020, - 20074, 19128, 18182, 17236, 16290, 15576, 14862, 14148, 13434, - 12720, 12176, 11632, 11088, 10544, 10000, 9584, 9168, 8753, - 8337, 7921, 7600, 7279, 6957, 6636, 6315, 6065, 5816, - 5566, 5317, 5067, 4872, 4676, 4481, 4285, 4090, 3936, - 3782, 3627, 3473, 3319, 3197, 3075, 2953, 2831, 2709, - 2612, 2514, 2417, 2319, 2222, 2144, 2066, 1988, 1910, - 1832, 1769, 1706, 1644, 1581, 1518, 1467, 1416, 1366, - 1315, 1264, 1223, 1181, 1140, 1098, 1057}; + 157300, 148800, 140300, 131800, 123300, 114800, 108772, 102744, 96716, + 90688, 84660, 80328, 75996, 71664, 67332, 63000, 59860, 56720, + 53580, 50440, 47300, 45004, 42708, 40412, 38116, 35820, 34124, + 32428, 30732, 29036, 27340, 26076, 24812, 23548, 22284, 21020, + 20074, 19128, 18182, 17236, 16290, 15576, 14862, 14148, 13434, + 12720, 12176, 11632, 11088, 10544, 10000, 9584, 9168, 8753, + 8337, 7921, 7600, 7279, 6957, 6636, 6315, 6065, 5816, + 5566, 5317, 5067, 4872, 4676, 4481, 4285, 4090, 3936, + 3782, 3627, 3473, 3319, 3197, 3075, 2953, 2831, 2709, + 2612, 2514, 2417, 2319, 2222, 2144, 2066, 1988, 1910, + 1832, 1769, 1706, 1644, 1581, 1518, 1467, 1416, 1366, + 1315, 1264, 1223, 1181, 1140, 1098, 1057 +}; const int32_t VOLT_TEMP_CALIB_OFFSET = 0; @@ -63,566 +64,673 @@ void pull_chip_configuration(void); int16_t calc_average(void); int8_t calc_therm_standard_dev(int16_t avg_temp); -void push_chip_configuration() { - LTC6804_wrcfg(ltc68041, NUM_CHIPS, local_config); +void push_chip_configuration() +{ + LTC6804_wrcfg(ltc68041, NUM_CHIPS, local_config); } -void segment_init() { - printf("Initializing Segments..."); - - ltc68041 = malloc(sizeof(ltc_config)); - LTC6804_initialize(ltc68041, &hspi1, GPIOA, SPI_1_CS_Pin); - - pull_chip_configuration(); - - for (int c = 0; c < NUM_CHIPS; c++) { - local_config[c][0] = 0xF8; - local_config[c][1] = 0x19; /* VUV = 0x619 = 1561 -> 2.4992V */ - local_config[c][2] = 0x06; /* VOV = 0xA60 = 2656 -> 4.2496V */ - local_config[c][3] = 0xA6; - local_config[c][4] = 0x00; - local_config[c][5] = 0x00; - } - push_chip_configuration(); - - start_timer(&voltage_reading_timer, VOLTAGE_WAIT_TIME); - start_timer(&therm_timer, THERM_WAIT_TIME); - - uint8_t i2c_write_data[NUM_CHIPS][3]; - - // Set GPIO expander to output - 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 - } - 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); +void segment_init() +{ + printf("Initializing Segments..."); + + ltc68041 = malloc(sizeof(ltc_config)); + LTC6804_initialize(ltc68041, &hspi1, GPIOA, SPI_1_CS_Pin); + + pull_chip_configuration(); + + for (int c = 0; c < NUM_CHIPS; c++) { + local_config[c][0] = 0xF8; + local_config[c][1] = 0x19; /* VUV = 0x619 = 1561 -> 2.4992V */ + local_config[c][2] = 0x06; /* VOV = 0xA60 = 2656 -> 4.2496V */ + local_config[c][3] = 0xA6; + local_config[c][4] = 0x00; + local_config[c][5] = 0x00; + } + push_chip_configuration(); + + start_timer(&voltage_reading_timer, VOLTAGE_WAIT_TIME); + start_timer(&therm_timer, THERM_WAIT_TIME); + + uint8_t i2c_write_data[NUM_CHIPS][3]; + + // Set GPIO expander to output + 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 + } + 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); } -void select_therm(uint8_t therm) { - /* Exit if out of range values */ - if (therm < 1 || therm > 16) { - return; - } - - uint8_t i2c_write_data[NUM_CHIPS][3]; - uint8_t comm_reg_data[NUM_CHIPS][6]; - - // select 0-16 on GPIO expander - for (int chip = 0; chip < NUM_CHIPS; chip++) { - i2c_write_data[chip][0] = GPIO_EXPANDER_ADDR; - i2c_write_data[chip][1] = GPIO_REGISTER_ADDR; - i2c_write_data[chip][2] = - (therm - 1); // 0-15, will change multiplexer to select thermistor - } - serialize_i2c_msg(i2c_write_data, comm_reg_data); - push_chip_configuration(); - LTC6804_wrcomm(ltc68041, NUM_CHIPS, comm_reg_data); - LTC6804_stcomm(ltc68041, 24); +void select_therm(uint8_t therm) +{ + /* Exit if out of range values */ + if (therm < 1 || therm > 16) { + return; + } + + uint8_t i2c_write_data[NUM_CHIPS][3]; + uint8_t comm_reg_data[NUM_CHIPS][6]; + + // select 0-16 on GPIO expander + for (int chip = 0; chip < NUM_CHIPS; chip++) { + i2c_write_data[chip][0] = GPIO_EXPANDER_ADDR; + i2c_write_data[chip][1] = GPIO_REGISTER_ADDR; + i2c_write_data[chip][2] = + (therm - + 1); // 0-15, will change multiplexer to select thermistor + } + serialize_i2c_msg(i2c_write_data, comm_reg_data); + push_chip_configuration(); + LTC6804_wrcomm(ltc68041, NUM_CHIPS, comm_reg_data); + LTC6804_stcomm(ltc68041, 24); } -int pull_voltages() { - /** +int pull_voltages() +{ + /** * If we haven't waited long enough between pulling voltage data * just copy over the contents of the last good reading and the fault status * from the most recent attempt */ - // 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, previous_data[i].voltage, - sizeof(segment_data[i].voltage)); - } - return voltage_error; - } + // 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, + previous_data[i].voltage, + sizeof(segment_data[i].voltage)); + } + return voltage_error; + } - uint16_t raw_voltages[NUM_CHIPS][12]; + uint16_t raw_voltages[NUM_CHIPS][12]; - push_chip_configuration(); - LTC6804_adcv(ltc68041); + push_chip_configuration(); + LTC6804_adcv(ltc68041); - /** + /** * 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, raw_voltages) == -1) { - for (uint8_t i = 0; i < NUM_CHIPS; i++) { - memcpy(segment_data[i].voltage, previous_data[i].voltage, - sizeof(segment_data[i].voltage)); - - crc_error_check++; - printf("Bad voltage read\n"); - } - return 1; - } - - /* If the read was successful, copy the voltage data */ - for (uint8_t i = 0; i < NUM_CHIPS; i++) { - int corrected_index = mapping_correction[i]; - - /* correction to account for missing index, see more info below */ - int dest_index = 0; - - for (uint8_t j = 0; j < NUM_CELLS_PER_CHIP + 1; j++) { - /* cell 6 on every chip is not a real reading, we need to have the array + if (LTC6804_rdcv(ltc68041, 0, NUM_CHIPS, raw_voltages) == -1) { + for (uint8_t i = 0; i < NUM_CHIPS; i++) { + memcpy(segment_data[i].voltage, + previous_data[i].voltage, + sizeof(segment_data[i].voltage)); + + crc_error_check++; + printf("Bad voltage read\n"); + } + return 1; + } + + /* If the read was successful, copy the voltage data */ + for (uint8_t i = 0; i < NUM_CHIPS; i++) { + int corrected_index = mapping_correction[i]; + + /* correction to account for missing index, see more info below */ + int dest_index = 0; + + for (uint8_t j = 0; j < NUM_CELLS_PER_CHIP + 1; j++) { + /* 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; - - 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 { - // 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); - - return 0; + if (j == 5) + continue; + + 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 { + // 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); + + return 0; } -int pull_thermistors() { - /* If polled too soon, just copy existing values from memory */ - if (!is_timer_expired(&therm_timer)) { - for (uint8_t i = 0; i < NUM_CHIPS; i++) { - memcpy(segment_data[i].thermistor_reading, - previous_data[i].thermistor_reading, - sizeof(segment_data[i].thermistor_reading)); - memcpy(segment_data[i].thermistor_value, - previous_data[i].thermistor_value, - sizeof(segment_data[i].thermistor_value)); - } - return voltage_error; - } - - uint16_t raw_temp_voltages[NUM_CHIPS][6]; - - static uint8_t current_therm = 1; - if (current_therm > 16) { - current_therm = 1; - } - - /* 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 (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]; - /* +int pull_thermistors() +{ + /* If polled too soon, just copy existing values from memory */ + if (!is_timer_expired(&therm_timer)) { + for (uint8_t i = 0; i < NUM_CHIPS; i++) { + memcpy(segment_data[i].thermistor_reading, + previous_data[i].thermistor_reading, + sizeof(segment_data[i].thermistor_reading)); + memcpy(segment_data[i].thermistor_value, + previous_data[i].thermistor_value, + sizeof(segment_data[i].thermistor_value)); + } + return voltage_error; + } + + uint16_t raw_temp_voltages[NUM_CHIPS][6]; + + static uint8_t current_therm = 1; + if (current_therm > 16) { + current_therm = 1; + } + + /* 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 (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]; + /* * Get current temperature LUT. Voltage is adjusted to account for 5V reg * fluctuations (index 2 is a reading of the ADC 5V ref) */ - 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 + 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]; - } - } - } - 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 + 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]; + } + } + } + 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(); - // standard_dev_therm_check(); - // averaging_therm_check(); - // discard_neutrals(); + // variance_therm_check(); + // standard_dev_therm_check(); + // averaging_therm_check(); + // discard_neutrals(); - return 0; /* Read successfully */ + return 0; /* Read successfully */ } -void segment_retrieve_data(chipdata_t databuf[NUM_CHIPS]) { - segment_data = databuf; +void segment_retrieve_data(chipdata_t databuf[NUM_CHIPS]) +{ + segment_data = databuf; - /* Pull voltages and thermistors and indiacate 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(); + voltage_error = pull_voltages(); + therm_error = pull_thermistors(); - /* Save the contents of the reading so that we can use it to fill in missing + /* Save the contents of the reading so that we can use it to fill in missing * data */ - memcpy(previous_data, segment_data, sizeof(chipdata_t) * NUM_CHIPS); + memcpy(previous_data, segment_data, sizeof(chipdata_t) * NUM_CHIPS); - segment_data = NULL; + segment_data = NULL; } -void configure_discharge(uint8_t chip, uint16_t cells) { - /* +void configure_discharge(uint8_t chip, uint16_t cells) +{ + /* * chipConfigurations[chip][4] == chipConfigurations[Literally what chip you * want][register] 4 and 5 are registers to discharge chips */ - local_config[chip][4] = (uint8_t)(cells & 0x00FF); + local_config[chip][4] = (uint8_t)(cells & 0x00FF); - /* + /* * Register 5 is split in half, so we maintain the upper half and add in the * bottom half to discharge cells */ - local_config[chip][5] = - (local_config[chip][5] & 0xF0) + (uint8_t)(cells >> 8); + local_config[chip][5] = + (local_config[chip][5] & 0xF0) + (uint8_t)(cells >> 8); } -void segment_enable_balancing(bool balance_enable) { - /* +void segment_enable_balancing(bool balance_enable) +{ + /* * Discharging all cells in series * Making the discharge command all 1's for all cells per chip */ - static const uint16_t DICHARGE_ALL_COMMAND = - 0xFFFF >> (16 - NUM_CELLS_PER_CHIP); - - if (balance_enable) { - for (int c = 0; c < NUM_CHIPS; c++) { - configure_discharge(c, DICHARGE_ALL_COMMAND); - discharge_commands[c] = DICHARGE_ALL_COMMAND; - } - push_chip_configuration(); - } else { - for (int c = 0; c < NUM_CHIPS; c++) { - configure_discharge(c, 0); - discharge_commands[c] = 0; - } - push_chip_configuration(); - } + static const uint16_t DICHARGE_ALL_COMMAND = 0xFFFF >> + (16 - NUM_CELLS_PER_CHIP); + + if (balance_enable) { + for (int c = 0; c < NUM_CHIPS; c++) { + configure_discharge(c, DICHARGE_ALL_COMMAND); + discharge_commands[c] = DICHARGE_ALL_COMMAND; + } + push_chip_configuration(); + } else { + for (int c = 0; c < NUM_CHIPS; c++) { + configure_discharge(c, 0); + discharge_commands[c] = 0; + } + push_chip_configuration(); + } } // @todo Revisit after testing void cell_enable_balancing(uint8_t chip_num, uint8_t cell_num, - bool balance_enable) { - pull_chip_configuration(); + bool balance_enable) +{ + pull_chip_configuration(); - if (balance_enable) - discharge_commands[chip_num] |= (1 << cell_num); - else - discharge_commands[chip_num] &= ~(1 << cell_num); + if (balance_enable) + discharge_commands[chip_num] |= (1 << cell_num); + else + discharge_commands[chip_num] &= ~(1 << cell_num); - configure_discharge(chip_num, discharge_commands[chip_num]); + configure_discharge(chip_num, discharge_commands[chip_num]); - push_chip_configuration(); + push_chip_configuration(); } void segment_configure_balancing( - bool discharge_config[NUM_CHIPS][NUM_CELLS_PER_CHIP]) { - for (int c = 0; c < NUM_CHIPS; c++) { - for (int cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { - if (discharge_config[mapping_correction[c]][cell]) - discharge_commands[mapping_correction[c]] |= 1 << cell; - else - discharge_commands[mapping_correction[c]] &= ~(1 << cell); - } - - configure_discharge(c, discharge_commands[c]); - } - push_chip_configuration(); + bool discharge_config[NUM_CHIPS][NUM_CELLS_PER_CHIP]) +{ + for (int c = 0; c < NUM_CHIPS; c++) { + for (int cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { + if (discharge_config[mapping_correction[c]][cell]) + discharge_commands[mapping_correction[c]] |= + 1 << cell; + else + discharge_commands[mapping_correction[c]] &= + ~(1 << cell); + } + + configure_discharge(c, discharge_commands[c]); + } + push_chip_configuration(); } -bool cell_is_balancing(uint8_t chip_num, uint8_t cell_num) { - /* If the cell is one of the first 8, check the 4th register */ - if (cell_num < 8) { - return local_config[chip_num][4] & (1 << cell_num); - } - /* If the cell number is greater than 8, check the 5th register */ - else { - return local_config[chip_num][5] & (1 << (cell_num - 8)); - } - - return false; /* default case */ +bool cell_is_balancing(uint8_t chip_num, uint8_t cell_num) +{ + /* If the cell is one of the first 8, check the 4th register */ + if (cell_num < 8) { + return local_config[chip_num][4] & (1 << cell_num); + } + /* If the cell number is greater than 8, check the 5th register */ + else { + return local_config[chip_num][5] & (1 << (cell_num - 8)); + } + + return false; /* default case */ } -bool segment_is_balancing() { - for (int c = 0; c < NUM_CHIPS; c++) { - /* Reading from the 4th config register */ - for (int cell = 0; cell < 8; cell++) { - if (local_config[c][4] & (1 << cell)) - return true; - } - - /* Reading from the 5th config register */ - for (int cell = 0; cell < 4; cell++) { - if (local_config[c][5] & (1 << (cell))) - return true; - } - } - - return false; +bool segment_is_balancing() +{ + for (int c = 0; c < NUM_CHIPS; c++) { + /* Reading from the 4th config register */ + for (int cell = 0; cell < 8; cell++) { + if (local_config[c][4] & (1 << cell)) + return true; + } + + /* Reading from the 5th config register */ + for (int cell = 0; cell < 4; cell++) { + if (local_config[c][5] & (1 << (cell))) + return true; + } + } + + return false; } -void pull_chip_configuration() { - uint8_t remote_config[NUM_CHIPS][8]; - LTC6804_rdcfg(ltc68041, NUM_CHIPS, remote_config); +void pull_chip_configuration() +{ + uint8_t remote_config[NUM_CHIPS][8]; + LTC6804_rdcfg(ltc68041, NUM_CHIPS, remote_config); - for (int chip = 0; chip < NUM_CHIPS; chip++) { - for (int index = 0; index < 6; index++) { - local_config[chip][index] = remote_config[chip][index]; - } - } + for (int chip = 0; chip < NUM_CHIPS; chip++) { + for (int index = 0; index < 6; index++) { + local_config[chip][index] = remote_config[chip][index]; + } + } } -int8_t steinhart_est(uint16_t V) { - /* min temp - max temp with buffer on both */ - for (int i = -25; i < 80; i++) { - if (V > VOLT_TEMP_CONV[i + 25]) { - return i; - } - } +int8_t steinhart_est(uint16_t V) +{ + /* min temp - max temp with buffer on both */ + for (int i = -25; i < 80; i++) { + if (V > VOLT_TEMP_CONV[i + 25]) { + return i; + } + } - return 80; + return 80; } -void disable_gpio_pulldowns() { - HAL_Delay(1000); - /* Turn OFF GPIO 1 & 2 pull downs */ - pull_chip_configuration(); - for (int c = 0; c < NUM_CHIPS; c++) { - local_config[c][0] |= 0x18; - } - push_chip_configuration(); - - pull_chip_configuration(); - printf("Chip CFG:\n"); - for (int c = 0; c < NUM_CHIPS; c++) { - for (int byte = 0; byte < 6; byte++) { - printf("%x", local_config[c][byte]); - printf("\t"); - } - printf("\n"); - } - printf("Done\n"); +void disable_gpio_pulldowns() +{ + HAL_Delay(1000); + /* Turn OFF GPIO 1 & 2 pull downs */ + pull_chip_configuration(); + for (int c = 0; c < NUM_CHIPS; c++) { + local_config[c][0] |= 0x18; + } + push_chip_configuration(); + + pull_chip_configuration(); + printf("Chip CFG:\n"); + for (int c = 0; c < NUM_CHIPS; c++) { + for (int byte = 0; byte < 6; byte++) { + printf("%x", local_config[c][byte]); + printf("\t"); + } + printf("\n"); + } + printf("Done\n"); } -void serialize_i2c_msg(uint8_t data_to_write[][3], uint8_t comm_output[][6]) { - for (int chip = 0; chip < NUM_CHIPS; chip++) { - comm_output[chip][0] = - 0x60 | (data_to_write[chip][0] >> 4); /* START + high side of B0 */ - comm_output[chip][1] = - (data_to_write[chip][0] << 4) | 0x00; /* low side of B0 + ACK */ - comm_output[chip][2] = - 0x00 | (data_to_write[chip][1] >> 4); /* BLANK + high side of B1 */ - comm_output[chip][3] = - (data_to_write[chip][1] << 4) | 0x00; /* low side of B1 + ACK */ - comm_output[chip][4] = - 0x00 | (data_to_write[chip][2] >> 4); /* BLANK + high side of B2 */ - comm_output[chip][5] = - (data_to_write[chip][2] << 4) | 0x09; /* low side of B2 + STOP & NACK */ - } +void serialize_i2c_msg(uint8_t data_to_write[][3], uint8_t comm_output[][6]) +{ + for (int chip = 0; chip < NUM_CHIPS; chip++) { + comm_output[chip][0] = 0x60 | (data_to_write[chip][0] >> + 4); /* START + high side of B0 */ + comm_output[chip][1] = (data_to_write[chip][0] << 4) | + 0x00; /* low side of B0 + ACK */ + comm_output[chip][2] = 0x00 | (data_to_write[chip][1] >> + 4); /* BLANK + high side of B1 */ + comm_output[chip][3] = (data_to_write[chip][1] << 4) | + 0x00; /* low side of B1 + ACK */ + comm_output[chip][4] = 0x00 | (data_to_write[chip][2] >> + 4); /* BLANK + high side of B2 */ + comm_output[chip][5] = (data_to_write[chip][2] << 4) | + 0x09; /* low side of B2 + STOP & NACK */ + } } -void averaging_therm_check() { - for (int therm = 1; therm <= 16; therm++) { - for (int c = 0; c < NUM_CHIPS; c++) { - /* Directly update for a set time from start up due to therm voltages +void averaging_therm_check() +{ + for (int therm = 1; therm <= 16; therm++) { + for (int c = 0; c < NUM_CHIPS; c++) { + /* Directly update for a set time from start up due to therm voltages * needing to settle */ - if (therm_avg_counter < THERM_AVG * 10) { - segment_data[c].thermistor_value[therm - 1] = - segment_data[c].thermistor_reading[therm - 1]; - segment_data[c].thermistor_value[therm + 15] = - segment_data[c].thermistor_reading[therm + 15]; - therm_avg_counter++; - } else { - /* We need to investigate this. Very sloppy */ - /* Discard if reading is 33C */ - if (segment_data[c].thermistor_reading[therm - 1] != 33) { - /* If measured value is larger than current "averaged" value, + if (therm_avg_counter < THERM_AVG * 10) { + segment_data[c].thermistor_value[therm - 1] = + segment_data[c] + .thermistor_reading[therm - 1]; + segment_data[c].thermistor_value[therm + 15] = + segment_data[c] + .thermistor_reading[therm + 15]; + therm_avg_counter++; + } else { + /* We need to investigate this. Very sloppy */ + /* Discard if reading is 33C */ + if (segment_data[c] + .thermistor_reading[therm - 1] != + 33) { + /* If measured value is larger than current "averaged" value, * increment value */ - if (segment_data[c].thermistor_reading[therm - 1] > - segment_data[c].thermistor_value[therm - 1]) { - segment_data[c].thermistor_value[therm - 1]++; - /* If measured value is smaller than current "averaged" value, + if (segment_data[c] + .thermistor_reading[therm - + 1] > + segment_data[c] + .thermistor_value[therm - + 1]) { + segment_data[c] + .thermistor_value[therm - + 1]++; + /* If measured value is smaller than current "averaged" value, * decrement value */ - } else if (segment_data[c].thermistor_reading[therm - 1] < - segment_data[c].thermistor_value[therm - 1]) { - segment_data[c].thermistor_value[therm - 1]--; - } - } - - /* See comments above. Identical but for the upper 16 therms */ - if (segment_data[c].thermistor_reading[therm + 15] != 33) { - if (segment_data[c].thermistor_reading[therm + 15] > - segment_data[c].thermistor_value[therm + 15]) { - segment_data[c].thermistor_value[therm + 15]++; - } else if (segment_data[c].thermistor_reading[therm + 15] < - segment_data[c].thermistor_value[therm + 15]) { - segment_data[c].thermistor_value[therm + 15]--; - } - } - } - } - } + } else if (segment_data[c] + .thermistor_reading + [therm - 1] < + segment_data[c] + .thermistor_value + [therm - 1]) { + segment_data[c] + .thermistor_value[therm - + 1]--; + } + } + + /* See comments above. Identical but for the upper 16 therms */ + if (segment_data[c] + .thermistor_reading[therm + 15] != + 33) { + if (segment_data[c] + .thermistor_reading[therm + + 15] > + segment_data[c] + .thermistor_value[therm + + 15]) { + segment_data[c] + .thermistor_value[therm + + 15]++; + } else if (segment_data[c] + .thermistor_reading + [therm + 15] < + segment_data[c].thermistor_value + [therm + 15]) { + segment_data[c] + .thermistor_value[therm + + 15]--; + } + } + } + } + } } -void standard_dev_therm_check() { - if (previous_data == NULL) - return; - int16_t avg_temp = calc_average(); - uint8_t standard_dev = calc_therm_standard_dev(avg_temp); - for (uint8_t c = 0; c < NUM_CHIPS; c++) { - for (uint8_t therm = 17; therm < 28; therm++) { - /* +void standard_dev_therm_check() +{ + if (previous_data == NULL) + return; + int16_t avg_temp = calc_average(); + uint8_t standard_dev = calc_therm_standard_dev(avg_temp); + for (uint8_t c = 0; c < NUM_CHIPS; c++) { + for (uint8_t therm = 17; therm < 28; therm++) { + /* * If difference between thermistor and average is more than * MAX_STANDARD_DEV set the therm to pack average */ - if (abs(segment_data[c].thermistor_value[therm] - avg_temp) > - (MAX_STANDARD_DEV * standard_dev)) { - /* Nullify thermistor by setting to pack average */ - segment_data[c].thermistor_value[therm] = - previous_data[c].thermistor_value[therm]; - } - } - } + if (abs(segment_data[c].thermistor_value[therm] - + avg_temp) > (MAX_STANDARD_DEV * standard_dev)) { + /* Nullify thermistor by setting to pack average */ + segment_data[c].thermistor_value[therm] = + previous_data[c].thermistor_value[therm]; + } + } + } } -int8_t calc_therm_standard_dev(int16_t avg_temp) { - uint16_t sum_diff_sqrd = 0; - for (uint8_t chip = 0; chip < NUM_CHIPS; chip++) { - for (uint8_t therm = 17; therm < 28; therm++) { - uint16_t sum_diff = - abs(segment_data[chip].thermistor_value[therm] - avg_temp); - sum_diff_sqrd += sum_diff * sum_diff; - } - } - - uint8_t standard_dev = sqrt(sum_diff_sqrd / 88); - if (standard_dev < 8) { - standard_dev = 8; - } - return standard_dev; +int8_t calc_therm_standard_dev(int16_t avg_temp) +{ + uint16_t sum_diff_sqrd = 0; + for (uint8_t chip = 0; chip < NUM_CHIPS; chip++) { + for (uint8_t therm = 17; therm < 28; therm++) { + uint16_t sum_diff = + abs(segment_data[chip].thermistor_value[therm] - + avg_temp); + sum_diff_sqrd += sum_diff * sum_diff; + } + } + + uint8_t standard_dev = sqrt(sum_diff_sqrd / 88); + if (standard_dev < 8) { + standard_dev = 8; + } + return standard_dev; } -int16_t calc_average() { - int16_t avg = 0; - for (int chip = 0; chip < NUM_CHIPS; chip++) { - for (int therm = 17; therm < 28; therm++) { - avg += segment_data[chip].thermistor_value[therm]; - } - } - - avg = avg / (NUM_CHIPS * 11); - return avg; +int16_t calc_average() +{ + int16_t avg = 0; + for (int chip = 0; chip < NUM_CHIPS; chip++) { + for (int therm = 17; therm < 28; therm++) { + avg += segment_data[chip].thermistor_value[therm]; + } + } + + avg = avg / (NUM_CHIPS * 11); + return avg; } -void variance_therm_check() { - if (previous_data == NULL) { - start_timer(&variance_timer, 1000); - return; - } - - if (is_timer_expired(&variance_timer)) { - for (uint8_t c = 0; c < NUM_CHIPS; c++) { - for (uint8_t therm = 17; therm < 28; therm++) { - if (abs(segment_data[c].thermistor_reading[therm] - - previous_data[c].thermistor_reading[therm]) > 5 && - (segment_data[c].thermistor_reading[therm] < 10 || - segment_data[c].thermistor_reading[therm] > 30)) { - segment_data[c].thermistor_reading[therm] = - previous_data[c].thermistor_reading[therm]; - segment_data[c].thermistor_value[therm] = - previous_data[c].thermistor_value[therm]; - } - } - } - } +void variance_therm_check() +{ + if (previous_data == NULL) { + start_timer(&variance_timer, 1000); + return; + } + + if (is_timer_expired(&variance_timer)) { + for (uint8_t c = 0; c < NUM_CHIPS; c++) { + for (uint8_t therm = 17; therm < 28; therm++) { + if (abs(segment_data[c] + .thermistor_reading[therm] - + previous_data[c] + .thermistor_reading[therm]) > + 5 && + (segment_data[c].thermistor_reading[therm] < + 10 || + segment_data[c].thermistor_reading[therm] > + 30)) { + segment_data[c] + .thermistor_reading[therm] = + previous_data[c] + .thermistor_reading + [therm]; + segment_data[c].thermistor_value[therm] = + previous_data[c] + .thermistor_value[therm]; + } + } + } + } } -void discard_neutrals() { - for (uint8_t c = 0; c < NUM_CHIPS; c++) { - for (uint8_t therm = 17; therm < 28; therm++) { - if (segment_data[c].thermistor_reading[therm] == 33) { - segment_data[c].thermistor_reading[therm] = 25; - segment_data[c].thermistor_value[therm] = 25; - } - } - } +void discard_neutrals() +{ + for (uint8_t c = 0; c < NUM_CHIPS; c++) { + for (uint8_t therm = 17; therm < 28; therm++) { + if (segment_data[c].thermistor_reading[therm] == 33) { + segment_data[c].thermistor_reading[therm] = 25; + segment_data[c].thermistor_value[therm] = 25; + } + } + } } diff --git a/Core/Src/stateMachine.c b/Core/Src/stateMachine.c index 4bdb8ca..cd92039 100644 --- a/Core/Src/stateMachine.c +++ b/Core/Src/stateMachine.c @@ -11,11 +11,11 @@ uint32_t bms_fault = FAULTS_CLEAR; BMSState_t current_state = BOOT_STATE; uint32_t previousFault = 0; -nertimer_t charger_settle_countup = {.active = false}; -nertimer_t charger_max_volt_timer = {.active = false}; -nertimer_t charger_settle_countdown = {.active = false}; +nertimer_t charger_settle_countup = { .active = false }; +nertimer_t charger_max_volt_timer = { .active = false }; +nertimer_t charger_settle_countdown = { .active = false }; -nertimer_t can_msg_timer = {.active = false}; +nertimer_t can_msg_timer = { .active = false }; extern TIM_HandleTypeDef htim1; extern TIM_HandleTypeDef htim8; @@ -28,11 +28,11 @@ nertimer_t bootup_timer; static const uint16_t CHARGE_MESSAGE_WAIT = 250; /* ms */ const bool valid_transition_from_to[NUM_STATES][NUM_STATES] = { - /* BOOT, READY, CHARGING, FAULTED */ - {true, true, false, true}, /* BOOT */ - {false, true, true, true}, /* READY */ - {false, true, true, true}, /* CHARGING */ - {true, false, false, true} /* FAULTED */ + /* BOOT, READY, CHARGING, FAULTED */ + { true, true, false, true }, /* BOOT */ + { false, true, true, true }, /* READY */ + { false, true, true, true }, /* CHARGING */ + { true, false, false, true } /* FAULTED */ }; /* private function prototypes */ @@ -49,140 +49,155 @@ void request_transition(BMSState_t next_state); typedef void (*HandlerFunction_t)(acc_data_t *bmsdata); typedef void (*InitFunction_t)(); -const InitFunction_t init_LUT[NUM_STATES] = {&init_boot, &init_ready, - &init_charging, &init_faulted}; +const InitFunction_t init_LUT[NUM_STATES] = { &init_boot, &init_ready, + &init_charging, &init_faulted }; -const HandlerFunction_t handler_LUT[NUM_STATES] = { - &handle_boot, &handle_ready, &handle_charging, &handle_faulted}; +const HandlerFunction_t handler_LUT[NUM_STATES] = { &handle_boot, &handle_ready, + &handle_charging, + &handle_faulted }; -void init_boot() { return; } +void init_boot() +{ + return; +} -void handle_boot(acc_data_t *bmsdata) { - prevAccData = NULL; - segment_enable_balancing(false); - compute_enable_charging(false); - start_timer(&bootup_timer, 10000); - printf("Bootup timer started\r\n"); +void handle_boot(acc_data_t *bmsdata) +{ + prevAccData = NULL; + segment_enable_balancing(false); + compute_enable_charging(false); + start_timer(&bootup_timer, 10000); + printf("Bootup timer started\r\n"); - compute_set_fault(1); - // bmsdata->fault_code = FAULTS_CLEAR; + compute_set_fault(1); + // bmsdata->fault_code = FAULTS_CLEAR; - request_transition(READY_STATE); - return; + request_transition(READY_STATE); + return; } -void init_ready() { - segment_enable_balancing(false); - compute_enable_charging(false); - return; +void init_ready() +{ + segment_enable_balancing(false); + compute_enable_charging(false); + return; } -void handle_ready(acc_data_t *bmsdata) { - /* check for charger connection */ - if (compute_charger_connected() && - is_timer_expired(&bootup_timer)) { // TODO Fix once charger works - request_transition(READY_STATE); - } else { - sm_broadcast_current_limit(bmsdata); - return; - } +void handle_ready(acc_data_t *bmsdata) +{ + /* check for charger connection */ + if (compute_charger_connected() && + is_timer_expired(&bootup_timer)) { // TODO Fix once charger works + request_transition(READY_STATE); + } else { + sm_broadcast_current_limit(bmsdata); + return; + } } -void init_charging() { - cancel_timer(&charger_settle_countup); - return; +void init_charging() +{ + cancel_timer(&charger_settle_countup); + return; } -void handle_charging(acc_data_t *bmsdata) { - if (!compute_charger_connected()) { - request_transition(READY_STATE); - return; - - } else { - /* Check if we should charge */ - if (sm_charging_check(bmsdata)) - compute_enable_charging(true); - else { - compute_enable_charging(false); - compute_send_charging_message(0, 0, bmsdata); - } +void handle_charging(acc_data_t *bmsdata) +{ + if (!compute_charger_connected()) { + request_transition(READY_STATE); + return; + + } else { + /* Check if we should charge */ + if (sm_charging_check(bmsdata)) + compute_enable_charging(true); + else { + compute_enable_charging(false); + compute_send_charging_message(0, 0, bmsdata); + } - /* Check if we should balance */ - if (sm_balancing_check(bmsdata)) - sm_balance_cells(bmsdata); - else - segment_enable_balancing(false); - - /* Send CAN message, but not too often */ - if (is_timer_expired(&charger_message_timer) || - !is_timer_active(&charger_message_timer)) { - compute_send_charging_message( - (MAX_CHARGE_VOLT * NUM_CELLS_PER_CHIP * NUM_CHIPS), 5, bmsdata); - start_timer(&charger_message_timer, CHARGE_MESSAGE_WAIT); - } - } + /* Check if we should balance */ + if (sm_balancing_check(bmsdata)) + sm_balance_cells(bmsdata); + else + segment_enable_balancing(false); + + /* Send CAN message, but not too often */ + if (is_timer_expired(&charger_message_timer) || + !is_timer_active(&charger_message_timer)) { + compute_send_charging_message((MAX_CHARGE_VOLT * + NUM_CELLS_PER_CHIP * + NUM_CHIPS), + 5, bmsdata); + start_timer(&charger_message_timer, + CHARGE_MESSAGE_WAIT); + } + } } -void init_faulted() { - segment_enable_balancing(false); - compute_enable_charging(false); - entered_faulted = true; - return; +void init_faulted() +{ + segment_enable_balancing(false); + compute_enable_charging(false); + entered_faulted = true; + return; } -void handle_faulted(acc_data_t *bmsdata) { - if (entered_faulted) { - entered_faulted = false; - previousFault = sm_fault_return(bmsdata); - } - - if (bmsdata->fault_code == FAULTS_CLEAR) { - compute_set_fault(1); - request_transition(BOOT_STATE); - return; - } - - else { - compute_set_fault(0); - - // TODO update to HAL - // digitalWrite(CHARGE_SAFETY_RELAY, 0); - } - return; +void handle_faulted(acc_data_t *bmsdata) +{ + if (entered_faulted) { + entered_faulted = false; + previousFault = sm_fault_return(bmsdata); + } + + if (bmsdata->fault_code == FAULTS_CLEAR) { + compute_set_fault(1); + request_transition(BOOT_STATE); + return; + } + + else { + compute_set_fault(0); + + // TODO update to HAL + // digitalWrite(CHARGE_SAFETY_RELAY, 0); + } + return; } -void sm_handle_state(acc_data_t *bmsdata) { - static uint8_t can_msg_to_send = 0; - enum { - ACC_STATUS, - CURRENT, - BMS_STATUS, - CELL_TEMP, - CELL_DATA, - SEGMENT_TEMP, - MC_DISCHARGE, - MC_CHARGE, - CAN_DEBUG, - MAX_MSGS - }; - - bmsdata->fault_code = sm_fault_return(bmsdata); - - // calculate_pwm(bmsdata); - - if (bmsdata->fault_code != FAULTS_CLEAR) { - bmsdata->discharge_limit = 0; - request_transition(FAULTED_STATE); - } - // TODO needs testing - (update, seems to work fine) - handler_LUT[current_state](bmsdata); - - bmsdata->is_charger_connected = compute_charger_connected(); - - sm_broadcast_current_limit(bmsdata); - - /* send relevant CAN msgs */ - // clang-format off +void sm_handle_state(acc_data_t *bmsdata) +{ + static uint8_t can_msg_to_send = 0; + enum { + ACC_STATUS, + CURRENT, + BMS_STATUS, + CELL_TEMP, + CELL_DATA, + SEGMENT_TEMP, + MC_DISCHARGE, + MC_CHARGE, + CAN_DEBUG, + MAX_MSGS + }; + + bmsdata->fault_code = sm_fault_return(bmsdata); + + // calculate_pwm(bmsdata); + + if (bmsdata->fault_code != FAULTS_CLEAR) { + bmsdata->discharge_limit = 0; + request_transition(FAULTED_STATE); + } + // TODO needs testing - (update, seems to work fine) + handler_LUT[current_state](bmsdata); + + bmsdata->is_charger_connected = compute_charger_connected(); + + sm_broadcast_current_limit(bmsdata); + + /* send relevant CAN msgs */ + // clang-format off if (is_timer_expired(&can_msg_timer) || !is_timer_active(&can_msg_timer)) { switch (can_msg_to_send) { @@ -221,39 +236,42 @@ void sm_handle_state(acc_data_t *bmsdata) { start_timer(&can_msg_timer, CAN_MESSAGE_WAIT); can_msg_to_send = (can_msg_to_send + 1) % MAX_MSGS; } - // clang-format on + // clang-format on } -void request_transition(BMSState_t next_state) { - if (current_state == next_state) - return; - if (!valid_transition_from_to[current_state][next_state]) - return; +void request_transition(BMSState_t next_state) +{ + if (current_state == next_state) + return; + if (!valid_transition_from_to[current_state][next_state]) + return; - init_LUT[next_state](); - current_state = next_state; + init_LUT[next_state](); + current_state = next_state; } -uint32_t sm_fault_return(acc_data_t *accData) { - /* FAULT CHECK (Check for fuckies) */ +uint32_t sm_fault_return(acc_data_t *accData) +{ + /* FAULT CHECK (Check for fuckies) */ - static nertimer_t ovr_curr_timer = {0}; - static nertimer_t ovr_chgcurr_timer = {0}; - static nertimer_t undr_volt_timer = {0}; - static nertimer_t ovr_chgvolt_timer = {0}; - static nertimer_t ovr_volt_timer = {0}; - static nertimer_t low_cell_timer = {0}; - static nertimer_t high_temp_timer = {0}; - static fault_eval_t *fault_table = NULL; - static acc_data_t *fault_data = NULL; + static nertimer_t ovr_curr_timer = { 0 }; + static nertimer_t ovr_chgcurr_timer = { 0 }; + static nertimer_t undr_volt_timer = { 0 }; + static nertimer_t ovr_chgvolt_timer = { 0 }; + static nertimer_t ovr_volt_timer = { 0 }; + static nertimer_t low_cell_timer = { 0 }; + static nertimer_t high_temp_timer = { 0 }; + static fault_eval_t *fault_table = NULL; + static acc_data_t *fault_data = NULL; - fault_data = accData; + fault_data = accData; - if (!fault_table) { - /* Note that we are only allocating this table once at runtime, so there is + if (!fault_table) { + /* Note that we are only allocating this table once at runtime, so there is * no need to free it */ - fault_table = (fault_eval_t *)malloc(NUM_FAULTS * sizeof(fault_eval_t)); - // clang-format off + fault_table = (fault_eval_t *)malloc(NUM_FAULTS * + sizeof(fault_eval_t)); + // clang-format off // ___________FAULT ID____________ __________TIMER___________ _____________DATA________________ __OPERATOR__ __________________________THRESHOLD____________________________ _______TIMER LENGTH_________ _____________FAULT CODE_________________ ___OPERATOR 2__ _______________DATA 2______________ __THRESHOLD 2__ fault_table[0] = (fault_eval_t) {.id = "Discharge Current Limit", .timer = ovr_curr_timer, .data_1 = fault_data->pack_current, .optype_1 = GT, .lim_1 = (fault_data->discharge_limit + DCDC_CURRENT_DRAW)*10 * CURR_ERR_MARG, .timeout = OVER_CURR_TIME, .code = DISCHARGE_LIMIT_ENFORCEMENT_FAULT, .optype_2 = NOP/* ---------------------------UNUSED------------------- */ }; fault_table[1] = (fault_eval_t) {.id = "Charge Current Limit", .timer = ovr_chgcurr_timer, .data_1 = fault_data->pack_current, .optype_1 = GT, .lim_1 = (fault_data->charge_limit)*10, .timeout = OVER_CHG_CURR_TIME, .code = CHARGE_LIMIT_ENFORCEMENT_FAULT, .optype_2 = LT, .data_2 = fault_data->pack_current, .lim_2 = 0 }; @@ -271,39 +289,41 @@ uint32_t sm_fault_return(acc_data_t *accData) { cancel_timer(&ovr_volt_timer); cancel_timer(&low_cell_timer); cancel_timer(&high_temp_timer); - // clang-format on - } - - 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; - fault_table[4].data_2 = fault_data->is_charger_connected; - 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; + // clang-format on + } + + 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; + fault_table[4].data_2 = fault_data->is_charger_connected; + 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; } -uint32_t sm_fault_eval(fault_eval_t *index) { - bool condition1; - bool condition2; +uint32_t sm_fault_eval(fault_eval_t *index) +{ + bool condition1; + bool condition2; - // clang-format off + // clang-format off switch (index->optype_1) { case GT: condition1 = index->data_1 > index->lim_1; break; @@ -327,48 +347,50 @@ uint32_t sm_fault_eval(fault_eval_t *index) { case NOP: condition2 = false; default: condition2 = false; } - // clang-format on - - bool fault_present = - ((condition1 && condition2) || (condition1 && (index->optype_2 == NOP))); - if ((!(is_timer_active(&index->timer))) && !fault_present) { - return 0; - } - - if (is_timer_active(&index->timer)) { - if (!fault_present) { - printf("\t\t\t*******Fault cleared: %s\r\n", index->id); - cancel_timer(&index->timer); - return 0; - } + // clang-format on - 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; - } + bool fault_present = ((condition1 && condition2) || + (condition1 && (index->optype_2 == NOP))); + if ((!(is_timer_active(&index->timer))) && !fault_present) { + return 0; + } - else - return 0; + if (is_timer_active(&index->timer)) { + if (!fault_present) { + printf("\t\t\t*******Fault cleared: %s\r\n", index->id); + cancel_timer(&index->timer); + return 0; + } - } + 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 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); - } + else + return 0; + + } - return 0; - } - /* if (index->code == CELL_VOLTAGE_TOO_LOW) { + 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) { printf("\t\t\t*******Not fautled!!!!!\t%d\r\n", !is_timer_active(&index->timer) && condition1 && condition2); printf("More stats...\t:%d\t%d\r\n", is_timer_expired(&index->timer), index->timer.active); } */ - printf("err should not get here"); - return 0; + printf("err should not get here"); + return 0; } /* charger settle countup = 1 minute pause to let readings settle and get good @@ -377,172 +399,182 @@ uint32_t sm_fault_eval(fault_eval_t *index) { */ /* charger_max_volt_timer = interval of time when voltage is too high before * trying to start again */ -bool sm_charging_check(acc_data_t *bmsdata) { - if (!compute_charger_connected()) { - printf("Charger not connected\r\n"); - return false; - } - - if (!is_timer_expired(&charger_settle_countup) && - is_timer_active(&charger_settle_countup)) { - printf("Charger settle countup active\r\n"); - return false; - } - - if (!is_timer_expired(&charger_max_volt_timer) && - is_timer_active(&charger_max_volt_timer)) { - printf("Charger max volt timer active\r\n"); - return false; - } - - if (bmsdata->max_voltage.val > MAX_CHARGE_VOLT * 10000) { - start_timer(&charger_max_volt_timer, CHARGE_VOLT_TIMEOUT); - printf("Charger max volt timer started\r\n"); - printf("Max voltage: %d\r\n", bmsdata->max_voltage.val); - return false; - } - - if (is_timer_active(&charger_settle_countdown)) { - if (is_timer_expired(&charger_settle_countdown)) { - start_timer(&charger_settle_countup, CHARGE_SETL_TIMEOUT); - return false; - } +bool sm_charging_check(acc_data_t *bmsdata) +{ + if (!compute_charger_connected()) { + printf("Charger not connected\r\n"); + return false; + } - else - return true; - } + if (!is_timer_expired(&charger_settle_countup) && + is_timer_active(&charger_settle_countup)) { + printf("Charger settle countup active\r\n"); + return false; + } - else { - start_timer(&charger_settle_countdown, CHARGE_SETL_TIMEUP); - return true; - } + if (!is_timer_expired(&charger_max_volt_timer) && + is_timer_active(&charger_max_volt_timer)) { + printf("Charger max volt timer active\r\n"); + return false; + } + + if (bmsdata->max_voltage.val > MAX_CHARGE_VOLT * 10000) { + start_timer(&charger_max_volt_timer, CHARGE_VOLT_TIMEOUT); + printf("Charger max volt timer started\r\n"); + printf("Max voltage: %d\r\n", bmsdata->max_voltage.val); + return false; + } + + if (is_timer_active(&charger_settle_countdown)) { + if (is_timer_expired(&charger_settle_countdown)) { + start_timer(&charger_settle_countup, + CHARGE_SETL_TIMEOUT); + return false; + } + + else + return true; + } + + else { + start_timer(&charger_settle_countdown, CHARGE_SETL_TIMEUP); + return true; + } } -bool sm_balancing_check(acc_data_t *bmsdata) { - if (!compute_charger_connected()) - return false; - if (bmsdata->max_temp.val > MAX_CELL_TEMP_BAL) - return false; - if (bmsdata->max_voltage.val <= (BAL_MIN_V * 10000)) - return false; - if (bmsdata->delt_voltage <= (MAX_DELTA_V * 10000)) - return false; - - if (is_timer_active(&charger_settle_countup) && - !is_timer_expired(&charger_settle_countup)) - return false; - - return true; +bool sm_balancing_check(acc_data_t *bmsdata) +{ + if (!compute_charger_connected()) + return false; + if (bmsdata->max_temp.val > MAX_CELL_TEMP_BAL) + return false; + if (bmsdata->max_voltage.val <= (BAL_MIN_V * 10000)) + return false; + if (bmsdata->delt_voltage <= (MAX_DELTA_V * 10000)) + return false; + + if (is_timer_active(&charger_settle_countup) && + !is_timer_expired(&charger_settle_countup)) + return false; + + return true; } -void sm_broadcast_current_limit(acc_data_t *bmsdata) { - // States for Boosting State Machine - static enum { BOOST_STANDBY, BOOSTING, BOOST_RECHARGE } BoostState; - - static nertimer_t boost_timer; - static nertimer_t boost_recharge_timer; - - /* Transitioning out of boost */ - if (is_timer_expired(&boost_timer) && BoostState == BOOSTING) { - BoostState = BOOST_RECHARGE; - start_timer(&boost_recharge_timer, BOOST_RECHARGE_TIME); - } - /* Transition out of boost recharge */ - if (is_timer_expired(&boost_recharge_timer) && BoostState == BOOST_RECHARGE) { - BoostState = BOOST_STANDBY; - } - /* Transition to boosting */ - if ((bmsdata->pack_current) > ((bmsdata->cont_DCL) * 10) && - BoostState == BOOST_STANDBY) { - BoostState = BOOSTING; - start_timer(&boost_timer, BOOST_TIME); - } - - /* Currently boosting */ - if (BoostState == BOOSTING || BoostState == BOOST_STANDBY) { - bmsdata->boost_setting = - MIN(bmsdata->discharge_limit, bmsdata->cont_DCL * CONTDCL_MULTIPLIER); - } - - /* Currently recharging boost */ - else { - bmsdata->boost_setting = MIN(bmsdata->cont_DCL, bmsdata->discharge_limit); - } +void sm_broadcast_current_limit(acc_data_t *bmsdata) +{ + // States for Boosting State Machine + static enum { BOOST_STANDBY, BOOSTING, BOOST_RECHARGE } BoostState; + + static nertimer_t boost_timer; + static nertimer_t boost_recharge_timer; + + /* Transitioning out of boost */ + if (is_timer_expired(&boost_timer) && BoostState == BOOSTING) { + BoostState = BOOST_RECHARGE; + start_timer(&boost_recharge_timer, BOOST_RECHARGE_TIME); + } + /* Transition out of boost recharge */ + if (is_timer_expired(&boost_recharge_timer) && + BoostState == BOOST_RECHARGE) { + BoostState = BOOST_STANDBY; + } + /* Transition to boosting */ + if ((bmsdata->pack_current) > ((bmsdata->cont_DCL) * 10) && + BoostState == BOOST_STANDBY) { + BoostState = BOOSTING; + start_timer(&boost_timer, BOOST_TIME); + } + + /* Currently boosting */ + if (BoostState == BOOSTING || BoostState == BOOST_STANDBY) { + bmsdata->boost_setting = + MIN(bmsdata->discharge_limit, + bmsdata->cont_DCL * CONTDCL_MULTIPLIER); + } + + /* Currently recharging boost */ + else { + bmsdata->boost_setting = + MIN(bmsdata->cont_DCL, bmsdata->discharge_limit); + } } -void sm_balance_cells(acc_data_t *bms_data) { - bool balanceConfig[NUM_CHIPS][NUM_CELLS_PER_CHIP]; +void sm_balance_cells(acc_data_t *bms_data) +{ + bool balanceConfig[NUM_CHIPS][NUM_CELLS_PER_CHIP]; - /* For all cells of all the chips, figure out if we need to balance by + /* For all cells of all the chips, figure out if we need to balance by * comparing the difference 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[cell] - - (uint16_t)bms_data->min_voltage.val; - if (delta > MAX_DELTA_V * 10000) - balanceConfig[chip][cell] = true; - else - balanceConfig[chip][cell] = false; - } - } + 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[cell] - + (uint16_t)bms_data->min_voltage.val; + if (delta > MAX_DELTA_V * 10000) + balanceConfig[chip][cell] = true; + else + balanceConfig[chip][cell] = false; + } + } #ifdef DEBUG_CHARGING - printf("Cell Balancing:"); - for (uint8_t c = 0; c < NUM_CHIPS; c++) { - for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { - printf(balanceConfig[c][cell]); - printf("\t"); - } - printf("\n"); - } + printf("Cell Balancing:"); + for (uint8_t c = 0; c < NUM_CHIPS; c++) { + for (uint8_t cell = 0; cell < NUM_CELLS_PER_CHIP; cell++) { + printf(balanceConfig[c][cell]); + printf("\t"); + } + printf("\n"); + } #endif - segment_configure_balancing(balanceConfig); + segment_configure_balancing(balanceConfig); } -void calculate_pwm(acc_data_t *bmsdata) { - // todo actually implement algorithm - // this should include: - // 1. set PWM based on temp of "nearby" cells - // 2. automate seleciton of htim rather than hardcode - - if (bmsdata->max_temp.val > 50) { - compute_set_fan_speed(&htim1, FAN1, 100); - compute_set_fan_speed(&htim1, FAN2, 100); - compute_set_fan_speed(&htim8, FAN3, 100); - compute_set_fan_speed(&htim8, FAN4, 100); - compute_set_fan_speed(&htim8, FAN5, 100); - compute_set_fan_speed(&htim8, FAN6, 100); - return; - } - - else if (bmsdata->max_temp.val > 40) { - compute_set_fan_speed(&htim1, FAN1, 50); - compute_set_fan_speed(&htim1, FAN2, 50); - compute_set_fan_speed(&htim8, FAN3, 50); - compute_set_fan_speed(&htim8, FAN4, 50); - compute_set_fan_speed(&htim8, FAN5, 50); - compute_set_fan_speed(&htim8, FAN6, 50); - return; - } - - else if (bmsdata->max_temp.val > 30) { - compute_set_fan_speed(&htim1, FAN1, 25); - compute_set_fan_speed(&htim1, FAN2, 25); - compute_set_fan_speed(&htim8, FAN3, 25); - compute_set_fan_speed(&htim8, FAN4, 25); - compute_set_fan_speed(&htim8, FAN5, 25); - compute_set_fan_speed(&htim8, FAN6, 25); - return; - } - - else { - compute_set_fan_speed(&htim1, FAN1, 0); - compute_set_fan_speed(&htim1, FAN2, 0); - compute_set_fan_speed(&htim8, FAN3, 0); - compute_set_fan_speed(&htim8, FAN4, 0); - compute_set_fan_speed(&htim8, FAN5, 0); - compute_set_fan_speed(&htim8, FAN6, 0); - return; - } +void calculate_pwm(acc_data_t *bmsdata) +{ + // todo actually implement algorithm + // this should include: + // 1. set PWM based on temp of "nearby" cells + // 2. automate seleciton of htim rather than hardcode + + if (bmsdata->max_temp.val > 50) { + compute_set_fan_speed(&htim1, FAN1, 100); + compute_set_fan_speed(&htim1, FAN2, 100); + compute_set_fan_speed(&htim8, FAN3, 100); + compute_set_fan_speed(&htim8, FAN4, 100); + compute_set_fan_speed(&htim8, FAN5, 100); + compute_set_fan_speed(&htim8, FAN6, 100); + return; + } + + else if (bmsdata->max_temp.val > 40) { + compute_set_fan_speed(&htim1, FAN1, 50); + compute_set_fan_speed(&htim1, FAN2, 50); + compute_set_fan_speed(&htim8, FAN3, 50); + compute_set_fan_speed(&htim8, FAN4, 50); + compute_set_fan_speed(&htim8, FAN5, 50); + compute_set_fan_speed(&htim8, FAN6, 50); + return; + } + + else if (bmsdata->max_temp.val > 30) { + compute_set_fan_speed(&htim1, FAN1, 25); + compute_set_fan_speed(&htim1, FAN2, 25); + compute_set_fan_speed(&htim8, FAN3, 25); + compute_set_fan_speed(&htim8, FAN4, 25); + compute_set_fan_speed(&htim8, FAN5, 25); + compute_set_fan_speed(&htim8, FAN6, 25); + return; + } + + else { + compute_set_fan_speed(&htim1, FAN1, 0); + compute_set_fan_speed(&htim1, FAN2, 0); + compute_set_fan_speed(&htim8, FAN3, 0); + compute_set_fan_speed(&htim8, FAN4, 0); + compute_set_fan_speed(&htim8, FAN5, 0); + compute_set_fan_speed(&htim8, FAN6, 0); + return; + } } From 9ade8e9023f69c6fd42498ae89dee396ed3e077b Mon Sep 17 00:00:00 2001 From: dyldonahue Date: Fri, 20 Sep 2024 12:43:22 -0400 Subject: [PATCH 4/5] length 8 byte --- Core/Src/compute.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Core/Src/compute.c b/Core/Src/compute.c index 77208d9..1d3ca83 100644 --- a/Core/Src/compute.c +++ b/Core/Src/compute.c @@ -674,17 +674,15 @@ void compute_send_debug_message(uint8_t *data, uint8_t len) { can_msg_t debug_msg; debug_msg.id = 0x702; - debug_msg.len = len; + debug_msg.len = 8; // yaml decodes this msg as 8 bytes if (len > 8) { len = 8; } - if (len > 1) { - endian_swap(data, len); - } - + memset(debug_msg.data, 0, 8); memcpy(debug_msg.data, data, len); + endian_swap(debug_msg.data, 8); #ifdef CHARGING_ENABLED can_t *line = &can2; From 218bdf0998b0ca8c2f9444203f71adc7884c6c0d Mon Sep 17 00:00:00 2001 From: Jack Rubacha Date: Fri, 20 Sep 2024 17:12:09 -0400 Subject: [PATCH 5/5] send a complete message --- Core/Inc/compute.h | 4 ++++ Core/Src/compute.c | 24 +++++++++++++++++------- Core/Src/stateMachine.c | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Core/Inc/compute.h b/Core/Inc/compute.h index 1673096..ae9763f 100644 --- a/Core/Inc/compute.h +++ b/Core/Inc/compute.h @@ -184,6 +184,10 @@ 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_debug_message(uint8_t debug0, uint8_t debug1, uint16_t debug2, + uint32_t debug3); + void compute_send_voltage_noise_message(acc_data_t *bmsdata); #endif // COMPUTE_H diff --git a/Core/Src/compute.c b/Core/Src/compute.c index 1d3ca83..472ea4d 100644 --- a/Core/Src/compute.c +++ b/Core/Src/compute.c @@ -670,19 +670,29 @@ void compute_send_voltage_noise_message(acc_data_t *bmsdata) can_send_msg(line, &acc_msg); } -void compute_send_debug_message(uint8_t *data, uint8_t len) +void compute_send_debug_message(uint8_t debug0, uint8_t debug1, uint16_t debug2, + uint32_t debug3) { + struct __attribute__((__packed__)) { + uint8_t debug0; + uint8_t debug1; + uint16_t debug2; + uint32_t debug3; + } debug_msg_data; + + debug_msg_data.debug0 = debug0; + debug_msg_data.debug1 = debug1; + debug_msg_data.debug2 = debug2; + debug_msg_data.debug3 = debug3; + can_msg_t debug_msg; debug_msg.id = 0x702; debug_msg.len = 8; // yaml decodes this msg as 8 bytes - if (len > 8) { - len = 8; - } + endian_swap(&debug_msg_data.debug2, sizeof(debug_msg_data.debug2)); + endian_swap(&debug_msg_data.debug3, sizeof(debug_msg_data.debug3)); - memset(debug_msg.data, 0, 8); - memcpy(debug_msg.data, data, len); - endian_swap(debug_msg.data, 8); + memcpy(debug_msg.data, &debug_msg_data, 8); #ifdef CHARGING_ENABLED can_t *line = &can2; diff --git a/Core/Src/stateMachine.c b/Core/Src/stateMachine.c index cd92039..f8e0ec0 100644 --- a/Core/Src/stateMachine.c +++ b/Core/Src/stateMachine.c @@ -227,7 +227,7 @@ void sm_handle_state(acc_data_t *bmsdata) break; case CAN_DEBUG: - compute_send_debug_message(&crc_error_check, 2); + compute_send_debug_message(0,0, crc_error_check, 0); default: break;