1933 lines
80 KiB
C++
1933 lines
80 KiB
C++
#include "ThermalController.h"
|
|
|
|
#include <bsp_q7s/core/defs.h>
|
|
#include <eive/objects.h>
|
|
#include <fsfw/datapool/PoolReadGuard.h>
|
|
#include <fsfw/thermal/ThermalComponentIF.h>
|
|
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
|
|
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h>
|
|
#include <mission/acs/gyroAdisHelpers.h>
|
|
#include <mission/acs/imtqHelpers.h>
|
|
#include <mission/acs/rwHelpers.h>
|
|
#include <mission/acs/str/strHelpers.h>
|
|
#include <mission/com/syrlinksDefs.h>
|
|
#include <mission/payload/payloadPcduDefinitions.h>
|
|
#include <mission/power/bpxBattDefs.h>
|
|
#include <mission/power/gsDefs.h>
|
|
#include <objects/systemObjectList.h>
|
|
|
|
// Enabling this should trigger a special event which in turn should trigger a system reaction.
|
|
#define LOWER_SYRLINKS_UPPER_LIMITS 0
|
|
#define LOWER_EBAND_UPPER_LIMITS 0
|
|
#define LOWER_PLOC_UPPER_LIMITS 0
|
|
#define LOWER_MGT_UPPER_LIMITS 0
|
|
#define LOWER_RW_UPPER_LIMITS 0
|
|
|
|
ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater,
|
|
const std::atomic_bool& tcsBoardShortUnavailable,
|
|
bool pollPcdu1Tmp)
|
|
: ExtendedControllerBase(objectId),
|
|
heaterHandler(heater),
|
|
pollPcdu1Tmp(pollPcdu1Tmp),
|
|
sensorTemperatures(this),
|
|
susTemperatures(this),
|
|
deviceTemperatures(this),
|
|
heaterInfo(this),
|
|
tcsCtrlInfo(this),
|
|
imtqThermalSet(objects::IMTQ_HANDLER, ThermalStateCfg()),
|
|
maxSet0PlocHspd(objects::RTD_0_IC3_PLOC_HEATSPREADER,
|
|
EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet1PlocMissionBrd(objects::RTD_1_IC4_PLOC_MISSIONBOARD,
|
|
EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet2PlCam(objects::RTD_2_IC5_4K_CAMERA, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet3DacHspd(objects::RTD_3_IC6_DAC_HEATSPREADER,
|
|
EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet4Str(objects::RTD_4_IC7_STARTRACKER, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet5Rw1MxMy(objects::RTD_5_IC8_RW1_MX_MY, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet6Dro(objects::RTD_6_IC9_DRO, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet7Scex(objects::RTD_7_IC10_SCEX, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet8X8(objects::RTD_8_IC11_X8, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet9Hpa(objects::RTD_9_IC12_HPA, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet10EbandTx(objects::RTD_10_IC13_PL_TX, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet11Mpa(objects::RTD_11_IC14_MPA, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet31865Set12(objects::RTD_12_IC15_ACU, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet13PlPcduHspd(objects::RTD_13_IC16_PLPCDU_HEATSPREADER,
|
|
EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet14TcsBrd(objects::RTD_14_IC17_TCS_BOARD, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
maxSet15Imtq(objects::RTD_15_IC18_IMTQ, EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
|
|
tmp1075SetTcs0(objects::TMP1075_HANDLER_TCS_0),
|
|
tmp1075SetTcs1(objects::TMP1075_HANDLER_TCS_1),
|
|
tmp1075SetPlPcdu0(objects::TMP1075_HANDLER_PLPCDU_0),
|
|
tmp1075SetIfBoard(objects::TMP1075_HANDLER_IF_BOARD),
|
|
susSet0(objects::SUS_0_N_LOC_XFYFZM_PT_XF),
|
|
susSet1(objects::SUS_1_N_LOC_XBYFZM_PT_XB),
|
|
susSet2(objects::SUS_2_N_LOC_XFYBZB_PT_YB),
|
|
susSet3(objects::SUS_3_N_LOC_XFYBZF_PT_YF),
|
|
susSet4(objects::SUS_4_N_LOC_XMYFZF_PT_ZF),
|
|
susSet5(objects::SUS_5_N_LOC_XFYMZB_PT_ZB),
|
|
susSet6(objects::SUS_6_R_LOC_XFYBZM_PT_XF),
|
|
susSet7(objects::SUS_7_R_LOC_XBYBZM_PT_XB),
|
|
susSet8(objects::SUS_8_R_LOC_XBYBZB_PT_YB),
|
|
susSet9(objects::SUS_9_R_LOC_XBYBZB_PT_YF),
|
|
susSet10(objects::SUS_10_N_LOC_XMYBZF_PT_ZF),
|
|
susSet11(objects::SUS_11_R_LOC_XBYMZB_PT_ZB),
|
|
tcsBrdShortlyUnavailable(tcsBoardShortUnavailable) {
|
|
if (pollPcdu1Tmp) {
|
|
tmp1075SetPlPcdu1 = new TMP1075::Tmp1075Dataset(objects::TMP1075_HANDLER_PLPCDU_1);
|
|
}
|
|
resetSensorsArray();
|
|
}
|
|
|
|
ReturnValue_t ThermalController::initialize() {
|
|
auto* camSwitcher = ObjectManager::instance()->get<HasHealthIF>(objects::CAM_SWITCHER);
|
|
if (camSwitcher == nullptr) {
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
}
|
|
camId = camSwitcher->getCommandQueue();
|
|
return ExtendedControllerBase::initialize();
|
|
}
|
|
|
|
ReturnValue_t ThermalController::handleCommandMessage(CommandMessage* message) {
|
|
return returnvalue::FAILED;
|
|
}
|
|
|
|
void ThermalController::performControlOperation() {
|
|
#if OBSW_THREAD_TRACING == 1
|
|
trace::threadTrace(opCounter, "TCS Task");
|
|
#endif
|
|
|
|
switch (internalState) {
|
|
case InternalState::STARTUP: {
|
|
initialCountdown.resetTimer();
|
|
internalState = InternalState::INITIAL_DELAY;
|
|
return;
|
|
}
|
|
case InternalState::INITIAL_DELAY: {
|
|
if (initialCountdown.hasTimedOut()) {
|
|
sif::info << "Starting thermal control operations" << std::endl;
|
|
internalState = InternalState::READY;
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
case InternalState::READY: {
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (cycles == 40) {
|
|
bool changedLimits = false;
|
|
#if LOWER_SYRLINKS_UPPER_LIMITS == 1
|
|
changedLimits = true;
|
|
sBandTransceiverLimits.cutOffLimit = 0;
|
|
sBandTransceiverLimits.opUpperLimit = 0;
|
|
sBandTransceiverLimits.nopUpperLimit = 0;
|
|
#endif
|
|
#if LOWER_PLOC_UPPER_LIMITS == 1
|
|
changedLimits = true;
|
|
plocMissionBoardLimits.cutOffLimit = 0;
|
|
plocMissionBoardLimits.opUpperLimit = 0;
|
|
plocMissionBoardLimits.nopUpperLimit = 0;
|
|
#endif
|
|
#if LOWER_EBAND_UPPER_LIMITS == 1
|
|
changedLimits = true;
|
|
hpaLimits.cutOffLimit = 0;
|
|
hpaLimits.opUpperLimit = 0;
|
|
hpaLimits.nopUpperLimit = 0;
|
|
#endif
|
|
#if LOWER_MGT_UPPER_LIMITS == 1
|
|
changedLimits = true;
|
|
mgtLimits.cutOffLimit = 0;
|
|
mgtLimits.opUpperLimit = 0;
|
|
mgtLimits.nopUpperLimit = 0;
|
|
#endif
|
|
#if LOWER_RW_UPPER_LIMITS == 1
|
|
changedLimits = true;
|
|
rwLimits.cutOffLimit = 0;
|
|
rwLimits.opUpperLimit = 0;
|
|
rwLimits.nopUpperLimit = 0;
|
|
#endif
|
|
if (changedLimits) {
|
|
sif::debug << "ThermalController: changing limits" << std::endl;
|
|
}
|
|
}
|
|
|
|
if (not tcsBrdShortlyUnavailable) {
|
|
{
|
|
PoolReadGuard pg(&sensorTemperatures);
|
|
if (pg.getReadResult() == returnvalue::OK) {
|
|
copySensors();
|
|
}
|
|
}
|
|
}
|
|
{
|
|
PoolReadGuard pg(&susTemperatures);
|
|
if (pg.getReadResult() == returnvalue::OK) {
|
|
copySus();
|
|
}
|
|
}
|
|
{
|
|
PoolReadGuard pg(&deviceTemperatures);
|
|
if (pg.getReadResult() == returnvalue::OK) {
|
|
copyDevices();
|
|
}
|
|
}
|
|
|
|
tcsCtrl::HeaterSwitchStates heaterSwitchStateArray{};
|
|
heaterHandler.getAllSwitchStates(heaterSwitchStateArray);
|
|
{
|
|
PoolReadGuard pg(&heaterInfo);
|
|
std::memcpy(heaterInfo.heaterSwitchState.value, heaterSwitchStateArray.data(), 8);
|
|
{
|
|
PoolReadGuard pg2(¤tVecPdu2);
|
|
if (pg.getReadResult() == returnvalue::OK and pg2.getReadResult() == returnvalue::OK) {
|
|
heaterInfo.heaterCurrent.value = currentVecPdu2.value[PDU2::Channels::TCS_HEATER_IN];
|
|
}
|
|
}
|
|
}
|
|
|
|
cycles++;
|
|
if (transitionWhenHeatersOff) {
|
|
bool allSwitchersOff = true;
|
|
for (size_t idx = 0; idx < heaterSwitchStateArray.size(); idx++) {
|
|
if (heaterSwitchStateArray[idx] != heater::SwitchState::OFF) {
|
|
allSwitchersOff = false;
|
|
// if heater still ON after 3 cycles, switch OFF again
|
|
if (transitionWhenHeatersOffCycles == 3) {
|
|
heaterHandler.switchHeater(static_cast<heater::Switch>(idx), heater::SwitchState::OFF);
|
|
triggerEvent(tcsCtrl::HEATER_NOT_OFF_FOR_OFF_MODE);
|
|
}
|
|
}
|
|
}
|
|
if (allSwitchersOff or transitionWhenHeatersOffCycles == 6) {
|
|
// Finish the transition
|
|
transitionWhenHeatersOff = false;
|
|
resetThermalStates();
|
|
setMode(targetMode, targetSubmode);
|
|
} else {
|
|
transitionWhenHeatersOffCycles++;
|
|
}
|
|
} else if (mode != MODE_OFF) {
|
|
if (not tcsBrdShortlyUnavailable) {
|
|
performThermalModuleCtrl(heaterSwitchStateArray);
|
|
}
|
|
heaterTransitionControl(heaterSwitchStateArray);
|
|
heaterMaxDurationControl(heaterSwitchStateArray);
|
|
// This dataset makes the TCS CTRL observable.
|
|
PoolReadGuard pg(&tcsCtrlInfo);
|
|
for (uint8_t i = 0; i < thermalStates.size(); i++) {
|
|
tcsCtrlInfo.heatingOnVec[i] = thermalStates[i].heating;
|
|
tcsCtrlInfo.sensorIdxUsedForTcsCtrl[i] = thermalStates[i].sensorIndex;
|
|
tcsCtrlInfo.heaterSwitchIdx[i] = thermalStates[i].heaterSwitch;
|
|
tcsCtrlInfo.heaterStartTimes[i] = thermalStates[i].heaterStartTime;
|
|
tcsCtrlInfo.heaterEndTimes[i] = thermalStates[i].heaterEndTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
|
LocalDataPoolManager& poolManager) {
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_PLOC_HEATSPREADER, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_PLOC_MISSIONBOARD, new PoolEntry<float>({1.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_4K_CAMERA, new PoolEntry<float>({2.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_DAC_HEATSPREADER, new PoolEntry<float>({3.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_STARTRACKER, new PoolEntry<float>({4.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_RW1, new PoolEntry<float>({5.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_DRO, new PoolEntry<float>({6.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_SCEX, new PoolEntry<float>({7.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_X8, new PoolEntry<float>({8.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_HPA, new PoolEntry<float>({9.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_TX_MODUL, new PoolEntry<float>({10.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_MPA, new PoolEntry<float>({11.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_ACU, new PoolEntry<float>({12.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_PLPCDU_HEATSPREADER, new PoolEntry<float>({13.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_TCS_BOARD, new PoolEntry<float>({14.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_MAGNETTORQUER, new PoolEntry<float>({15.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_TMP1075_TCS_0, &tmp1075Tcs0);
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_TMP1075_TCS_1, &tmp1075Tcs1);
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_TMP1075_PLPCDU_0, &tmp1075PlPcdu0);
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_TMP1075_PLPCDU_1, &tmp1075PlPcdu1);
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_TMP1075_IF_BOARD, &tmp1075IfBrd);
|
|
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_0_N_LOC_XFYFZM_PT_XF, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_6_R_LOC_XFYBZM_PT_XF, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_1_N_LOC_XBYFZM_PT_XB, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_7_R_LOC_XBYBZM_PT_XB, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_2_N_LOC_XFYBZB_PT_YB, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_8_R_LOC_XBYBZB_PT_YB, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_3_N_LOC_XFYBZF_PT_YF, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_9_R_LOC_XBYBZB_PT_YF, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_4_N_LOC_XMYFZF_PT_ZF, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_10_N_LOC_XMYBZF_PT_ZF, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_5_N_LOC_XFYMZB_PT_ZB, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::SUS_11_R_LOC_XBYMZB_PT_ZB, new PoolEntry<float>({0.0}));
|
|
|
|
localDataPoolMap.emplace(tcsCtrl::COMPONENT_RW, new PoolEntry<float>({0.0}));
|
|
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_Q7S, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::BATTERY_TEMP_1, new PoolEntry<int16_t>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::BATTERY_TEMP_2, new PoolEntry<int16_t>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::BATTERY_TEMP_3, new PoolEntry<int16_t>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::BATTERY_TEMP_4, new PoolEntry<int16_t>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_RW1, new PoolEntry<int32_t>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_RW2, new PoolEntry<int32_t>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_RW3, new PoolEntry<int32_t>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_RW4, new PoolEntry<int32_t>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_STAR_TRACKER, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_SYRLINKS_POWER_AMPLIFIER, new PoolEntry<float>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_SYRLINKS_BASEBAND_BOARD, new PoolEntry<float>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_MGT, new PoolEntry<int16_t>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_ACU, new PoolEntry<float>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_PDU1, new PoolEntry<float>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_PDU2, new PoolEntry<float>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_1_P60DOCK, new PoolEntry<float>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_2_P60DOCK, new PoolEntry<float>({0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_GYRO_0_SIDE_A, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_GYRO_1_SIDE_A, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_GYRO_2_SIDE_B, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_GYRO_3_SIDE_B, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_MGM_0_SIDE_A, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_MGM_2_SIDE_B, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::TEMP_ADC_PAYLOAD_PCDU, new PoolEntry<float>({0.0}));
|
|
localDataPoolMap.emplace(tcsCtrl::HEATER_SWITCH_LIST, &heaterSwitchStates);
|
|
localDataPoolMap.emplace(tcsCtrl::HEATER_CURRENT, &heaterCurrent);
|
|
localDataPoolMap.emplace(tcsCtrl::HEATER_ON_FOR_COMPONENT_VEC, &tcsCtrlHeaterOn);
|
|
localDataPoolMap.emplace(tcsCtrl::SENSOR_USED_FOR_TCS_CTRL, &tcsCtrlSensorIdx);
|
|
localDataPoolMap.emplace(tcsCtrl::HEATER_IDX_USED_FOR_TCS_CTRL, &tcsCtrlHeaterIdx);
|
|
localDataPoolMap.emplace(tcsCtrl::HEATER_START_TIME, &tcsCtrlStartTimes);
|
|
localDataPoolMap.emplace(tcsCtrl::HEATER_END_TIME, &tcsCtrlEndTimes);
|
|
|
|
bool enableHkSets = false;
|
|
#if OBSW_ENABLE_PERIODIC_HK == 1
|
|
enableHkSets = true;
|
|
#endif
|
|
poolManager.subscribeForRegularPeriodicPacket(
|
|
subdp::RegularHkPeriodicParams(sensorTemperatures.getSid(), enableHkSets, 120.0));
|
|
poolManager.subscribeForRegularPeriodicPacket(
|
|
subdp::RegularHkPeriodicParams(susTemperatures.getSid(), enableHkSets, 240.0));
|
|
poolManager.subscribeForRegularPeriodicPacket(
|
|
subdp::RegularHkPeriodicParams(deviceTemperatures.getSid(), enableHkSets, 120.0));
|
|
poolManager.subscribeForDiagPeriodicPacket(
|
|
subdp::DiagnosticsHkPeriodicParams(heaterInfo.getSid(), enableHkSets, 120.0));
|
|
poolManager.subscribeForRegularPeriodicPacket(
|
|
subdp::RegularHkPeriodicParams(tcsCtrlInfo.getSid(), enableHkSets, 120.0));
|
|
|
|
return returnvalue::OK;
|
|
}
|
|
|
|
LocalPoolDataSetBase* ThermalController::getDataSetHandle(sid_t sid) {
|
|
switch (sid.ownerSetId) {
|
|
case tcsCtrl::SENSOR_TEMPERATURES:
|
|
return &sensorTemperatures;
|
|
case tcsCtrl::SUS_TEMPERATURES:
|
|
return &susTemperatures;
|
|
case tcsCtrl::DEVICE_TEMPERATURES:
|
|
return &deviceTemperatures;
|
|
case tcsCtrl::HEATER_SET:
|
|
return &heaterInfo;
|
|
case tcsCtrl::TCS_CTRL_INFO:
|
|
return &tcsCtrlInfo;
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
ReturnValue_t ThermalController::checkModeCommand(Mode_t mode, Submode_t submode,
|
|
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) {
|
|
return INVALID_SUBMODE;
|
|
}
|
|
return returnvalue::OK;
|
|
}
|
|
|
|
void ThermalController::copySensors() {
|
|
{
|
|
PoolReadGuard pg0(&maxSet0PlocHspd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg0.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.plocHeatspreader.value = maxSet0PlocHspd.temperatureCelcius.value;
|
|
sensorTemperatures.plocHeatspreader.setValid(maxSet0PlocHspd.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.plocHeatspreader.isValid()) {
|
|
sensorTemperatures.plocHeatspreader.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg1(&maxSet1PlocMissionBrd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg1.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.plocMissionboard.value = maxSet1PlocMissionBrd.temperatureCelcius.value;
|
|
sensorTemperatures.plocMissionboard.setValid(
|
|
maxSet1PlocMissionBrd.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.plocMissionboard.isValid()) {
|
|
sensorTemperatures.plocMissionboard.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg2(&maxSet2PlCam, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg2.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.payload4kCamera.value = maxSet2PlCam.temperatureCelcius.value;
|
|
sensorTemperatures.payload4kCamera.setValid(maxSet2PlCam.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.payload4kCamera.isValid()) {
|
|
sensorTemperatures.payload4kCamera.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg3(&maxSet3DacHspd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg3.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.dacHeatspreader.value = maxSet3DacHspd.temperatureCelcius.value;
|
|
sensorTemperatures.dacHeatspreader.setValid(maxSet3DacHspd.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.dacHeatspreader.isValid()) {
|
|
sensorTemperatures.dacHeatspreader.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg4(&maxSet4Str, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg4.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.startracker.value = maxSet4Str.temperatureCelcius.value;
|
|
sensorTemperatures.startracker.setValid(maxSet4Str.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.startracker.isValid()) {
|
|
sensorTemperatures.startracker.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg5(&maxSet5Rw1MxMy, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg5.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.rw1.value = maxSet5Rw1MxMy.temperatureCelcius.value;
|
|
sensorTemperatures.rw1.setValid(maxSet5Rw1MxMy.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.rw1.isValid()) {
|
|
sensorTemperatures.rw1.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg6(&maxSet6Dro, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg6.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.dro.value = maxSet6Dro.temperatureCelcius.value;
|
|
sensorTemperatures.dro.setValid(maxSet6Dro.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.dro.isValid()) {
|
|
sensorTemperatures.dro.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg7(&maxSet7Scex, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg7.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.scex.value = maxSet7Scex.temperatureCelcius.value;
|
|
sensorTemperatures.scex.setValid(maxSet7Scex.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.scex.isValid()) {
|
|
sensorTemperatures.scex.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg8(&maxSet8X8, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg8.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.x8.value = maxSet8X8.temperatureCelcius.value;
|
|
sensorTemperatures.x8.setValid(maxSet8X8.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.x8.isValid()) {
|
|
sensorTemperatures.x8.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg9(&maxSet9Hpa, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg9.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.hpa.value = maxSet9Hpa.temperatureCelcius.value;
|
|
sensorTemperatures.hpa.setValid(maxSet9Hpa.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.hpa.isValid()) {
|
|
sensorTemperatures.hpa.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg10(&maxSet10EbandTx, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg10.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.eBandTx.value = maxSet10EbandTx.temperatureCelcius.value;
|
|
sensorTemperatures.eBandTx.setValid(maxSet10EbandTx.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.eBandTx.isValid()) {
|
|
sensorTemperatures.eBandTx.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg11(&maxSet11Mpa, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg11.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.mpa.value = maxSet11Mpa.temperatureCelcius.value;
|
|
sensorTemperatures.mpa.setValid(maxSet11Mpa.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.mpa.isValid()) {
|
|
sensorTemperatures.mpa.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg12(&maxSet31865Set12, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg12.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.acu.value = maxSet31865Set12.temperatureCelcius.value;
|
|
sensorTemperatures.acu.setValid(maxSet31865Set12.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.acu.isValid()) {
|
|
sensorTemperatures.acu.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg13(&maxSet13PlPcduHspd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg13.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.plpcduHeatspreader.value = maxSet13PlPcduHspd.temperatureCelcius.value;
|
|
sensorTemperatures.plpcduHeatspreader.setValid(
|
|
maxSet13PlPcduHspd.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.plpcduHeatspreader.isValid()) {
|
|
sensorTemperatures.plpcduHeatspreader.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg14(&maxSet14TcsBrd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg14.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.tcsBoard.value = maxSet14TcsBrd.temperatureCelcius.value;
|
|
sensorTemperatures.tcsBoard.setValid(maxSet14TcsBrd.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.tcsBoard.isValid()) {
|
|
sensorTemperatures.tcsBoard.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg15(&maxSet15Imtq, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg15.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.mgt.value = maxSet15Imtq.temperatureCelcius.value;
|
|
sensorTemperatures.mgt.setValid(maxSet15Imtq.temperatureCelcius.isValid());
|
|
if (not sensorTemperatures.mgt.isValid()) {
|
|
sensorTemperatures.mgt.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tmp1075SetTcs0, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.tmp1075Tcs0.value = tmp1075SetTcs0.temperatureCelcius.value;
|
|
sensorTemperatures.tmp1075Tcs0.setValid(tmp1075SetTcs0.temperatureCelcius.isValid());
|
|
if (not tmp1075SetTcs0.temperatureCelcius.isValid()) {
|
|
sensorTemperatures.tmp1075Tcs0.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tmp1075SetTcs1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.tmp1075Tcs1.value = tmp1075SetTcs1.temperatureCelcius.value;
|
|
sensorTemperatures.tmp1075Tcs1.setValid(tmp1075SetTcs1.temperatureCelcius.isValid());
|
|
if (not tmp1075SetTcs1.temperatureCelcius.isValid()) {
|
|
sensorTemperatures.tmp1075Tcs1.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
{
|
|
PoolReadGuard pg(&tmp1075SetPlPcdu0, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.tmp1075PlPcdu0.value = tmp1075SetPlPcdu0.temperatureCelcius.value;
|
|
sensorTemperatures.tmp1075PlPcdu0.setValid(tmp1075SetPlPcdu0.temperatureCelcius.isValid());
|
|
if (not tmp1075SetPlPcdu0.temperatureCelcius.isValid()) {
|
|
sensorTemperatures.tmp1075PlPcdu0.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
// damaged on FM, and no dummies for now
|
|
if (pollPcdu1Tmp) {
|
|
{
|
|
PoolReadGuard pg(tmp1075SetPlPcdu1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.tmp1075PlPcdu1.value = tmp1075SetPlPcdu1->temperatureCelcius.value;
|
|
sensorTemperatures.tmp1075PlPcdu1.setValid(tmp1075SetPlPcdu1->temperatureCelcius.isValid());
|
|
if (not tmp1075SetPlPcdu1->temperatureCelcius.isValid()) {
|
|
sensorTemperatures.tmp1075PlPcdu1.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
{
|
|
PoolReadGuard pg(&tmp1075SetIfBoard, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() == returnvalue::OK) {
|
|
sensorTemperatures.tmp1075IfBrd.value = tmp1075SetIfBoard.temperatureCelcius.value;
|
|
sensorTemperatures.tmp1075IfBrd.setValid(tmp1075SetIfBoard.temperatureCelcius.isValid());
|
|
if (not tmp1075SetIfBoard.temperatureCelcius.isValid()) {
|
|
sensorTemperatures.tmp1075IfBrd.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ThermalController::copySus() {
|
|
{
|
|
PoolReadGuard pg0(&susSet0, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg0.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.value = susSet0.tempC.value;
|
|
susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.setValid(susSet0.tempC.isValid());
|
|
if (not susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.isValid()) {
|
|
susTemperatures.sus_0_n_loc_xfyfzm_pt_xf.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg1(&susSet1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg1.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_6_r_loc_xfybzm_pt_xf.value = susSet1.tempC.value;
|
|
susTemperatures.sus_6_r_loc_xfybzm_pt_xf.setValid(susSet1.tempC.isValid());
|
|
if (not susTemperatures.sus_6_r_loc_xfybzm_pt_xf.isValid()) {
|
|
susTemperatures.sus_6_r_loc_xfybzm_pt_xf.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg2(&susSet2, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg2.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.value = susSet2.tempC.value;
|
|
susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.setValid(susSet2.tempC.isValid());
|
|
if (not susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.isValid()) {
|
|
susTemperatures.sus_1_n_loc_xbyfzm_pt_xb.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg3(&susSet3, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg3.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_7_r_loc_xbybzm_pt_xb.value = susSet3.tempC.value;
|
|
susTemperatures.sus_7_r_loc_xbybzm_pt_xb.setValid(susSet3.tempC.isValid());
|
|
if (not susTemperatures.sus_7_r_loc_xbybzm_pt_xb.isValid()) {
|
|
susTemperatures.sus_7_r_loc_xbybzm_pt_xb.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg4(&susSet4, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg4.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_2_n_loc_xfybzb_pt_yb.value = susSet4.tempC.value;
|
|
susTemperatures.sus_2_n_loc_xfybzb_pt_yb.setValid(susSet4.tempC.isValid());
|
|
if (not susTemperatures.sus_2_n_loc_xfybzb_pt_yb.isValid()) {
|
|
susTemperatures.sus_2_n_loc_xfybzb_pt_yb.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg5(&susSet5, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg5.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_8_r_loc_xbybzb_pt_yb.value = susSet5.tempC.value;
|
|
susTemperatures.sus_8_r_loc_xbybzb_pt_yb.setValid(susSet5.tempC.isValid());
|
|
if (not susTemperatures.sus_8_r_loc_xbybzb_pt_yb.isValid()) {
|
|
susTemperatures.sus_8_r_loc_xbybzb_pt_yb.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg6(&susSet6, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg6.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_3_n_loc_xfybzf_pt_yf.value = susSet6.tempC.value;
|
|
susTemperatures.sus_3_n_loc_xfybzf_pt_yf.setValid(susSet6.tempC.isValid());
|
|
if (not susTemperatures.sus_3_n_loc_xfybzf_pt_yf.isValid()) {
|
|
susTemperatures.sus_3_n_loc_xfybzf_pt_yf.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg7(&susSet7, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg7.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_9_r_loc_xbybzb_pt_yf.value = susSet7.tempC.value;
|
|
susTemperatures.sus_9_r_loc_xbybzb_pt_yf.setValid(susSet7.tempC.isValid());
|
|
if (not susTemperatures.sus_9_r_loc_xbybzb_pt_yf.isValid()) {
|
|
susTemperatures.sus_9_r_loc_xbybzb_pt_yf.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg8(&susSet8, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg8.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.value = susSet8.tempC.value;
|
|
susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.setValid(susSet8.tempC.isValid());
|
|
if (not susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.isValid()) {
|
|
susTemperatures.sus_4_n_loc_xmyfzf_pt_zf.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg9(&susSet9, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg9.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_10_n_loc_xmybzf_pt_zf.value = susSet9.tempC.value;
|
|
susTemperatures.sus_10_n_loc_xmybzf_pt_zf.setValid(susSet9.tempC.isValid());
|
|
if (not susTemperatures.sus_10_n_loc_xmybzf_pt_zf.isValid()) {
|
|
susTemperatures.sus_10_n_loc_xmybzf_pt_zf.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg10(&susSet10, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg10.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_5_n_loc_xfymzb_pt_zb.value = susSet10.tempC.value;
|
|
susTemperatures.sus_5_n_loc_xfymzb_pt_zb.setValid(susSet10.tempC.isValid());
|
|
if (not susTemperatures.sus_5_n_loc_xfymzb_pt_zb.isValid()) {
|
|
susTemperatures.sus_5_n_loc_xfymzb_pt_zb.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg11(&susSet11, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg11.getReadResult() == returnvalue::OK) {
|
|
susTemperatures.sus_11_r_loc_xbymzb_pt_zb.value = susSet11.tempC.value;
|
|
susTemperatures.sus_11_r_loc_xbymzb_pt_zb.setValid(susSet11.tempC.isValid());
|
|
if (not susTemperatures.sus_11_r_loc_xbymzb_pt_zb.isValid()) {
|
|
susTemperatures.sus_11_r_loc_xbymzb_pt_zb.value = INVALID_TEMPERATURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ThermalController::copyDevices() {
|
|
{
|
|
PoolReadGuard pg(&tempQ7s, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() == returnvalue::OK) {
|
|
deviceTemperatures.q7s = tempQ7s;
|
|
deviceTemperatures.q7s.setValid(tempQ7s.isValid());
|
|
} else {
|
|
deviceTemperatures.q7s.setValid(false);
|
|
deviceTemperatures.q7s = static_cast<float>(INVALID_TEMPERATURE);
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&battTemp1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read battery temperature 1" << std::endl;
|
|
deviceTemperatures.batteryTemp1.setValid(false);
|
|
deviceTemperatures.batteryTemp1 = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.batteryTemp1 = battTemp1;
|
|
deviceTemperatures.batteryTemp1.setValid(battTemp1.isValid());
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&battTemp2, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read battery temperature 2" << std::endl;
|
|
deviceTemperatures.batteryTemp2.setValid(false);
|
|
deviceTemperatures.batteryTemp2 = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.batteryTemp2 = battTemp2;
|
|
deviceTemperatures.batteryTemp2.setValid(battTemp2.isValid());
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&battTemp3, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read battery temperature 3" << std::endl;
|
|
deviceTemperatures.batteryTemp3.setValid(false);
|
|
deviceTemperatures.batteryTemp3 = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.batteryTemp3 = battTemp3;
|
|
deviceTemperatures.batteryTemp3.setValid(battTemp3.isValid());
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&battTemp4, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read battery temperature 4" << std::endl;
|
|
deviceTemperatures.batteryTemp4.setValid(false);
|
|
deviceTemperatures.batteryTemp4 = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.batteryTemp4 = battTemp4;
|
|
deviceTemperatures.batteryTemp4.setValid(battTemp4.isValid());
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempRw1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read reaction wheel 1 temperature" << std::endl;
|
|
deviceTemperatures.rw1.setValid(false);
|
|
deviceTemperatures.rw1 = static_cast<int32_t>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.rw1.setValid(tempRw1.isValid());
|
|
deviceTemperatures.rw1 = tempRw1;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempRw2, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read reaction wheel 2 temperature" << std::endl;
|
|
deviceTemperatures.rw2.setValid(false);
|
|
deviceTemperatures.rw2 = static_cast<int32_t>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.rw2.setValid(tempRw2.isValid());
|
|
deviceTemperatures.rw2 = tempRw2;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempRw3, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read reaction wheel 3 temperature" << std::endl;
|
|
deviceTemperatures.rw3.setValid(false);
|
|
deviceTemperatures.rw3 = static_cast<int32_t>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.rw3.setValid(tempRw3.isValid());
|
|
deviceTemperatures.rw3 = tempRw3;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempRw4, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read reaction wheel 4 temperature" << std::endl;
|
|
deviceTemperatures.rw4.setValid(false);
|
|
deviceTemperatures.rw4 = static_cast<int32_t>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.rw4.setValid(tempRw4.isValid());
|
|
deviceTemperatures.rw4 = tempRw4;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempStartracker, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read startracker temperature" << std::endl;
|
|
deviceTemperatures.startracker.setValid(false);
|
|
deviceTemperatures.startracker = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.startracker.setValid(tempStartracker.isValid());
|
|
deviceTemperatures.startracker = tempStartracker;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempSyrlinksPowerAmplifier, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read syrlinks power amplifier temperature"
|
|
<< std::endl;
|
|
deviceTemperatures.syrlinksPowerAmplifier.setValid(false);
|
|
deviceTemperatures.syrlinksPowerAmplifier = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.syrlinksPowerAmplifier.setValid(tempSyrlinksPowerAmplifier.isValid());
|
|
deviceTemperatures.syrlinksPowerAmplifier = tempSyrlinksPowerAmplifier;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempSyrlinksBasebandBoard, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read syrlinks baseband board temperature"
|
|
<< std::endl;
|
|
deviceTemperatures.syrlinksBasebandBoard.setValid(false);
|
|
deviceTemperatures.syrlinksBasebandBoard = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.syrlinksBasebandBoard.setValid(tempSyrlinksBasebandBoard.isValid());
|
|
deviceTemperatures.syrlinksBasebandBoard = tempSyrlinksBasebandBoard;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempMgt, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read MGT temperature" << std::endl;
|
|
deviceTemperatures.mgt.setValid(false);
|
|
deviceTemperatures.mgt = static_cast<int16_t>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.mgt.setValid(tempMgt.isValid());
|
|
deviceTemperatures.mgt = tempMgt;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempAcu, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read ACU temperatures" << std::endl;
|
|
deviceTemperatures.acu.setValid(false);
|
|
deviceTemperatures.acu[0] = static_cast<float>(INVALID_TEMPERATURE);
|
|
deviceTemperatures.acu[1] = static_cast<float>(INVALID_TEMPERATURE);
|
|
deviceTemperatures.acu[2] = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.acu.setValid(tempAcu.isValid());
|
|
deviceTemperatures.acu = tempAcu;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempPdu1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read PDU1 temperature" << std::endl;
|
|
deviceTemperatures.pdu1.setValid(false);
|
|
deviceTemperatures.pdu1 = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.pdu1.setValid(tempPdu1.isValid());
|
|
deviceTemperatures.pdu1 = tempPdu1;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempPdu2, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read PDU2 temperature" << std::endl;
|
|
deviceTemperatures.pdu2.setValid(false);
|
|
deviceTemperatures.pdu2 = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.pdu2.setValid(tempPdu2.isValid());
|
|
deviceTemperatures.pdu2 = tempPdu2;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&temp1P60dock, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read P60 dock temperature 1" << std::endl;
|
|
deviceTemperatures.temp1P60dock.setValid(false);
|
|
deviceTemperatures.temp1P60dock = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.temp1P60dock.setValid(temp1P60dock.isValid());
|
|
deviceTemperatures.temp1P60dock = temp1P60dock;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&temp2P60dock, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read P60 dock temperature 2" << std::endl;
|
|
deviceTemperatures.temp2P60dock.setValid(false);
|
|
deviceTemperatures.temp2P60dock = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.temp2P60dock.setValid(temp2P60dock.isValid());
|
|
deviceTemperatures.temp2P60dock = temp2P60dock;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempGyro0, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read gyro 0 temperature" << std::endl;
|
|
deviceTemperatures.gyro0SideA.setValid(false);
|
|
deviceTemperatures.gyro0SideA = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.gyro0SideA.setValid(tempGyro0.isValid());
|
|
deviceTemperatures.gyro0SideA = tempGyro0;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempGyro1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read gyro 1 temperature" << std::endl;
|
|
deviceTemperatures.gyro1SideA.setValid(false);
|
|
deviceTemperatures.gyro1SideA = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.gyro1SideA.setValid(tempGyro1.isValid());
|
|
deviceTemperatures.gyro1SideA = tempGyro1;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempGyro2, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read gyro 2 temperature" << std::endl;
|
|
deviceTemperatures.gyro2SideB.setValid(false);
|
|
deviceTemperatures.gyro2SideB = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.gyro2SideB.setValid(tempGyro2.isValid());
|
|
deviceTemperatures.gyro2SideB = tempGyro2;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempGyro3, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read gyro 3 temperature" << std::endl;
|
|
deviceTemperatures.gyro3SideB.setValid(false);
|
|
deviceTemperatures.gyro3SideB = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.gyro3SideB.setValid(tempGyro3.isValid());
|
|
deviceTemperatures.gyro3SideB = tempGyro3;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempMgm0, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read MGM 0 temperature" << std::endl;
|
|
deviceTemperatures.mgm0SideA.setValid(false);
|
|
deviceTemperatures.mgm0SideA = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.mgm0SideA.setValid(tempMgm0.isValid());
|
|
deviceTemperatures.mgm0SideA = tempMgm0;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempMgm2, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read MGM 2 temperature" << std::endl;
|
|
deviceTemperatures.mgm2SideB.setValid(false);
|
|
deviceTemperatures.mgm2SideB = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.mgm2SideB.setValid(tempMgm2.isValid());
|
|
deviceTemperatures.mgm2SideB = tempMgm2;
|
|
}
|
|
}
|
|
|
|
{
|
|
PoolReadGuard pg(&tempAdcPayloadPcdu, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
|
|
if (pg.getReadResult() != returnvalue::OK) {
|
|
sif::warning << "ThermalController: Failed to read payload PCDU ADC temperature" << std::endl;
|
|
deviceTemperatures.adcPayloadPcdu.setValid(false);
|
|
deviceTemperatures.adcPayloadPcdu = static_cast<float>(INVALID_TEMPERATURE);
|
|
} else {
|
|
deviceTemperatures.adcPayloadPcdu.setValid(tempAdcPayloadPcdu.isValid());
|
|
deviceTemperatures.adcPayloadPcdu = tempAdcPayloadPcdu;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ThermalController::ctrlAcsBoard() {
|
|
heater::Switch switchNr = heater::HEATER_2_ACS_BRD;
|
|
heater::Switch redSwitchNr = heater::HEATER_3_OBC_BRD;
|
|
|
|
// A side
|
|
ctrlCtx.thermalComponent = tcsCtrl::ACS_BOARD;
|
|
sensors[0].first = deviceTemperatures.gyro0SideA.isValid();
|
|
sensors[0].second = deviceTemperatures.gyro0SideA.value;
|
|
sensors[1].first = deviceTemperatures.gyro2SideB.isValid();
|
|
sensors[1].second = deviceTemperatures.gyro2SideB.value;
|
|
sensors[2].first = deviceTemperatures.mgm0SideA.isValid();
|
|
sensors[2].second = deviceTemperatures.mgm0SideA.value;
|
|
sensors[3].first = deviceTemperatures.mgm2SideB.isValid();
|
|
sensors[3].second = deviceTemperatures.mgm2SideB.value;
|
|
sensors[4].first = sensorTemperatures.tcsBoard.isValid();
|
|
sensors[4].second = sensorTemperatures.tcsBoard.value;
|
|
numSensors = 5;
|
|
{
|
|
HeaterContext htrCtx(switchNr, redSwitchNr, acsBoardLimits);
|
|
if (selectAndReadSensorTemp(htrCtx)) {
|
|
if (chooseHeater(switchNr, redSwitchNr)) {
|
|
checkLimitsAndCtrlHeater(htrCtx);
|
|
}
|
|
resetSensorsArray();
|
|
return;
|
|
}
|
|
}
|
|
resetSensorsArray();
|
|
// B side
|
|
sensors[0].first = deviceTemperatures.gyro2SideB.isValid();
|
|
sensors[0].second = deviceTemperatures.gyro2SideB.value;
|
|
sensors[1].first = deviceTemperatures.mgm2SideB.isValid();
|
|
sensors[1].second = deviceTemperatures.mgm2SideB.value;
|
|
sensors[2].first = deviceTemperatures.gyro3SideB.isValid();
|
|
sensors[2].second = deviceTemperatures.gyro3SideB.value;
|
|
sensors[3].first = sensorTemperatures.tcsBoard.isValid();
|
|
sensors[3].second = sensorTemperatures.tcsBoard.value;
|
|
numSensors = 4;
|
|
|
|
{
|
|
HeaterContext htrCtx(switchNr, redSwitchNr, acsBoardLimits);
|
|
if (selectAndReadSensorTemp(htrCtx)) {
|
|
if (chooseHeater(switchNr, redSwitchNr)) {
|
|
checkLimitsAndCtrlHeater(htrCtx);
|
|
}
|
|
} else {
|
|
if (chooseHeater(switchNr, redSwitchNr)) {
|
|
if (heaterHandler.getSwitchState(switchNr)) {
|
|
if (submode != SUBMODE_NO_HEATER_CTRL) {
|
|
heaterSwitchHelper(switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
resetSensorsArray();
|
|
}
|
|
|
|
void ThermalController::ctrlMgt() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::MGT;
|
|
sensors[0].first = sensorTemperatures.mgt.isValid();
|
|
sensors[0].second = sensorTemperatures.mgt.value;
|
|
sensors[1].first = deviceTemperatures.mgt.isValid();
|
|
sensors[1].second = deviceTemperatures.mgt.value;
|
|
sensors[2].first = sensorTemperatures.plpcduHeatspreader.isValid();
|
|
sensors[2].second = sensorTemperatures.plpcduHeatspreader.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_1_PCDU_PDU, mgtLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.mgtTooHotFlag) {
|
|
triggerEvent(tcsCtrl::MGT_OVERHEATING, tempFloatToU32());
|
|
tooHotFlags.mgtTooHotFlag = true;
|
|
} else if (not ctrlCtx.componentAboveUpperLimit) {
|
|
tooHotFlags.mgtTooHotFlag = false;
|
|
}
|
|
}
|
|
|
|
void ThermalController::ctrlRw() {
|
|
Event eventToTrigger = 0;
|
|
bool oneIsAboveLimit = false;
|
|
|
|
std::array<uint32_t, 4> sensorTemps{};
|
|
|
|
// RW1
|
|
ctrlCtx.thermalComponent = tcsCtrl::RW;
|
|
sensors[0].first = sensorTemperatures.rw1.isValid();
|
|
sensors[0].second = sensorTemperatures.rw1.value;
|
|
sensors[1].first = deviceTemperatures.rw1.isValid();
|
|
sensors[1].second = deviceTemperatures.rw1.value;
|
|
sensors[2].first = deviceTemperatures.rw4.isValid();
|
|
sensors[2].second = deviceTemperatures.rw4.value;
|
|
sensors[3].first = sensorTemperatures.dro.isValid();
|
|
sensors[3].second = sensorTemperatures.dro.value;
|
|
numSensors = 4;
|
|
{
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
sensorTemps[0] = tempFloatToU32();
|
|
if (ctrlCtx.componentAboveUpperLimit) {
|
|
oneIsAboveLimit = true;
|
|
eventToTrigger = ctrlCtx.overHeatEventToTrigger;
|
|
}
|
|
}
|
|
|
|
// RW2
|
|
ctrlCtx.thermalComponent = tcsCtrl::RW;
|
|
sensors[0].first = deviceTemperatures.rw2.isValid();
|
|
sensors[0].second = deviceTemperatures.rw2.value;
|
|
sensors[1].first = deviceTemperatures.rw3.isValid();
|
|
sensors[1].second = deviceTemperatures.rw3.value;
|
|
sensors[2].first = sensorTemperatures.rw1.isValid();
|
|
sensors[2].second = sensorTemperatures.rw1.value;
|
|
sensors[3].first = sensorTemperatures.dro.isValid();
|
|
sensors[3].second = sensorTemperatures.dro.value;
|
|
numSensors = 4;
|
|
{
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
sensorTemps[1] = tempFloatToU32();
|
|
if (ctrlCtx.componentAboveUpperLimit) {
|
|
oneIsAboveLimit = true;
|
|
if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) {
|
|
eventToTrigger = ctrlCtx.overHeatEventToTrigger;
|
|
}
|
|
}
|
|
}
|
|
// RW3
|
|
ctrlCtx.thermalComponent = tcsCtrl::RW;
|
|
sensors[0].first = deviceTemperatures.rw3.isValid();
|
|
sensors[0].second = deviceTemperatures.rw3.value;
|
|
sensors[1].first = deviceTemperatures.rw4.isValid();
|
|
sensors[1].second = deviceTemperatures.rw4.value;
|
|
sensors[2].first = sensorTemperatures.rw1.isValid();
|
|
sensors[2].second = sensorTemperatures.rw1.value;
|
|
sensors[3].first = sensorTemperatures.dro.isValid();
|
|
sensors[3].second = sensorTemperatures.dro.value;
|
|
numSensors = 4;
|
|
{
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
sensorTemps[2] = tempFloatToU32();
|
|
if (ctrlCtx.componentAboveUpperLimit) {
|
|
oneIsAboveLimit = true;
|
|
if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) {
|
|
eventToTrigger = ctrlCtx.overHeatEventToTrigger;
|
|
}
|
|
}
|
|
}
|
|
|
|
// RW4
|
|
ctrlCtx.thermalComponent = tcsCtrl::RW;
|
|
sensors[0].first = deviceTemperatures.rw4.isValid();
|
|
sensors[0].second = deviceTemperatures.rw4.value;
|
|
sensors[1].first = deviceTemperatures.rw1.isValid();
|
|
sensors[1].second = deviceTemperatures.rw1.value;
|
|
sensors[2].first = sensorTemperatures.rw1.isValid();
|
|
sensors[2].second = sensorTemperatures.rw1.value;
|
|
sensors[3].first = sensorTemperatures.dro.isValid();
|
|
sensors[3].second = sensorTemperatures.dro.value;
|
|
numSensors = 4;
|
|
{
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
sensorTemps[3] = tempFloatToU32();
|
|
if (ctrlCtx.componentAboveUpperLimit) {
|
|
oneIsAboveLimit = true;
|
|
if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) {
|
|
eventToTrigger = ctrlCtx.overHeatEventToTrigger;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (oneIsAboveLimit and not tooHotFlags.rwTooHotFlag) {
|
|
EventManagerIF::triggerEvent(objects::RW1, eventToTrigger, sensorTemps[0]);
|
|
EventManagerIF::triggerEvent(objects::RW2, eventToTrigger, sensorTemps[1]);
|
|
EventManagerIF::triggerEvent(objects::RW3, eventToTrigger, sensorTemps[2]);
|
|
EventManagerIF::triggerEvent(objects::RW4, eventToTrigger, sensorTemps[3]);
|
|
tooHotFlags.rwTooHotFlag = true;
|
|
} else if (not oneIsAboveLimit) {
|
|
tooHotFlags.rwTooHotFlag = false;
|
|
}
|
|
}
|
|
|
|
void ThermalController::ctrlStr() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::STR;
|
|
sensors[0].first = sensorTemperatures.startracker.isValid();
|
|
sensors[0].second = sensorTemperatures.startracker.value;
|
|
sensors[1].first = deviceTemperatures.startracker.isValid();
|
|
sensors[1].second = deviceTemperatures.startracker.value;
|
|
sensors[2].first = sensorTemperatures.dro.isValid();
|
|
sensors[2].second = sensorTemperatures.dro.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_5_STR, heater::HEATER_6_DRO, strLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandlerWhichClearsOneShotFlag(objects::STAR_TRACKER, tooHotFlags.strTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::ctrlIfBoard() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::IF_BOARD;
|
|
sensors[0].first = sensorTemperatures.tmp1075IfBrd.isValid();
|
|
sensors[0].second = sensorTemperatures.tmp1075IfBrd.value;
|
|
sensors[1].first = sensorTemperatures.mgt.isValid();
|
|
sensors[1].second = sensorTemperatures.mgt.value;
|
|
sensors[2].first = deviceTemperatures.mgm2SideB.isValid();
|
|
sensors[2].second = deviceTemperatures.mgm2SideB.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_1_PCDU_PDU, ifBoardLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
// TODO: special event overheating + could go back to safe mode
|
|
}
|
|
|
|
void ThermalController::ctrlTcsBoard() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::TCS_BOARD;
|
|
sensors[0].first = sensorTemperatures.tcsBoard.isValid();
|
|
sensors[0].second = sensorTemperatures.tcsBoard.value;
|
|
sensors[1].first = sensorTemperatures.tmp1075Tcs0.isValid();
|
|
sensors[1].second = sensorTemperatures.tmp1075Tcs0.value;
|
|
sensors[2].first = sensorTemperatures.tmp1075Tcs1.isValid();
|
|
sensors[2].second = sensorTemperatures.tmp1075Tcs1.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_3_OBC_BRD, heater::HEATER_2_ACS_BRD, tcsBoardLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
// TODO: special event overheating + could go back to safe mode
|
|
}
|
|
|
|
void ThermalController::ctrlObc() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::OBC;
|
|
sensors[0].first = deviceTemperatures.q7s.isValid();
|
|
sensors[0].second = deviceTemperatures.q7s.value;
|
|
sensors[1].first = sensorTemperatures.tmp1075Tcs1.isValid();
|
|
sensors[1].second = sensorTemperatures.tmp1075Tcs1.value;
|
|
sensors[2].first = sensorTemperatures.tmp1075Tcs0.isValid();
|
|
sensors[2].second = sensorTemperatures.tmp1075Tcs0.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_3_OBC_BRD, heater::HEATER_2_ACS_BRD, obcLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.obcTooHotFlag) {
|
|
triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32());
|
|
tooHotFlags.obcTooHotFlag = true;
|
|
} else if (not ctrlCtx.componentAboveUpperLimit) {
|
|
tooHotFlags.obcTooHotFlag = false;
|
|
}
|
|
}
|
|
|
|
void ThermalController::ctrlSBandTransceiver() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::SBAND_TRANSCEIVER;
|
|
sensors[0].first = deviceTemperatures.syrlinksPowerAmplifier.isValid();
|
|
sensors[0].second = deviceTemperatures.syrlinksPowerAmplifier.value;
|
|
sensors[1].first = deviceTemperatures.syrlinksBasebandBoard.isValid();
|
|
sensors[1].second = deviceTemperatures.syrlinksBasebandBoard.value;
|
|
sensors[2].first = sensorTemperatures.payload4kCamera.isValid();
|
|
sensors[2].second = sensorTemperatures.payload4kCamera.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_7_S_BAND, heater::HEATER_4_CAMERA, sBandTransceiverLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.syrlinksTooHotFlag) {
|
|
triggerEvent(tcsCtrl::SYRLINKS_OVERHEATING, tempFloatToU32());
|
|
tooHotFlags.syrlinksTooHotFlag = true;
|
|
} else if (not ctrlCtx.componentAboveUpperLimit) {
|
|
tooHotFlags.syrlinksTooHotFlag = false;
|
|
}
|
|
}
|
|
void ThermalController::ctrlPcduP60Board() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::PCDUP60_BOARD;
|
|
sensors[0].first = deviceTemperatures.temp1P60dock.isValid();
|
|
sensors[0].second = deviceTemperatures.temp1P60dock.value;
|
|
sensors[1].first = deviceTemperatures.temp2P60dock.isValid();
|
|
sensors[1].second = deviceTemperatures.temp2P60dock.value;
|
|
numSensors = 2;
|
|
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduP60BoardLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.pcduSystemTooHotFlag) {
|
|
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
|
|
tooHotFlags.pcduSystemTooHotFlag = true;
|
|
} else if (not ctrlCtx.componentAboveUpperLimit) {
|
|
tooHotFlags.pcduSystemTooHotFlag = false;
|
|
} // TODO: !
|
|
}
|
|
|
|
void ThermalController::ctrlPcduAcu() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::PCDUACU;
|
|
heater::Switch switchNr = heater::HEATER_1_PCDU_PDU;
|
|
heater::Switch redSwitchNr = heater::HEATER_2_ACS_BRD;
|
|
|
|
if (chooseHeater(switchNr, redSwitchNr)) {
|
|
bool sensorTempAvailable = true;
|
|
// TODO: check
|
|
if (deviceTemperatures.acu.value[0] != INVALID_TEMPERATURE) {
|
|
ctrlCtx.sensorTemp = deviceTemperatures.acu.value[0];
|
|
} else if (deviceTemperatures.acu.value[1] != INVALID_TEMPERATURE) {
|
|
ctrlCtx.sensorTemp = deviceTemperatures.acu.value[1];
|
|
} else if (deviceTemperatures.acu.value[2] != INVALID_TEMPERATURE) {
|
|
ctrlCtx.sensorTemp = deviceTemperatures.acu.value[2];
|
|
} else if (sensorTemperatures.acu.isValid()) {
|
|
ctrlCtx.sensorTemp = sensorTemperatures.acu.value;
|
|
} else {
|
|
triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, ctrlCtx.thermalComponent);
|
|
sensorTempAvailable = false;
|
|
}
|
|
if (sensorTempAvailable) {
|
|
HeaterContext htrCtx(switchNr, redSwitchNr, pcduAcuLimits);
|
|
checkLimitsAndCtrlHeater(htrCtx);
|
|
}
|
|
}
|
|
if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.pcduSystemTooHotFlag) {
|
|
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
|
|
tooHotFlags.pcduSystemTooHotFlag = true;
|
|
} else if (not ctrlCtx.componentAboveUpperLimit) {
|
|
tooHotFlags.pcduSystemTooHotFlag = false;
|
|
}
|
|
}
|
|
|
|
void ThermalController::ctrlPcduPdu() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::PCDUPDU;
|
|
sensors[0].first = deviceTemperatures.pdu1.isValid();
|
|
sensors[0].second = deviceTemperatures.pdu1.value;
|
|
sensors[1].first = deviceTemperatures.pdu2.isValid();
|
|
sensors[1].second = deviceTemperatures.pdu2.value;
|
|
sensors[2].first = sensorTemperatures.tmp1075Tcs0.isValid();
|
|
sensors[2].second = sensorTemperatures.tmp1075Tcs0.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduPduLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.pcduSystemTooHotFlag) {
|
|
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
|
|
tooHotFlags.pcduSystemTooHotFlag = true;
|
|
} else if (not ctrlCtx.componentAboveUpperLimit) {
|
|
tooHotFlags.pcduSystemTooHotFlag = false;
|
|
}
|
|
}
|
|
|
|
void ThermalController::ctrlPlPcduBoard() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::PLPCDU_BOARD;
|
|
sensors[0].first = sensorTemperatures.tmp1075PlPcdu0.isValid();
|
|
sensors[0].second = sensorTemperatures.tmp1075PlPcdu0.value;
|
|
sensors[1].first = sensorTemperatures.tmp1075PlPcdu1.isValid();
|
|
sensors[1].second = sensorTemperatures.tmp1075PlPcdu1.value;
|
|
sensors[2].first = deviceTemperatures.adcPayloadPcdu.isValid();
|
|
sensors[2].second = deviceTemperatures.adcPayloadPcdu.value;
|
|
sensors[3].first = sensorTemperatures.plpcduHeatspreader.isValid();
|
|
sensors[3].second = sensorTemperatures.plpcduHeatspreader.value;
|
|
numSensors = 4;
|
|
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, plPcduBoardLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
|
|
}
|
|
|
|
// ToDo: remove one of the following 2
|
|
void ThermalController::ctrlPlocMissionBoard() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::PLOCMISSION_BOARD;
|
|
sensors[0].first = sensorTemperatures.plocMissionboard.isValid();
|
|
sensors[0].second = sensorTemperatures.plocMissionboard.value;
|
|
sensors[1].first = sensorTemperatures.plocHeatspreader.isValid();
|
|
sensors[1].second = sensorTemperatures.plocHeatspreader.value;
|
|
sensors[2].first = sensorTemperatures.dacHeatspreader.isValid();
|
|
sensors[2].second = sensorTemperatures.dacHeatspreader.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD,
|
|
plocMissionBoardLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, tooHotFlags.plocTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::ctrlPlocProcessingBoard() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::PLOCPROCESSING_BOARD;
|
|
sensors[0].first = sensorTemperatures.plocMissionboard.isValid();
|
|
sensors[0].second = sensorTemperatures.plocMissionboard.value;
|
|
sensors[1].first = sensorTemperatures.plocHeatspreader.isValid();
|
|
sensors[1].second = sensorTemperatures.plocHeatspreader.value;
|
|
sensors[2].first = sensorTemperatures.dacHeatspreader.isValid();
|
|
sensors[2].second = sensorTemperatures.dacHeatspreader.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD,
|
|
plocProcessingBoardLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, tooHotFlags.plocTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::ctrlDac() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::DAC;
|
|
sensors[0].first = sensorTemperatures.dacHeatspreader.isValid();
|
|
sensors[0].second = sensorTemperatures.dacHeatspreader.value;
|
|
sensors[1].first = sensorTemperatures.plocMissionboard.isValid();
|
|
sensors[1].second = sensorTemperatures.plocMissionboard.value;
|
|
sensors[2].first = sensorTemperatures.plocHeatspreader.isValid();
|
|
sensors[2].second = sensorTemperatures.plocHeatspreader.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD, dacLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::ctrlCameraBody() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::CAMERA;
|
|
sensors[0].first = sensorTemperatures.payload4kCamera.isValid();
|
|
sensors[0].second = sensorTemperatures.payload4kCamera.value;
|
|
sensors[1].first = sensorTemperatures.dro.isValid();
|
|
sensors[1].second = sensorTemperatures.dro.value;
|
|
sensors[2].first = sensorTemperatures.mpa.isValid();
|
|
sensors[2].second = sensorTemperatures.mpa.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_4_CAMERA, heater::HEATER_6_DRO, cameraLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.camTooHotOneShotFlag) {
|
|
triggerEvent(tcsCtrl::CAMERA_OVERHEATING, tempFloatToU32());
|
|
CommandMessage msg;
|
|
HealthMessage::setHealthMessage(&msg, HealthMessage::HEALTH_SET, HealthState::FAULTY);
|
|
ReturnValue_t result = commandQueue->sendMessage(camId, &msg);
|
|
if (result != returnvalue::OK) {
|
|
sif::error << "ThermalController::ctrlCameraBody(): Sending health message failed"
|
|
<< std::endl;
|
|
}
|
|
tooHotFlags.camTooHotOneShotFlag = true;
|
|
} else if (not ctrlCtx.componentAboveUpperLimit) {
|
|
tooHotFlags.camTooHotOneShotFlag = false;
|
|
}
|
|
}
|
|
|
|
void ThermalController::ctrlDro() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::DRO;
|
|
sensors[0].first = sensorTemperatures.dro.isValid();
|
|
sensors[0].second = sensorTemperatures.dro.value;
|
|
sensors[1].first = sensorTemperatures.payload4kCamera.isValid();
|
|
sensors[1].second = sensorTemperatures.payload4kCamera.value;
|
|
sensors[2].first = sensorTemperatures.mpa.isValid();
|
|
sensors[2].second = sensorTemperatures.mpa.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, droLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::ctrlX8() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::X8;
|
|
sensors[0].first = sensorTemperatures.x8.isValid();
|
|
sensors[0].second = sensorTemperatures.x8.value;
|
|
sensors[1].first = sensorTemperatures.hpa.isValid();
|
|
sensors[1].second = sensorTemperatures.hpa.value;
|
|
sensors[2].first = sensorTemperatures.eBandTx.isValid();
|
|
sensors[2].second = sensorTemperatures.eBandTx.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, x8Limits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::ctrlTx() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::TX;
|
|
sensors[0].first = sensorTemperatures.eBandTx.isValid();
|
|
sensors[0].second = sensorTemperatures.eBandTx.value;
|
|
sensors[1].first = sensorTemperatures.x8.isValid();
|
|
sensors[1].second = sensorTemperatures.x8.value;
|
|
sensors[2].first = sensorTemperatures.mpa.isValid();
|
|
sensors[2].second = sensorTemperatures.mpa.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, txLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::ctrlMpa() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::MPA;
|
|
sensors[0].first = sensorTemperatures.mpa.isValid();
|
|
sensors[0].second = sensorTemperatures.mpa.value;
|
|
sensors[1].first = sensorTemperatures.hpa.isValid();
|
|
sensors[1].second = sensorTemperatures.hpa.value;
|
|
sensors[2].first = sensorTemperatures.eBandTx.isValid();
|
|
sensors[2].second = sensorTemperatures.eBandTx.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, mpaLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::ctrlHpa() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::HPA;
|
|
sensors[0].first = sensorTemperatures.hpa.isValid();
|
|
sensors[0].second = sensorTemperatures.hpa.value;
|
|
sensors[1].first = sensorTemperatures.x8.isValid();
|
|
sensors[1].second = sensorTemperatures.x8.value;
|
|
sensors[2].first = sensorTemperatures.mpa.isValid();
|
|
sensors[2].second = sensorTemperatures.mpa.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, hpaLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::ctrlScexBoard() {
|
|
ctrlCtx.thermalComponent = tcsCtrl::SCEX_BOARD;
|
|
sensors[0].first = sensorTemperatures.scex.isValid();
|
|
sensors[0].second = sensorTemperatures.scex.value;
|
|
sensors[1].first = sensorTemperatures.x8.isValid();
|
|
sensors[1].second = sensorTemperatures.x8.value;
|
|
sensors[2].first = sensorTemperatures.hpa.isValid();
|
|
sensors[2].second = sensorTemperatures.hpa.value;
|
|
numSensors = 3;
|
|
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_5_STR, scexBoardLimits);
|
|
ctrlComponentTemperature(htrCtx);
|
|
tooHotHandlerWhichClearsOneShotFlag(objects::SCEX, tooHotFlags.scexTooHotFlag);
|
|
}
|
|
|
|
void ThermalController::performThermalModuleCtrl(
|
|
const tcsCtrl::HeaterSwitchStates& heaterSwitchStates) {
|
|
ctrlAcsBoard();
|
|
ctrlMgt();
|
|
ctrlRw();
|
|
ctrlStr();
|
|
ctrlIfBoard();
|
|
ctrlTcsBoard();
|
|
ctrlObc();
|
|
ctrlSBandTransceiver();
|
|
ctrlPcduP60Board();
|
|
ctrlPcduAcu();
|
|
ctrlPcduPdu();
|
|
|
|
// Payload components
|
|
std::array<bool, 2> plocInAllowedRange{};
|
|
ctrlPlocMissionBoard();
|
|
plocInAllowedRange.at(0) = not ctrlCtx.componentAboveUpperLimit;
|
|
ctrlPlocProcessingBoard();
|
|
plocInAllowedRange.at(1) = not ctrlCtx.componentAboveUpperLimit;
|
|
|
|
if (tooHotFlags.plocTooHotFlag) {
|
|
bool clearFlag = true;
|
|
for (const auto& inRange : plocInAllowedRange) {
|
|
if (not inRange) {
|
|
clearFlag = false;
|
|
}
|
|
}
|
|
if (clearFlag) {
|
|
tooHotFlags.plocTooHotFlag = false;
|
|
}
|
|
}
|
|
ctrlCameraBody();
|
|
ctrlScexBoard();
|
|
|
|
// E-Band
|
|
std::array<bool, 7> eBandInAllowedRange{};
|
|
ctrlPlPcduBoard();
|
|
eBandInAllowedRange.at(0) = not ctrlCtx.componentAboveUpperLimit;
|
|
ctrlDac();
|
|
eBandInAllowedRange.at(1) = not ctrlCtx.componentAboveUpperLimit;
|
|
ctrlDro();
|
|
eBandInAllowedRange.at(2) = not ctrlCtx.componentAboveUpperLimit;
|
|
ctrlX8();
|
|
eBandInAllowedRange.at(3) = not ctrlCtx.componentAboveUpperLimit;
|
|
ctrlHpa();
|
|
eBandInAllowedRange.at(4) = not ctrlCtx.componentAboveUpperLimit;
|
|
ctrlTx();
|
|
eBandInAllowedRange.at(5) = not ctrlCtx.componentAboveUpperLimit;
|
|
ctrlMpa();
|
|
eBandInAllowedRange.at(6) = not ctrlCtx.componentAboveUpperLimit;
|
|
|
|
if (tooHotFlags.eBandTooHotFlag) {
|
|
bool clearFlag = true;
|
|
for (const auto& inRange : eBandInAllowedRange) {
|
|
if (not inRange) {
|
|
clearFlag = false;
|
|
}
|
|
}
|
|
if (clearFlag) {
|
|
tooHotFlags.eBandTooHotFlag = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) {
|
|
if (selectAndReadSensorTemp(htrCtx)) {
|
|
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
|
|
// Core loop for a thermal component, after sensors and heaters were selected.
|
|
checkLimitsAndCtrlHeater(htrCtx);
|
|
}
|
|
} else {
|
|
// No sensors available, so switch the heater off. We can not perform control tasks if we
|
|
// are blind..
|
|
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
|
|
// Also track the counter to prevent heater handler message spam. The heater handle can only
|
|
// process 2 messages per cycle.
|
|
if (heaterCtrlAllowed() and
|
|
(thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter < 3)) {
|
|
heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
|
|
}
|
|
}
|
|
}
|
|
resetSensorsArray();
|
|
}
|
|
bool ThermalController::selectAndReadSensorTemp(HeaterContext& htrCtx) {
|
|
for (unsigned i = 0; i < numSensors; i++) {
|
|
if (sensors[i].first and sensors[i].second != INVALID_TEMPERATURE and
|
|
sensors[i].second > SANITY_LIMIT_LOWER_TEMP and
|
|
sensors[i].second < SANITY_LIMIT_UPPER_TEMP) {
|
|
ctrlCtx.sensorTemp = sensors[i].second;
|
|
ctrlCtx.currentSensorIndex = i;
|
|
thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter = 0;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter++;
|
|
if (ctrlCtx.thermalComponent != tcsCtrl::RW and ctrlCtx.thermalComponent != tcsCtrl::ACS_BOARD) {
|
|
if (thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter <= 3) {
|
|
triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, ctrlCtx.thermalComponent);
|
|
}
|
|
} else {
|
|
if (thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter <= 8) {
|
|
triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, ctrlCtx.thermalComponent);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch redSwitchNr) {
|
|
bool heaterAvailable = true;
|
|
|
|
HasHealthIF::HealthState mainHealth = heaterHandler.getHealth(switchNr);
|
|
HasHealthIF::HealthState redHealth = heaterHandler.getHealth(redSwitchNr);
|
|
if (mainHealth != HasHealthIF::HEALTHY) {
|
|
if (redHealth == HasHealthIF::HEALTHY) {
|
|
switchNr = redSwitchNr;
|
|
ctrlCtx.redSwitchNrInUse = true;
|
|
} else {
|
|
heaterAvailable = false;
|
|
// Special case: Ground might command/do something with the heaters, so prevent spam.
|
|
if (not(mainHealth == EXTERNAL_CONTROL and redHealth == EXTERNAL_CONTROL)) {
|
|
triggerEvent(tcsCtrl::NO_HEALTHY_HEATER_AVAILABLE, switchNr, redSwitchNr);
|
|
}
|
|
}
|
|
} else {
|
|
ctrlCtx.redSwitchNrInUse = false;
|
|
}
|
|
return heaterAvailable;
|
|
}
|
|
|
|
void ThermalController::heaterCtrlTempTooHighHandler(HeaterContext& htrCtx, const char* whatLimit) {
|
|
if (not heaterCtrlAllowed()) {
|
|
return;
|
|
}
|
|
if (htrCtx.switchState == heater::SwitchState::ON) {
|
|
sif::info << "TCS: Component " << static_cast<int>(ctrlCtx.thermalComponent)
|
|
<< " too warm, above " << whatLimit << ", switching off heater" << std::endl;
|
|
heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
|
|
heaterStates[htrCtx.switchNr].switchTransition = true;
|
|
heaterStates[htrCtx.switchNr].target = heater::SwitchState::OFF;
|
|
}
|
|
if (heaterHandler.getSwitchState(htrCtx.redSwitchNr) == heater::SwitchState::ON) {
|
|
heaterSwitchHelper(htrCtx.redSwitchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
|
|
heaterStates[htrCtx.redSwitchNr].switchTransition = true;
|
|
heaterStates[htrCtx.redSwitchNr].target = heater::SwitchState::OFF;
|
|
}
|
|
}
|
|
|
|
void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
|
|
ctrlCtx.componentAboveCutOffLimit = false;
|
|
ctrlCtx.componentAboveUpperLimit = false;
|
|
// Stay passive during switch transitions, wait for heater switching to complete. Otherwise,
|
|
// still check whether components are out of range, which might be important information for the
|
|
// top level control loop.
|
|
if (heaterStates[htrCtx.switchNr].switchTransition) {
|
|
htrCtx.doHeaterHandling = false;
|
|
heaterCtrlCheckUpperLimits(htrCtx);
|
|
return;
|
|
}
|
|
|
|
htrCtx.switchState =
|
|
static_cast<heater::SwitchState>(heaterInfo.heaterSwitchState[htrCtx.switchNr]);
|
|
// Heater off
|
|
if (htrCtx.switchState == heater::SwitchState::OFF) {
|
|
if (ctrlCtx.sensorTemp < htrCtx.tempLimit.opLowerLimit and heaterCtrlAllowed()) {
|
|
sif::info << "TCS: Heater " << static_cast<int>(ctrlCtx.thermalComponent) << " ON"
|
|
<< std::endl;
|
|
heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::ON, ctrlCtx.thermalComponent);
|
|
} else {
|
|
// Even if heater control is now allowed, we can update the state.
|
|
thermalStates[ctrlCtx.thermalComponent].heating = false;
|
|
}
|
|
heaterCtrlCheckUpperLimits(htrCtx);
|
|
return;
|
|
}
|
|
|
|
// Heater on
|
|
if (htrCtx.switchState == heater::SwitchState::ON) {
|
|
if (thermalStates[ctrlCtx.thermalComponent].heating) {
|
|
// We are already in a heating cycle, so need to check whether heating task is complete.
|
|
if (ctrlCtx.sensorTemp >= htrCtx.tempLimit.opLowerLimit + TEMP_OFFSET and
|
|
heaterCtrlAllowed()) {
|
|
sif::info << "TCS: Heater " << static_cast<int>(ctrlCtx.thermalComponent) << " OFF"
|
|
<< std::endl;
|
|
heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
|
|
heaterStates[htrCtx.switchNr].switchTransition = true;
|
|
heaterStates[htrCtx.switchNr].target = heater::SwitchState::OFF;
|
|
}
|
|
return;
|
|
}
|
|
// This can happen if heater is used as alternative heater (no regular heating cycle), so we
|
|
// should still check the upper limits.
|
|
bool tooHighHandlerAlreadyCalled = heaterCtrlCheckUpperLimits(htrCtx);
|
|
if (ctrlCtx.sensorTemp >= htrCtx.tempLimit.cutOffLimit) {
|
|
ctrlCtx.componentAboveCutOffLimit = true;
|
|
if (not tooHighHandlerAlreadyCalled) {
|
|
heaterCtrlTempTooHighHandler(htrCtx, "CutOff-Limit");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ThermalController::heaterCtrlCheckUpperLimits(HeaterContext& htrCtx) {
|
|
if (ctrlCtx.sensorTemp >= htrCtx.tempLimit.nopUpperLimit) {
|
|
ctrlCtx.componentAboveUpperLimit = true;
|
|
if (htrCtx.doHeaterHandling) {
|
|
heaterCtrlTempTooHighHandler(htrCtx, "NOP-Limit");
|
|
}
|
|
ctrlCtx.overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH;
|
|
return true;
|
|
} else if (ctrlCtx.sensorTemp >= htrCtx.tempLimit.opUpperLimit) {
|
|
ctrlCtx.componentAboveUpperLimit = true;
|
|
if (htrCtx.doHeaterHandling) {
|
|
heaterCtrlTempTooHighHandler(htrCtx, "OP-Limit");
|
|
}
|
|
ctrlCtx.overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_HIGH;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ThermalController::resetSensorsArray() {
|
|
for (auto& validValuePair : sensors) {
|
|
validValuePair.first = false;
|
|
validValuePair.second = INVALID_TEMPERATURE;
|
|
}
|
|
ctrlCtx.thermalComponent = tcsCtrl::NONE;
|
|
}
|
|
|
|
void ThermalController::heaterTransitionControl(
|
|
const tcsCtrl::HeaterSwitchStates& currentHeaterStates) {
|
|
for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) {
|
|
if (heaterStates[i].switchTransition) {
|
|
if (currentHeaterStates[i] == heaterStates[i].target) {
|
|
// Required for max heater period control
|
|
if (currentHeaterStates[i] == heater::SwitchState::ON) {
|
|
heaterStates[i].heaterOnMaxBurnTime.setTimeout(MAX_HEATER_ON_DURATIONS_MS[i]);
|
|
heaterStates[i].heaterOnMaxBurnTime.resetTimer();
|
|
heaterStates[i].trackHeaterMaxBurnTime = true;
|
|
} else {
|
|
heaterStates[i].trackHeaterMaxBurnTime = false;
|
|
// The heater might still be one for some thermal components, so cross-check
|
|
// those components
|
|
crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(static_cast<heater::Switch>(i));
|
|
}
|
|
heaterStates[i].switchTransition = false;
|
|
heaterStates[i].heaterSwitchControlCycles = 0;
|
|
continue;
|
|
}
|
|
if (heaterStates[i].heaterSwitchControlCycles > 5) {
|
|
heaterStates[i].switchTransition = false;
|
|
heaterStates[i].heaterSwitchControlCycles = 0;
|
|
}
|
|
heaterStates[i].heaterSwitchControlCycles++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ThermalController::heaterMaxDurationControl(
|
|
const tcsCtrl::HeaterSwitchStates& currentHeaterStates) {
|
|
for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) {
|
|
// Right now, we only track the maximum duration for heater which were commanded by the TCS
|
|
// controller.
|
|
if (currentHeaterStates[i] == heater::SwitchState::ON and
|
|
heaterStates[i].trackHeaterMaxBurnTime and
|
|
heaterStates[i].heaterOnMaxBurnTime.hasTimedOut()) {
|
|
heaterStates[i].switchTransition = false;
|
|
heaterStates[i].heaterSwitchControlCycles = 0;
|
|
heaterStates[i].trackHeaterMaxBurnTime = false;
|
|
triggerEvent(tcsCtrl::TCS_HEATER_MAX_BURN_TIME_REACHED, static_cast<uint32_t>(i),
|
|
MAX_HEATER_ON_DURATIONS_MS[i]);
|
|
heaterSwitchHelper(static_cast<heater::Switch>(i), heater::SwitchState::OFF, std::nullopt);
|
|
// The heater might still be one for some thermal components, so cross-check
|
|
// those components
|
|
crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(static_cast<heater::Switch>(i));
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t ThermalController::tempFloatToU32() const {
|
|
auto sensorTempAsFloat = static_cast<float>(ctrlCtx.sensorTemp);
|
|
uint32_t tempRaw = 0;
|
|
size_t dummyLen = 0;
|
|
SerializeAdapter::serialize(&sensorTempAsFloat, reinterpret_cast<uint8_t*>(&tempRaw), &dummyLen,
|
|
sizeof(tempRaw), SerializeIF::Endianness::NETWORK);
|
|
return tempRaw;
|
|
}
|
|
|
|
void ThermalController::setMode(Mode_t mode, Submode_t submode) {
|
|
if (mode == MODE_OFF) {
|
|
transitionWhenHeatersOff = false;
|
|
}
|
|
this->mode = mode;
|
|
this->submode = submode;
|
|
modeHelper.modeChanged(mode, submode);
|
|
announceMode(false);
|
|
}
|
|
|
|
bool ThermalController::tooHotHandler(object_id_t object, bool& oneShotFlag) {
|
|
if (ctrlCtx.componentAboveUpperLimit and not oneShotFlag) {
|
|
// Too hot -> returns true
|
|
EventManagerIF::triggerEvent(object, ctrlCtx.overHeatEventToTrigger, tempFloatToU32());
|
|
oneShotFlag = true;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ThermalController::heaterCtrlAllowed() const { return submode != SUBMODE_NO_HEATER_CTRL; }
|
|
|
|
void ThermalController::resetThermalStates() {
|
|
for (auto& thermalState : thermalStates) {
|
|
thermalState.heating = false;
|
|
thermalState.noSensorAvailableCounter = 0;
|
|
thermalState.heaterStartTime = 0;
|
|
thermalState.heaterEndTime = 0;
|
|
thermalState.sensorIndex = 0;
|
|
thermalState.heaterSwitch = heater::Switch::NUMBER_OF_SWITCHES;
|
|
}
|
|
}
|
|
|
|
void ThermalController::heaterSwitchHelper(heater::Switch switchNr, heater::SwitchState targetState,
|
|
std::optional<unsigned> componentIdx) {
|
|
timeval currentTime;
|
|
Clock::getClock(¤tTime);
|
|
if (targetState == heater::SwitchState::ON) {
|
|
heaterHandler.switchHeater(switchNr, targetState);
|
|
heaterStates[switchNr].target = heater::SwitchState::ON;
|
|
heaterStates[switchNr].switchTransition = true;
|
|
if (componentIdx.has_value()) {
|
|
unsigned componentIdxVal = componentIdx.value();
|
|
thermalStates[componentIdxVal].sensorIndex = ctrlCtx.currentSensorIndex;
|
|
thermalStates[componentIdxVal].heaterSwitch = switchNr;
|
|
thermalStates[componentIdxVal].heating = true;
|
|
thermalStates[componentIdxVal].heaterStartTime = currentTime.tv_sec;
|
|
}
|
|
triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_ON, static_cast<uint32_t>(ctrlCtx.thermalComponent),
|
|
static_cast<uint32_t>(switchNr));
|
|
} else {
|
|
heaterHandler.switchHeater(switchNr, targetState);
|
|
if (componentIdx.has_value()) {
|
|
thermalStates[componentIdx.value()].heating = false;
|
|
thermalStates[componentIdx.value()].heaterEndTime = currentTime.tv_sec;
|
|
}
|
|
triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_OFF, static_cast<uint32_t>(ctrlCtx.thermalComponent),
|
|
static_cast<uint32_t>(switchNr));
|
|
}
|
|
}
|
|
|
|
void ThermalController::heaterSwitchHelperAllOff() {
|
|
timeval currentTime;
|
|
Clock::getClock(¤tTime);
|
|
size_t idx = 0;
|
|
for (; idx < heater::Switch::NUMBER_OF_SWITCHES; idx++) {
|
|
heaterHandler.switchHeater(static_cast<heater::Switch>(idx), heater::SwitchState::OFF);
|
|
}
|
|
for (idx = 0; idx < thermalStates.size(); idx++) {
|
|
thermalStates[idx].heating = false;
|
|
thermalStates[idx].heaterEndTime = currentTime.tv_sec;
|
|
}
|
|
}
|
|
|
|
ThermalController::~ThermalController() {
|
|
if (tmp1075SetPlPcdu1 != nullptr) {
|
|
delete tmp1075SetPlPcdu1;
|
|
}
|
|
}
|
|
|
|
void ThermalController::crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(
|
|
heater::Switch switchIdx) {
|
|
for (unsigned j = 0; j < thermalStates.size(); j++) {
|
|
if (thermalStates[j].heating and thermalStates[j].heaterSwitch == switchIdx) {
|
|
timeval currentTime;
|
|
Clock::getClock(¤tTime);
|
|
thermalStates[j].heating = false;
|
|
thermalStates[j].heaterEndTime = currentTime.tv_sec;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ThermalController::tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag) {
|
|
// Clear the one shot flag is the component is in acceptable temperature range.
|
|
if (not tooHotHandler(object, oneShotFlag) and not ctrlCtx.componentAboveUpperLimit) {
|
|
oneShotFlag = false;
|
|
}
|
|
}
|
|
|
|
void ThermalController::startTransition(Mode_t mode_, Submode_t submode_) {
|
|
triggerEvent(CHANGING_MODE, mode_, submode_);
|
|
// For MODE_OFF and the no heater control submode, we command all switches to off before
|
|
// completing the transition. This ensures a consistent state when commanding these modes.
|
|
if ((mode_ == MODE_OFF) or ((mode_ == MODE_ON) and (submode_ == SUBMODE_NO_HEATER_CTRL))) {
|
|
heaterSwitchHelperAllOff();
|
|
transitionWhenHeatersOff = true;
|
|
targetMode = mode_;
|
|
targetSubmode = submode_;
|
|
transitionWhenHeatersOffCycles = 0;
|
|
} else {
|
|
setMode(mode_, submode_);
|
|
}
|
|
}
|