From f39decb8f9ab068bf299df68fbaaed5f9d8f6676 Mon Sep 17 00:00:00 2001 From: BlakeFreer Date: Fri, 1 Nov 2024 21:27:52 -0400 Subject: [PATCH] fix: :bug: Fix TMS halt and temperature calculations. Previously, TMS would appear to crash upon boot. This was caused by the `HAL_CAN_RxFifo0MsgPendingCallback` interrupt being triggered when the BMS sent CAN messages, even though the TMS does not care about them. TMS did not call `HAL_CAN_GetRxMessage()` in the interrupt to clear the interrupt flag, so the interrupt continued to fire, preventing the main code from running. This commit fixes the problem by handling the messages. Also fixes the temperature calculation which is now explicitly calculated from the sensor datasheet table and the physical hardware circuit. --- firmware/mcal/stm32f767/periph/can.h | 4 +- firmware/projects/EV5/TMS/inc/app.h | 9 +- firmware/projects/EV5/TMS/main.cc | 112 +++++++++++------- .../EV5/TMS/platforms/stm32f767/bindings.cc | 26 +++- firmware/shared/util/mappers/mapper.h | 3 +- 5 files changed, 101 insertions(+), 53 deletions(-) diff --git a/firmware/mcal/stm32f767/periph/can.h b/firmware/mcal/stm32f767/periph/can.h index 8b44f5103..d6674da0a 100644 --- a/firmware/mcal/stm32f767/periph/can.h +++ b/firmware/mcal/stm32f767/periph/can.h @@ -15,12 +15,12 @@ namespace mcal::stm32f767::periph { class CanBase : public shared::periph::CanBase { public: - CanBase(CAN_HandleTypeDef* hcan) : hcan_(hcan){}; + CanBase(CAN_HandleTypeDef* hcan) : hcan_(hcan) {}; void Setup() { - HAL_CAN_ActivateNotification(hcan_, kCanRxActiveInterruptFifo0); ConfigFilters(); HAL_CAN_Start(hcan_); + HAL_CAN_ActivateNotification(hcan_, kCanRxActiveInterruptFifo0); } void Send(const shared::can::RawCanMsg& can_tx_msg) override { diff --git a/firmware/projects/EV5/TMS/inc/app.h b/firmware/projects/EV5/TMS/inc/app.h index 4880f5f8f..ed8a60832 100644 --- a/firmware/projects/EV5/TMS/inc/app.h +++ b/firmware/projects/EV5/TMS/inc/app.h @@ -25,14 +25,14 @@ class TempSensor { public: TempSensor(shared::periph::ADCInput& adc, - shared::util::Mapper& adc_to_temp) - : adc_(adc), adc_to_temp_(adc_to_temp), rolling_temperature_() {} + const shared::util::Mapper& volt_to_temp) + : adc_(adc), volt_to_temp_(volt_to_temp), rolling_temperature_() {} private: shared::periph::ADCInput& adc_; /// @brief Mapping from raw ADC value to temperature [degC] - shared::util::Mapper& adc_to_temp_; + const shared::util::Mapper& volt_to_temp_; static constexpr int moving_average_length_ = 20; shared::util::MovingAverage @@ -40,7 +40,8 @@ class TempSensor { float Read() { uint32_t adc_value = adc_.Read(); - float temperature = adc_to_temp_.Evaluate(float(adc_value)); + float volt = static_cast(adc_value) * 3.3f / 4095.0f; + float temperature = volt_to_temp_.Evaluate(volt); return temperature; } diff --git a/firmware/projects/EV5/TMS/main.cc b/firmware/projects/EV5/TMS/main.cc index 648b4b633..f3b813716 100644 --- a/firmware/projects/EV5/TMS/main.cc +++ b/firmware/projects/EV5/TMS/main.cc @@ -13,7 +13,9 @@ #include "shared/periph/gpio.h" #include "shared/periph/pwm.h" #include "shared/util/algorithms/arrays.h" +#include "shared/util/mappers/linear_map.h" #include "shared/util/mappers/lookup_table.h" +#include "shared/util/mappers/mapper.h" #include "veh_can_messages.h" #include "veh_msg_registry.h" @@ -27,54 +29,76 @@ extern "C" { void UpdateTask(void* argument); } -const float temp_lut_data[][2] = { +namespace tempsensor { + +/// This table is directly copied from Table 4 of the temperature sensor +/// datasheet. `datasheets/energus/Datasheet_with_VTC6_rev_A(2021-10-26).pdf` +const float ts_table[][2] = { // clang-format off - {2475, 120}, - {2480, 115}, - {2485, 110}, - {2491, 105}, - {2496, 100}, - {2501, 95}, - {2512, 90}, - {2517, 85}, - {2528, 80}, - {2543, 75}, - {2554, 70}, - {2570, 65}, - {2586, 60}, - {2607, 55}, - {2628, 50}, - {2649, 45}, - {2675, 40}, - {2707, 35}, - {2739, 30}, - {2771, 25}, - {2802, 20}, - {2839, 15}, - {2871, 10}, - {2903, 5}, - {2934, 0}, - {2966, -5}, - {2987, -10}, - {3014, -15}, - {3029, -20}, - {3045, -25}, - {3056, -30}, - {3066, -35}, - {3077, -40}, + {1.30f, 120.0f}, + {1.31f, 115.0f}, + {1.32f, 110.0f}, + {1.33f, 105.0f}, + {1.34f, 100.0f}, + {1.35f, 95.0f}, + {1.37f, 90.0f}, + {1.38f, 85.0f}, + {1.40f, 80.0f}, + {1.43f, 75.0f}, + {1.45f, 70.0f}, + {1.48f, 65.0f}, + {1.51f, 60.0f}, + {1.55f, 55.0f}, + {1.59f, 50.0f}, + {1.63f, 45.0f}, + {1.68f, 40.0f}, + {1.74f, 35.0f}, + {1.80f, 30.0f}, + {1.86f, 25.0f}, + {1.92f, 20.0f}, + {1.99f, 15.0f}, + {2.05f, 10.0f}, + {2.11f, 5.0f}, + {2.17f, 0.0f}, + {2.23f, -5.0f}, + {2.27f, -10.0f}, + {2.32f, -15.0f}, + {2.35f, -20.0f}, + {2.38f, -25.0f}, + {2.40f, -30.0f}, + {2.42f, -35.0f}, + {2.44f, -40.0f} // clang-format on }; +constexpr int lut_length = (sizeof(ts_table)) / (sizeof(ts_table[0])); +const shared::util::LookupTable volt_ts_to_degC{ts_table}; + +/// Calculate the voltage at the temperature sensor from the voltage at the STM. +/// They are not equal because there is a non-unity gain buffer between them. +/// V_STM = 1.44 + 0.836 * V_TS / 2 +/// So the inverse is +/// V_TS = 2 * (V_STM - 1.44) / 0.836 = 2/0.836 * V_STM - 2*1.44/0.836 +const shared::util::LinearMap volt_stm_to_volt_ts{ + 2.0f / 0.836f, + -2.0f * 1.44f / 0.836f, +}; + +/// Compose the two maps to get the final map from the STM voltage to the +/// temperature in degrees C. +const shared::util::CompositeMap volt_stm_to_degC{ + volt_ts_to_degC, // outer (second) function + volt_stm_to_volt_ts, // inner (first) function +}; + +} // namespace tempsensor +/// Spin the fan faster when the acculumator is hotter. const float fan_lut_data[][2] = { {-1, 0}, {0, 30}, {50, 100}, }; -constexpr int temp_lut_length = - (sizeof(temp_lut_data)) / (sizeof(temp_lut_data[0])); -shared::util::LookupTable temp_adc_lut{temp_lut_data}; - constexpr int fan_lut_length = (sizeof(fan_lut_data) / (sizeof(fan_lut_data[0]))); shared::util::LookupTable fan_temp_lut{fan_lut_data}; @@ -99,12 +123,12 @@ DebugIndicator debug_green{bindings::debug_led_green}; DebugIndicator debug_red{bindings::debug_led_red}; TempSensor temp_sensors[] = { - TempSensor{bindings::temp_sensor_adc_1, temp_adc_lut}, - TempSensor{bindings::temp_sensor_adc_2, temp_adc_lut}, - TempSensor{bindings::temp_sensor_adc_3, temp_adc_lut}, - TempSensor{bindings::temp_sensor_adc_4, temp_adc_lut}, - TempSensor{bindings::temp_sensor_adc_5, temp_adc_lut}, - TempSensor{bindings::temp_sensor_adc_6, temp_adc_lut}, + TempSensor{bindings::temp_sensor_adc_1, tempsensor::volt_stm_to_degC}, + TempSensor{bindings::temp_sensor_adc_2, tempsensor::volt_stm_to_degC}, + TempSensor{bindings::temp_sensor_adc_3, tempsensor::volt_stm_to_degC}, + TempSensor{bindings::temp_sensor_adc_4, tempsensor::volt_stm_to_degC}, + TempSensor{bindings::temp_sensor_adc_5, tempsensor::volt_stm_to_degC}, + TempSensor{bindings::temp_sensor_adc_6, tempsensor::volt_stm_to_degC}, }; const int kSensorCount = 6; diff --git a/firmware/projects/EV5/TMS/platforms/stm32f767/bindings.cc b/firmware/projects/EV5/TMS/platforms/stm32f767/bindings.cc index 6dbd41b3c..2b1fd63a9 100644 --- a/firmware/projects/EV5/TMS/platforms/stm32f767/bindings.cc +++ b/firmware/projects/EV5/TMS/platforms/stm32f767/bindings.cc @@ -1,6 +1,8 @@ /// @author Blake Freer /// @date 2023-12-25 +#include + #include // cubemx files @@ -10,6 +12,7 @@ #include "main.h" #include "mcal/stm32f767/periph/can.h" #include "shared/comms/can/can_msg.h" +#include "stm32f7xx_hal_tim.h" #include "tim.h" // fw imports @@ -59,17 +62,36 @@ shared::periph::ADCInput& temp_sensor_adc_6 = mcal::temp_sensor_adc_6; shared::periph::PWMOutput& fan_controller_pwm = mcal::fan_controller_pwm; shared::periph::DigitalOutput& debug_led_green = mcal::debug_led_green; shared::periph::DigitalOutput& debug_led_red = mcal::debug_led_red; -// shared::periph::DigitalOutput& debug_led_red = mcal::debug_led_nucleo; +// shared::periph::DigitalOutput& debug_led_red = mcal::debug_led_nucleo; shared::periph::CanBase& veh_can_base = mcal::veh_can_base; void Initialize() { - SystemClock_Config(); HAL_Init(); + SystemClock_Config(); MX_ADC1_Init(); MX_TIM4_Init(); MX_GPIO_Init(); MX_CAN2_Init(); + + mcal::veh_can_base.Setup(); } } // namespace bindings + +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef* hcan) { + /* Prevent unused argument(s) compilation warning */ + + CAN_RxHeaderTypeDef RxHeader; + uint8_t RxData[8]; + + // Retrieve message to clear the interrupt flag + if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK) { + // Process the message data here or set a flag for the main loop + } + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_RxFifo0MsgPendingCallback could be implemented in the + user file + */ +} \ No newline at end of file diff --git a/firmware/shared/util/mappers/mapper.h b/firmware/shared/util/mappers/mapper.h index 09cb4757f..c4dcc3a06 100644 --- a/firmware/shared/util/mappers/mapper.h +++ b/firmware/shared/util/mappers/mapper.h @@ -34,7 +34,8 @@ class CompositeMap : public Mapper { * @param g Inner function. * @note Evaulates `f(g(x))`, so `g` is applied before `f`. */ - CompositeMap(Mapper& f, Mapper& g) : f_(f), g_(g) {} + CompositeMap(const Mapper& f, const Mapper& g) + : f_(f), g_(g) {} /** * @brief Evaluates `f(g(x))`.