From 3ffeb07ba0c6c3334e6d8d83354ae3672214f16c Mon Sep 17 00:00:00 2001 From: Frank Sinapi Date: Mon, 22 May 2023 10:33:49 -0400 Subject: [PATCH] feat(tempdeck-gen3): include thermal calibration offsets when calculating temperature (#443) * Convert thermistor readings with thermal offset constants * Added tests that EEPROM constants change the temperature readings --- .../tempdeck-gen3/thermal_task.hpp | 44 +++++++++++-------- .../tempdeck-gen3/tests/test_thermal_task.cpp | 41 +++++++++++++++++ 2 files changed, 67 insertions(+), 18 deletions(-) diff --git a/stm32-modules/include/tempdeck-gen3/tempdeck-gen3/thermal_task.hpp b/stm32-modules/include/tempdeck-gen3/tempdeck-gen3/thermal_task.hpp index 6b715c63e..2360bbddb 100644 --- a/stm32-modules/include/tempdeck-gen3/tempdeck-gen3/thermal_task.hpp +++ b/stm32-modules/include/tempdeck-gen3/tempdeck-gen3/thermal_task.hpp @@ -210,24 +210,14 @@ class ThermalTask { _readings.last_tick = message.timestamp; // Reading conversion - auto res = _converter.convert(_readings.plate_adc_1); - if (std::holds_alternative(res)) { - _readings.plate_temp_1 = std::get(res); - } else { - _readings.plate_temp_1 = 0.0F; - } - res = _converter.convert(_readings.plate_adc_2); - if (std::holds_alternative(res)) { - _readings.plate_temp_2 = std::get(res); - } else { - _readings.plate_temp_2 = 0.0F; - } - res = _converter.convert(_readings.heatsink_adc); - if (std::holds_alternative(res)) { - _readings.heatsink_temp = std::get(res); - } else { - _readings.heatsink_temp = 0.0F; - } + _readings.heatsink_temp = convert_thermistor(message.heatsink, false); + auto heatsink_temp = _readings.heatsink_temp.has_value() + ? _readings.heatsink_temp.value() + : 0; + _readings.plate_temp_1 = + convert_thermistor(message.plate_1, true, heatsink_temp); + _readings.plate_temp_2 = + convert_thermistor(message.plate_2, true, heatsink_temp); _readings.peltier_current_milliamps = PeltierReadback::adc_to_milliamps(message.imeas); @@ -411,6 +401,7 @@ class ThermalTask { constants.c = message.c.value(); } + _offset_constants = constants; auto ret = _eeprom.write_offset_constants(constants, policy); if (ret) { // Succesful, so overwrite the task's constants @@ -529,6 +520,23 @@ class ThermalTask { } } + auto convert_thermistor(uint32_t raw_reading, bool add_offsets, + double heatsink_temp = 0.0) + -> std::optional { + auto res = _converter.convert(raw_reading); + if (!std::holds_alternative(res)) { + return std::nullopt; + } + double reading = std::get(res); + if (add_offsets) { + double offset = (_offset_constants.a * heatsink_temp) + + (_offset_constants.b * reading) + + (_offset_constants.c); + reading += offset; + } + return reading; + } + Queue& _message_queue; Aggregator* _task_registry; ThermalReadings _readings; diff --git a/stm32-modules/tempdeck-gen3/tests/test_thermal_task.cpp b/stm32-modules/tempdeck-gen3/tests/test_thermal_task.cpp index 4ad7c9914..d27d7639e 100644 --- a/stm32-modules/tempdeck-gen3/tests/test_thermal_task.cpp +++ b/stm32-modules/tempdeck-gen3/tests/test_thermal_task.cpp @@ -580,6 +580,47 @@ TEST_CASE("thermal task offset constants message handling") { } } +TEST_CASE("thermal task offset constant compensation") { + auto *tasks = tasks::BuildTasks(); + TestThermalPolicy policy; + eeprom::Eeprom_thermal_task)::EEPROM_ADDRESS> eeprom; + thermistor_conversion::Conversion converter( + decltype(tasks->_thermal_task)::THERMISTOR_CIRCUIT_BIAS_RESISTANCE_KOHM, + decltype(tasks->_thermal_task)::ADC_BIT_MAX, false); + GIVEN("a set of offset constants") { + double a = GENERATE(0, -0.5, 0.5); + double b = GENERATE(0, -0.5, 0.5); + double c = GENERATE(0, -0.5, 0.5); + auto constants = eeprom::OffsetConstants{.a = a, .b = b, .c = c}; + REQUIRE(eeprom.write_offset_constants(constants, policy)); + WHEN("receiving a new temperature reading") { + static constexpr double PLATE_TEMP = 25.0; + static constexpr double HEATSINK_TEMP = 50.0; + auto thermistors_msg = messages::ThermistorReadings{ + .timestamp = 1000, + .plate_1 = converter.backconvert(PLATE_TEMP), + .plate_2 = converter.backconvert(PLATE_TEMP), + .heatsink = converter.backconvert(HEATSINK_TEMP), + .imeas = 555, + }; + tasks->_thermal_queue.backing_deque.push_back(thermistors_msg); + tasks->_thermal_task.run_once(policy); + THEN("the readings are updated properly") { + // Alg is READING = (A * heatsink) + ((B+1) * plate) + C + double expected = + (a * HEATSINK_TEMP) + ((b + 1.0) * PLATE_TEMP) + c; + auto readings = tasks->_thermal_task.get_readings(); + REQUIRE_THAT(readings.heatsink_temp.value(), + Catch::Matchers::WithinAbs(HEATSINK_TEMP, 0.1)); + REQUIRE_THAT(readings.plate_temp_1.value(), + Catch::Matchers::WithinAbs(expected, 0.1)); + REQUIRE_THAT(readings.plate_temp_2.value(), + Catch::Matchers::WithinAbs(expected, 0.1)); + } + } + } +} + TEST_CASE("thermal task power debug functionality") { auto *tasks = tasks::BuildTasks(); TestThermalPolicy policy;