Skip to content

Commit

Permalink
fix: 🐛 Fix TMS halt and temperature calculations.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
BlakeFreer committed Nov 2, 2024
1 parent f0128b5 commit f39decb
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 53 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
112 changes: 68 additions & 44 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 Down
26 changes: 24 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 All @@ -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
Expand Down Expand Up @@ -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
*/
}
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 f39decb

Please sign in to comment.