TCS Observability #733

Merged
muellerr merged 19 commits from tcs-observability into main 2023-07-11 16:48:00 +02:00
9 changed files with 397 additions and 320 deletions

View File

@ -54,6 +54,8 @@ will consitute of a breaking change warranting a new major release:
- Upper limit for burn time of TCS heaters. Currently set to 1 hour for each heater. - Upper limit for burn time of TCS heaters. Currently set to 1 hour for each heater.
This mechanism will only track the burn time for heaters which were commanded by the This mechanism will only track the burn time for heaters which were commanded by the
TCS controller. TCS controller.
- TCS controller is now observable by introducing a new HK dataset which exposes some internal
fields related to TCS control.
# [v6.0.0] 2023-07-02 # [v6.0.0] 2023-07-02

View File

@ -33,6 +33,7 @@ ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater
susTemperatures(this), susTemperatures(this),
deviceTemperatures(this), deviceTemperatures(this),
heaterInfo(this), heaterInfo(this),
tcsCtrlInfo(this),
imtqThermalSet(objects::IMTQ_HANDLER, ThermalStateCfg()), imtqThermalSet(objects::IMTQ_HANDLER, ThermalStateCfg()),
maxSet0PlocHspd(objects::RTD_0_IC3_PLOC_HEATSPREADER, maxSet0PlocHspd(objects::RTD_0_IC3_PLOC_HEATSPREADER,
EiveMax31855::RtdCommands::EXCHANGE_SET_ID), EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
@ -174,7 +175,7 @@ void ThermalController::performControlOperation() {
} }
} }
HeaterSwitchStates heaterSwitchStateArray{}; tcsCtrl::HeaterSwitchStates heaterSwitchStateArray{};
heaterHandler.getAllSwitchStates(heaterSwitchStateArray); heaterHandler.getAllSwitchStates(heaterSwitchStateArray);
{ {
PoolReadGuard pg(&heaterInfo); PoolReadGuard pg(&heaterInfo);
@ -191,12 +192,11 @@ void ThermalController::performControlOperation() {
if (transitionWhenHeatersOff) { if (transitionWhenHeatersOff) {
bool allSwitchersOff = true; bool allSwitchersOff = true;
for (size_t idx = 0; idx < heaterSwitchStateArray.size(); idx++) { for (size_t idx = 0; idx < heaterSwitchStateArray.size(); idx++) {
if (heaterSwitchStateArray[idx] != HeaterHandler::SwitchState::OFF) { if (heaterSwitchStateArray[idx] != heater::SwitchState::OFF) {
allSwitchersOff = false; allSwitchersOff = false;
// if heater still ON after 3 cycles, switch OFF again // if heater still ON after 3 cycles, switch OFF again
if (transitionWhenHeatersOffCycles == 3) { if (transitionWhenHeatersOffCycles == 3) {
heaterHandler.switchHeater(static_cast<heater::Switch>(idx), heaterHandler.switchHeater(static_cast<heater::Switch>(idx), heater::SwitchState::OFF);
HeaterHandler::SwitchState::OFF);
triggerEvent(tcsCtrl::HEATER_NOT_OFF_FOR_OFF_MODE); triggerEvent(tcsCtrl::HEATER_NOT_OFF_FOR_OFF_MODE);
} }
} }
@ -215,6 +215,15 @@ void ThermalController::performControlOperation() {
} }
heaterTransitionControl(heaterSwitchStateArray); heaterTransitionControl(heaterSwitchStateArray);
heaterMaxDurationControl(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;
}
} }
} }
@ -284,6 +293,11 @@ ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& lo
localDataPoolMap.emplace(tcsCtrl::TEMP_ADC_PAYLOAD_PCDU, 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_SWITCH_LIST, &heaterSwitchStates);
localDataPoolMap.emplace(tcsCtrl::HEATER_CURRENT, &heaterCurrent); 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; bool enableHkSets = false;
#if OBSW_ENABLE_PERIODIC_HK == 1 #if OBSW_ENABLE_PERIODIC_HK == 1
@ -297,6 +311,8 @@ ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& lo
subdp::RegularHkPeriodicParams(deviceTemperatures.getSid(), enableHkSets, 120.0)); subdp::RegularHkPeriodicParams(deviceTemperatures.getSid(), enableHkSets, 120.0));
poolManager.subscribeForDiagPeriodicPacket( poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(heaterInfo.getSid(), enableHkSets, 120.0)); subdp::DiagnosticsHkPeriodicParams(heaterInfo.getSid(), enableHkSets, 120.0));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(tcsCtrlInfo.getSid(), enableHkSets, 120.0));
return returnvalue::OK; return returnvalue::OK;
} }
@ -311,6 +327,8 @@ LocalPoolDataSetBase* ThermalController::getDataSetHandle(sid_t sid) {
return &deviceTemperatures; return &deviceTemperatures;
case tcsCtrl::HEATER_SET: case tcsCtrl::HEATER_SET:
return &heaterInfo; return &heaterInfo;
case tcsCtrl::TCS_CTRL_INFO:
return &tcsCtrlInfo;
default: default:
return nullptr; return nullptr;
} }
@ -1012,7 +1030,7 @@ void ThermalController::ctrlAcsBoard() {
heater::Switch redSwitchNr = heater::HEATER_3_OBC_BRD; heater::Switch redSwitchNr = heater::HEATER_3_OBC_BRD;
// A side // A side
currThermalComponent = ACS_BOARD; ctrlCtx.thermalComponent = tcsCtrl::ACS_BOARD;
sensors[0].first = deviceTemperatures.gyro0SideA.isValid(); sensors[0].first = deviceTemperatures.gyro0SideA.isValid();
sensors[0].second = deviceTemperatures.gyro0SideA.value; sensors[0].second = deviceTemperatures.gyro0SideA.value;
sensors[1].first = deviceTemperatures.gyro2SideB.isValid(); sensors[1].first = deviceTemperatures.gyro2SideB.isValid();
@ -1056,7 +1074,7 @@ void ThermalController::ctrlAcsBoard() {
if (chooseHeater(switchNr, redSwitchNr)) { if (chooseHeater(switchNr, redSwitchNr)) {
if (heaterHandler.getSwitchState(switchNr)) { if (heaterHandler.getSwitchState(switchNr)) {
if (submode != SUBMODE_NO_HEATER_CTRL) { if (submode != SUBMODE_NO_HEATER_CTRL) {
heaterSwitchHelper(switchNr, HeaterHandler::SwitchState::OFF, currThermalComponent); heaterSwitchHelper(switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
} }
} }
} }
@ -1066,7 +1084,7 @@ void ThermalController::ctrlAcsBoard() {
} }
void ThermalController::ctrlMgt() { void ThermalController::ctrlMgt() {
currThermalComponent = MGT; ctrlCtx.thermalComponent = tcsCtrl::MGT;
sensors[0].first = sensorTemperatures.mgt.isValid(); sensors[0].first = sensorTemperatures.mgt.isValid();
sensors[0].second = sensorTemperatures.mgt.value; sensors[0].second = sensorTemperatures.mgt.value;
sensors[1].first = deviceTemperatures.mgt.isValid(); sensors[1].first = deviceTemperatures.mgt.isValid();
@ -1076,11 +1094,11 @@ void ThermalController::ctrlMgt() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_1_PCDU_PDU, mgtLimits); HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_1_PCDU_PDU, mgtLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
if (componentAboveUpperLimit and not mgtTooHotFlag) { if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.mgtTooHotFlag) {
triggerEvent(tcsCtrl::MGT_OVERHEATING, tempFloatToU32()); triggerEvent(tcsCtrl::MGT_OVERHEATING, tempFloatToU32());
mgtTooHotFlag = true; tooHotFlags.mgtTooHotFlag = true;
} else if (not componentAboveUpperLimit) { } else if (not ctrlCtx.componentAboveUpperLimit) {
mgtTooHotFlag = false; tooHotFlags.mgtTooHotFlag = false;
} }
} }
@ -1091,7 +1109,7 @@ void ThermalController::ctrlRw() {
std::array<uint32_t, 4> sensorTemps{}; std::array<uint32_t, 4> sensorTemps{};
// RW1 // RW1
currThermalComponent = RW; ctrlCtx.thermalComponent = tcsCtrl::RW;
sensors[0].first = sensorTemperatures.rw1.isValid(); sensors[0].first = sensorTemperatures.rw1.isValid();
sensors[0].second = sensorTemperatures.rw1.value; sensors[0].second = sensorTemperatures.rw1.value;
sensors[1].first = deviceTemperatures.rw1.isValid(); sensors[1].first = deviceTemperatures.rw1.isValid();
@ -1105,14 +1123,14 @@ void ThermalController::ctrlRw() {
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
sensorTemps[0] = tempFloatToU32(); sensorTemps[0] = tempFloatToU32();
if (componentAboveUpperLimit) { if (ctrlCtx.componentAboveUpperLimit) {
oneIsAboveLimit = true; oneIsAboveLimit = true;
eventToTrigger = overHeatEventToTrigger; eventToTrigger = ctrlCtx.overHeatEventToTrigger;
} }
} }
// RW2 // RW2
currThermalComponent = RW; ctrlCtx.thermalComponent = tcsCtrl::RW;
sensors[0].first = deviceTemperatures.rw2.isValid(); sensors[0].first = deviceTemperatures.rw2.isValid();
sensors[0].second = deviceTemperatures.rw2.value; sensors[0].second = deviceTemperatures.rw2.value;
sensors[1].first = deviceTemperatures.rw3.isValid(); sensors[1].first = deviceTemperatures.rw3.isValid();
@ -1126,15 +1144,15 @@ void ThermalController::ctrlRw() {
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
sensorTemps[1] = tempFloatToU32(); sensorTemps[1] = tempFloatToU32();
if (componentAboveUpperLimit) { if (ctrlCtx.componentAboveUpperLimit) {
oneIsAboveLimit = true; oneIsAboveLimit = true;
if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) { if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) {
eventToTrigger = overHeatEventToTrigger; eventToTrigger = ctrlCtx.overHeatEventToTrigger;
} }
} }
} }
// RW3 // RW3
currThermalComponent = RW; ctrlCtx.thermalComponent = tcsCtrl::RW;
sensors[0].first = deviceTemperatures.rw3.isValid(); sensors[0].first = deviceTemperatures.rw3.isValid();
sensors[0].second = deviceTemperatures.rw3.value; sensors[0].second = deviceTemperatures.rw3.value;
sensors[1].first = deviceTemperatures.rw4.isValid(); sensors[1].first = deviceTemperatures.rw4.isValid();
@ -1148,16 +1166,16 @@ void ThermalController::ctrlRw() {
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
sensorTemps[2] = tempFloatToU32(); sensorTemps[2] = tempFloatToU32();
if (componentAboveUpperLimit) { if (ctrlCtx.componentAboveUpperLimit) {
oneIsAboveLimit = true; oneIsAboveLimit = true;
if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) { if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) {
eventToTrigger = overHeatEventToTrigger; eventToTrigger = ctrlCtx.overHeatEventToTrigger;
} }
} }
} }
// RW4 // RW4
currThermalComponent = RW; ctrlCtx.thermalComponent = tcsCtrl::RW;
sensors[0].first = deviceTemperatures.rw4.isValid(); sensors[0].first = deviceTemperatures.rw4.isValid();
sensors[0].second = deviceTemperatures.rw4.value; sensors[0].second = deviceTemperatures.rw4.value;
sensors[1].first = deviceTemperatures.rw1.isValid(); sensors[1].first = deviceTemperatures.rw1.isValid();
@ -1171,27 +1189,27 @@ void ThermalController::ctrlRw() {
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
sensorTemps[3] = tempFloatToU32(); sensorTemps[3] = tempFloatToU32();
if (componentAboveUpperLimit) { if (ctrlCtx.componentAboveUpperLimit) {
oneIsAboveLimit = true; oneIsAboveLimit = true;
if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) { if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) {
eventToTrigger = overHeatEventToTrigger; eventToTrigger = ctrlCtx.overHeatEventToTrigger;
} }
} }
} }
if (oneIsAboveLimit and not rwTooHotFlag) { if (oneIsAboveLimit and not tooHotFlags.rwTooHotFlag) {
EventManagerIF::triggerEvent(objects::RW1, eventToTrigger, sensorTemps[0]); EventManagerIF::triggerEvent(objects::RW1, eventToTrigger, sensorTemps[0]);
EventManagerIF::triggerEvent(objects::RW2, eventToTrigger, sensorTemps[1]); EventManagerIF::triggerEvent(objects::RW2, eventToTrigger, sensorTemps[1]);
EventManagerIF::triggerEvent(objects::RW3, eventToTrigger, sensorTemps[2]); EventManagerIF::triggerEvent(objects::RW3, eventToTrigger, sensorTemps[2]);
EventManagerIF::triggerEvent(objects::RW4, eventToTrigger, sensorTemps[3]); EventManagerIF::triggerEvent(objects::RW4, eventToTrigger, sensorTemps[3]);
rwTooHotFlag = true; tooHotFlags.rwTooHotFlag = true;
} else if (not oneIsAboveLimit) { } else if (not oneIsAboveLimit) {
rwTooHotFlag = false; tooHotFlags.rwTooHotFlag = false;
} }
} }
void ThermalController::ctrlStr() { void ThermalController::ctrlStr() {
currThermalComponent = STR; ctrlCtx.thermalComponent = tcsCtrl::STR;
sensors[0].first = sensorTemperatures.startracker.isValid(); sensors[0].first = sensorTemperatures.startracker.isValid();
sensors[0].second = sensorTemperatures.startracker.value; sensors[0].second = sensorTemperatures.startracker.value;
sensors[1].first = deviceTemperatures.startracker.isValid(); sensors[1].first = deviceTemperatures.startracker.isValid();
@ -1201,11 +1219,11 @@ void ThermalController::ctrlStr() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_5_STR, heater::HEATER_6_DRO, strLimits); HeaterContext htrCtx(heater::HEATER_5_STR, heater::HEATER_6_DRO, strLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandlerWhichClearsOneShotFlag(objects::STAR_TRACKER, strTooHotFlag); tooHotHandlerWhichClearsOneShotFlag(objects::STAR_TRACKER, tooHotFlags.strTooHotFlag);
} }
void ThermalController::ctrlIfBoard() { void ThermalController::ctrlIfBoard() {
currThermalComponent = IF_BOARD; ctrlCtx.thermalComponent = tcsCtrl::IF_BOARD;
sensors[0].first = sensorTemperatures.tmp1075IfBrd.isValid(); sensors[0].first = sensorTemperatures.tmp1075IfBrd.isValid();
sensors[0].second = sensorTemperatures.tmp1075IfBrd.value; sensors[0].second = sensorTemperatures.tmp1075IfBrd.value;
sensors[1].first = sensorTemperatures.mgt.isValid(); sensors[1].first = sensorTemperatures.mgt.isValid();
@ -1219,7 +1237,7 @@ void ThermalController::ctrlIfBoard() {
} }
void ThermalController::ctrlTcsBoard() { void ThermalController::ctrlTcsBoard() {
currThermalComponent = TCS_BOARD; ctrlCtx.thermalComponent = tcsCtrl::TCS_BOARD;
sensors[0].first = sensorTemperatures.tcsBoard.isValid(); sensors[0].first = sensorTemperatures.tcsBoard.isValid();
sensors[0].second = sensorTemperatures.tcsBoard.value; sensors[0].second = sensorTemperatures.tcsBoard.value;
sensors[1].first = sensorTemperatures.tmp1075Tcs0.isValid(); sensors[1].first = sensorTemperatures.tmp1075Tcs0.isValid();
@ -1233,7 +1251,7 @@ void ThermalController::ctrlTcsBoard() {
} }
void ThermalController::ctrlObc() { void ThermalController::ctrlObc() {
currThermalComponent = OBC; ctrlCtx.thermalComponent = tcsCtrl::OBC;
sensors[0].first = deviceTemperatures.q7s.isValid(); sensors[0].first = deviceTemperatures.q7s.isValid();
sensors[0].second = deviceTemperatures.q7s.value; sensors[0].second = deviceTemperatures.q7s.value;
sensors[1].first = sensorTemperatures.tmp1075Tcs1.isValid(); sensors[1].first = sensorTemperatures.tmp1075Tcs1.isValid();
@ -1243,16 +1261,16 @@ void ThermalController::ctrlObc() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_3_OBC_BRD, heater::HEATER_2_ACS_BRD, obcLimits); HeaterContext htrCtx(heater::HEATER_3_OBC_BRD, heater::HEATER_2_ACS_BRD, obcLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
if (componentAboveUpperLimit and not obcTooHotFlag) { if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.obcTooHotFlag) {
triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32()); triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32());
obcTooHotFlag = true; tooHotFlags.obcTooHotFlag = true;
} else if (not componentAboveUpperLimit) { } else if (not ctrlCtx.componentAboveUpperLimit) {
obcTooHotFlag = false; tooHotFlags.obcTooHotFlag = false;
} }
} }
void ThermalController::ctrlSBandTransceiver() { void ThermalController::ctrlSBandTransceiver() {
currThermalComponent = SBAND_TRANSCEIVER; ctrlCtx.thermalComponent = tcsCtrl::SBAND_TRANSCEIVER;
sensors[0].first = deviceTemperatures.syrlinksPowerAmplifier.isValid(); sensors[0].first = deviceTemperatures.syrlinksPowerAmplifier.isValid();
sensors[0].second = deviceTemperatures.syrlinksPowerAmplifier.value; sensors[0].second = deviceTemperatures.syrlinksPowerAmplifier.value;
sensors[1].first = deviceTemperatures.syrlinksBasebandBoard.isValid(); sensors[1].first = deviceTemperatures.syrlinksBasebandBoard.isValid();
@ -1262,15 +1280,15 @@ void ThermalController::ctrlSBandTransceiver() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_7_S_BAND, heater::HEATER_4_CAMERA, sBandTransceiverLimits); HeaterContext htrCtx(heater::HEATER_7_S_BAND, heater::HEATER_4_CAMERA, sBandTransceiverLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
if (componentAboveUpperLimit and not syrlinksTooHotFlag) { if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.syrlinksTooHotFlag) {
triggerEvent(tcsCtrl::SYRLINKS_OVERHEATING, tempFloatToU32()); triggerEvent(tcsCtrl::SYRLINKS_OVERHEATING, tempFloatToU32());
syrlinksTooHotFlag = true; tooHotFlags.syrlinksTooHotFlag = true;
} else if (not componentAboveUpperLimit) { } else if (not ctrlCtx.componentAboveUpperLimit) {
syrlinksTooHotFlag = false; tooHotFlags.syrlinksTooHotFlag = false;
} }
} }
void ThermalController::ctrlPcduP60Board() { void ThermalController::ctrlPcduP60Board() {
currThermalComponent = PCDUP60_BOARD; ctrlCtx.thermalComponent = tcsCtrl::PCDUP60_BOARD;
sensors[0].first = deviceTemperatures.temp1P60dock.isValid(); sensors[0].first = deviceTemperatures.temp1P60dock.isValid();
sensors[0].second = deviceTemperatures.temp1P60dock.value; sensors[0].second = deviceTemperatures.temp1P60dock.value;
sensors[1].first = deviceTemperatures.temp2P60dock.isValid(); sensors[1].first = deviceTemperatures.temp2P60dock.isValid();
@ -1278,16 +1296,16 @@ void ThermalController::ctrlPcduP60Board() {
numSensors = 2; numSensors = 2;
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduP60BoardLimits); HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduP60BoardLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
if (componentAboveUpperLimit and not pcduSystemTooHotFlag) { if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.pcduSystemTooHotFlag) {
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32()); triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
pcduSystemTooHotFlag = true; tooHotFlags.pcduSystemTooHotFlag = true;
} else if (not componentAboveUpperLimit) { } else if (not ctrlCtx.componentAboveUpperLimit) {
pcduSystemTooHotFlag = false; tooHotFlags.pcduSystemTooHotFlag = false;
} // TODO: ! } // TODO: !
} }
void ThermalController::ctrlPcduAcu() { void ThermalController::ctrlPcduAcu() {
currThermalComponent = PCDUACU; ctrlCtx.thermalComponent = tcsCtrl::PCDUACU;
heater::Switch switchNr = heater::HEATER_1_PCDU_PDU; heater::Switch switchNr = heater::HEATER_1_PCDU_PDU;
heater::Switch redSwitchNr = heater::HEATER_2_ACS_BRD; heater::Switch redSwitchNr = heater::HEATER_2_ACS_BRD;
@ -1295,15 +1313,15 @@ void ThermalController::ctrlPcduAcu() {
bool sensorTempAvailable = true; bool sensorTempAvailable = true;
// TODO: check // TODO: check
if (deviceTemperatures.acu.value[0] != INVALID_TEMPERATURE) { if (deviceTemperatures.acu.value[0] != INVALID_TEMPERATURE) {
sensorTemp = deviceTemperatures.acu.value[0]; ctrlCtx.sensorTemp = deviceTemperatures.acu.value[0];
} else if (deviceTemperatures.acu.value[1] != INVALID_TEMPERATURE) { } else if (deviceTemperatures.acu.value[1] != INVALID_TEMPERATURE) {
sensorTemp = deviceTemperatures.acu.value[1]; ctrlCtx.sensorTemp = deviceTemperatures.acu.value[1];
} else if (deviceTemperatures.acu.value[2] != INVALID_TEMPERATURE) { } else if (deviceTemperatures.acu.value[2] != INVALID_TEMPERATURE) {
sensorTemp = deviceTemperatures.acu.value[2]; ctrlCtx.sensorTemp = deviceTemperatures.acu.value[2];
} else if (sensorTemperatures.acu.isValid()) { } else if (sensorTemperatures.acu.isValid()) {
sensorTemp = sensorTemperatures.acu.value; ctrlCtx.sensorTemp = sensorTemperatures.acu.value;
} else { } else {
triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, currThermalComponent); triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, ctrlCtx.thermalComponent);
sensorTempAvailable = false; sensorTempAvailable = false;
} }
if (sensorTempAvailable) { if (sensorTempAvailable) {
@ -1311,16 +1329,16 @@ void ThermalController::ctrlPcduAcu() {
checkLimitsAndCtrlHeater(htrCtx); checkLimitsAndCtrlHeater(htrCtx);
} }
} }
if (componentAboveUpperLimit and not pcduSystemTooHotFlag) { if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.pcduSystemTooHotFlag) {
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32()); triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
pcduSystemTooHotFlag = true; tooHotFlags.pcduSystemTooHotFlag = true;
} else if (not componentAboveUpperLimit) { } else if (not ctrlCtx.componentAboveUpperLimit) {
pcduSystemTooHotFlag = false; tooHotFlags.pcduSystemTooHotFlag = false;
} }
} }
void ThermalController::ctrlPcduPdu() { void ThermalController::ctrlPcduPdu() {
currThermalComponent = PCDUPDU; ctrlCtx.thermalComponent = tcsCtrl::PCDUPDU;
sensors[0].first = deviceTemperatures.pdu1.isValid(); sensors[0].first = deviceTemperatures.pdu1.isValid();
sensors[0].second = deviceTemperatures.pdu1.value; sensors[0].second = deviceTemperatures.pdu1.value;
sensors[1].first = deviceTemperatures.pdu2.isValid(); sensors[1].first = deviceTemperatures.pdu2.isValid();
@ -1330,16 +1348,16 @@ void ThermalController::ctrlPcduPdu() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduPduLimits); HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduPduLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
if (componentAboveUpperLimit and not pcduSystemTooHotFlag) { if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.pcduSystemTooHotFlag) {
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32()); triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
pcduSystemTooHotFlag = true; tooHotFlags.pcduSystemTooHotFlag = true;
} else if (not componentAboveUpperLimit) { } else if (not ctrlCtx.componentAboveUpperLimit) {
pcduSystemTooHotFlag = false; tooHotFlags.pcduSystemTooHotFlag = false;
} }
} }
void ThermalController::ctrlPlPcduBoard() { void ThermalController::ctrlPlPcduBoard() {
currThermalComponent = PLPCDU_BOARD; ctrlCtx.thermalComponent = tcsCtrl::PLPCDU_BOARD;
sensors[0].first = sensorTemperatures.tmp1075PlPcdu0.isValid(); sensors[0].first = sensorTemperatures.tmp1075PlPcdu0.isValid();
sensors[0].second = sensorTemperatures.tmp1075PlPcdu0.value; sensors[0].second = sensorTemperatures.tmp1075PlPcdu0.value;
sensors[1].first = sensorTemperatures.tmp1075PlPcdu1.isValid(); sensors[1].first = sensorTemperatures.tmp1075PlPcdu1.isValid();
@ -1351,11 +1369,11 @@ void ThermalController::ctrlPlPcduBoard() {
numSensors = 4; numSensors = 4;
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, plPcduBoardLimits); HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, plPcduBoardLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
} }
void ThermalController::ctrlPlocMissionBoard() { void ThermalController::ctrlPlocMissionBoard() {
currThermalComponent = PLOCMISSION_BOARD; ctrlCtx.thermalComponent = tcsCtrl::PLOCMISSION_BOARD;
sensors[0].first = sensorTemperatures.plocHeatspreader.isValid(); sensors[0].first = sensorTemperatures.plocHeatspreader.isValid();
sensors[0].second = sensorTemperatures.plocHeatspreader.value; sensors[0].second = sensorTemperatures.plocHeatspreader.value;
sensors[1].first = sensorTemperatures.plocMissionboard.isValid(); sensors[1].first = sensorTemperatures.plocMissionboard.isValid();
@ -1366,11 +1384,11 @@ void ThermalController::ctrlPlocMissionBoard() {
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD, HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD,
plocMissionBoardLimits); plocMissionBoardLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, plocTooHotFlag); tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, tooHotFlags.plocTooHotFlag);
} }
void ThermalController::ctrlPlocProcessingBoard() { void ThermalController::ctrlPlocProcessingBoard() {
currThermalComponent = PLOCPROCESSING_BOARD; ctrlCtx.thermalComponent = tcsCtrl::PLOCPROCESSING_BOARD;
sensors[0].first = sensorTemperatures.plocMissionboard.isValid(); sensors[0].first = sensorTemperatures.plocMissionboard.isValid();
sensors[0].second = sensorTemperatures.plocMissionboard.value; sensors[0].second = sensorTemperatures.plocMissionboard.value;
sensors[1].first = sensorTemperatures.plocHeatspreader.isValid(); sensors[1].first = sensorTemperatures.plocHeatspreader.isValid();
@ -1381,11 +1399,11 @@ void ThermalController::ctrlPlocProcessingBoard() {
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD, HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD,
plocProcessingBoardLimits); plocProcessingBoardLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, plocTooHotFlag); tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, tooHotFlags.plocTooHotFlag);
} }
void ThermalController::ctrlDac() { void ThermalController::ctrlDac() {
currThermalComponent = DAC; ctrlCtx.thermalComponent = tcsCtrl::DAC;
sensors[0].first = sensorTemperatures.dacHeatspreader.isValid(); sensors[0].first = sensorTemperatures.dacHeatspreader.isValid();
sensors[0].second = sensorTemperatures.dacHeatspreader.value; sensors[0].second = sensorTemperatures.dacHeatspreader.value;
sensors[1].first = sensorTemperatures.plocMissionboard.isValid(); sensors[1].first = sensorTemperatures.plocMissionboard.isValid();
@ -1395,11 +1413,11 @@ void ThermalController::ctrlDac() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD, dacLimits); HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD, dacLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
} }
void ThermalController::ctrlCameraBody() { void ThermalController::ctrlCameraBody() {
currThermalComponent = CAMERA; ctrlCtx.thermalComponent = tcsCtrl::CAMERA;
sensors[0].first = sensorTemperatures.payload4kCamera.isValid(); sensors[0].first = sensorTemperatures.payload4kCamera.isValid();
sensors[0].second = sensorTemperatures.payload4kCamera.value; sensors[0].second = sensorTemperatures.payload4kCamera.value;
sensors[1].first = sensorTemperatures.dro.isValid(); sensors[1].first = sensorTemperatures.dro.isValid();
@ -1409,7 +1427,7 @@ void ThermalController::ctrlCameraBody() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_4_CAMERA, heater::HEATER_6_DRO, cameraLimits); HeaterContext htrCtx(heater::HEATER_4_CAMERA, heater::HEATER_6_DRO, cameraLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
if (componentAboveUpperLimit and not camTooHotOneShotFlag) { if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.camTooHotOneShotFlag) {
triggerEvent(tcsCtrl::CAMERA_OVERHEATING, tempFloatToU32()); triggerEvent(tcsCtrl::CAMERA_OVERHEATING, tempFloatToU32());
CommandMessage msg; CommandMessage msg;
HealthMessage::setHealthMessage(&msg, HealthMessage::HEALTH_SET, HealthState::FAULTY); HealthMessage::setHealthMessage(&msg, HealthMessage::HEALTH_SET, HealthState::FAULTY);
@ -1418,14 +1436,14 @@ void ThermalController::ctrlCameraBody() {
sif::error << "ThermalController::ctrlCameraBody(): Sending health message failed" sif::error << "ThermalController::ctrlCameraBody(): Sending health message failed"
<< std::endl; << std::endl;
} }
camTooHotOneShotFlag = true; tooHotFlags.camTooHotOneShotFlag = true;
} else if (not componentAboveUpperLimit) { } else if (not ctrlCtx.componentAboveUpperLimit) {
camTooHotOneShotFlag = false; tooHotFlags.camTooHotOneShotFlag = false;
} }
} }
void ThermalController::ctrlDro() { void ThermalController::ctrlDro() {
currThermalComponent = DRO; ctrlCtx.thermalComponent = tcsCtrl::DRO;
sensors[0].first = sensorTemperatures.dro.isValid(); sensors[0].first = sensorTemperatures.dro.isValid();
sensors[0].second = sensorTemperatures.dro.value; sensors[0].second = sensorTemperatures.dro.value;
sensors[1].first = sensorTemperatures.payload4kCamera.isValid(); sensors[1].first = sensorTemperatures.payload4kCamera.isValid();
@ -1435,11 +1453,11 @@ void ThermalController::ctrlDro() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, droLimits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, droLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
} }
void ThermalController::ctrlX8() { void ThermalController::ctrlX8() {
currThermalComponent = X8; ctrlCtx.thermalComponent = tcsCtrl::X8;
sensors[0].first = sensorTemperatures.x8.isValid(); sensors[0].first = sensorTemperatures.x8.isValid();
sensors[0].second = sensorTemperatures.x8.value; sensors[0].second = sensorTemperatures.x8.value;
sensors[1].first = sensorTemperatures.hpa.isValid(); sensors[1].first = sensorTemperatures.hpa.isValid();
@ -1449,11 +1467,11 @@ void ThermalController::ctrlX8() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, x8Limits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, x8Limits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
} }
void ThermalController::ctrlTx() { void ThermalController::ctrlTx() {
currThermalComponent = TX; ctrlCtx.thermalComponent = tcsCtrl::TX;
sensors[0].first = sensorTemperatures.eBandTx.isValid(); sensors[0].first = sensorTemperatures.eBandTx.isValid();
sensors[0].second = sensorTemperatures.eBandTx.value; sensors[0].second = sensorTemperatures.eBandTx.value;
sensors[1].first = sensorTemperatures.x8.isValid(); sensors[1].first = sensorTemperatures.x8.isValid();
@ -1463,11 +1481,11 @@ void ThermalController::ctrlTx() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, txLimits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, txLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
} }
void ThermalController::ctrlMpa() { void ThermalController::ctrlMpa() {
currThermalComponent = MPA; ctrlCtx.thermalComponent = tcsCtrl::MPA;
sensors[0].first = sensorTemperatures.mpa.isValid(); sensors[0].first = sensorTemperatures.mpa.isValid();
sensors[0].second = sensorTemperatures.mpa.value; sensors[0].second = sensorTemperatures.mpa.value;
sensors[1].first = sensorTemperatures.hpa.isValid(); sensors[1].first = sensorTemperatures.hpa.isValid();
@ -1477,11 +1495,11 @@ void ThermalController::ctrlMpa() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, mpaLimits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, mpaLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
} }
void ThermalController::ctrlHpa() { void ThermalController::ctrlHpa() {
currThermalComponent = HPA; ctrlCtx.thermalComponent = tcsCtrl::HPA;
sensors[0].first = sensorTemperatures.hpa.isValid(); sensors[0].first = sensorTemperatures.hpa.isValid();
sensors[0].second = sensorTemperatures.hpa.value; sensors[0].second = sensorTemperatures.hpa.value;
sensors[1].first = sensorTemperatures.x8.isValid(); sensors[1].first = sensorTemperatures.x8.isValid();
@ -1491,11 +1509,11 @@ void ThermalController::ctrlHpa() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, hpaLimits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, hpaLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
} }
void ThermalController::ctrlScexBoard() { void ThermalController::ctrlScexBoard() {
currThermalComponent = SCEX_BOARD; ctrlCtx.thermalComponent = tcsCtrl::SCEX_BOARD;
sensors[0].first = sensorTemperatures.scex.isValid(); sensors[0].first = sensorTemperatures.scex.isValid();
sensors[0].second = sensorTemperatures.scex.value; sensors[0].second = sensorTemperatures.scex.value;
sensors[1].first = sensorTemperatures.x8.isValid(); sensors[1].first = sensorTemperatures.x8.isValid();
@ -1505,10 +1523,11 @@ void ThermalController::ctrlScexBoard() {
numSensors = 3; numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_5_STR, scexBoardLimits); HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_5_STR, scexBoardLimits);
ctrlComponentTemperature(htrCtx); ctrlComponentTemperature(htrCtx);
tooHotHandlerWhichClearsOneShotFlag(objects::SCEX, scexTooHotFlag); tooHotHandlerWhichClearsOneShotFlag(objects::SCEX, tooHotFlags.scexTooHotFlag);
} }
void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates) { void ThermalController::performThermalModuleCtrl(
const tcsCtrl::HeaterSwitchStates& heaterSwitchStates) {
ctrlAcsBoard(); ctrlAcsBoard();
ctrlMgt(); ctrlMgt();
ctrlRw(); ctrlRw();
@ -1524,11 +1543,11 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
// Payload components // Payload components
std::array<bool, 2> plocInAllowedRange{}; std::array<bool, 2> plocInAllowedRange{};
ctrlPlocMissionBoard(); ctrlPlocMissionBoard();
plocInAllowedRange.at(0) = not componentAboveUpperLimit; plocInAllowedRange.at(0) = not ctrlCtx.componentAboveUpperLimit;
ctrlPlocProcessingBoard(); ctrlPlocProcessingBoard();
plocInAllowedRange.at(1) = not componentAboveUpperLimit; plocInAllowedRange.at(1) = not ctrlCtx.componentAboveUpperLimit;
if (plocTooHotFlag) { if (tooHotFlags.plocTooHotFlag) {
bool clearFlag = true; bool clearFlag = true;
for (const auto& inRange : plocInAllowedRange) { for (const auto& inRange : plocInAllowedRange) {
if (not inRange) { if (not inRange) {
@ -1536,7 +1555,7 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
} }
} }
if (clearFlag) { if (clearFlag) {
plocTooHotFlag = false; tooHotFlags.plocTooHotFlag = false;
} }
} }
ctrlCameraBody(); ctrlCameraBody();
@ -1545,21 +1564,21 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
// E-Band // E-Band
std::array<bool, 7> eBandInAllowedRange{}; std::array<bool, 7> eBandInAllowedRange{};
ctrlPlPcduBoard(); ctrlPlPcduBoard();
eBandInAllowedRange.at(0) = not componentAboveUpperLimit; eBandInAllowedRange.at(0) = not ctrlCtx.componentAboveUpperLimit;
ctrlDac(); ctrlDac();
eBandInAllowedRange.at(1) = not componentAboveUpperLimit; eBandInAllowedRange.at(1) = not ctrlCtx.componentAboveUpperLimit;
ctrlDro(); ctrlDro();
eBandInAllowedRange.at(2) = not componentAboveUpperLimit; eBandInAllowedRange.at(2) = not ctrlCtx.componentAboveUpperLimit;
ctrlX8(); ctrlX8();
eBandInAllowedRange.at(3) = not componentAboveUpperLimit; eBandInAllowedRange.at(3) = not ctrlCtx.componentAboveUpperLimit;
ctrlHpa(); ctrlHpa();
eBandInAllowedRange.at(4) = not componentAboveUpperLimit; eBandInAllowedRange.at(4) = not ctrlCtx.componentAboveUpperLimit;
ctrlTx(); ctrlTx();
eBandInAllowedRange.at(5) = not componentAboveUpperLimit; eBandInAllowedRange.at(5) = not ctrlCtx.componentAboveUpperLimit;
ctrlMpa(); ctrlMpa();
eBandInAllowedRange.at(6) = not componentAboveUpperLimit; eBandInAllowedRange.at(6) = not ctrlCtx.componentAboveUpperLimit;
if (eBandTooHotFlag) { if (tooHotFlags.eBandTooHotFlag) {
bool clearFlag = true; bool clearFlag = true;
for (const auto& inRange : eBandInAllowedRange) { for (const auto& inRange : eBandInAllowedRange) {
if (not inRange) { if (not inRange) {
@ -1567,7 +1586,7 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
} }
} }
if (clearFlag) { if (clearFlag) {
eBandTooHotFlag = false; tooHotFlags.eBandTooHotFlag = false;
} }
} }
} }
@ -1584,8 +1603,9 @@ void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) {
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) { if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
// Also track the counter to prevent heater handler message spam. The heater handle can only // Also track the counter to prevent heater handler message spam. The heater handle can only
// process 2 messages per cycle. // process 2 messages per cycle.
if (heaterCtrlAllowed() and (thermalStates[currThermalComponent].noSensorAvailableCounter < 3)) { if (heaterCtrlAllowed() and
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, currThermalComponent); (thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter < 3)) {
heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
} }
} }
} }
@ -1596,21 +1616,21 @@ bool ThermalController::selectAndReadSensorTemp(HeaterContext& htrCtx) {
if (sensors[i].first and sensors[i].second != INVALID_TEMPERATURE and if (sensors[i].first and sensors[i].second != INVALID_TEMPERATURE and
sensors[i].second > SANITY_LIMIT_LOWER_TEMP and sensors[i].second > SANITY_LIMIT_LOWER_TEMP and
sensors[i].second < SANITY_LIMIT_UPPER_TEMP) { sensors[i].second < SANITY_LIMIT_UPPER_TEMP) {
sensorTemp = sensors[i].second; ctrlCtx.sensorTemp = sensors[i].second;
currentSensorIndex = i; ctrlCtx.currentSensorIndex = i;
thermalStates[currThermalComponent].noSensorAvailableCounter = 0; thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter = 0;
return true; return true;
} }
} }
thermalStates[currThermalComponent].noSensorAvailableCounter++; thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter++;
if (currThermalComponent != RW and currThermalComponent != ACS_BOARD) { if (ctrlCtx.thermalComponent != tcsCtrl::RW and ctrlCtx.thermalComponent != tcsCtrl::ACS_BOARD) {
if (thermalStates[currThermalComponent].noSensorAvailableCounter <= 3) { if (thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter <= 3) {
triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, currThermalComponent); triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, ctrlCtx.thermalComponent);
} }
} else { } else {
if (thermalStates[currThermalComponent].noSensorAvailableCounter <= 8) { if (thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter <= 8) {
triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, currThermalComponent); triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, ctrlCtx.thermalComponent);
} }
} }
@ -1624,7 +1644,7 @@ bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch re
if (mainHealth != HasHealthIF::HEALTHY) { if (mainHealth != HasHealthIF::HEALTHY) {
if (redHealth == HasHealthIF::HEALTHY) { if (redHealth == HasHealthIF::HEALTHY) {
switchNr = redSwitchNr; switchNr = redSwitchNr;
redSwitchNrInUse = true; ctrlCtx.redSwitchNrInUse = true;
} else { } else {
heaterAvailable = false; heaterAvailable = false;
// Special case: Ground might command/do something with the heaters, so prevent spam. // Special case: Ground might command/do something with the heaters, so prevent spam.
@ -1633,7 +1653,7 @@ bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch re
} }
} }
} else { } else {
redSwitchNrInUse = false; ctrlCtx.redSwitchNrInUse = false;
} }
return heaterAvailable; return heaterAvailable;
} }
@ -1642,23 +1662,23 @@ void ThermalController::heaterCtrlTempTooHighHandler(HeaterContext& htrCtx, cons
if (not heaterCtrlAllowed()) { if (not heaterCtrlAllowed()) {
return; return;
} }
if (htrCtx.switchState == HeaterHandler::SwitchState::ON) { if (htrCtx.switchState == heater::SwitchState::ON) {
sif::info << "TCS: Component " << static_cast<int>(currThermalComponent) << " too warm, above " sif::info << "TCS: Component " << static_cast<int>(ctrlCtx.thermalComponent)
<< whatLimit << ", switching off heater" << std::endl; << " too warm, above " << whatLimit << ", switching off heater" << std::endl;
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, currThermalComponent); heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
heaterStates[htrCtx.switchNr].switchTransition = true; heaterStates[htrCtx.switchNr].switchTransition = true;
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF; heaterStates[htrCtx.switchNr].target = heater::SwitchState::OFF;
} }
if (heaterHandler.getSwitchState(htrCtx.redSwitchNr) == HeaterHandler::SwitchState::ON) { if (heaterHandler.getSwitchState(htrCtx.redSwitchNr) == heater::SwitchState::ON) {
heaterSwitchHelper(htrCtx.redSwitchNr, HeaterHandler::SwitchState::OFF, currThermalComponent); heaterSwitchHelper(htrCtx.redSwitchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
heaterStates[htrCtx.redSwitchNr].switchTransition = true; heaterStates[htrCtx.redSwitchNr].switchTransition = true;
heaterStates[htrCtx.redSwitchNr].target = HeaterHandler::SwitchState::OFF; heaterStates[htrCtx.redSwitchNr].target = heater::SwitchState::OFF;
} }
} }
void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) { void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
componentAboveCutOffLimit = false; ctrlCtx.componentAboveCutOffLimit = false;
componentAboveUpperLimit = false; ctrlCtx.componentAboveUpperLimit = false;
// Stay passive during switch transitions, wait for heater switching to complete. Otherwise, // 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 // still check whether components are out of range, which might be important information for the
// top level control loop. // top level control loop.
@ -1669,39 +1689,40 @@ void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
} }
htrCtx.switchState = htrCtx.switchState =
static_cast<HeaterHandler::SwitchState>(heaterInfo.heaterSwitchState[htrCtx.switchNr]); static_cast<heater::SwitchState>(heaterInfo.heaterSwitchState[htrCtx.switchNr]);
// Heater off // Heater off
if (htrCtx.switchState == HeaterHandler::SwitchState::OFF) { if (htrCtx.switchState == heater::SwitchState::OFF) {
if (sensorTemp < htrCtx.tempLimit.opLowerLimit and heaterCtrlAllowed()) { if (ctrlCtx.sensorTemp < htrCtx.tempLimit.opLowerLimit and heaterCtrlAllowed()) {
sif::info << "TCS: Heater " << static_cast<int>(htrCtx.switchNr) << " for component " sif::info << "TCS: Heater " << static_cast<int>(ctrlCtx.thermalComponent) << " ON"
<< static_cast<int>(currThermalComponent) << " ON" << std::endl; << std::endl;
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::ON, currThermalComponent); heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::ON, ctrlCtx.thermalComponent);
} else { } else {
// Even if heater control is now allowed, we can update the state. // Even if heater control is now allowed, we can update the state.
thermalStates[currThermalComponent].heating = false; thermalStates[ctrlCtx.thermalComponent].heating = false;
} }
heaterCtrlCheckUpperLimits(htrCtx); heaterCtrlCheckUpperLimits(htrCtx);
return; return;
} }
// Heater on // Heater on
if (htrCtx.switchState == HeaterHandler::SwitchState::ON) { if (htrCtx.switchState == heater::SwitchState::ON) {
if (thermalStates[currThermalComponent].heating) { if (thermalStates[ctrlCtx.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 and heaterCtrlAllowed()) { if (ctrlCtx.sensorTemp >= htrCtx.tempLimit.opLowerLimit + TEMP_OFFSET and
sif::info << "TCS: Heater " << static_cast<int>(htrCtx.switchNr) << " for component " heaterCtrlAllowed()) {
<< static_cast<int>(currThermalComponent) << " OFF" << std::endl; sif::info << "TCS: Heater " << static_cast<int>(ctrlCtx.thermalComponent) << " OFF"
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, currThermalComponent); << std::endl;
heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
heaterStates[htrCtx.switchNr].switchTransition = true; heaterStates[htrCtx.switchNr].switchTransition = true;
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF; heaterStates[htrCtx.switchNr].target = heater::SwitchState::OFF;
} }
return; 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);
if (sensorTemp >= htrCtx.tempLimit.cutOffLimit) { if (ctrlCtx.sensorTemp >= htrCtx.tempLimit.cutOffLimit) {
componentAboveCutOffLimit = true; ctrlCtx.componentAboveCutOffLimit = true;
if (not tooHighHandlerAlreadyCalled) { if (not tooHighHandlerAlreadyCalled) {
heaterCtrlTempTooHighHandler(htrCtx, "CutOff-Limit"); heaterCtrlTempTooHighHandler(htrCtx, "CutOff-Limit");
} }
@ -1710,19 +1731,19 @@ void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
} }
bool ThermalController::heaterCtrlCheckUpperLimits(HeaterContext& htrCtx) { bool ThermalController::heaterCtrlCheckUpperLimits(HeaterContext& htrCtx) {
if (sensorTemp >= htrCtx.tempLimit.nopUpperLimit) { if (ctrlCtx.sensorTemp >= htrCtx.tempLimit.nopUpperLimit) {
componentAboveUpperLimit = true; ctrlCtx.componentAboveUpperLimit = true;
if (htrCtx.doHeaterHandling) { if (htrCtx.doHeaterHandling) {
heaterCtrlTempTooHighHandler(htrCtx, "NOP-Limit"); heaterCtrlTempTooHighHandler(htrCtx, "NOP-Limit");
} }
overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH; ctrlCtx.overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH;
return true; return true;
} else if (sensorTemp >= htrCtx.tempLimit.opUpperLimit) { } else if (ctrlCtx.sensorTemp >= htrCtx.tempLimit.opUpperLimit) {
componentAboveUpperLimit = true; ctrlCtx.componentAboveUpperLimit = true;
if (htrCtx.doHeaterHandling) { if (htrCtx.doHeaterHandling) {
heaterCtrlTempTooHighHandler(htrCtx, "OP-Limit"); heaterCtrlTempTooHighHandler(htrCtx, "OP-Limit");
} }
overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_HIGH; ctrlCtx.overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_HIGH;
return true; return true;
} }
return false; return false;
@ -1733,20 +1754,21 @@ void ThermalController::resetSensorsArray() {
validValuePair.first = false; validValuePair.first = false;
validValuePair.second = INVALID_TEMPERATURE; validValuePair.second = INVALID_TEMPERATURE;
} }
currThermalComponent = NONE; ctrlCtx.thermalComponent = tcsCtrl::NONE;
} }
void ThermalController::heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates) { void ThermalController::heaterTransitionControl(
const tcsCtrl::HeaterSwitchStates& currentHeaterStates) {
for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) { for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) {
if (heaterStates[i].switchTransition) { if (heaterStates[i].switchTransition) {
if (currentHeaterStates[i] == heaterStates[i].target) { if (currentHeaterStates[i] == heaterStates[i].target) {
// Required for max heater period control // Required for max heater period control
if (currentHeaterStates[i] == HeaterHandler::SwitchState::ON) { if (currentHeaterStates[i] == heater::SwitchState::ON) {
heaterStates[i].heaterOnPeriod.setTimeout(MAX_HEATER_ON_DURATIONS_MS[i]); heaterStates[i].heaterOnMaxBurnTime.setTimeout(MAX_HEATER_ON_DURATIONS_MS[i]);
heaterStates[i].heaterOnPeriod.resetTimer(); heaterStates[i].heaterOnMaxBurnTime.resetTimer();
heaterStates[i].trackHeaterMaxPeriod = true; heaterStates[i].trackHeaterMaxBurnTime = true;
} else { } else {
heaterStates[i].trackHeaterMaxPeriod = false; heaterStates[i].trackHeaterMaxBurnTime = false;
// The heater might still be one for some thermal components, so cross-check // The heater might still be one for some thermal components, so cross-check
// those components // those components
crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(static_cast<heater::Switch>(i)); crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(static_cast<heater::Switch>(i));
@ -1764,19 +1786,20 @@ void ThermalController::heaterTransitionControl(const HeaterSwitchStates& curren
} }
} }
void ThermalController::heaterMaxDurationControl(const HeaterSwitchStates& currentHeaterStates) { void ThermalController::heaterMaxDurationControl(
const tcsCtrl::HeaterSwitchStates& currentHeaterStates) {
for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) { 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 // Right now, we only track the maximum duration for heater which were commanded by the TCS
// controller. // controller.
if (currentHeaterStates[i] == HeaterHandler::SwitchState::ON and if (currentHeaterStates[i] == heater::SwitchState::ON and
heaterStates[i].trackHeaterMaxPeriod and heaterStates[i].heaterOnPeriod.hasTimedOut()) { heaterStates[i].trackHeaterMaxBurnTime and
heaterStates[i].heaterOnMaxBurnTime.hasTimedOut()) {
heaterStates[i].switchTransition = false; heaterStates[i].switchTransition = false;
heaterStates[i].heaterSwitchControlCycles = 0; heaterStates[i].heaterSwitchControlCycles = 0;
heaterStates[i].trackHeaterMaxPeriod = false; heaterStates[i].trackHeaterMaxBurnTime = false;
triggerEvent(tcsCtrl::TCS_HEATER_MAX_BURN_TIME_REACHED, static_cast<uint32_t>(i), triggerEvent(tcsCtrl::TCS_HEATER_MAX_BURN_TIME_REACHED, static_cast<uint32_t>(i),
MAX_HEATER_ON_DURATIONS_MS[i]); MAX_HEATER_ON_DURATIONS_MS[i]);
heaterSwitchHelper(static_cast<heater::Switch>(i), HeaterHandler::SwitchState::OFF, heaterSwitchHelper(static_cast<heater::Switch>(i), heater::SwitchState::OFF, std::nullopt);
std::nullopt);
// The heater might still be one for some thermal components, so cross-check // The heater might still be one for some thermal components, so cross-check
// those components // those components
crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(static_cast<heater::Switch>(i)); crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(static_cast<heater::Switch>(i));
@ -1785,7 +1808,7 @@ void ThermalController::heaterMaxDurationControl(const HeaterSwitchStates& curre
} }
uint32_t ThermalController::tempFloatToU32() const { uint32_t ThermalController::tempFloatToU32() const {
auto sensorTempAsFloat = static_cast<float>(sensorTemp); auto sensorTempAsFloat = static_cast<float>(ctrlCtx.sensorTemp);
uint32_t tempRaw = 0; uint32_t tempRaw = 0;
size_t dummyLen = 0; size_t dummyLen = 0;
SerializeAdapter::serialize(&sensorTempAsFloat, reinterpret_cast<uint8_t*>(&tempRaw), &dummyLen, SerializeAdapter::serialize(&sensorTempAsFloat, reinterpret_cast<uint8_t*>(&tempRaw), &dummyLen,
@ -1804,9 +1827,9 @@ void ThermalController::setMode(Mode_t mode, Submode_t submode) {
} }
bool ThermalController::tooHotHandler(object_id_t object, bool& oneShotFlag) { bool ThermalController::tooHotHandler(object_id_t object, bool& oneShotFlag) {
if (componentAboveUpperLimit and not oneShotFlag) { if (ctrlCtx.componentAboveUpperLimit and not oneShotFlag) {
// Too hot -> returns true // Too hot -> returns true
EventManagerIF::triggerEvent(object, overHeatEventToTrigger, tempFloatToU32()); EventManagerIF::triggerEvent(object, ctrlCtx.overHeatEventToTrigger, tempFloatToU32());
oneShotFlag = true; oneShotFlag = true;
return true; return true;
} }
@ -1826,23 +1849,22 @@ void ThermalController::resetThermalStates() {
} }
} }
void ThermalController::heaterSwitchHelper(heater::Switch switchNr, void ThermalController::heaterSwitchHelper(heater::Switch switchNr, heater::SwitchState targetState,
HeaterHandler::SwitchState targetState,
std::optional<unsigned> componentIdx) { std::optional<unsigned> componentIdx) {
timeval currentTime; timeval currentTime;
Clock::getClockMonotonic(&currentTime); Clock::getClockMonotonic(&currentTime);
if (targetState == HeaterHandler::SwitchState::ON) { if (targetState == heater::SwitchState::ON) {
heaterHandler.switchHeater(switchNr, targetState); heaterHandler.switchHeater(switchNr, targetState);
heaterStates[switchNr].target = HeaterHandler::SwitchState::ON; heaterStates[switchNr].target = heater::SwitchState::ON;
heaterStates[switchNr].switchTransition = true; heaterStates[switchNr].switchTransition = true;
if (componentIdx.has_value()) { if (componentIdx.has_value()) {
unsigned componentIdxVal = componentIdx.value(); unsigned componentIdxVal = componentIdx.value();
thermalStates[componentIdxVal].sensorIndex = currentSensorIndex; thermalStates[componentIdxVal].sensorIndex = ctrlCtx.currentSensorIndex;
thermalStates[componentIdxVal].heaterSwitch = switchNr; thermalStates[componentIdxVal].heaterSwitch = switchNr;
thermalStates[componentIdxVal].heating = true; thermalStates[componentIdxVal].heating = true;
thermalStates[componentIdxVal].heaterStartTime = currentTime.tv_sec; thermalStates[componentIdxVal].heaterStartTime = currentTime.tv_sec;
} }
triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_ON, static_cast<uint32_t>(currThermalComponent), triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_ON, static_cast<uint32_t>(ctrlCtx.thermalComponent),
static_cast<uint32_t>(switchNr)); static_cast<uint32_t>(switchNr));
} else { } else {
heaterHandler.switchHeater(switchNr, targetState); heaterHandler.switchHeater(switchNr, targetState);
@ -1850,7 +1872,7 @@ void ThermalController::heaterSwitchHelper(heater::Switch switchNr,
thermalStates[componentIdx.value()].heating = false; thermalStates[componentIdx.value()].heating = false;
thermalStates[componentIdx.value()].heaterEndTime = currentTime.tv_sec; thermalStates[componentIdx.value()].heaterEndTime = currentTime.tv_sec;
} }
triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_OFF, static_cast<uint32_t>(currThermalComponent), triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_OFF, static_cast<uint32_t>(ctrlCtx.thermalComponent),
static_cast<uint32_t>(switchNr)); static_cast<uint32_t>(switchNr));
} }
} }
@ -1860,7 +1882,7 @@ void ThermalController::heaterSwitchHelperAllOff() {
Clock::getClockMonotonic(&currentTime); Clock::getClockMonotonic(&currentTime);
size_t idx = 0; size_t idx = 0;
for (; idx < heater::Switch::NUMBER_OF_SWITCHES; idx++) { for (; idx < heater::Switch::NUMBER_OF_SWITCHES; idx++) {
heaterHandler.switchHeater(static_cast<heater::Switch>(idx), HeaterHandler::SwitchState::OFF); heaterHandler.switchHeater(static_cast<heater::Switch>(idx), heater::SwitchState::OFF);
} }
for (idx = 0; idx < thermalStates.size(); idx++) { for (idx = 0; idx < thermalStates.size(); idx++) {
thermalStates[idx].heating = false; thermalStates[idx].heating = false;
@ -1888,7 +1910,7 @@ void ThermalController::crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(
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 ctrlCtx.componentAboveUpperLimit) {
oneShotFlag = false; oneShotFlag = false;
} }
} }

View File

@ -26,80 +26,6 @@
#include <list> #include <list>
#include <optional> #include <optional>
/**
* NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit
* is exceeded.
* OP Limit: Soft limit. Device should be switched off or TCS controller should take action if the
* limit is exceeded to avoid reaching NOP limit
*/
struct TempLimits {
TempLimits(float nopLowerLimit, float opLowerLimit, float cutOffLimit, float opUpperLimit,
float nopUpperLimit)
: opLowerLimit(opLowerLimit),
opUpperLimit(opUpperLimit),
cutOffLimit(cutOffLimit),
nopLowerLimit(nopLowerLimit),
nopUpperLimit(nopUpperLimit) {}
float opLowerLimit;
float opUpperLimit;
float cutOffLimit;
float nopLowerLimit;
float nopUpperLimit;
};
struct ThermalState {
uint8_t noSensorAvailableCounter;
// Which sensor is used for this component?
uint8_t sensorIndex = 0;
// Is heating on for that thermal module?
bool heating = false;
// Which switch is being used for heating the component
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 {
bool switchTransition = false;
HeaterHandler::SwitchState target = HeaterHandler::SwitchState::OFF;
uint8_t heaterSwitchControlCycles = 0;
bool trackHeaterMaxPeriod = false;
Countdown heaterOnPeriod;
};
using HeaterSwitchStates = std::array<HeaterHandler::SwitchState, heater::NUMBER_OF_SWITCHES>;
enum ThermalComponents : uint8_t {
NONE = 0,
ACS_BOARD = 1,
MGT = 2,
RW = 3,
STR = 4,
IF_BOARD = 5,
TCS_BOARD = 6,
OBC = 7,
// Not used anymore, was identical to OBC module.
LEGACY_OBCIF_BOARD = 8,
SBAND_TRANSCEIVER = 9,
PCDUP60_BOARD = 10,
PCDUACU = 11,
PCDUPDU = 12,
PLPCDU_BOARD = 13,
PLOCMISSION_BOARD = 14,
PLOCPROCESSING_BOARD = 15,
DAC = 16,
CAMERA = 17,
DRO = 18,
X8 = 19,
HPA = 20,
TX = 21,
MPA = 22,
SCEX_BOARD = 23,
NUM_ENTRIES
};
class ThermalController : public ExtendedControllerBase { class ThermalController : public ExtendedControllerBase {
public: public:
static constexpr uint8_t SUBMODE_NO_HEATER_CTRL = 1; static constexpr uint8_t SUBMODE_NO_HEATER_CTRL = 1;
@ -138,16 +64,16 @@ class ThermalController : public ExtendedControllerBase {
struct HeaterContext { struct HeaterContext {
public: public:
HeaterContext(heater::Switch switchNr, heater::Switch redundantSwitchNr, HeaterContext(heater::Switch switchNr, heater::Switch redundantSwitchNr,
const TempLimits& tempLimit) const tcsCtrl::TempLimits& tempLimit)
: switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {} : switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {}
bool doHeaterHandling = true; bool doHeaterHandling = true;
heater::Switch switchNr; heater::Switch switchNr;
HeaterHandler::SwitchState switchState = HeaterHandler::SwitchState::OFF; heater::SwitchState switchState = heater::SwitchState::OFF;
heater::Switch redSwitchNr; heater::Switch redSwitchNr;
const TempLimits& tempLimit; const tcsCtrl::TempLimits& tempLimit;
}; };
void performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates); void performThermalModuleCtrl(const tcsCtrl::HeaterSwitchStates& heaterSwitchStates);
ReturnValue_t handleCommandMessage(CommandMessage* message) override; ReturnValue_t handleCommandMessage(CommandMessage* message) override;
void performControlOperation() override; void performControlOperation() override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
@ -174,8 +100,7 @@ class ThermalController : public ExtendedControllerBase {
tcsCtrl::SusTemperatures susTemperatures; tcsCtrl::SusTemperatures susTemperatures;
tcsCtrl::DeviceTemperatures deviceTemperatures; tcsCtrl::DeviceTemperatures deviceTemperatures;
tcsCtrl::HeaterInfo heaterInfo; tcsCtrl::HeaterInfo heaterInfo;
lp_vec_t<int16_t, 9> currentVecPdu2 = tcsCtrl::TcsCtrlInfo tcsCtrlInfo;
lp_vec_t<int16_t, 9>(gp_id_t(objects::PDU2_HANDLER, PDU::pool::PDU_CURRENTS));
DeviceHandlerThermalSet imtqThermalSet; DeviceHandlerThermalSet imtqThermalSet;
@ -255,40 +180,48 @@ class ThermalController : public ExtendedControllerBase {
lp_var_t<float> tempMgm2 = lp_var_t<float> tempMgm2 =
lp_var_t<float>(objects::MGM_2_LIS3_HANDLER, mgmLis3::TEMPERATURE_CELCIUS); lp_var_t<float>(objects::MGM_2_LIS3_HANDLER, mgmLis3::TEMPERATURE_CELCIUS);
lp_var_t<float> tempAdcPayloadPcdu = lp_var_t<float>(objects::PLPCDU_HANDLER, plpcdu::TEMP); lp_var_t<float> tempAdcPayloadPcdu = lp_var_t<float>(objects::PLPCDU_HANDLER, plpcdu::TEMP);
lp_vec_t<int16_t, 9> currentVecPdu2 =
lp_vec_t<int16_t, 9>(gp_id_t(objects::PDU2_HANDLER, PDU::pool::PDU_CURRENTS));
// TempLimits // TempLimits
TempLimits acsBoardLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0); tcsCtrl::TempLimits acsBoardLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
TempLimits mgtLimits = TempLimits(-40.0, -40.0, 65.0, 70.0, 70.0); tcsCtrl::TempLimits mgtLimits = tcsCtrl::TempLimits(-40.0, -40.0, 65.0, 70.0, 70.0);
TempLimits rwLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0); tcsCtrl::TempLimits rwLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
TempLimits strLimits = TempLimits(-30.0, -20.0, 65.0, 70.0, 80.0); tcsCtrl::TempLimits strLimits = tcsCtrl::TempLimits(-30.0, -20.0, 65.0, 70.0, 80.0);
TempLimits ifBoardLimits = TempLimits(-65.0, -40.0, 80.0, 85.0, 150.0); tcsCtrl::TempLimits ifBoardLimits = tcsCtrl::TempLimits(-65.0, -40.0, 80.0, 85.0, 150.0);
TempLimits tcsBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 130.0); tcsCtrl::TempLimits tcsBoardLimits = tcsCtrl::TempLimits(-60.0, -40.0, 80.0, 85.0, 130.0);
TempLimits obcLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0); tcsCtrl::TempLimits obcLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
TempLimits obcIfBoardLimits = TempLimits(-65.0, -40.0, 80.0, 85.0, 125.0); tcsCtrl::TempLimits obcIfBoardLimits = tcsCtrl::TempLimits(-65.0, -40.0, 80.0, 85.0, 125.0);
TempLimits sBandTransceiverLimits = TempLimits(-40.0, -25.0, 35.0, 40.0, 65.0); tcsCtrl::TempLimits sBandTransceiverLimits = tcsCtrl::TempLimits(-40.0, -25.0, 35.0, 40.0, 65.0);
TempLimits pcduP60BoardLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0); tcsCtrl::TempLimits pcduP60BoardLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
TempLimits pcduAcuLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0); tcsCtrl::TempLimits pcduAcuLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
TempLimits pcduPduLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0); tcsCtrl::TempLimits pcduPduLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
TempLimits plPcduBoardLimits = TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0); tcsCtrl::TempLimits plPcduBoardLimits = tcsCtrl::TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0);
TempLimits plocMissionBoardLimits = TempLimits(-30.0, -10.0, 40.0, 45.0, 60); tcsCtrl::TempLimits plocMissionBoardLimits = tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60);
TempLimits plocProcessingBoardLimits = TempLimits(-30.0, -10.0, 40.0, 45.0, 60.0); tcsCtrl::TempLimits plocProcessingBoardLimits =
TempLimits dacLimits = TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0); tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60.0);
TempLimits cameraLimits = TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0); tcsCtrl::TempLimits dacLimits = tcsCtrl::TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0);
TempLimits droLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); tcsCtrl::TempLimits cameraLimits = tcsCtrl::TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0);
TempLimits x8Limits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); tcsCtrl::TempLimits droLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits hpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); tcsCtrl::TempLimits x8Limits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits txLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); tcsCtrl::TempLimits hpaLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits mpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); tcsCtrl::TempLimits txLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits scexBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0); tcsCtrl::TempLimits mpaLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits scexBoardLimits = tcsCtrl::TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0);
struct CtrlContext {
double sensorTemp = INVALID_TEMPERATURE; double sensorTemp = INVALID_TEMPERATURE;
uint8_t currentSensorIndex = 0; uint8_t currentSensorIndex = 0;
ThermalComponents currThermalComponent = NONE; tcsCtrl::ThermalComponents thermalComponent = tcsCtrl::NONE;
bool redSwitchNrInUse = false; bool redSwitchNrInUse = false;
MessageQueueId_t camId = MessageQueueIF::NO_QUEUE;
bool componentAboveCutOffLimit = false; bool componentAboveCutOffLimit = false;
bool componentAboveUpperLimit = false; bool componentAboveUpperLimit = false;
Event overHeatEventToTrigger; Event overHeatEventToTrigger;
} ctrlCtx;
MessageQueueId_t camId = MessageQueueIF::NO_QUEUE;
struct TooHotFlags {
bool eBandTooHotFlag = false; bool eBandTooHotFlag = false;
bool camTooHotOneShotFlag = false; bool camTooHotOneShotFlag = false;
bool scexTooHotFlag = false; bool scexTooHotFlag = false;
@ -299,14 +232,15 @@ class ThermalController : public ExtendedControllerBase {
bool mgtTooHotFlag = false; bool mgtTooHotFlag = false;
bool strTooHotFlag = false; bool strTooHotFlag = false;
bool rwTooHotFlag = false; bool rwTooHotFlag = false;
} tooHotFlags;
bool transitionWhenHeatersOff = false; bool transitionWhenHeatersOff = false;
uint32_t transitionWhenHeatersOffCycles = 0; uint32_t transitionWhenHeatersOffCycles = 0;
Mode_t targetMode = MODE_OFF; Mode_t targetMode = MODE_OFF;
Submode_t targetSubmode = SUBMODE_NONE; Submode_t targetSubmode = SUBMODE_NONE;
uint32_t cycles = 0; uint32_t cycles = 0;
std::array<ThermalState, ThermalComponents::NUM_ENTRIES> thermalStates{}; std::array<tcsCtrl::ThermalState, tcsCtrl::NUM_THERMAL_COMPONENTS> thermalStates{};
std::array<HeaterState, heater::NUMBER_OF_SWITCHES> heaterStates{}; std::array<tcsCtrl::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.
@ -327,6 +261,12 @@ class ThermalController : public ExtendedControllerBase {
PoolEntry<uint8_t> heaterSwitchStates = PoolEntry<uint8_t>(heater::NUMBER_OF_SWITCHES); PoolEntry<uint8_t> heaterSwitchStates = PoolEntry<uint8_t>(heater::NUMBER_OF_SWITCHES);
PoolEntry<int16_t> heaterCurrent = PoolEntry<int16_t>(); PoolEntry<int16_t> heaterCurrent = PoolEntry<int16_t>();
PoolEntry<uint8_t> tcsCtrlHeaterOn = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint8_t> tcsCtrlSensorIdx = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint8_t> tcsCtrlHeaterIdx = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint32_t> tcsCtrlStartTimes = PoolEntry<uint32_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint32_t> tcsCtrlEndTimes = PoolEntry<uint32_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
static constexpr dur_millis_t MUTEX_TIMEOUT = 50; static constexpr dur_millis_t MUTEX_TIMEOUT = 50;
void startTransition(Mode_t mode, Submode_t submode) override; void startTransition(Mode_t mode, Submode_t submode) override;
@ -348,7 +288,7 @@ class ThermalController : public ExtendedControllerBase {
bool selectAndReadSensorTemp(HeaterContext& htrCtx); bool selectAndReadSensorTemp(HeaterContext& htrCtx);
void heaterSwitchHelperAllOff(); void heaterSwitchHelperAllOff();
void heaterSwitchHelper(heater::Switch switchNr, HeaterHandler::SwitchState state, void heaterSwitchHelper(heater::Switch switchNr, heater::SwitchState state,
std::optional<unsigned> componentIdx); std::optional<unsigned> componentIdx);
void ctrlAcsBoard(); void ctrlAcsBoard();
@ -380,14 +320,14 @@ class ThermalController : public ExtendedControllerBase {
* of tracking transition and capturing their completion. * of tracking transition and capturing their completion.
* @param currentHeaterStates * @param currentHeaterStates
*/ */
void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates); void heaterTransitionControl(const tcsCtrl::HeaterSwitchStates& currentHeaterStates);
/** /**
* Control tasks to prevent heaters being on for prolonged periods. Ideally, this * Control tasks to prevent heaters being on for prolonged periods. Ideally, this
* should never happen, but this task prevents bugs from causing heaters to stay on * should never happen, but this task prevents bugs from causing heaters to stay on
* for a long time, which draws a lot of power. * for a long time, which draws a lot of power.
* @param currentHeaterStates * @param currentHeaterStates
*/ */
void heaterMaxDurationControl(const HeaterSwitchStates& currentHeaterStates); void heaterMaxDurationControl(const tcsCtrl::HeaterSwitchStates& currentHeaterStates);
void crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(heater::Switch switchIdx); void crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(heater::Switch switchIdx);
void setMode(Mode_t mode, Submode_t submode); void setMode(Mode_t mode, Submode_t submode);
uint32_t tempFloatToU32() const; uint32_t tempFloatToU32() const;

View File

@ -9,6 +9,85 @@
namespace tcsCtrl { namespace tcsCtrl {
/**
* NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit
* is exceeded.
* OP Limit: Soft limit. Device should be switched off or TCS controller should take action if the
* limit is exceeded to avoid reaching NOP limit
*/
struct TempLimits {
TempLimits(float nopLowerLimit, float opLowerLimit, float cutOffLimit, float opUpperLimit,
float nopUpperLimit)
: opLowerLimit(opLowerLimit),
opUpperLimit(opUpperLimit),
cutOffLimit(cutOffLimit),
nopLowerLimit(nopLowerLimit),
nopUpperLimit(nopUpperLimit) {}
float opLowerLimit;
float opUpperLimit;
float cutOffLimit;
float nopLowerLimit;
float nopUpperLimit;
};
/**
* Abstraction for the state of a single thermal component
*/
struct ThermalState {
uint8_t noSensorAvailableCounter;
// Which sensor is used for this component?
uint8_t sensorIndex = 0;
// Is heating on for that thermal module?
bool heating = false;
// Which switch is being used for heating the component
heater::Switch heaterSwitch = heater::Switch::HEATER_NONE;
// 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;
};
/**
* Abstraction for the state of a single heater.
*/
struct HeaterState {
bool switchTransition = false;
heater::SwitchState target = heater::SwitchState::OFF;
uint8_t heaterSwitchControlCycles = 0;
bool trackHeaterMaxBurnTime = false;
Countdown heaterOnMaxBurnTime;
};
using HeaterSwitchStates = std::array<heater::SwitchState, heater::NUMBER_OF_SWITCHES>;
enum ThermalComponents : uint8_t {
NONE = 0,
ACS_BOARD = 1,
MGT = 2,
RW = 3,
STR = 4,
IF_BOARD = 5,
TCS_BOARD = 6,
OBC = 7,
LEGACY_OBCIF_BOARD = 8,

didn't you change this naming to something different elsewhere

didn't you change this naming to something different elsewhere
SBAND_TRANSCEIVER = 9,
PCDUP60_BOARD = 10,
PCDUACU = 11,
PCDUPDU = 12,
PLPCDU_BOARD = 13,
PLOCMISSION_BOARD = 14,
PLOCPROCESSING_BOARD = 15,
DAC = 16,
CAMERA = 17,
DRO = 18,
X8 = 19,
HPA = 20,
TX = 21,
MPA = 22,
SCEX_BOARD = 23,
NUM_THERMAL_COMPONENTS
};
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_CONTROLLER; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_CONTROLLER;
static constexpr Event NO_VALID_SENSOR_TEMPERATURE = MAKE_EVENT(0, severity::MEDIUM); static constexpr Event NO_VALID_SENSOR_TEMPERATURE = MAKE_EVENT(0, severity::MEDIUM);
static constexpr Event NO_HEALTHY_HEATER_AVAILABLE = MAKE_EVENT(1, severity::MEDIUM); static constexpr Event NO_HEALTHY_HEATER_AVAILABLE = MAKE_EVENT(1, severity::MEDIUM);
@ -31,6 +110,7 @@ enum SetId : uint32_t {
SUS_TEMPERATURES = 2, SUS_TEMPERATURES = 2,
COMPONENT_TEMPERATURES = 3, COMPONENT_TEMPERATURES = 3,
HEATER_SET = 4, HEATER_SET = 4,
TCS_CTRL_INFO = 5
}; };
enum PoolIds : lp_id_t { enum PoolIds : lp_id_t {
@ -98,7 +178,13 @@ enum PoolIds : lp_id_t {
TEMP_ADC_PAYLOAD_PCDU, TEMP_ADC_PAYLOAD_PCDU,
HEATER_SWITCH_LIST, HEATER_SWITCH_LIST,
HEATER_CURRENT HEATER_CURRENT,
HEATER_ON_FOR_COMPONENT_VEC,
SENSOR_USED_FOR_TCS_CTRL,
HEATER_IDX_USED_FOR_TCS_CTRL,
HEATER_START_TIME,
HEATER_END_TIME
}; };
static const uint8_t ENTRIES_SENSOR_TEMPERATURE_SET = 25; static const uint8_t ENTRIES_SENSOR_TEMPERATURE_SET = 25;
@ -238,6 +324,29 @@ class HeaterInfo : public StaticLocalDataSet<3> {
lp_var_t<int16_t> heaterCurrent = lp_var_t<int16_t>(sid.objectId, PoolIds::HEATER_CURRENT, this); lp_var_t<int16_t> heaterCurrent = lp_var_t<int16_t>(sid.objectId, PoolIds::HEATER_CURRENT, this);
}; };
class TcsCtrlInfo : public StaticLocalDataSet<6> {
public:
explicit TcsCtrlInfo(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, TCS_CTRL_INFO) {}
explicit TcsCtrlInfo(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, TCS_CTRL_INFO)) {}
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heatingOnVec =
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(
sid.objectId, PoolIds::HEATER_ON_FOR_COMPONENT_VEC, this);
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> sensorIdxUsedForTcsCtrl =
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId,
PoolIds::SENSOR_USED_FOR_TCS_CTRL, this);
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterSwitchIdx =
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(
sid.objectId, PoolIds::HEATER_IDX_USED_FOR_TCS_CTRL, this);
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterStartTimes =
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_START_TIME,
this);
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterEndTimes =
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_END_TIME,
this);
};
} // namespace tcsCtrl } // namespace tcsCtrl
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_THERMALCONTROLLERDEFINITIONS_H_ */ #endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_THERMALCONTROLLERDEFINITIONS_H_ */

View File

@ -97,7 +97,7 @@ ReturnValue_t HeaterHandler::initialize() {
ReturnValue_t HeaterHandler::initializeHeaterMap() { ReturnValue_t HeaterHandler::initializeHeaterMap() {
for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) { for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) {
heaterVec.push_back(HeaterWrapper(helper.heaters[switchNr], SwitchState::OFF)); heaterVec.push_back(HeaterWrapper(helper.heaters[switchNr], heater::SwitchState::OFF));
} }
return returnvalue::OK; return returnvalue::OK;
} }
@ -214,7 +214,7 @@ ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t o
void HeaterHandler::handleSwitchHandling() { void HeaterHandler::handleSwitchHandling() {
for (uint8_t idx = 0; idx < heater::NUMBER_OF_SWITCHES; idx++) { for (uint8_t idx = 0; idx < heater::NUMBER_OF_SWITCHES; idx++) {
auto health = heaterVec[idx].healthDevice->getHealth(); auto health = heaterVec[idx].healthDevice->getHealth();
if (heaterVec[idx].switchState == SwitchState::ON) { if (heaterVec[idx].switchState == heater::SwitchState::ON) {
// If a heater is still on but the device was marked faulty by the operator, the SW // If a heater is still on but the device was marked faulty by the operator, the SW
// will shut down the heater // will shut down the heater
if (health == HasHealthIF::FAULTY or health == HasHealthIF::PERMANENT_FAULTY) { if (health == HasHealthIF::FAULTY or health == HasHealthIF::PERMANENT_FAULTY) {
@ -277,7 +277,7 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
triggerEvent(HEATER_WENT_ON, heaterIdx, 0); triggerEvent(HEATER_WENT_ON, heaterIdx, 0);
{ {
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
heater.switchState = ON; heater.switchState = heater::SwitchState::ON;
} }
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO, EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
MODE_ON, 0); MODE_ON, 0);
@ -326,10 +326,10 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
} }
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
// Check whether switch is already off // Check whether switch is already off
if (getSwitchState(heaterIdx) == SwitchState::ON) { if (getSwitchState(heaterIdx) == heater::SwitchState::ON) {
{ {
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
heater.switchState = OFF; heater.switchState = heater::SwitchState::OFF;
} }
triggerEvent(HEATER_WENT_OFF, heaterIdx, 0); triggerEvent(HEATER_WENT_OFF, heaterIdx, 0);
} else { } else {
@ -356,15 +356,15 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
heater.cmdActive = false; heater.cmdActive = false;
} }
HeaterHandler::SwitchState HeaterHandler::getSwitchState(heater::Switch switchNr) const { heater::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::Switch heater, SwitchState switchState) { ReturnValue_t HeaterHandler::switchHeater(heater::Switch heater, heater::SwitchState switchState) {
if (switchState == SwitchState::ON) { if (switchState == heater::SwitchState::ON) {
return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_ON); return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_ON);
} else if (switchState == SwitchState::OFF) { } else if (switchState == heater::SwitchState::OFF) {
return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_OFF); return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_OFF);
} }
return returnvalue::FAILED; return returnvalue::FAILED;
@ -373,10 +373,10 @@ ReturnValue_t HeaterHandler::switchHeater(heater::Switch heater, SwitchState swi
void HeaterHandler::announceMode(bool recursive) { void HeaterHandler::announceMode(bool recursive) {
triggerEvent(MODE_INFO, mode, submode); triggerEvent(MODE_INFO, mode, submode);
std::array<SwitchState, 8> states; std::array<heater::SwitchState, 8> states;
getAllSwitchStates(states); getAllSwitchStates(states);
for (unsigned idx = 0; idx < helper.heaters.size(); idx++) { for (unsigned idx = 0; idx < helper.heaters.size(); idx++) {
if (states[idx] == ON) { if (states[idx] == heater::SwitchState::ON) {
EventManagerIF::triggerEvent(helper.heaters[idx].first->getObjectId(), MODE_INFO, MODE_ON, 0); EventManagerIF::triggerEvent(helper.heaters[idx].first->getObjectId(), MODE_INFO, MODE_ON, 0);
} else { } else {
EventManagerIF::triggerEvent(helper.heaters[idx].first->getObjectId(), MODE_INFO, MODE_OFF, EventManagerIF::triggerEvent(helper.heaters[idx].first->getObjectId(), MODE_INFO, MODE_OFF,
@ -405,7 +405,7 @@ ModeTreeChildIF& HeaterHandler::getModeTreeChildIF() { return *this; }
object_id_t HeaterHandler::getObjectId() const { return SystemObject::getObjectId(); } object_id_t HeaterHandler::getObjectId() const { return SystemObject::getObjectId(); }
ReturnValue_t HeaterHandler::getAllSwitchStates(std::array<SwitchState, 8>& statesBuf) { ReturnValue_t HeaterHandler::getAllSwitchStates(std::array<heater::SwitchState, 8>& statesBuf) {
{ {
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
if (mg.getLockResult() != returnvalue::OK) { if (mg.getLockResult() != returnvalue::OK) {
@ -421,7 +421,7 @@ ReturnValue_t HeaterHandler::getAllSwitchStates(std::array<SwitchState, 8>& stat
bool HeaterHandler::allSwitchesOff() { bool HeaterHandler::allSwitchesOff() {
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) { for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) {
if (heaterVec.at(switchNr).switchState == SwitchState::ON) { if (heaterVec.at(switchNr).switchState == heater::SwitchState::ON) {
return false; return false;
} }
} }
@ -440,7 +440,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::Switch>(switchNr)) == SwitchState::ON) { if (getSwitchState(static_cast<heater::Switch>(switchNr)) == heater::SwitchState::ON) {
return PowerSwitchIF::SWITCH_ON; return PowerSwitchIF::SWITCH_ON;
} }
return PowerSwitchIF::SWITCH_OFF; return PowerSwitchIF::SWITCH_OFF;

View File

@ -60,7 +60,6 @@ class HeaterHandler : public ExecutableObjectIF,
static const ReturnValue_t COMMAND_ALREADY_WAITING = MAKE_RETURN_CODE(0xA5); static const ReturnValue_t COMMAND_ALREADY_WAITING = MAKE_RETURN_CODE(0xA5);
enum CmdSourceParam : uint8_t { INTERNAL = 0, EXTERNAL = 1 }; enum CmdSourceParam : uint8_t { INTERNAL = 0, EXTERNAL = 1 };
enum SwitchState : uint8_t { ON = 1, OFF = 0 };
/** Device command IDs */ /** Device command IDs */
static const DeviceCommandId_t SWITCH_HEATER = 0x0; static const DeviceCommandId_t SWITCH_HEATER = 0x0;
@ -69,14 +68,14 @@ class HeaterHandler : public ExecutableObjectIF,
PowerSwitchIF* mainLineSwitcherObjectId, power::Switch_t mainLineSwitch); PowerSwitchIF* mainLineSwitcherObjectId, power::Switch_t mainLineSwitch);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override; ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
ReturnValue_t getAllSwitchStates(std::array<SwitchState, 8>& statesBuf); ReturnValue_t getAllSwitchStates(std::array<heater::SwitchState, 8>& statesBuf);
virtual ~HeaterHandler(); virtual ~HeaterHandler();
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::Switch heater, SwitchState switchState); ReturnValue_t switchHeater(heater::Switch heater, heater::SwitchState switchState);
HasHealthIF::HealthState getHealth(heater::Switch heater); HasHealthIF::HealthState getHealth(heater::Switch heater);
ReturnValue_t performOperation(uint8_t operationCode = 0) override; ReturnValue_t performOperation(uint8_t operationCode = 0) override;
@ -121,14 +120,14 @@ class HeaterHandler : public ExecutableObjectIF,
* @param mainSwitchCountdown Sets timeout to wait for main switch being set on. * @param mainSwitchCountdown Sets timeout to wait for main switch being set on.
*/ */
struct HeaterWrapper { struct HeaterWrapper {
HeaterWrapper(HeaterPair pair, SwitchState initState) HeaterWrapper(HeaterPair pair, heater::SwitchState initState)
: healthDevice(pair.first), gpioId(pair.second), switchState(initState) {} : healthDevice(pair.first), gpioId(pair.second), switchState(initState) {}
HealthDevice* healthDevice = nullptr; HealthDevice* healthDevice = nullptr;
gpioId_t gpioId = gpio::NO_GPIO; gpioId_t gpioId = gpio::NO_GPIO;
SwitchAction action = SwitchAction::NONE; SwitchAction action = SwitchAction::NONE;
MessageQueueId_t replyQueue = MessageQueueIF::NO_QUEUE; MessageQueueId_t replyQueue = MessageQueueIF::NO_QUEUE;
bool cmdActive = false; bool cmdActive = false;
SwitchState switchState = SwitchState::OFF; heater::SwitchState switchState = heater::SwitchState::OFF;
bool waitMainSwitchOn = false; bool waitMainSwitchOn = false;
Countdown mainSwitchCountdown; Countdown mainSwitchCountdown;
}; };
@ -177,7 +176,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::Switch switchNr) const; heater::SwitchState getSwitchState(heater::Switch switchNr) const;
/** /**
* @brief This function runs commands waiting for execution. * @brief This function runs commands waiting for execution.

View File

@ -4,6 +4,7 @@
#include <cstdint> #include <cstdint>
namespace heater { namespace heater {
enum Switch : uint8_t { enum Switch : uint8_t {
HEATER_0_PLOC_PROC_BRD, HEATER_0_PLOC_PROC_BRD,
HEATER_1_PCDU_PDU, HEATER_1_PCDU_PDU,
@ -13,9 +14,13 @@ enum Switch : uint8_t {
HEATER_5_STR, HEATER_5_STR,
HEATER_6_DRO, HEATER_6_DRO,
HEATER_7_S_BAND, HEATER_7_S_BAND,
NUMBER_OF_SWITCHES NUMBER_OF_SWITCHES = 8,
HEATER_NONE = 0xff
}; };
}
enum SwitchState : uint8_t { ON = 1, OFF = 0 };
} // namespace heater
namespace tcs { namespace tcs {

2
tmtc

@ -1 +1 @@
Subproject commit 15d25b4c5b7ad21603a83a6c09835f5c97273b17 Subproject commit 9be81f1725004b55e937718fbaddc4f4e4e74081