Merge pull request 'TCS continued' (#576) from continue_tcs_tests into develop
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #576 Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
This commit is contained in:
commit
b5f4b6cf7b
13
CHANGELOG.md
13
CHANGELOG.md
@ -37,6 +37,7 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
|
|
||||||
- Bugfixes and improvements for SDC state machine. Internal state was not updated correctly due
|
- Bugfixes and improvements for SDC state machine. Internal state was not updated correctly due
|
||||||
to a regression, so commanding the SDC state machine externally lead to confusing results.
|
to a regression, so commanding the SDC state machine externally lead to confusing results.
|
||||||
|
- Heater states array in TCS controller was too small.
|
||||||
- Fixed a bug in persistent TM store, where the active file was not reset of SD card switches.
|
- Fixed a bug in persistent TM store, where the active file was not reset of SD card switches.
|
||||||
SD card switch from 0 to 1 and vice-versa works without errors from persistent TM stores now.
|
SD card switch from 0 to 1 and vice-versa works without errors from persistent TM stores now.
|
||||||
- Add a way for the SUS polling to detect broken or off devices by checking the retrieved
|
- Add a way for the SUS polling to detect broken or off devices by checking the retrieved
|
||||||
@ -52,16 +53,22 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
the active SD card is switched or there is a transition from hot redundant to cold redundant mode.
|
the active SD card is switched or there is a transition from hot redundant to cold redundant mode.
|
||||||
This gives other tasks some time to register the SD cards being unusable, and therefore provides
|
This gives other tasks some time to register the SD cards being unusable, and therefore provides
|
||||||
a way for them to perform any re-initialization tasks necessary after SD card switches.
|
a way for them to perform any re-initialization tasks necessary after SD card switches.
|
||||||
|
- TCS controller now only has an OFF mode and an ON mode
|
||||||
- The TCS controller pauses operations related to the TCS board assembly (reading sensors and
|
- The TCS controller pauses operations related to the TCS board assembly (reading sensors and
|
||||||
the primary control loop) while a TCS board recovery is on-going.
|
the primary control loop) while a TCS board recovery is on-going.
|
||||||
|
|
||||||
## Changed
|
|
||||||
|
|
||||||
- Allow specifying custom OBSW update filename. This allowed keeping a cleaner file structure
|
- Allow specifying custom OBSW update filename. This allowed keeping a cleaner file structure
|
||||||
where each update has a name including the version
|
where each update has a name including the version
|
||||||
- The files extracted during an update process are deleted after the update was performed to keep
|
- The files extracted during an update process are deleted after the update was performed to keep
|
||||||
the update directory cleaner.
|
the update directory cleaner.
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- TCS controller: SUBMODE_NO_HEATER_CTRL (1) added for ON mode. If this submode is
|
||||||
|
commanded, all heaters will be switched off and then no further heater
|
||||||
|
commanding will be done.
|
||||||
|
- Fixed a bug in persistent TM store, where the active file was not reset of SD card switches.
|
||||||
|
SD card switch from 0 to 1 and vice-versa works without errors from persistent TM stores now.
|
||||||
|
|
||||||
# [v1.44.0] 2023-04-07
|
# [v1.44.0] 2023-04-07
|
||||||
|
|
||||||
- eive-tmtc: v2.22.0
|
- eive-tmtc: v2.22.0
|
||||||
|
@ -94,6 +94,9 @@ set(OBSW_ADD_SUN_SENSORS
|
|||||||
set(OBSW_ADD_SUS_BOARD_ASS
|
set(OBSW_ADD_SUS_BOARD_ASS
|
||||||
${INIT_VAL}
|
${INIT_VAL}
|
||||||
CACHE STRING "Add sun sensor board assembly")
|
CACHE STRING "Add sun sensor board assembly")
|
||||||
|
set(OBSW_ADD_THERMAL_TEMP_INSERTER
|
||||||
|
${OBSW_Q7S_EM}
|
||||||
|
CACHE STRING "Add thermal sensor temperature inserter")
|
||||||
set(OBSW_ADD_ACS_BOARD
|
set(OBSW_ADD_ACS_BOARD
|
||||||
${INIT_VAL}
|
${INIT_VAL}
|
||||||
CACHE STRING "Add ACS board module")
|
CACHE STRING "Add ACS board module")
|
||||||
|
@ -151,7 +151,6 @@ void scheduling::initTasks() {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("Core controller dummy", objects::CORE_CONTROLLER);
|
scheduling::printAddObjectError("Core controller dummy", objects::CORE_CONTROLLER);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = thermalTask->addComponent(objects::THERMAL_CONTROLLER);
|
result = thermalTask->addComponent(objects::THERMAL_CONTROLLER);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("THERMAL_CONTROLLER", objects::THERMAL_CONTROLLER);
|
scheduling::printAddObjectError("THERMAL_CONTROLLER", objects::THERMAL_CONTROLLER);
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
#define OBSW_ADD_PL_PCDU @OBSW_ADD_PL_PCDU@
|
#define OBSW_ADD_PL_PCDU @OBSW_ADD_PL_PCDU@
|
||||||
#define OBSW_ADD_SYRLINKS @OBSW_ADD_SYRLINKS@
|
#define OBSW_ADD_SYRLINKS @OBSW_ADD_SYRLINKS@
|
||||||
#define OBSW_ADD_CCSDS_IP_CORES @OBSW_ADD_CCSDS_IP_CORES@
|
#define OBSW_ADD_CCSDS_IP_CORES @OBSW_ADD_CCSDS_IP_CORES@
|
||||||
|
// Only relevant for EM for TCS tests.
|
||||||
|
#define OBSW_ADD_THERMAL_TEMP_INSERTER @OBSW_ADD_THERMAL_TEMP_INSERTER@
|
||||||
|
|
||||||
// Set to 1 if all telemetry should be sent to the PTME IP Core
|
// Set to 1 if all telemetry should be sent to the PTME IP Core
|
||||||
#define OBSW_TM_TO_PTME @OBSW_TM_TO_PTME@
|
#define OBSW_TM_TO_PTME @OBSW_TM_TO_PTME@
|
||||||
// Set to 1 if telecommands are received via the PDEC IP Core
|
// Set to 1 if telecommands are received via the PDEC IP Core
|
||||||
|
@ -302,6 +302,9 @@ void scheduling::initTasks() {
|
|||||||
|
|
||||||
PeriodicTaskIF* tcsSystemTask = factory->createPeriodicTask(
|
PeriodicTaskIF* tcsSystemTask = factory->createPeriodicTask(
|
||||||
"TCS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING);
|
"TCS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING);
|
||||||
|
#if OBSW_ADD_THERMAL_TEMP_INSERTER == 1
|
||||||
|
tcsSystemTask->addComponent(objects::THERMAL_TEMP_INSERTER);
|
||||||
|
#endif
|
||||||
scheduling::scheduleRtdSensors(tcsSystemTask);
|
scheduling::scheduleRtdSensors(tcsSystemTask);
|
||||||
result = tcsSystemTask->addComponent(objects::TCS_SUBSYSTEM);
|
result = tcsSystemTask->addComponent(objects::TCS_SUBSYSTEM);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
@ -317,12 +320,10 @@ void scheduling::initTasks() {
|
|||||||
scheduling::printAddObjectError("THERMAL_CONTROLLER", objects::THERMAL_CONTROLLER);
|
scheduling::printAddObjectError("THERMAL_CONTROLLER", objects::THERMAL_CONTROLLER);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if OBSW_ADD_HEATERS == 1
|
|
||||||
result = tcsSystemTask->addComponent(objects::HEATER_HANDLER);
|
result = tcsSystemTask->addComponent(objects::HEATER_HANDLER);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
|
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if OBSW_ADD_SYRLINKS == 1
|
#if OBSW_ADD_SYRLINKS == 1
|
||||||
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
|
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
#ifndef FSFWCONFIG_DEVICES_HEATERSWITCHERLIST_H_
|
|
||||||
#define FSFWCONFIG_DEVICES_HEATERSWITCHERLIST_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace heater {
|
|
||||||
enum Switchers : uint8_t {
|
|
||||||
HEATER_0_OBC_BRD,
|
|
||||||
HEATER_1_PLOC_PROC_BRD,
|
|
||||||
HEATER_2_ACS_BRD,
|
|
||||||
HEATER_3_PCDU_PDU,
|
|
||||||
HEATER_4_CAMERA,
|
|
||||||
HEATER_5_STR,
|
|
||||||
HEATER_6_DRO,
|
|
||||||
HEATER_7_S_BAND,
|
|
||||||
NUMBER_OF_SWITCHES
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* FSFWCONFIG_DEVICES_HEATERSWITCHERLIST_H_ */
|
|
@ -1,5 +1,6 @@
|
|||||||
#include "TemperatureSensorInserter.h"
|
#include "TemperatureSensorInserter.h"
|
||||||
|
|
||||||
|
#include <fsfw/datapool/PoolReadGuard.h>
|
||||||
#include <objects/systemObjectList.h>
|
#include <objects/systemObjectList.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -14,10 +15,7 @@ TemperatureSensorInserter::TemperatureSensorInserter(object_id_t objectId,
|
|||||||
tmp1075DummyMap(std::move(tempTmpSensorDummies_)) {}
|
tmp1075DummyMap(std::move(tempTmpSensorDummies_)) {}
|
||||||
|
|
||||||
ReturnValue_t TemperatureSensorInserter::initialize() {
|
ReturnValue_t TemperatureSensorInserter::initialize() {
|
||||||
if (performTest) {
|
testCase = TestCase::COLD_STR_CONSECUTIVE;
|
||||||
if (testCase == TestCase::COOL_SYRLINKS) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,35 +31,72 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
|
|||||||
tempsWereInitialized = true;
|
tempsWereInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cycles == 10) {
|
switch (testCase) {
|
||||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-100, true);
|
case (TestCase::NONE): {
|
||||||
max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(-100, true);
|
break;
|
||||||
}
|
}
|
||||||
|
case (TestCase::COLD_SYRLINKS): {
|
||||||
if (cycles == 35) {
|
// TODO: How do I insert this?
|
||||||
|
// Does not work on EM, where a real syrlinks device is connected.
|
||||||
|
if (cycles == 15) {
|
||||||
|
lp_var_t<float> tempSyrlinksBasebandBoard =
|
||||||
|
lp_var_t<float>(objects::SYRLINKS_HANDLER, syrlinks::TEMP_BASEBAND_BOARD);
|
||||||
|
PoolReadGuard pg(&tempSyrlinksBasebandBoard);
|
||||||
|
tempSyrlinksBasebandBoard.value = -50;
|
||||||
|
}
|
||||||
|
if (cycles == 30) {
|
||||||
|
lp_var_t<float> tempSyrlinksBasebandBoard =
|
||||||
|
lp_var_t<float>(objects::SYRLINKS_HANDLER, syrlinks::TEMP_BASEBAND_BOARD);
|
||||||
|
PoolReadGuard pg(&tempSyrlinksBasebandBoard);
|
||||||
|
tempSyrlinksBasebandBoard.value = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (TestCase::COLD_HPA): {
|
||||||
|
if (cycles == 15) {
|
||||||
|
sif::debug << "Setting cold HPA temperature" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-60, true);
|
||||||
|
}
|
||||||
|
if (cycles == 30) {
|
||||||
|
sif::debug << "Setting HPA temperature back to normal" << std::endl;
|
||||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(0, true);
|
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(0, true);
|
||||||
max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(0, true);
|
}
|
||||||
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-100, true);
|
break;
|
||||||
|
}
|
||||||
|
case (TestCase::COLD_MGT): {
|
||||||
|
if (cycles == 15) {
|
||||||
|
sif::debug << "Setting cold MGT temperature" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_15_IC18_IMTQ]->setTemperature(-60, true);
|
||||||
|
}
|
||||||
|
if (cycles == 30) {
|
||||||
|
sif::debug << "Setting MGT temperature back to normal" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_15_IC18_IMTQ]->setTemperature(0, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (TestCase::COLD_STR):
|
||||||
|
case (TestCase::COLD_STR_CONSECUTIVE): {
|
||||||
|
if (cycles == 15) {
|
||||||
|
sif::debug << "Setting cold STR temperature" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_4_IC7_STARTRACKER]->setTemperature(-40, true);
|
||||||
|
}
|
||||||
|
if (cycles == 30) {
|
||||||
|
sif::debug << "Setting STR temperature back to normal" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_4_IC7_STARTRACKER]->setTemperature(0, true);
|
||||||
|
}
|
||||||
|
if (testCase == TestCase::COLD_STR_CONSECUTIVE) {
|
||||||
|
if (cycles == 45) {
|
||||||
|
sif::debug << "Setting cold STR temperature again" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_4_IC7_STARTRACKER]->setTemperature(-40, true);
|
||||||
}
|
}
|
||||||
if (cycles == 60) {
|
if (cycles == 60) {
|
||||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-100, true);
|
sif::debug << "Setting STR temperature back to normal again" << std::endl;
|
||||||
max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(0, true);
|
max31865DummyMap[objects::RTD_4_IC7_STARTRACKER]->setTemperature(0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
ReturnValue_t result = max31865PlocHeatspreaderSet.read();
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
sif::warning << "Failed to read temperature from MAX31865 dataset" << std::endl;
|
|
||||||
}
|
}
|
||||||
max31865PlocHeatspreaderSet.rtdValue = value - 5;
|
break;
|
||||||
max31865PlocHeatspreaderSet.temperatureCelcius = value;
|
}
|
||||||
if ((iteration % 100) < 20) {
|
|
||||||
max31865PlocHeatspreaderSet.setValidity(false, true);
|
|
||||||
} else {
|
|
||||||
max31865PlocHeatspreaderSet.setValidity(true, true);
|
|
||||||
}
|
}
|
||||||
max31865PlocHeatspreaderSet.commit();
|
|
||||||
*/
|
|
||||||
cycles++;
|
cycles++;
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||||
|
#include <mission/com/syrlinksDefs.h>
|
||||||
#include <mission/tcs/Max31865Definitions.h>
|
#include <mission/tcs/Max31865Definitions.h>
|
||||||
|
|
||||||
#include "Max31865Dummy.h"
|
#include "Max31865Dummy.h"
|
||||||
@ -22,11 +23,18 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
|
|||||||
private:
|
private:
|
||||||
Max31865DummyMap max31865DummyMap;
|
Max31865DummyMap max31865DummyMap;
|
||||||
Tmp1075DummyMap tmp1075DummyMap;
|
Tmp1075DummyMap tmp1075DummyMap;
|
||||||
enum TestCase { NONE = 0, COOL_SYRLINKS = 1 };
|
|
||||||
|
enum TestCase {
|
||||||
|
NONE = 0,
|
||||||
|
COLD_SYRLINKS = 1,
|
||||||
|
COLD_HPA = 2,
|
||||||
|
COLD_MGT = 3,
|
||||||
|
COLD_STR = 4,
|
||||||
|
COLD_STR_CONSECUTIVE = 5,
|
||||||
|
};
|
||||||
int iteration = 0;
|
int iteration = 0;
|
||||||
uint32_t cycles = 0;
|
uint32_t cycles = 0;
|
||||||
bool tempsWereInitialized = false;
|
bool tempsWereInitialized = false;
|
||||||
bool performTest = false;
|
|
||||||
TestCase testCase = TestCase::NONE;
|
TestCase testCase = TestCase::NONE;
|
||||||
|
|
||||||
// void noise();
|
// void noise();
|
||||||
|
@ -194,9 +194,11 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
|||||||
tmpSensorDummies.emplace(
|
tmpSensorDummies.emplace(
|
||||||
objects::TMP1075_HANDLER_PLPCDU_0,
|
objects::TMP1075_HANDLER_PLPCDU_0,
|
||||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0, objects::DUMMY_COM_IF, comCookieDummy));
|
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0, objects::DUMMY_COM_IF, comCookieDummy));
|
||||||
tmpSensorDummies.emplace(
|
// damaged.
|
||||||
objects::TMP1075_HANDLER_PLPCDU_1,
|
// tmpSensorDummies.emplace(
|
||||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1, objects::DUMMY_COM_IF, comCookieDummy));
|
// objects::TMP1075_HANDLER_PLPCDU_1,
|
||||||
|
// new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1, objects::DUMMY_COM_IF,
|
||||||
|
// comCookieDummy));
|
||||||
tmpSensorDummies.emplace(
|
tmpSensorDummies.emplace(
|
||||||
objects::TMP1075_HANDLER_IF_BOARD,
|
objects::TMP1075_HANDLER_IF_BOARD,
|
||||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD, objects::DUMMY_COM_IF, comCookieDummy));
|
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD, objects::DUMMY_COM_IF, comCookieDummy));
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include <objects/systemObjectList.h>
|
#include <objects/systemObjectList.h>
|
||||||
|
|
||||||
// Enabling this should trigger a special event which in turn should trigger a system reaction.
|
// Enabling this should trigger a special event which in turn should trigger a system reaction.
|
||||||
#define LOWER_SYRLINKS_UPPER_LIMITS 0
|
#define LOWER_SYRLINKS_UPPER_LIMITS 1
|
||||||
#define LOWER_EBAND_UPPER_LIMITS 0
|
#define LOWER_EBAND_UPPER_LIMITS 0
|
||||||
#define LOWER_PLOC_UPPER_LIMITS 0
|
#define LOWER_PLOC_UPPER_LIMITS 0
|
||||||
|
|
||||||
@ -170,26 +170,31 @@ void ThermalController::performControlOperation() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transitionToOff) {
|
cycles++;
|
||||||
for (const auto& switchState : heaterSwitchStateArray) {
|
if (transitionWhenHeatersOff) {
|
||||||
if (switchState != HeaterHandler::SwitchState::OFF) {
|
bool allSwitchersOff = true;
|
||||||
transitionToOffCycles++;
|
for (size_t idx = 0; idx < heaterSwitchStateArray.size(); idx++) {
|
||||||
// if heater still ON after 10 cycles, switch OFF again
|
if (heaterSwitchStateArray[idx] != HeaterHandler::SwitchState::OFF) {
|
||||||
if (transitionToOffCycles == 10) {
|
allSwitchersOff = false;
|
||||||
for (uint8_t i = 0; i < heater::Switchers::NUMBER_OF_SWITCHES; i++) {
|
// if heater still ON after 3 cycles, switch OFF again
|
||||||
heaterHandler.switchHeater(static_cast<heater::Switchers>(i),
|
if (transitionWhenHeatersOffCycles == 3) {
|
||||||
|
heaterHandler.switchHeater(static_cast<heater::Switch>(idx),
|
||||||
HeaterHandler::SwitchState::OFF);
|
HeaterHandler::SwitchState::OFF);
|
||||||
}
|
|
||||||
triggerEvent(tcsCtrl::HEATER_NOT_OFF_FOR_OFF_MODE);
|
triggerEvent(tcsCtrl::HEATER_NOT_OFF_FOR_OFF_MODE);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
setMode(MODE_OFF);
|
}
|
||||||
|
if (allSwitchersOff or transitionWhenHeatersOffCycles == 6) {
|
||||||
|
// Finish the transition
|
||||||
|
transitionWhenHeatersOff = false;
|
||||||
|
resetThermalStates();
|
||||||
|
setMode(targetMode, targetSubmode);
|
||||||
|
} else {
|
||||||
|
transitionWhenHeatersOffCycles++;
|
||||||
}
|
}
|
||||||
} else if (mode != MODE_OFF and not tcsBrdShortlyUnavailable) {
|
} else if (mode != MODE_OFF and not tcsBrdShortlyUnavailable) {
|
||||||
performThermalModuleCtrl(heaterSwitchStateArray);
|
performThermalModuleCtrl(heaterSwitchStateArray);
|
||||||
}
|
}
|
||||||
cycles++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
@ -292,12 +297,18 @@ LocalPoolDataSetBase* ThermalController::getDataSetHandle(sid_t sid) {
|
|||||||
|
|
||||||
ReturnValue_t ThermalController::checkModeCommand(Mode_t mode, Submode_t submode,
|
ReturnValue_t ThermalController::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t* msToReachTheMode) {
|
uint32_t* msToReachTheMode) {
|
||||||
|
if ((mode != MODE_OFF) and (mode != MODE_ON)) {
|
||||||
|
return INVALID_MODE;
|
||||||
|
}
|
||||||
|
if (mode == MODE_ON) {
|
||||||
|
if (submode != SUBMODE_NONE and submode != SUBMODE_NO_HEATER_CTRL) {
|
||||||
|
return HasModesIF::INVALID_SUBMODE;
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
if (submode != SUBMODE_NONE) {
|
if (submode != SUBMODE_NONE) {
|
||||||
return INVALID_SUBMODE;
|
return INVALID_SUBMODE;
|
||||||
}
|
}
|
||||||
if ((mode != MODE_OFF) && (mode != MODE_ON) && (mode != MODE_NORMAL)) {
|
|
||||||
return INVALID_MODE;
|
|
||||||
}
|
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,8 +987,8 @@ void ThermalController::copyDevices() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThermalController::ctrlAcsBoard() {
|
void ThermalController::ctrlAcsBoard() {
|
||||||
heater::Switchers switchNr = heater::HEATER_2_ACS_BRD;
|
heater::Switch switchNr = heater::HEATER_2_ACS_BRD;
|
||||||
heater::Switchers redSwitchNr = heater::HEATER_0_OBC_BRD;
|
heater::Switch redSwitchNr = heater::HEATER_0_OBC_BRD;
|
||||||
|
|
||||||
// A side
|
// A side
|
||||||
thermalComponent = ACS_BOARD;
|
thermalComponent = ACS_BOARD;
|
||||||
@ -1023,7 +1034,9 @@ void ThermalController::ctrlAcsBoard() {
|
|||||||
} else {
|
} else {
|
||||||
if (chooseHeater(switchNr, redSwitchNr)) {
|
if (chooseHeater(switchNr, redSwitchNr)) {
|
||||||
if (heaterHandler.getSwitchState(switchNr)) {
|
if (heaterHandler.getSwitchState(switchNr)) {
|
||||||
heaterHandler.switchHeater(switchNr, HeaterHandler::SwitchState::OFF);
|
if (submode != SUBMODE_NO_HEATER_CTRL) {
|
||||||
|
heaterSwitchHelper(switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1268,8 +1281,8 @@ void ThermalController::ctrlPcduP60Board() {
|
|||||||
|
|
||||||
void ThermalController::ctrlPcduAcu() {
|
void ThermalController::ctrlPcduAcu() {
|
||||||
thermalComponent = PCDUACU;
|
thermalComponent = PCDUACU;
|
||||||
heater::Switchers switchNr = heater::HEATER_3_PCDU_PDU;
|
heater::Switch switchNr = heater::HEATER_3_PCDU_PDU;
|
||||||
heater::Switchers redSwitchNr = heater::HEATER_2_ACS_BRD;
|
heater::Switch redSwitchNr = heater::HEATER_2_ACS_BRD;
|
||||||
|
|
||||||
if (chooseHeater(switchNr, redSwitchNr)) {
|
if (chooseHeater(switchNr, redSwitchNr)) {
|
||||||
bool sensorTempAvailable = true;
|
bool sensorTempAvailable = true;
|
||||||
@ -1557,13 +1570,16 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
|
|||||||
void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) {
|
void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) {
|
||||||
if (selectAndReadSensorTemp(htrCtx)) {
|
if (selectAndReadSensorTemp(htrCtx)) {
|
||||||
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
|
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
|
||||||
|
// Core loop for a thermal component, after sensors and heaters were selected.
|
||||||
checkLimitsAndCtrlHeater(htrCtx);
|
checkLimitsAndCtrlHeater(htrCtx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: muss der Heater dann wirklich abgeschalten werden?
|
// No sensors available, so switch the heater off. We can not perform control tasks if we
|
||||||
|
// are blind..
|
||||||
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
|
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
|
||||||
if (heaterHandler.getSwitchState(htrCtx.switchNr)) {
|
if (heaterCtrlAllowed() and
|
||||||
heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::OFF);
|
(heaterHandler.getSwitchState(htrCtx.switchNr) == HeaterHandler::SwitchState::ON)) {
|
||||||
|
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1593,7 +1609,7 @@ bool ThermalController::selectAndReadSensorTemp(HeaterContext& htrCtx) {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool ThermalController::chooseHeater(heater::Switchers& switchNr, heater::Switchers redSwitchNr) {
|
bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch redSwitchNr) {
|
||||||
bool heaterAvailable = true;
|
bool heaterAvailable = true;
|
||||||
|
|
||||||
if (heaterHandler.getHealth(switchNr) != HasHealthIF::HEALTHY) {
|
if (heaterHandler.getHealth(switchNr) != HasHealthIF::HEALTHY) {
|
||||||
@ -1611,15 +1627,18 @@ bool ThermalController::chooseHeater(heater::Switchers& switchNr, heater::Switch
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ThermalController::heaterCtrlTempTooHighHandler(HeaterContext& htrCtx, const char* whatLimit) {
|
void ThermalController::heaterCtrlTempTooHighHandler(HeaterContext& htrCtx, const char* whatLimit) {
|
||||||
|
if (not heaterCtrlAllowed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (htrCtx.switchState == HeaterHandler::SwitchState::ON) {
|
if (htrCtx.switchState == HeaterHandler::SwitchState::ON) {
|
||||||
sif::info << "TCS: Component " << static_cast<int>(thermalComponent) << " too warm, above "
|
sif::info << "TCS: Component " << static_cast<int>(thermalComponent) << " too warm, above "
|
||||||
<< whatLimit << ", switching off heater" << std::endl;
|
<< whatLimit << ", switching off heater" << std::endl;
|
||||||
heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::OFF);
|
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||||
heaterStates[htrCtx.switchNr].switchTransition = true;
|
heaterStates[htrCtx.switchNr].switchTransition = true;
|
||||||
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF;
|
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF;
|
||||||
}
|
}
|
||||||
if (heaterHandler.getSwitchState(htrCtx.redSwitchNr) == HeaterHandler::SwitchState::ON) {
|
if (heaterHandler.getSwitchState(htrCtx.redSwitchNr) == HeaterHandler::SwitchState::ON) {
|
||||||
heaterHandler.switchHeater(htrCtx.redSwitchNr, HeaterHandler::SwitchState::OFF);
|
heaterSwitchHelper(htrCtx.redSwitchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||||
heaterStates[htrCtx.redSwitchNr].switchTransition = true;
|
heaterStates[htrCtx.redSwitchNr].switchTransition = true;
|
||||||
heaterStates[htrCtx.redSwitchNr].target = HeaterHandler::SwitchState::OFF;
|
heaterStates[htrCtx.redSwitchNr].target = HeaterHandler::SwitchState::OFF;
|
||||||
}
|
}
|
||||||
@ -1634,34 +1653,37 @@ void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
|
|||||||
if (heaterStates[htrCtx.switchNr].switchTransition) {
|
if (heaterStates[htrCtx.switchNr].switchTransition) {
|
||||||
htrCtx.doHeaterHandling = false;
|
htrCtx.doHeaterHandling = false;
|
||||||
heaterCtrlCheckUpperLimits(htrCtx);
|
heaterCtrlCheckUpperLimits(htrCtx);
|
||||||
} else {
|
return;
|
||||||
// Heater off
|
}
|
||||||
|
|
||||||
htrCtx.switchState = heaterHandler.getSwitchState(htrCtx.switchNr);
|
htrCtx.switchState = heaterHandler.getSwitchState(htrCtx.switchNr);
|
||||||
|
// Heater off
|
||||||
if (htrCtx.switchState == HeaterHandler::SwitchState::OFF) {
|
if (htrCtx.switchState == HeaterHandler::SwitchState::OFF) {
|
||||||
if (sensorTemp < htrCtx.tempLimit.opLowerLimit) {
|
if (sensorTemp < htrCtx.tempLimit.opLowerLimit and heaterCtrlAllowed()) {
|
||||||
heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::ON);
|
sif::info << "TCS: Heater " << static_cast<int>(thermalComponent) << " ON" << std::endl;
|
||||||
sif::info << "ThermalController::checkLimitsAndCtrlHeater: Heater "
|
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::ON, thermalComponent);
|
||||||
<< static_cast<int>(thermalComponent) << " ON" << std::endl;
|
|
||||||
heaterStates[htrCtx.switchNr].switchTransition = true;
|
heaterStates[htrCtx.switchNr].switchTransition = true;
|
||||||
thermalStates[thermalComponent].heating = true;
|
|
||||||
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::ON;
|
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::ON;
|
||||||
} else {
|
} else {
|
||||||
|
// Even if heater control is now allowed, we can update the state.
|
||||||
thermalStates[thermalComponent].heating = false;
|
thermalStates[thermalComponent].heating = false;
|
||||||
}
|
}
|
||||||
heaterCtrlCheckUpperLimits(htrCtx);
|
heaterCtrlCheckUpperLimits(htrCtx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Heater on
|
// Heater on
|
||||||
} else if (heaterHandler.getSwitchState(htrCtx.switchNr) == HeaterHandler::SwitchState::ON) {
|
if (htrCtx.switchState == HeaterHandler::SwitchState::ON) {
|
||||||
if (thermalStates[thermalComponent].heating) {
|
if (thermalStates[thermalComponent].heating) {
|
||||||
// We are already in a heating cycle, so need to check whether heating task is complete.
|
// We are already in a heating cycle, so need to check whether heating task is complete.
|
||||||
if (sensorTemp >= htrCtx.tempLimit.opLowerLimit + TEMP_OFFSET) {
|
if (sensorTemp >= htrCtx.tempLimit.opLowerLimit + TEMP_OFFSET and heaterCtrlAllowed()) {
|
||||||
heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::OFF);
|
sif::info << "TCS: Heater " << static_cast<int>(thermalComponent) << " OFF" << std::endl;
|
||||||
sif::info << "ThermalController::checkLimitsAndCtrlHeater: Heater "
|
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||||
<< static_cast<int>(thermalComponent) << " OFF" << std::endl;
|
|
||||||
heaterStates[htrCtx.switchNr].switchTransition = true;
|
heaterStates[htrCtx.switchNr].switchTransition = true;
|
||||||
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF;
|
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF;
|
||||||
thermalStates[thermalComponent].heating = false;
|
|
||||||
}
|
}
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
// This can happen if heater is used as alternative heater (no regular heating cycle), so we
|
// This can happen if heater is used as alternative heater (no regular heating cycle), so we
|
||||||
// should still check the upper limits.
|
// should still check the upper limits.
|
||||||
bool tooHighHandlerAlreadyCalled = heaterCtrlCheckUpperLimits(htrCtx);
|
bool tooHighHandlerAlreadyCalled = heaterCtrlCheckUpperLimits(htrCtx);
|
||||||
@ -1673,8 +1695,6 @@ void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ThermalController::heaterCtrlCheckUpperLimits(HeaterContext& htrCtx) {
|
bool ThermalController::heaterCtrlCheckUpperLimits(HeaterContext& htrCtx) {
|
||||||
if (sensorTemp >= htrCtx.tempLimit.nopUpperLimit) {
|
if (sensorTemp >= htrCtx.tempLimit.nopUpperLimit) {
|
||||||
@ -1702,8 +1722,8 @@ void ThermalController::resetSensorsArray() {
|
|||||||
}
|
}
|
||||||
thermalComponent = NONE;
|
thermalComponent = NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThermalController::heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates) {
|
void ThermalController::heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates) {
|
||||||
// TODO: Test
|
|
||||||
for (unsigned i = 0; i < 7; i++) {
|
for (unsigned i = 0; i < 7; i++) {
|
||||||
if (heaterStates[i].switchTransition) {
|
if (heaterStates[i].switchTransition) {
|
||||||
if (currentHeaterStates[i] == heaterStates[i].target) {
|
if (currentHeaterStates[i] == heaterStates[i].target) {
|
||||||
@ -1727,11 +1747,12 @@ uint32_t ThermalController::tempFloatToU32() const {
|
|||||||
return tempRaw;
|
return tempRaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThermalController::setMode(Mode_t mode) {
|
void ThermalController::setMode(Mode_t mode, Submode_t submode) {
|
||||||
if (mode == MODE_OFF) {
|
if (mode == MODE_OFF) {
|
||||||
transitionToOff = false;
|
transitionWhenHeatersOff = false;
|
||||||
}
|
}
|
||||||
this->mode = mode;
|
this->mode = mode;
|
||||||
|
this->submode = submode;
|
||||||
modeHelper.modeChanged(mode, submode);
|
modeHelper.modeChanged(mode, submode);
|
||||||
announceMode(false);
|
announceMode(false);
|
||||||
}
|
}
|
||||||
@ -1746,6 +1767,43 @@ bool ThermalController::tooHotHandler(object_id_t object, bool& oneShotFlag) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ThermalController::heaterCtrlAllowed() const { return submode != SUBMODE_NO_HEATER_CTRL; }
|
||||||
|
|
||||||
|
void ThermalController::resetThermalStates() {
|
||||||
|
for (auto& thermalState : thermalStates) {
|
||||||
|
thermalState.heating = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThermalController::heaterSwitchHelper(heater::Switch switchNr,
|
||||||
|
HeaterHandler::SwitchState state,
|
||||||
|
unsigned componentIdx) {
|
||||||
|
timeval currentTime;
|
||||||
|
Clock::getClockMonotonic(¤tTime);
|
||||||
|
if (state == HeaterHandler::SwitchState::ON) {
|
||||||
|
heaterHandler.switchHeater(switchNr, state);
|
||||||
|
thermalStates[componentIdx].heating = true;
|
||||||
|
thermalStates[componentIdx].heaterStartTime = currentTime.tv_sec;
|
||||||
|
} else {
|
||||||
|
heaterHandler.switchHeater(switchNr, state);
|
||||||
|
thermalStates[componentIdx].heating = false;
|
||||||
|
thermalStates[componentIdx].heaterEndTime = currentTime.tv_sec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThermalController::heaterSwitchHelperAllOff() {
|
||||||
|
timeval currentTime;
|
||||||
|
Clock::getClockMonotonic(¤tTime);
|
||||||
|
size_t idx = 0;
|
||||||
|
for (; idx < heater::Switch::NUMBER_OF_SWITCHES; idx++) {
|
||||||
|
heaterHandler.switchHeater(static_cast<heater::Switch>(idx), HeaterHandler::SwitchState::OFF);
|
||||||
|
}
|
||||||
|
for (idx = 0; idx < thermalStates.size(); idx++) {
|
||||||
|
thermalStates[idx].heating = false;
|
||||||
|
thermalStates[idx].heaterEndTime = currentTime.tv_sec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ThermalController::tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag) {
|
void ThermalController::tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag) {
|
||||||
// Clear the one shot flag is the component is in acceptable temperature range.
|
// Clear the one shot flag is the component is in acceptable temperature range.
|
||||||
if (not tooHotHandler(object, oneShotFlag) and not componentAboveUpperLimit) {
|
if (not tooHotHandler(object, oneShotFlag) and not componentAboveUpperLimit) {
|
||||||
@ -1755,14 +1813,15 @@ void ThermalController::tooHotHandlerWhichClearsOneShotFlag(object_id_t object,
|
|||||||
|
|
||||||
void ThermalController::startTransition(Mode_t mode_, Submode_t submode_) {
|
void ThermalController::startTransition(Mode_t mode_, Submode_t submode_) {
|
||||||
triggerEvent(CHANGING_MODE, mode_, submode_);
|
triggerEvent(CHANGING_MODE, mode_, submode_);
|
||||||
if (mode_ == MODE_OFF) {
|
// For MODE_OFF and the no heater control submode, we command all switches to off before
|
||||||
for (uint8_t i = 0; i < heater::Switchers::NUMBER_OF_SWITCHES; i++) {
|
// completing the transition. This ensures a consistent state when commanding these modes.
|
||||||
heaterHandler.switchHeater(static_cast<heater::Switchers>(i),
|
if ((mode_ == MODE_OFF) or ((mode_ == MODE_ON) and (submode_ == SUBMODE_NO_HEATER_CTRL))) {
|
||||||
HeaterHandler::SwitchState::OFF);
|
heaterSwitchHelperAllOff();
|
||||||
}
|
transitionWhenHeatersOff = true;
|
||||||
transitionToOff = true;
|
targetMode = mode_;
|
||||||
transitionToOffCycles = 0;
|
targetSubmode = submode_;
|
||||||
|
transitionWhenHeatersOffCycles = 0;
|
||||||
} else {
|
} else {
|
||||||
setMode(mode_);
|
setMode(mode_, submode_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,13 @@ struct TempLimits {
|
|||||||
|
|
||||||
struct ThermalState {
|
struct ThermalState {
|
||||||
uint8_t errorCounter;
|
uint8_t errorCounter;
|
||||||
bool heating;
|
// Is heating on for that thermal module?
|
||||||
uint32_t heaterStartTime;
|
bool heating = false;
|
||||||
|
heater::Switch heaterSwitch = heater::Switch::NUMBER_OF_SWITCHES;
|
||||||
|
// Heater start time and end times as UNIX seconds. Please note that these times will be updated
|
||||||
|
// when a switch command is sent, with no guarantess that the heater actually went on.
|
||||||
|
uint32_t heaterStartTime = 0;
|
||||||
|
uint32_t heaterEndTime = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HeaterState {
|
struct HeaterState {
|
||||||
@ -90,6 +95,8 @@ enum ThermalComponents : uint8_t {
|
|||||||
|
|
||||||
class ThermalController : public ExtendedControllerBase {
|
class ThermalController : public ExtendedControllerBase {
|
||||||
public:
|
public:
|
||||||
|
static constexpr uint8_t SUBMODE_NO_HEATER_CTRL = 1;
|
||||||
|
|
||||||
static const uint16_t INVALID_TEMPERATURE = 999;
|
static const uint16_t INVALID_TEMPERATURE = 999;
|
||||||
static const uint8_t NUMBER_OF_SENSORS = 16;
|
static const uint8_t NUMBER_OF_SENSORS = 16;
|
||||||
static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80;
|
static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80;
|
||||||
@ -103,13 +110,13 @@ class ThermalController : public ExtendedControllerBase {
|
|||||||
protected:
|
protected:
|
||||||
struct HeaterContext {
|
struct HeaterContext {
|
||||||
public:
|
public:
|
||||||
HeaterContext(heater::Switchers switchNr, heater::Switchers redundantSwitchNr,
|
HeaterContext(heater::Switch switchNr, heater::Switch redundantSwitchNr,
|
||||||
const TempLimits& tempLimit)
|
const TempLimits& tempLimit)
|
||||||
: switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {}
|
: switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {}
|
||||||
bool doHeaterHandling = true;
|
bool doHeaterHandling = true;
|
||||||
heater::Switchers switchNr;
|
heater::Switch switchNr;
|
||||||
HeaterHandler::SwitchState switchState = HeaterHandler::SwitchState::OFF;
|
HeaterHandler::SwitchState switchState = HeaterHandler::SwitchState::OFF;
|
||||||
heater::Switchers redSwitchNr;
|
heater::Switch redSwitchNr;
|
||||||
const TempLimits& tempLimit;
|
const TempLimits& tempLimit;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -263,11 +270,13 @@ class ThermalController : public ExtendedControllerBase {
|
|||||||
bool strTooHotFlag = false;
|
bool strTooHotFlag = false;
|
||||||
bool rwTooHotFlag = false;
|
bool rwTooHotFlag = false;
|
||||||
|
|
||||||
bool transitionToOff = false;
|
bool transitionWhenHeatersOff = false;
|
||||||
uint32_t transitionToOffCycles = 0;
|
uint32_t transitionWhenHeatersOffCycles = 0;
|
||||||
|
Mode_t targetMode = MODE_OFF;
|
||||||
|
Submode_t targetSubmode = SUBMODE_NONE;
|
||||||
uint32_t cycles = 0;
|
uint32_t cycles = 0;
|
||||||
std::array<ThermalState, 30> thermalStates{};
|
std::array<ThermalState, ThermalComponents::NUM_ENTRIES> thermalStates{};
|
||||||
std::array<HeaterState, 7> heaterStates{};
|
std::array<HeaterState, heater::NUMBER_OF_SWITCHES> heaterStates{};
|
||||||
|
|
||||||
// Initial delay to make sure all pool variables have been initialized their owners.
|
// Initial delay to make sure all pool variables have been initialized their owners.
|
||||||
// Also, wait for system initialization to complete.
|
// Also, wait for system initialization to complete.
|
||||||
@ -292,6 +301,9 @@ class ThermalController : public ExtendedControllerBase {
|
|||||||
|
|
||||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||||
|
|
||||||
|
bool heaterCtrlAllowed() const;
|
||||||
|
void resetThermalStates();
|
||||||
|
|
||||||
void resetSensorsArray();
|
void resetSensorsArray();
|
||||||
void copySensors();
|
void copySensors();
|
||||||
void copySus();
|
void copySus();
|
||||||
@ -302,9 +314,13 @@ class ThermalController : public ExtendedControllerBase {
|
|||||||
bool heaterCtrlCheckUpperLimits(HeaterContext& heaterContext);
|
bool heaterCtrlCheckUpperLimits(HeaterContext& heaterContext);
|
||||||
void heaterCtrlTempTooHighHandler(HeaterContext& heaterContext, const char* whatLimit);
|
void heaterCtrlTempTooHighHandler(HeaterContext& heaterContext, const char* whatLimit);
|
||||||
|
|
||||||
bool chooseHeater(heater::Switchers& switchNr, heater::Switchers redSwitchNr);
|
bool chooseHeater(heater::Switch& switchNr, heater::Switch redSwitchNr);
|
||||||
bool selectAndReadSensorTemp(HeaterContext& htrCtx);
|
bool selectAndReadSensorTemp(HeaterContext& htrCtx);
|
||||||
|
|
||||||
|
void heaterSwitchHelperAllOff();
|
||||||
|
void heaterSwitchHelper(heater::Switch switchNr, HeaterHandler::SwitchState state,
|
||||||
|
unsigned componentIdx);
|
||||||
|
|
||||||
void ctrlAcsBoard();
|
void ctrlAcsBoard();
|
||||||
void ctrlMgt();
|
void ctrlMgt();
|
||||||
void ctrlRw();
|
void ctrlRw();
|
||||||
@ -329,7 +345,7 @@ class ThermalController : public ExtendedControllerBase {
|
|||||||
void ctrlMpa();
|
void ctrlMpa();
|
||||||
void ctrlScexBoard();
|
void ctrlScexBoard();
|
||||||
void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates);
|
void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates);
|
||||||
void setMode(Mode_t mode);
|
void setMode(Mode_t mode, Submode_t submode);
|
||||||
uint32_t tempFloatToU32() const;
|
uint32_t tempFloatToU32() const;
|
||||||
bool tooHotHandler(object_id_t object, bool& oneShotFlag);
|
bool tooHotHandler(object_id_t object, bool& oneShotFlag);
|
||||||
void tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag);
|
void tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag);
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||||
|
|
||||||
#include "devices/heaterSwitcherList.h"
|
|
||||||
#include "eive/eventSubsystemIds.h"
|
#include "eive/eventSubsystemIds.h"
|
||||||
|
#include "mission/tcs/defs.h"
|
||||||
|
|
||||||
namespace tcsCtrl {
|
namespace tcsCtrl {
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ void buildNormalSequence(Subsystem& ss, ModeListEntry& eh) {
|
|||||||
ctxc);
|
ctxc);
|
||||||
|
|
||||||
// Transition 1
|
// Transition 1
|
||||||
iht(objects::THERMAL_CONTROLLER, NML, 0, TCS_TABLE_NORMAL_TRANS_1.second);
|
iht(objects::THERMAL_CONTROLLER, HasModesIF::MODE_ON, 0, TCS_TABLE_NORMAL_TRANS_1.second);
|
||||||
check(ss.addTable(TableEntry(TCS_TABLE_NORMAL_TRANS_1.first, &TCS_TABLE_NORMAL_TRANS_1.second)),
|
check(ss.addTable(TableEntry(TCS_TABLE_NORMAL_TRANS_1.first, &TCS_TABLE_NORMAL_TRANS_1.second)),
|
||||||
ctxc);
|
ctxc);
|
||||||
|
|
||||||
|
@ -215,17 +215,17 @@ void HeaterHandler::handleSwitchHandling() {
|
|||||||
heaterVec[idx].cmdActive = true;
|
heaterVec[idx].cmdActive = true;
|
||||||
heaterVec[idx].action = SET_SWITCH_OFF;
|
heaterVec[idx].action = SET_SWITCH_OFF;
|
||||||
triggerEvent(FAULTY_HEATER_WAS_ON, idx, 0);
|
triggerEvent(FAULTY_HEATER_WAS_ON, idx, 0);
|
||||||
handleSwitchOffCommand(static_cast<heater::Switchers>(idx));
|
handleSwitchOffCommand(static_cast<heater::Switch>(idx));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (heaterVec[idx].cmdActive) {
|
if (heaterVec[idx].cmdActive) {
|
||||||
switch (heaterVec[idx].action) {
|
switch (heaterVec[idx].action) {
|
||||||
case SET_SWITCH_ON:
|
case SET_SWITCH_ON:
|
||||||
handleSwitchOnCommand(static_cast<heater::Switchers>(idx));
|
handleSwitchOnCommand(static_cast<heater::Switch>(idx));
|
||||||
break;
|
break;
|
||||||
case SET_SWITCH_OFF:
|
case SET_SWITCH_OFF:
|
||||||
handleSwitchOffCommand(static_cast<heater::Switchers>(idx));
|
handleSwitchOffCommand(static_cast<heater::Switch>(idx));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sif::error << "HeaterHandler::handleActiveCommands: Invalid action commanded"
|
sif::error << "HeaterHandler::handleActiveCommands: Invalid action commanded"
|
||||||
@ -236,7 +236,7 @@ void HeaterHandler::handleSwitchHandling() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeaterHandler::handleSwitchOnCommand(heater::Switchers heaterIdx) {
|
void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
auto& heater = heaterVec.at(heaterIdx);
|
auto& heater = heaterVec.at(heaterIdx);
|
||||||
if (waitForSwitchOff) {
|
if (waitForSwitchOff) {
|
||||||
@ -307,7 +307,7 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switchers heaterIdx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeaterHandler::handleSwitchOffCommand(heater::Switchers heaterIdx) {
|
void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
auto& heater = heaterVec.at(heaterIdx);
|
auto& heater = heaterVec.at(heaterIdx);
|
||||||
// Check whether switch is already off
|
// Check whether switch is already off
|
||||||
@ -344,12 +344,12 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switchers heaterIdx) {
|
|||||||
heater.cmdActive = false;
|
heater.cmdActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeaterHandler::SwitchState HeaterHandler::getSwitchState(heater::Switchers switchNr) const {
|
HeaterHandler::SwitchState HeaterHandler::getSwitchState(heater::Switch switchNr) const {
|
||||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||||
return heaterVec.at(switchNr).switchState;
|
return heaterVec.at(switchNr).switchState;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t HeaterHandler::switchHeater(heater::Switchers heater, SwitchState switchState) {
|
ReturnValue_t HeaterHandler::switchHeater(heater::Switch heater, SwitchState switchState) {
|
||||||
if (switchState == SwitchState::ON) {
|
if (switchState == SwitchState::ON) {
|
||||||
return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_ON);
|
return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_ON);
|
||||||
} else if (switchState == SwitchState::OFF) {
|
} else if (switchState == SwitchState::OFF) {
|
||||||
@ -428,7 +428,7 @@ ReturnValue_t HeaterHandler::getSwitchState(uint8_t switchNr) const {
|
|||||||
if (switchNr > 7) {
|
if (switchNr > 7) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
if (getSwitchState(static_cast<heater::Switchers>(switchNr)) == SwitchState::ON) {
|
if (getSwitchState(static_cast<heater::Switch>(switchNr)) == SwitchState::ON) {
|
||||||
return PowerSwitchIF::SWITCH_ON;
|
return PowerSwitchIF::SWITCH_ON;
|
||||||
}
|
}
|
||||||
return PowerSwitchIF::SWITCH_OFF;
|
return PowerSwitchIF::SWITCH_OFF;
|
||||||
@ -438,7 +438,7 @@ ReturnValue_t HeaterHandler::getFuseState(uint8_t fuseNr) const { return 0; }
|
|||||||
|
|
||||||
uint32_t HeaterHandler::getSwitchDelayMs(void) const { return 2000; }
|
uint32_t HeaterHandler::getSwitchDelayMs(void) const { return 2000; }
|
||||||
|
|
||||||
HasHealthIF::HealthState HeaterHandler::getHealth(heater::Switchers heater) {
|
HasHealthIF::HealthState HeaterHandler::getHealth(heater::Switch heater) {
|
||||||
auto* healthDev = heaterVec.at(heater).healthDevice;
|
auto* healthDev = heaterVec.at(heater).healthDevice;
|
||||||
if (healthDev != nullptr) {
|
if (healthDev != nullptr) {
|
||||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "devices/heaterSwitcherList.h"
|
|
||||||
#include "events/subsystemIdRanges.h"
|
#include "events/subsystemIdRanges.h"
|
||||||
|
#include "mission/tcs/defs.h"
|
||||||
#include "returnvalues/classIds.h"
|
#include "returnvalues/classIds.h"
|
||||||
|
|
||||||
class PowerSwitchIF;
|
class PowerSwitchIF;
|
||||||
@ -75,8 +75,8 @@ class HeaterHandler : public ExecutableObjectIF,
|
|||||||
protected:
|
protected:
|
||||||
enum SwitchAction : uint8_t { SET_SWITCH_OFF, SET_SWITCH_ON, NONE };
|
enum SwitchAction : uint8_t { SET_SWITCH_OFF, SET_SWITCH_ON, NONE };
|
||||||
|
|
||||||
ReturnValue_t switchHeater(heater::Switchers heater, SwitchState switchState);
|
ReturnValue_t switchHeater(heater::Switch heater, SwitchState switchState);
|
||||||
HasHealthIF::HealthState getHealth(heater::Switchers heater);
|
HasHealthIF::HealthState getHealth(heater::Switch heater);
|
||||||
|
|
||||||
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ class HeaterHandler : public ExecutableObjectIF,
|
|||||||
* @brief Returns the state of a switch (ON - true, or OFF - false).
|
* @brief Returns the state of a switch (ON - true, or OFF - false).
|
||||||
* @param switchNr The number of the switch to check.
|
* @param switchNr The number of the switch to check.
|
||||||
*/
|
*/
|
||||||
SwitchState getSwitchState(heater::Switchers switchNr) const;
|
SwitchState getSwitchState(heater::Switch switchNr) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function runs commands waiting for execution.
|
* @brief This function runs commands waiting for execution.
|
||||||
@ -198,9 +198,9 @@ class HeaterHandler : public ExecutableObjectIF,
|
|||||||
const HasModesIF& getModeIF() const override;
|
const HasModesIF& getModeIF() const override;
|
||||||
ModeTreeChildIF& getModeTreeChildIF() override;
|
ModeTreeChildIF& getModeTreeChildIF() override;
|
||||||
|
|
||||||
void handleSwitchOnCommand(heater::Switchers heaterIdx);
|
void handleSwitchOnCommand(heater::Switch heaterIdx);
|
||||||
|
|
||||||
void handleSwitchOffCommand(heater::Switchers heaterIdx);
|
void handleSwitchOffCommand(heater::Switch heaterIdx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if all switches are off.
|
* @brief Checks if all switches are off.
|
||||||
|
@ -1,6 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace heater {
|
||||||
|
enum Switch : uint8_t {
|
||||||
|
HEATER_0_OBC_BRD,
|
||||||
|
HEATER_1_PLOC_PROC_BRD,
|
||||||
|
HEATER_2_ACS_BRD,
|
||||||
|
HEATER_3_PCDU_PDU,
|
||||||
|
HEATER_4_CAMERA,
|
||||||
|
HEATER_5_STR,
|
||||||
|
HEATER_6_DRO,
|
||||||
|
HEATER_7_S_BAND,
|
||||||
|
NUMBER_OF_SWITCHES
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace tcs {
|
namespace tcs {
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ TEST_CASE("Thermal Controller", "[ThermalController]") {
|
|||||||
CommandMessage modeMessage;
|
CommandMessage modeMessage;
|
||||||
|
|
||||||
ModeMessage::setModeMessage(&modeMessage, ModeMessage::CMD_MODE_COMMAND,
|
ModeMessage::setModeMessage(&modeMessage, ModeMessage::CMD_MODE_COMMAND,
|
||||||
ControllerBase::MODE_NORMAL, HasModesIF::SUBMODE_NONE);
|
HasModesIF::MODE_ON, HasModesIF::SUBMODE_NONE);
|
||||||
|
|
||||||
MessageQueueIF* commandQueue =
|
MessageQueueIF* commandQueue =
|
||||||
QueueFactory::instance()->createMessageQueue(5, MessageQueueMessage::MAX_MESSAGE_SIZE);
|
QueueFactory::instance()->createMessageQueue(5, MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||||
@ -58,7 +58,7 @@ TEST_CASE("Thermal Controller", "[ThermalController]") {
|
|||||||
REQUIRE(controller.performOperation(0) == returnvalue::OK);
|
REQUIRE(controller.performOperation(0) == returnvalue::OK);
|
||||||
|
|
||||||
REQUIRE(testEnvironment::eventManager->isEventInEventList(
|
REQUIRE(testEnvironment::eventManager->isEventInEventList(
|
||||||
THERMAL_CONTROLLER_ID, HasModesIF::MODE_INFO, ControllerBase::MODE_NORMAL,
|
THERMAL_CONTROLLER_ID, HasModesIF::MODE_INFO, HasModesIF::MODE_ON,
|
||||||
HasModesIF::SUBMODE_NONE) == true);
|
HasModesIF::SUBMODE_NONE) == true);
|
||||||
|
|
||||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||||
|
Loading…
Reference in New Issue
Block a user