Skip to content

Commit

Permalink
fix: 🐛 Fix TMS halt and temperature calculations. (#277)
Browse files Browse the repository at this point in the history
* fix: 🐛 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.

* clean up interrupt callback

* Only toggle green on Update() and remove unused import
  • Loading branch information
BlakeFreer authored Nov 5, 2024
1 parent 158e5c5 commit 4b7f411
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 54 deletions.
4 changes: 2 additions & 2 deletions firmware/mcal/stm32f767/periph/can.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 5 additions & 4 deletions firmware/projects/EV5/TMS/inc/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,23 @@
class TempSensor {
public:
TempSensor(shared::periph::ADCInput& adc,
shared::util::Mapper<float>& adc_to_temp)
: adc_(adc), adc_to_temp_(adc_to_temp), rolling_temperature_() {}
const shared::util::Mapper<float>& 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<float>& adc_to_temp_;
const shared::util::Mapper<float>& volt_to_temp_;

static constexpr int moving_average_length_ = 20;
shared::util::MovingAverage<float, moving_average_length_>
rolling_temperature_;

float Read() {
uint32_t adc_value = adc_.Read();
float temperature = adc_to_temp_.Evaluate(float(adc_value));
float volt = static_cast<float>(adc_value) * 3.3f / 4095.0f;
float temperature = volt_to_temp_.Evaluate(volt);
return temperature;
}

Expand Down
113 changes: 68 additions & 45 deletions firmware/projects/EV5/TMS/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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<lut_length> 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<float> 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<float> 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_lut_length> temp_adc_lut{temp_lut_data};

constexpr int fan_lut_length =
(sizeof(fan_lut_data) / (sizeof(fan_lut_data[0])));
shared::util::LookupTable<fan_lut_length> fan_temp_lut{fan_lut_data};
Expand All @@ -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;
Expand All @@ -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();
Expand Down
17 changes: 15 additions & 2 deletions firmware/projects/EV5/TMS/platforms/stm32f767/bindings.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/// @author Blake Freer
/// @date 2023-12-25

#include <stdio.h>

#include <string>

// cubemx files
Expand Down Expand Up @@ -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);
}
3 changes: 2 additions & 1 deletion firmware/shared/util/mappers/mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class CompositeMap : public Mapper<Tf, U> {
* @param g Inner function.
* @note Evaulates `f(g(x))`, so `g` is applied before `f`.
*/
CompositeMap(Mapper<Tf, Tg>& f, Mapper<Tg, U>& g) : f_(f), g_(g) {}
CompositeMap(const Mapper<Tf, Tg>& f, const Mapper<Tg, U>& g)
: f_(f), g_(g) {}

/**
* @brief Evaluates `f(g(x))`.
Expand Down

0 comments on commit 4b7f411

Please sign in to comment.