diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 9c42be86..bbfa4c8a 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -971,7 +971,7 @@ void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enable new ImtqPollingTask(objects::IMTQ_POLLING, I2C_FATAL_ERRORS); I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, q7s::I2C_PL_EIVE); auto imtqHandler = new ImtqHandler(objects::IMTQ_HANDLER, objects::IMTQ_POLLING, imtqI2cCookie, - pcdu::Switches::PDU1_CH3_MGT_5V, enableHkSets); + power::Switches::PDU1_CH3_MGT_5V, enableHkSets); imtqHandler->enableThermalModule(ThermalStateCfg()); imtqHandler->setPowerSwitcher(pwrSwitcher); imtqHandler->connectModeTreeParent(*imtqAssy); diff --git a/fsfw b/fsfw index 314f0fa2..4f632e2c 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 314f0fa2cde749ee1021d311e222bb0044cc2e5b +Subproject commit 4f632e2c6866cee88dd9920a965aa0d079799aa3 diff --git a/mission/controller/ThermalController.cpp b/mission/controller/ThermalController.cpp index 38c32d3b..abf20bb8 100644 --- a/mission/controller/ThermalController.cpp +++ b/mission/controller/ThermalController.cpp @@ -18,7 +18,7 @@ // 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_EBAND_UPPER_LIMITS 1 #define LOWER_PLOC_UPPER_LIMITS 0 ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater) @@ -110,11 +110,21 @@ void ThermalController::performControlOperation() { } if (cycles == 50) { - sif::debug << "ThermalController: changing limits" << std::endl; + sif::debug << "ThermalController: changing limits" << std::endl; // TODO: rausschmeissen #if LOWER_SYRLINKS_UPPER_LIMITS == 1 sBandTransceiverLimits.cutOffLimit = 0; sBandTransceiverLimits.opUpperLimit = 0; sBandTransceiverLimits.nopUpperLimit = 0; +#endif +#if LOWER_PLOC_UPPER_LIMITS == 1 + plocMissionBoardLimits.cutOffLimit = 0; + plocMissionBoardLimits.opUpperLimit = 0; + plocMissionBoardLimits.nopUpperLimit = 0; +#endif +#if LOWER_EBAND_UPPER_LIMITS == 1 + hpaLimits.cutOffLimit = 0; + hpaLimits.opUpperLimit = 0; + hpaLimits.nopUpperLimit = 0; #endif } @@ -137,7 +147,7 @@ void ThermalController::performControlOperation() { } } - std::array heaterSwitchStateArray{}; + HeaterSwitchStates heaterSwitchStateArray{}; heaterHandler.getAllSwitchStates(heaterSwitchStateArray); { PoolReadGuard pg(&heaterInfo); @@ -153,12 +163,21 @@ void ThermalController::performControlOperation() { if (transitionToOff) { for (const auto& switchState : heaterSwitchStateArray) { if (switchState != HeaterHandler::SwitchState::OFF) { + transitionToOffCycles++; + // if heater still ON after 10 cycles, switch OFF again + if (transitionToOffCycles == 10) { + for (uint8_t i; i < heater::Switchers::NUMBER_OF_SWITCHES; i++) { + heaterHandler.switchHeater(static_cast(i), + HeaterHandler::SwitchState::OFF); + } + triggerEvent(tcsCtrl::HEATER_NOT_OFF_FOR_OFF_MODE); + } return; } setMode(MODE_OFF); } } else if (mode != MODE_OFF) { - performThermalModuleCtrl(); + performThermalModuleCtrl(heaterSwitchStateArray); } cycles++; } @@ -1005,6 +1024,7 @@ void ThermalController::ctrlMgt() { sensors[2].second = sensorTemperatures.plpcduHeatspreader.value; numSensors = 3; ctrlComponentTemperature(heater::HEATER_2_ACS_BRD, heater::HEATER_3_PCDU_PDU, mgtLimits); + // TODO: trigger special event } void ThermalController::ctrlRw() { @@ -1112,7 +1132,7 @@ void ThermalController::ctrlStr() { sensors[2].second = sensorTemperatures.dro.value; numSensors = 3; ctrlComponentTemperature(heater::HEATER_5_STR, heater::HEATER_6_DRO, strLimits); - tooHotHandler(objects::STAR_TRACKER, strTooHotFlag); + tooHotHandlerWhichClearsOneShotFlag(objects::STAR_TRACKER, strTooHotFlag); } void ThermalController::ctrlIfBoard() { @@ -1173,7 +1193,7 @@ void ThermalController::ctrlObcIfBoard() { triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32()); obcTooHotFlag = true; } else if (not componentAboveUpperLimit) { - obcTooHotFlag = false; + obcTooHotFlag = false; // TODO: !! } } @@ -1208,7 +1228,7 @@ void ThermalController::ctrlPcduP60Board() { pcduSystemTooHotFlag = true; } else if (not componentAboveUpperLimit) { pcduSystemTooHotFlag = false; - } + } // TODO: ! } void ThermalController::ctrlPcduAcu() { @@ -1417,10 +1437,10 @@ void ThermalController::ctrlScexBoard() { sensors[2].second = sensorTemperatures.hpa.value; numSensors = 3; ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_5_STR, scexBoardLimits); - tooHotHandler(objects::SCEX, scexTooHotFlag); + tooHotHandlerWhichClearsOneShotFlag(objects::SCEX, scexTooHotFlag); } -void ThermalController::performThermalModuleCtrl() { +void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates) { ctrlAcsBoard(); ctrlMgt(); ctrlRw(); @@ -1435,21 +1455,56 @@ void ThermalController::performThermalModuleCtrl() { ctrlPcduPdu(); // Payload components + std::array plocInAllowedRange{}; ctrlPlocMissionBoard(); + plocInAllowedRange.at(0) = not componentAboveUpperLimit; ctrlPlocProcessingBoard(); + plocInAllowedRange.at(1) = not componentAboveUpperLimit; + + if (plocTooHotFlag) { + bool clearFlag = true; + for (const auto& inRange : plocInAllowedRange) { + if (not inRange) { + clearFlag = false; + } + } + if (clearFlag) { + plocTooHotFlag = false; + } + } ctrlCameraBody(); ctrlScexBoard(); // E-Band + std::array eBandInAllowedRange{}; ctrlPlPcduBoard(); + eBandInAllowedRange.at(0) = not componentAboveUpperLimit; ctrlDac(); + eBandInAllowedRange.at(1) = not componentAboveUpperLimit; ctrlDro(); + eBandInAllowedRange.at(2) = not componentAboveUpperLimit; ctrlX8(); + eBandInAllowedRange.at(3) = not componentAboveUpperLimit; ctrlHpa(); + eBandInAllowedRange.at(4) = not componentAboveUpperLimit; ctrlTx(); + eBandInAllowedRange.at(5) = not componentAboveUpperLimit; ctrlMpa(); + eBandInAllowedRange.at(6) = not componentAboveUpperLimit; - heaterTransitionControl(); + if (eBandTooHotFlag) { + bool clearFlag = true; + for (const auto& inRange : eBandInAllowedRange) { + if (not inRange) { + clearFlag = false; + } + } + if (clearFlag) { + eBandTooHotFlag = false; + } + } + + heaterTransitionControl(heaterSwitchStates); } void ThermalController::ctrlComponentTemperature(heater::Switchers switchNr, heater::Switchers redSwitchNr, @@ -1506,39 +1561,32 @@ bool ThermalController::chooseHeater(heater::Switchers& switchNr, heater::Switch } return heaterAvailable; } + +void ThermalController::heaterCtrlTempTooHighHandler(heater::Switchers switchNr, + heater::Switchers redSwitchNr, + const char* whatLimit) { + sif::info << "TCS: Component " << static_cast(thermalComponent) << " too warm" << std::endl; + heaterHandler.switchHeater(switchNr, HeaterHandler::SwitchState::OFF); + heaterStates[switchNr].switchTransition = true; + heaterStates[switchNr].target = HeaterHandler::SwitchState::OFF; + if (heaterHandler.checkSwitchState(redSwitchNr) == HeaterHandler::SwitchState::ON) { + heaterHandler.switchHeater(redSwitchNr, HeaterHandler::SwitchState::OFF); + heaterStates[redSwitchNr].switchTransition = true; + heaterStates[redSwitchNr].target = HeaterHandler::SwitchState::OFF; + } +} + void ThermalController::checkLimitsAndCtrlHeater(heater::Switchers switchNr, heater::Switchers redSwitchNr, const TempLimits& tempLimit) { componentAboveCutOffLimit = false; componentAboveUpperLimit = false; - auto tempTooHighHandler = [&](const char* whatLimit, bool heaterIsOn) { - heaterHandler.switchHeater(switchNr, HeaterHandler::SwitchState::OFF); - sif::info << "ThermalController::checkLimitsAndCtrlHeater: Exceeded " << whatLimit - << ": " - "Heater for component " - << static_cast(thermalComponent) << std::endl; - heaterStates[switchNr].switchTransition = true; - if (heaterIsOn) { - heaterHandler.switchHeater(redSwitchNr, HeaterHandler::SwitchState::OFF); - heaterStates[redSwitchNr].switchTransition = true; - } - }; - auto checkUpperLimits = [&](bool heaterIsOn) { - if (sensorTemp >= tempLimit.nopUpperLimit) { - componentAboveUpperLimit = true; - tempTooHighHandler("NOP-Limit", heaterIsOn); - overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH; - return true; - } else if (sensorTemp >= tempLimit.opUpperLimit) { - componentAboveUpperLimit = true; - tempTooHighHandler("OP-Limit", heaterIsOn); - overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_HIGH; - return true; - } - return false; - }; - // Stay passive during switch transitions, wait for heater switching to complete. - if (not heaterStates[switchNr].switchTransition) { + // 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[switchNr].switchTransition) { + heaterCtrlCheckUpperLimits(switchNr, redSwitchNr, false, tempLimit); + } else { // Heater off if (not heaterHandler.checkSwitchState(switchNr)) { // TODO: check NOP limit and maybe trigger fdir @@ -1548,10 +1596,11 @@ void ThermalController::checkLimitsAndCtrlHeater(heater::Switchers switchNr, << static_cast(thermalComponent) << " ON" << std::endl; heaterStates[switchNr].switchTransition = true; thermalStates[thermalComponent].heating = true; + heaterStates[switchNr].target = HeaterHandler::SwitchState::ON; } else { thermalStates[thermalComponent].heating = false; } - checkUpperLimits(false); + heaterCtrlCheckUpperLimits(switchNr, redSwitchNr, true, tempLimit); // Heater on } else if (heaterHandler.checkSwitchState(switchNr)) { if (thermalStates[thermalComponent].heating) { @@ -1561,22 +1610,47 @@ void ThermalController::checkLimitsAndCtrlHeater(heater::Switchers switchNr, sif::info << "ThermalController::checkLimitsAndCtrlHeater: Heater " << static_cast(thermalComponent) << " OFF" << std::endl; heaterStates[switchNr].switchTransition = true; + heaterStates[switchNr].target = HeaterHandler::SwitchState::OFF; thermalStates[thermalComponent].heating = false; } } else { // This can happen if heater is used as alternative heater (no regular heating cycle), so we // should still check the upper limits. - bool tooHighHandlerAlreadyCalled = checkUpperLimits(true); + bool tooHighHandlerAlreadyCalled = + heaterCtrlCheckUpperLimits(switchNr, redSwitchNr, true, tempLimit); if (sensorTemp >= tempLimit.cutOffLimit) { componentAboveCutOffLimit = true; if (not tooHighHandlerAlreadyCalled) { - tempTooHighHandler("CutOff-Limit", true); + heaterCtrlTempTooHighHandler(switchNr, redSwitchNr, "CutOff-Limit"); } } } } } } + +bool ThermalController::heaterCtrlCheckUpperLimits(heater::Switchers switchNr, + heater::Switchers redSwitchNr, + bool doHeaterHandling, + const TempLimits& tempLimit) { + if (sensorTemp >= tempLimit.nopUpperLimit) { + componentAboveUpperLimit = true; + if (doHeaterHandling) { + heaterCtrlTempTooHighHandler(switchNr, redSwitchNr, "NOP-Limit"); + } + overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH; + return true; + } else if (sensorTemp >= tempLimit.opUpperLimit) { + componentAboveUpperLimit = true; + if (doHeaterHandling) { + heaterCtrlTempTooHighHandler(switchNr, redSwitchNr, "OP-Limit"); + } + overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_HIGH; + return true; + } + return false; +} + void ThermalController::resetSensorsArray() { for (auto& validValuePair : sensors) { validValuePair.first = false; @@ -1584,15 +1658,19 @@ void ThermalController::resetSensorsArray() { } thermalComponent = NONE; } -void ThermalController::heaterTransitionControl() { +void ThermalController::heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates) { // TODO: Test for (unsigned i = 0; i < 7; i++) { if (heaterStates[i].switchTransition) { - if (heaterStates[i].heaterSwitchControlErrorCounter > 3) { + if (currentHeaterStates[i] == heaterStates[i].target) { heaterStates[i].switchTransition = false; - heaterStates[i].heaterSwitchControlErrorCounter = 0; + continue; } - heaterStates[i].heaterSwitchControlErrorCounter++; + if (heaterStates[i].heaterSwitchControlCycles > 3) { + heaterStates[i].switchTransition = false; + heaterStates[i].heaterSwitchControlCycles = 0; + } + heaterStates[i].heaterSwitchControlCycles++; } } } @@ -1606,29 +1684,40 @@ uint32_t ThermalController::tempFloatToU32() const { } void ThermalController::setMode(Mode_t mode) { + if (mode == MODE_OFF) { + transitionToOff = false; + } this->mode = mode; modeHelper.modeChanged(mode, submode); - modeChanged(mode, submode); announceMode(false); } -void ThermalController::tooHotHandler(object_id_t object, bool& oneShotFlag) { +bool ThermalController::tooHotHandler(object_id_t object, bool& oneShotFlag) { if (componentAboveUpperLimit and not oneShotFlag) { + // Too hot -> returns true EventManagerIF::triggerEvent(object, overHeatEventToTrigger, tempFloatToU32()); oneShotFlag = true; - } else if (not componentAboveUpperLimit) { + return true; + } + return false; +} + +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 componentAboveUpperLimit) { oneShotFlag = false; } } void ThermalController::startTransition(Mode_t mode_, Submode_t submode_) { - triggerEvent(CHANGING_MODE, mode, submode); - if (mode == MODE_OFF) { + triggerEvent(CHANGING_MODE, mode_, submode_); + if (mode_ == MODE_OFF) { for (uint8_t i; i < heater::Switchers::NUMBER_OF_SWITCHES; i++) { heaterHandler.switchHeater(static_cast(i), HeaterHandler::SwitchState::OFF); } transitionToOff = true; + transitionToOffCycles = 0; } else { setMode(mode_); } diff --git a/mission/controller/ThermalController.h b/mission/controller/ThermalController.h index d2e1954d..37ed9d87 100644 --- a/mission/controller/ThermalController.h +++ b/mission/controller/ThermalController.h @@ -53,9 +53,12 @@ struct ThermalState { struct HeaterState { bool switchTransition; - uint8_t heaterSwitchControlErrorCounter; + HeaterHandler::SwitchState target; + uint8_t heaterSwitchControlCycles; }; +using HeaterSwitchStates = std::array; + enum ThermalComponents : uint8_t { NONE = 0, ACS_BOARD = 1, @@ -94,7 +97,7 @@ class ThermalController : public ExtendedControllerBase { ReturnValue_t initialize() override; protected: - void performThermalModuleCtrl(); + void performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates); ReturnValue_t handleCommandMessage(CommandMessage* message) override; void performControlOperation() override; ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, @@ -245,6 +248,7 @@ class ThermalController : public ExtendedControllerBase { bool rwTooHotFlag = false; bool transitionToOff = false; + uint32_t transitionToOffCycles = 0; uint32_t cycles = 0; std::array thermalStates{}; std::array heaterStates{}; @@ -281,6 +285,11 @@ class ThermalController : public ExtendedControllerBase { const TempLimits& tempLimit); void checkLimitsAndCtrlHeater(heater::Switchers switchNr, heater::Switchers redSwitchNr, const TempLimits& tempLimit); + bool heaterCtrlCheckUpperLimits(heater::Switchers switchNr, heater::Switchers redSwitchNr, + bool doHeaterHandling, const TempLimits& tempLimit); + void heaterCtrlTempTooHighHandler(heater::Switchers switchNr, heater::Switchers redSwitchNr, + const char* whatLimit); + bool chooseHeater(heater::Switchers& switchNr, heater::Switchers redSwitchNr); bool selectAndReadSensorTemp(); @@ -307,10 +316,11 @@ class ThermalController : public ExtendedControllerBase { void ctrlTx(); void ctrlMpa(); void ctrlScexBoard(); - void heaterTransitionControl(); + void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates); void setMode(Mode_t mode); uint32_t tempFloatToU32() const; - void tooHotHandler(object_id_t object, bool& oneShotFlag); + bool tooHotHandler(object_id_t object, bool& oneShotFlag); + void tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag); }; #endif /* MISSION_CONTROLLER_THERMALCONTROLLER_H_ */ diff --git a/mission/controller/tcsDefs.h b/mission/controller/tcsDefs.h index 321a9c71..e187091b 100644 --- a/mission/controller/tcsDefs.h +++ b/mission/controller/tcsDefs.h @@ -16,6 +16,7 @@ static constexpr Event SYRLINKS_OVERHEATING = MAKE_EVENT(2, severity::HIGH); static constexpr Event OBC_OVERHEATING = MAKE_EVENT(4, severity::HIGH); static constexpr Event CAMERA_OVERHEATING = MAKE_EVENT(5, severity::HIGH); static constexpr Event PCDU_SYSTEM_OVERHEATING = MAKE_EVENT(6, severity::HIGH); +static constexpr Event HEATER_NOT_OFF_FOR_OFF_MODE = MAKE_EVENT(7, severity::MEDIUM); enum SetId : uint32_t { SENSOR_TEMPERATURES = 0,