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..c98d4cec2 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; @@ -122,7 +146,6 @@ void Update() { static uint8_t high_thermistor_idx; debug_green.Toggle(); - debug_red.Toggle(); veh_can_bus.Update(); ts_manager.Update(); diff --git a/firmware/projects/EV5/TMS/platforms/stm32f767/bindings.cc b/firmware/projects/EV5/TMS/platforms/stm32f767/bindings.cc index 6dbd41b3c..a78bdd24b 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 @@ -59,17 +61,28 @@ 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) { + CAN_RxHeaderTypeDef RxHeader; + uint8_t RxData[8]; + + // TMS doesn't care about any Rx messages but we need to call this to + // clear the interrupt flag. + HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData); +} \ 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))`.