diff --git a/.idea/cmake.xml b/.idea/cmake.xml index e8d9d9dd..3be3a2b0 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -2,7 +2,6 @@ - diff --git a/CHANGELOG.md b/CHANGELOG.md index e45fcc01..918b6534 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -100,6 +100,7 @@ will consitute of a breaking change warranting a new major release: ## Added +- Version of thermal controller which performs basic control tasks. - The event `MEKF_RECOVERY` will be triggered in case the `MEKF` does manage to recover itself. - The persistent TM stores now have low priorities and behave like background threads now. This should prevent them from blocking or slowing down the system even during dumps @@ -111,6 +112,8 @@ will consitute of a breaking change warranting a new major release: ## Changed +- EIVE system fallback and COM system fallback: Perform general subsystem handling first, then + event reception, and finally any new transition handling. - Rework FSFW OSALs to properly support regular scheduling (NICE priorities) and real-time scheduling. - STR: Move datalink layer to `StrComHandler` completely. DLL is now completely hidden from @@ -134,6 +137,7 @@ will consitute of a breaking change warranting a new major release: - Bugfix for STR: Some action commands wrongfully declined. - STR: No normal command handling while a special request like an image upload is active. - RS485 data line was not enabled when the transmitter was switched on. +>>>>>>> origin/develop # [v1.39.0] 2023-03-21 diff --git a/CMakeLists.txt b/CMakeLists.txt index 29da10da..ed144b38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,7 @@ set(OBSW_ADD_TCS_CTRL 1 CACHE STRING "Add TCS controllers") set(OBSW_ADD_HEATERS - ${INIT_VAL} + 1 CACHE STRING "Add TCS heaters") set(OBSW_ADD_PLOC_SUPERVISOR ${INIT_VAL} diff --git a/bsp_hosted/ObjectFactory.cpp b/bsp_hosted/ObjectFactory.cpp index 77ea7828..3d618cdb 100644 --- a/bsp_hosted/ObjectFactory.cpp +++ b/bsp_hosted/ObjectFactory.cpp @@ -11,6 +11,7 @@ #include "../mission/utility/DummySdCardManager.h" #include "OBSWConfig.h" #include "fsfw/platform.h" +#include "fsfw/power/PowerSwitchIF.h" #include "fsfw_tests/integration/task/TestTask.h" #if OBSW_ADD_TMTC_UDP_SERVER == 1 @@ -67,6 +68,12 @@ void ObjectFactory::produce(void* args) { auto* dummyGpioIF = new DummyGpioIF(); auto* dummySwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0); + std::vector switcherList; + auto initVal = PowerSwitchIF::SWITCH_OFF; + for (unsigned i = 0; i < 18; i++) { + switcherList.emplace_back(initVal); + } + dummySwitcher->setInitialSwitcherList(switcherList); #ifdef PLATFORM_UNIX new SerialComIF(objects::UART_COM_IF); #if OBSW_ADD_PLOC_MPSOC == 1 diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index b8b4c675..a070245a 100644 --- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp +++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 284 translations. * @details - * Generated on: 2023-04-01 15:26:43 + * Generated on: 2023-04-01 16:00:01 */ #include "translateEvents.h" @@ -272,10 +272,10 @@ const char *I2C_UNAVAILABLE_REBOOT_STRING = "I2C_UNAVAILABLE_REBOOT"; const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE"; const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE"; const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING"; -const char *PLOC_OVERHEATING_STRING = "PLOC_OVERHEATING"; const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING"; -const char *HPA_OVERHEATING_STRING = "HPA_OVERHEATING"; -const char *PLPCDU_OVERHEATING_STRING = "PLPCDU_OVERHEATING"; +const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING"; +const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING"; +const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE"; const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED"; const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON"; const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION"; @@ -824,14 +824,14 @@ const char *translateEvents(Event event) { return NO_HEALTHY_HEATER_AVAILABLE_STRING; case (14102): return SYRLINKS_OVERHEATING_STRING; - case (14103): - return PLOC_OVERHEATING_STRING; case (14104): return OBC_OVERHEATING_STRING; case (14105): - return HPA_OVERHEATING_STRING; + return CAMERA_OVERHEATING_STRING; case (14106): - return PLPCDU_OVERHEATING_STRING; + return PCDU_SYSTEM_OVERHEATING_STRING; + case (14107): + return HEATER_NOT_OFF_FOR_OFF_MODE_STRING; case (14201): return TX_TIMER_EXPIRED_STRING; case (14202): diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index b3857629..4ceb3a4f 100644 --- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp +++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 171 translations. - * Generated on: 2023-04-01 15:26:43 + * Generated on: 2023-04-01 16:00:01 */ #include "translateObjects.h" diff --git a/bsp_hosted/scheduling.cpp b/bsp_hosted/scheduling.cpp index 350b706d..600a94e1 100644 --- a/bsp_hosted/scheduling.cpp +++ b/bsp_hosted/scheduling.cpp @@ -156,6 +156,10 @@ void scheduling::initTasks() { if (result != returnvalue::OK) { scheduling::printAddObjectError("THERMAL_CONTROLLER", objects::THERMAL_CONTROLLER); } + result = thermalTask->addComponent(objects::HEATER_HANDLER); + if (result != returnvalue::OK) { + scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER); + } FixedTimeslotTaskIF* pstTask = factory->createFixedTimeslotTask( "DUMMY_PST", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc); @@ -193,7 +197,8 @@ void scheduling::initTasks() { #endif /* OBSW_ADD_TEST_CODE == 1 */ PeriodicTaskIF* dummyTask = factory->createPeriodicTask( - "DUMMY_TASK", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc); + "DUMMY_TASK", 35, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc); + dummyTask->addComponent(objects::THERMAL_TEMP_INSERTER); scheduling::scheduleTmpTempSensors(dummyTask); scheduling::scheduleRtdSensors(dummyTask); dummyTask->addComponent(objects::SUS_0_N_LOC_XFYFZM_PT_XF); diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index c1b8ea4e..dea4a675 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -592,7 +592,7 @@ void ObjectFactory::createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitc } new SolarArrayDeploymentHandler(objects::SOLAR_ARRAY_DEPL_HANDLER, gpioIF, pwrSwitcher, - pcdu::Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V, + power::Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V, gpioIds::DEPLSA1, gpioIds::DEPLSA2, *SdCardManager::instance()); } @@ -608,7 +608,7 @@ void ObjectFactory::createSyrlinksComponents(PowerSwitchIF* pwrSwitcher) { auto syrlinksFdir = new SyrlinksFdir(objects::SYRLINKS_HANDLER); auto syrlinksHandler = new SyrlinksHandler(objects::SYRLINKS_HANDLER, objects::SYRLINKS_COM_HANDLER, - syrlinksUartCookie, pcdu::PDU1_CH1_SYRLINKS_12V, syrlinksFdir); + syrlinksUartCookie, power::PDU1_CH1_SYRLINKS_12V, syrlinksFdir); syrlinksHandler->setPowerSwitcher(pwrSwitcher); syrlinksHandler->connectModeTreeParent(*syrlinksAssy); #if OBSW_DEBUG_SYRLINKS == 1 @@ -620,7 +620,7 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit using namespace gpio; std::stringstream consumer; auto* camSwitcher = - new CamSwitcher(objects::CAM_SWITCHER, pwrSwitch, pcdu::PDU2_CH8_PAYLOAD_CAMERA); + new CamSwitcher(objects::CAM_SWITCHER, pwrSwitch, power::PDU2_CH8_PAYLOAD_CAMERA); camSwitcher->connectModeTreeParent(satsystem::payload::SUBSYSTEM); #if OBSW_ADD_PLOC_MPSOC == 1 consumer << "0x" << std::hex << objects::PLOC_MPSOC_HANDLER; @@ -653,7 +653,7 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit auto supvHelper = new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER); auto* supvHandler = new PlocSupervisorHandler(objects::PLOC_SUPERVISOR_HANDLER, supervisorCookie, Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF), - pcdu::PDU1_CH6_PLOC_12V, *supvHelper); + power::PDU1_CH6_PLOC_12V, *supvHelper); supvHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM); #endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */ static_cast(consumer); @@ -730,7 +730,7 @@ void ObjectFactory::createReactionWheelComponents(LinuxLibgpioIF* gpioComIF, rws[idx] = rwHandler; } - createRwAssy(*pwrSwitcher, pcdu::Switches::PDU2_CH2_RW_5V, rws, rwIds); + createRwAssy(*pwrSwitcher, power::Switches::PDU2_CH2_RW_5V, rws, rwIds); #endif /* OBSW_ADD_RW == 1 */ } @@ -968,7 +968,7 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) { auto strFdir = new StrFdir(objects::STAR_TRACKER); auto starTracker = new StarTrackerHandler(objects::STAR_TRACKER, objects::STR_COM_IF, starTrackerCookie, - paramJsonFile, strComIF, pcdu::PDU1_CH2_STAR_TRACKER_5V); + paramJsonFile, strComIF, power::PDU1_CH2_STAR_TRACKER_5V); starTracker->setPowerSwitcher(pwrSwitcher); starTracker->connectModeTreeParent(*strAssy); starTracker->setCustomFdir(strFdir); @@ -981,7 +981,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/bsp_q7s/em/emObjectFactory.cpp b/bsp_q7s/em/emObjectFactory.cpp index 1f873b99..ad520441 100644 --- a/bsp_q7s/em/emObjectFactory.cpp +++ b/bsp_q7s/em/emObjectFactory.cpp @@ -137,8 +137,8 @@ void ObjectFactory::produce(void* args) { pcdu::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V); #endif createAcsController(true, enableHkSets); - HeaterHandler* heaterHandler = nullptr; - ObjectFactory::createGenericHeaterComponents(*gpioComIF, *pwrSwitcher, heaterHandler); + HeaterHandler* heaterHandler; + createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler); createThermalController(*heaterHandler); satsystem::init(); } diff --git a/bsp_q7s/fmObjectFactory.cpp b/bsp_q7s/fmObjectFactory.cpp index a962e149..16528070 100644 --- a/bsp_q7s/fmObjectFactory.cpp +++ b/bsp_q7s/fmObjectFactory.cpp @@ -97,7 +97,7 @@ void ObjectFactory::produce(void* args) { #if OBSW_ADD_SCEX_DEVICE == 1 createScexComponents(q7s::UART_SCEX_DEV, pwrSwitcher, *SdCardManager::instance(), false, - pcdu::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V); + power::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V); #endif /* Test Task */ #if OBSW_ADD_TEST_CODE == 1 diff --git a/dummies/GyroAdisDummy.cpp b/dummies/GyroAdisDummy.cpp index 1caace7a..6f2e8e7f 100644 --- a/dummies/GyroAdisDummy.cpp +++ b/dummies/GyroAdisDummy.cpp @@ -46,7 +46,7 @@ ReturnValue_t GyroAdisDummy::initializeLocalDataPool(localpool::DataPool &localD localDataPoolMap.emplace(adis1650x::ACCELERATION_X, new PoolEntry({0.0})); localDataPoolMap.emplace(adis1650x::ACCELERATION_Y, new PoolEntry({0.0})); localDataPoolMap.emplace(adis1650x::ACCELERATION_Z, new PoolEntry({0.0})); - localDataPoolMap.emplace(adis1650x::TEMPERATURE, new PoolEntry({0.0})); + localDataPoolMap.emplace(adis1650x::TEMPERATURE, new PoolEntry({10.0}, true)); return returnvalue::OK; } diff --git a/dummies/Max31865Dummy.cpp b/dummies/Max31865Dummy.cpp index 43198bba..6ec1a716 100644 --- a/dummies/Max31865Dummy.cpp +++ b/dummies/Max31865Dummy.cpp @@ -1,5 +1,7 @@ #include "Max31865Dummy.h" +#include "fsfw/datapool/PoolReadGuard.h" + using namespace returnvalue; Max31865Dummy::Max31865Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie) @@ -28,15 +30,20 @@ ReturnValue_t Max31865Dummy::initializeLocalDataPool(localpool::DataPool &localD LocalDataPoolManager &poolManager) { using namespace MAX31865; localDataPoolMap.emplace(static_cast(PoolIds::RTD_VALUE), new PoolEntry({0})); - localDataPoolMap.emplace(static_cast(PoolIds::TEMPERATURE_C), new PoolEntry({0})); + localDataPoolMap.emplace(static_cast(PoolIds::TEMPERATURE_C), + new PoolEntry({10.0}, true)); localDataPoolMap.emplace(static_cast(PoolIds::LAST_FAULT_BYTE), new PoolEntry({0})); localDataPoolMap.emplace(static_cast(PoolIds::FAULT_BYTE), new PoolEntry({0})); return OK; } -void Max31865Dummy::setTemperature(float temperature) { - set.temperatureCelcius.value = temperature; +void Max31865Dummy::setTemperature(float temperature, bool valid) { + PoolReadGuard pg(&set); + if (pg.getReadResult() == returnvalue::OK) { + set.temperatureCelcius.value = temperature; + set.setValidity(valid, true); + } } LocalPoolDataSetBase *Max31865Dummy::getDataSetHandle(sid_t sid) { return &set; } diff --git a/dummies/Max31865Dummy.h b/dummies/Max31865Dummy.h index 87556166..56b13a4b 100644 --- a/dummies/Max31865Dummy.h +++ b/dummies/Max31865Dummy.h @@ -10,7 +10,7 @@ class Max31865Dummy : public DeviceHandlerBase { Max31865Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie); Max31865Dummy(object_id_t objectId, CookieIF *comCookie); - void setTemperature(float temperature); + void setTemperature(float temperature, bool setValid); private: MAX31865::PrimarySet set; diff --git a/dummies/MgmLIS3MDLDummy.cpp b/dummies/MgmLIS3MDLDummy.cpp index 0ce9a520..03b163fc 100644 --- a/dummies/MgmLIS3MDLDummy.cpp +++ b/dummies/MgmLIS3MDLDummy.cpp @@ -40,7 +40,7 @@ uint32_t MgmLIS3MDLDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { ReturnValue_t MgmLIS3MDLDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(mgmLis3::TEMPERATURE_CELCIUS, new PoolEntry({0.0})); + localDataPoolMap.emplace(mgmLis3::TEMPERATURE_CELCIUS, new PoolEntry({10.0}, true)); localDataPoolMap.emplace(mgmLis3::FIELD_STRENGTHS, new PoolEntry({1.02, 0.56, -0.78}, true)); return returnvalue::OK; diff --git a/dummies/P60DockDummy.cpp b/dummies/P60DockDummy.cpp index 17c48e8c..79ad8cae 100644 --- a/dummies/P60DockDummy.cpp +++ b/dummies/P60DockDummy.cpp @@ -2,6 +2,8 @@ #include +#include "fsfw/datapool/PoolReadGuard.h" + P60DockDummy::P60DockDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie) : DeviceHandlerBase(objectId, comif, comCookie) {} diff --git a/dummies/P60DockDummy.h b/dummies/P60DockDummy.h index 9b67b155..46e6303e 100644 --- a/dummies/P60DockDummy.h +++ b/dummies/P60DockDummy.h @@ -3,6 +3,8 @@ #include +#include "mission/power/gsDefs.h" + class P60DockDummy : public DeviceHandlerBase { public: static const DeviceCommandId_t SIMPLE_COMMAND = 1; @@ -15,6 +17,8 @@ class P60DockDummy : public DeviceHandlerBase { virtual ~P60DockDummy(); protected: + lp_var_t temp1 = lp_var_t(this, P60Dock::pool::P60DOCK_TEMPERATURE_1); + lp_var_t temp2 = lp_var_t(this, P60Dock::pool::P60DOCK_TEMPERATURE_2); void doStartUp() override; void doShutDown() override; ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override; diff --git a/dummies/PlocMpsocDummy.h b/dummies/PlocMpsocDummy.h index 7beaa76b..cc09e45e 100644 --- a/dummies/PlocMpsocDummy.h +++ b/dummies/PlocMpsocDummy.h @@ -2,6 +2,8 @@ #include +#include "mission/power/defs.h" + class PlocMpsocDummy : public DeviceHandlerBase { public: static const DeviceCommandId_t SIMPLE_COMMAND = 1; diff --git a/dummies/PlocSupervisorDummy.cpp b/dummies/PlocSupervisorDummy.cpp index c3eea5b0..b9b1948f 100644 --- a/dummies/PlocSupervisorDummy.cpp +++ b/dummies/PlocSupervisorDummy.cpp @@ -1,8 +1,10 @@ #include "PlocSupervisorDummy.h" PlocSupervisorDummy::PlocSupervisorDummy(object_id_t objectId, object_id_t comif, - CookieIF *comCookie) - : DeviceHandlerBase(objectId, comif, comCookie) {} + CookieIF *comCookie, PowerSwitchIF &pwrSwitcher) + : DeviceHandlerBase(objectId, comif, comCookie) { + setPowerSwitcher(&pwrSwitcher); +} PlocSupervisorDummy::~PlocSupervisorDummy() {} @@ -42,3 +44,10 @@ ReturnValue_t PlocSupervisorDummy::initializeLocalDataPool(localpool::DataPool & LocalDataPoolManager &poolManager) { return returnvalue::OK; } + +ReturnValue_t PlocSupervisorDummy::getSwitches(const uint8_t **switches, + uint8_t *numberOfSwitches) { + *numberOfSwitches = 1; + *switches = reinterpret_cast(&switchId); + return returnvalue::OK; +} diff --git a/dummies/PlocSupervisorDummy.h b/dummies/PlocSupervisorDummy.h index 4118c893..33951cb7 100644 --- a/dummies/PlocSupervisorDummy.h +++ b/dummies/PlocSupervisorDummy.h @@ -1,6 +1,7 @@ #pragma once #include +#include class PlocSupervisorDummy : public DeviceHandlerBase { public: @@ -10,10 +11,13 @@ class PlocSupervisorDummy : public DeviceHandlerBase { static const uint8_t SIMPLE_COMMAND_DATA = 1; static const uint8_t PERIODIC_REPLY_DATA = 2; - PlocSupervisorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie); + PlocSupervisorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie, + PowerSwitchIF &pwrSwitcher); virtual ~PlocSupervisorDummy(); protected: + const power::Switches switchId = power::Switches::PDU1_CH6_PLOC_12V; + void doStartUp() override; void doShutDown() override; ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override; @@ -27,4 +31,5 @@ class PlocSupervisorDummy : public DeviceHandlerBase { uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) override; + ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override; }; diff --git a/dummies/StarTrackerDummy.cpp b/dummies/StarTrackerDummy.cpp index 5ee53b8c..937b3422 100644 --- a/dummies/StarTrackerDummy.cpp +++ b/dummies/StarTrackerDummy.cpp @@ -40,7 +40,7 @@ uint32_t StarTrackerDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) ReturnValue_t StarTrackerDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(startracker::MCU_TEMPERATURE, new PoolEntry({0})); + localDataPoolMap.emplace(startracker::MCU_TEMPERATURE, new PoolEntry({10.0}, true)); localDataPoolMap.emplace(startracker::TICKS_SOLUTION_SET, new PoolEntry({0})); localDataPoolMap.emplace(startracker::TIME_SOLUTION_SET, new PoolEntry({0})); diff --git a/dummies/SyrlinksDummy.cpp b/dummies/SyrlinksDummy.cpp index 343fc85d..9ae3c2f0 100644 --- a/dummies/SyrlinksDummy.cpp +++ b/dummies/SyrlinksDummy.cpp @@ -40,7 +40,7 @@ uint32_t SyrlinksDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { r ReturnValue_t SyrlinksDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(syrlinks::TEMP_BASEBAND_BOARD, new PoolEntry({0})); - localDataPoolMap.emplace(syrlinks::TEMP_POWER_AMPLIFIER, new PoolEntry({0})); + localDataPoolMap.emplace(syrlinks::TEMP_BASEBAND_BOARD, new PoolEntry({10}, true)); + localDataPoolMap.emplace(syrlinks::TEMP_POWER_AMPLIFIER, new PoolEntry({10}, true)); return returnvalue::OK; } diff --git a/dummies/TemperatureSensorInserter.cpp b/dummies/TemperatureSensorInserter.cpp index c75b008c..3d268953 100644 --- a/dummies/TemperatureSensorInserter.cpp +++ b/dummies/TemperatureSensorInserter.cpp @@ -9,7 +9,7 @@ TemperatureSensorInserter::TemperatureSensorInserter(object_id_t objectId, Max31865DummyMap tempSensorDummies_, Tmp1075DummyMap tempTmpSensorDummies_) - : SystemObject(objects::THERMAL_TEMP_INSERTER), + : SystemObject(objectId), max31865DummyMap(std::move(tempSensorDummies_)), tmp1075DummyMap(std::move(tempTmpSensorDummies_)) {} @@ -22,6 +22,32 @@ ReturnValue_t TemperatureSensorInserter::initialize() { } ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) { + // TODO: deviceSensors + if (not tempsWereInitialized) { + for (auto& rtdDummy : max31865DummyMap) { + rtdDummy.second->setTemperature(10, true); + } + for (auto& tmpDummy : tmp1075DummyMap) { + tmpDummy.second->setTemperature(10, true); + } + tempsWereInitialized = true; + } + + if (cycles == 10) { + max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-100, true); + max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(-100, true); + } + + if (cycles == 35) { + max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(0, true); + max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(0, true); + max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-100, true); + } + if (cycles == 60) { + max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-100, true); + max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(0, true); + } + /* ReturnValue_t result = max31865PlocHeatspreaderSet.read(); if (result != returnvalue::OK) { @@ -36,5 +62,7 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) { } max31865PlocHeatspreaderSet.commit(); */ + cycles++; return returnvalue::OK; } +ReturnValue_t TemperatureSensorInserter::initializeAfterTaskCreation() { return returnvalue::OK; } diff --git a/dummies/TemperatureSensorInserter.h b/dummies/TemperatureSensorInserter.h index 5ad3c2e8..0c05cf34 100644 --- a/dummies/TemperatureSensorInserter.h +++ b/dummies/TemperatureSensorInserter.h @@ -14,6 +14,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject Tmp1075DummyMap tempTmpSensorDummies_); ReturnValue_t initialize() override; + ReturnValue_t initializeAfterTaskCreation() override; protected: ReturnValue_t performOperation(uint8_t opCode) override; @@ -23,6 +24,8 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject Tmp1075DummyMap tmp1075DummyMap; enum TestCase { NONE = 0, COOL_SYRLINKS = 1 }; int iteration = 0; + uint32_t cycles = 0; + bool tempsWereInitialized = false; bool performTest = false; TestCase testCase = TestCase::NONE; diff --git a/dummies/Tmp1075Dummy.cpp b/dummies/Tmp1075Dummy.cpp index ed9b9285..91a50774 100644 --- a/dummies/Tmp1075Dummy.cpp +++ b/dummies/Tmp1075Dummy.cpp @@ -1,5 +1,6 @@ #include "Tmp1075Dummy.h" +#include #include using namespace returnvalue; @@ -26,11 +27,16 @@ ReturnValue_t Tmp1075Dummy::scanForReply(const uint8_t *start, size_t len, ReturnValue_t Tmp1075Dummy::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { return 0; } +void Tmp1075Dummy::setTemperature(float temperature, bool valid) { + PoolReadGuard pg(&set); + set.temperatureCelcius.value = temperature; + set.setValidity(valid, true); +} void Tmp1075Dummy::fillCommandAndReplyMap() {} uint32_t Tmp1075Dummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 1000; } ReturnValue_t Tmp1075Dummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075, new PoolEntry({0.0})); + localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075, new PoolEntry({10.0}, true)); return OK; } LocalPoolDataSetBase *Tmp1075Dummy::getDataSetHandle(sid_t sid) { return &set; } diff --git a/dummies/Tmp1075Dummy.h b/dummies/Tmp1075Dummy.h index 7f84d198..570fcd42 100644 --- a/dummies/Tmp1075Dummy.h +++ b/dummies/Tmp1075Dummy.h @@ -8,6 +8,7 @@ class Tmp1075Dummy : public DeviceHandlerBase { public: Tmp1075Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie); + void setTemperature(float temperature, bool setValid); private: TMP1075::Tmp1075Dataset set; diff --git a/dummies/helperFactory.cpp b/dummies/helperFactory.cpp index c0390a5e..703683f4 100644 --- a/dummies/helperFactory.cpp +++ b/dummies/helperFactory.cpp @@ -57,7 +57,7 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio rws[1] = new RwDummy(objects::RW2, objects::DUMMY_COM_IF, comCookieDummy); rws[2] = new RwDummy(objects::RW3, objects::DUMMY_COM_IF, comCookieDummy); rws[3] = new RwDummy(objects::RW4, objects::DUMMY_COM_IF, comCookieDummy); - ObjectFactory::createRwAssy(pwrSwitcher, pcdu::Switches::PDU2_CH2_RW_5V, rws, rwIds); + ObjectFactory::createRwAssy(pwrSwitcher, power::Switches::PDU2_CH2_RW_5V, rws, rwIds); new SaDeplDummy(objects::SOLAR_ARRAY_DEPL_HANDLER); auto* strAssy = new StrAssembly(objects::STR_ASSY); strAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM); @@ -213,7 +213,7 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio } } auto* camSwitcher = - new CamSwitcher(objects::CAM_SWITCHER, pwrSwitcher, pcdu::Switches::PDU2_CH8_PAYLOAD_CAMERA); + new CamSwitcher(objects::CAM_SWITCHER, pwrSwitcher, power::Switches::PDU2_CH8_PAYLOAD_CAMERA); camSwitcher->connectModeTreeParent(satsystem::payload::SUBSYSTEM); auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy); scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM); @@ -224,8 +224,8 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio auto* plocMpsocDummy = new PlocMpsocDummy(objects::PLOC_MPSOC_HANDLER, objects::DUMMY_COM_IF, comCookieDummy); plocMpsocDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM); - auto* plocSupervisorDummy = new PlocSupervisorDummy(objects::PLOC_SUPERVISOR_HANDLER, - objects::DUMMY_COM_IF, comCookieDummy); + auto* plocSupervisorDummy = new PlocSupervisorDummy( + objects::PLOC_SUPERVISOR_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, pwrSwitcher); plocSupervisorDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM); } } diff --git a/fsfw b/fsfw index 4f632e2c..e2e87b14 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 4f632e2c6866cee88dd9920a965aa0d079799aa3 +Subproject commit e2e87b149d91c51196c76d6b84243fce1c77a28a diff --git a/generators/bsp_hosted_events.csv b/generators/bsp_hosted_events.csv index 7184d8ce..d7265738 100644 --- a/generators/bsp_hosted_events.csv +++ b/generators/bsp_hosted_events.csv @@ -261,13 +261,13 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;bsp_q7s/core/CoreController.h 14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;bsp_q7s/core/CoreController.h 14010;0x36ba;I2C_UNAVAILABLE_REBOOT;MEDIUM;No description;bsp_q7s/core/CoreController.h -14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h -14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h -14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h -14103;0x3717;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h -14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h -14105;0x3719;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h -14106;0x371a;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h +14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h +14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h +14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h +14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h +14105;0x3719;CAMERA_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h +14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h +14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h 14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h 14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h 14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 7184d8ce..d7265738 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -261,13 +261,13 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;bsp_q7s/core/CoreController.h 14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;bsp_q7s/core/CoreController.h 14010;0x36ba;I2C_UNAVAILABLE_REBOOT;MEDIUM;No description;bsp_q7s/core/CoreController.h -14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h -14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h -14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h -14103;0x3717;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h -14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h -14105;0x3719;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h -14106;0x371a;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h +14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h +14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h +14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h +14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h +14105;0x3719;CAMERA_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h +14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h +14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h 14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h 14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h 14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index b42ee2b7..3e1dd369 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 284 translations. * @details - * Generated on: 2023-04-01 15:26:43 + * Generated on: 2023-04-01 16:00:01 */ #include "translateEvents.h" @@ -270,10 +270,10 @@ const char *I2C_UNAVAILABLE_REBOOT_STRING = "I2C_UNAVAILABLE_REBOOT"; const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE"; const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE"; const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING"; -const char *PLOC_OVERHEATING_STRING = "PLOC_OVERHEATING"; const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING"; -const char *HPA_OVERHEATING_STRING = "HPA_OVERHEATING"; -const char *PLPCDU_OVERHEATING_STRING = "PLPCDU_OVERHEATING"; +const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING"; +const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING"; +const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE"; const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED"; const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON"; const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION"; @@ -822,14 +822,14 @@ const char *translateEvents(Event event) { return NO_HEALTHY_HEATER_AVAILABLE_STRING; case (14102): return SYRLINKS_OVERHEATING_STRING; - case (14103): - return PLOC_OVERHEATING_STRING; case (14104): return OBC_OVERHEATING_STRING; case (14105): - return HPA_OVERHEATING_STRING; + return CAMERA_OVERHEATING_STRING; case (14106): - return PLPCDU_OVERHEATING_STRING; + return PCDU_SYSTEM_OVERHEATING_STRING; + case (14107): + return HEATER_NOT_OFF_FOR_OFF_MODE_STRING; case (14201): return TX_TIMER_EXPIRED_STRING; case (14202): diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 5a33acf3..9697c7ef 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 175 translations. - * Generated on: 2023-04-01 15:26:43 + * Generated on: 2023-04-01 16:00:01 */ #include "translateObjects.h" diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index b8b4c675..a070245a 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 284 translations. * @details - * Generated on: 2023-04-01 15:26:43 + * Generated on: 2023-04-01 16:00:01 */ #include "translateEvents.h" @@ -272,10 +272,10 @@ const char *I2C_UNAVAILABLE_REBOOT_STRING = "I2C_UNAVAILABLE_REBOOT"; const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE"; const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE"; const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING"; -const char *PLOC_OVERHEATING_STRING = "PLOC_OVERHEATING"; const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING"; -const char *HPA_OVERHEATING_STRING = "HPA_OVERHEATING"; -const char *PLPCDU_OVERHEATING_STRING = "PLPCDU_OVERHEATING"; +const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING"; +const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING"; +const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE"; const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED"; const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON"; const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION"; @@ -824,14 +824,14 @@ const char *translateEvents(Event event) { return NO_HEALTHY_HEATER_AVAILABLE_STRING; case (14102): return SYRLINKS_OVERHEATING_STRING; - case (14103): - return PLOC_OVERHEATING_STRING; case (14104): return OBC_OVERHEATING_STRING; case (14105): - return HPA_OVERHEATING_STRING; + return CAMERA_OVERHEATING_STRING; case (14106): - return PLPCDU_OVERHEATING_STRING; + return PCDU_SYSTEM_OVERHEATING_STRING; + case (14107): + return HEATER_NOT_OFF_FOR_OFF_MODE_STRING; case (14201): return TX_TIMER_EXPIRED_STRING; case (14202): diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 5a33acf3..9697c7ef 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 175 translations. - * Generated on: 2023-04-01 15:26:43 + * Generated on: 2023-04-01 16:00:01 */ #include "translateObjects.h" diff --git a/mission/SolarArrayDeploymentHandler.cpp b/mission/SolarArrayDeploymentHandler.cpp index 05128d24..b8ec4d77 100644 --- a/mission/SolarArrayDeploymentHandler.cpp +++ b/mission/SolarArrayDeploymentHandler.cpp @@ -17,7 +17,7 @@ static constexpr bool DEBUG_MODE = true; SolarArrayDeploymentHandler::SolarArrayDeploymentHandler(object_id_t setObjectId_, GpioIF& gpioInterface, PowerSwitchIF& mainLineSwitcher_, - pcdu::Switches mainLineSwitch_, + power::Switches mainLineSwitch_, gpioId_t deplSA1, gpioId_t deplSA2, SdCardMountedIF& sdcMountedIF) : SystemObject(setObjectId_), diff --git a/mission/SolarArrayDeploymentHandler.h b/mission/SolarArrayDeploymentHandler.h index 3c15c77e..6be3affa 100644 --- a/mission/SolarArrayDeploymentHandler.h +++ b/mission/SolarArrayDeploymentHandler.h @@ -107,7 +107,7 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF, * @param burnTimeMs Time duration the power will be applied to the burn wires. */ SolarArrayDeploymentHandler(object_id_t setObjectId, GpioIF& gpio, - PowerSwitchIF& mainLineSwitcher, pcdu::Switches mainLineSwitch, + PowerSwitchIF& mainLineSwitcher, power::Switches mainLineSwitch, gpioId_t deplSA1, gpioId_t deplSA2, SdCardMountedIF& sdcMountedIF); virtual ~SolarArrayDeploymentHandler(); diff --git a/mission/controller/ThermalController.cpp b/mission/controller/ThermalController.cpp index 26a26eee..9ab16cf2 100644 --- a/mission/controller/ThermalController.cpp +++ b/mission/controller/ThermalController.cpp @@ -1,6 +1,7 @@ #include "ThermalController.h" #include +#include #include #include #include @@ -15,6 +16,11 @@ #include #include +// 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 1 +#define LOWER_PLOC_UPPER_LIMITS 0 + ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater) : ExtendedControllerBase(objectId), heaterHandler(heater), @@ -23,25 +29,26 @@ ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater deviceTemperatures(this), heaterInfo(this), imtqThermalSet(objects::IMTQ_HANDLER, ThermalStateCfg()), - max31865Set0(objects::RTD_0_IC3_PLOC_HEATSPREADER, - EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set1(objects::RTD_1_IC4_PLOC_MISSIONBOARD, - EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set2(objects::RTD_2_IC5_4K_CAMERA, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set3(objects::RTD_3_IC6_DAC_HEATSPREADER, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set4(objects::RTD_4_IC7_STARTRACKER, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set5(objects::RTD_5_IC8_RW1_MX_MY, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set6(objects::RTD_6_IC9_DRO, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set7(objects::RTD_7_IC10_SCEX, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set8(objects::RTD_8_IC11_X8, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set9(objects::RTD_9_IC12_HPA, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set10(objects::RTD_10_IC13_PL_TX, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set11(objects::RTD_11_IC14_MPA, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set12(objects::RTD_12_IC15_ACU, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set13(objects::RTD_13_IC16_PLPCDU_HEATSPREADER, - EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set14(objects::RTD_14_IC17_TCS_BOARD, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), - max31865Set15(objects::RTD_15_IC18_IMTQ, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet0PlocHspd(objects::RTD_0_IC3_PLOC_HEATSPREADER, + EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet1PlocMissionBrd(objects::RTD_1_IC4_PLOC_MISSIONBOARD, + EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet2PlCam(objects::RTD_2_IC5_4K_CAMERA, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet3DacHspd(objects::RTD_3_IC6_DAC_HEATSPREADER, + EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet4Str(objects::RTD_4_IC7_STARTRACKER, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet5Rw1MxMy(objects::RTD_5_IC8_RW1_MX_MY, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet6Dro(objects::RTD_6_IC9_DRO, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet7Scex(objects::RTD_7_IC10_SCEX, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet8X8(objects::RTD_8_IC11_X8, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet9Hpa(objects::RTD_9_IC12_HPA, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet10EbandTx(objects::RTD_10_IC13_PL_TX, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet11Mpa(objects::RTD_11_IC14_MPA, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet31865Set12(objects::RTD_12_IC15_ACU, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet13PlPcduHspd(objects::RTD_13_IC16_PLPCDU_HEATSPREADER, + EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet14TcsBrd(objects::RTD_14_IC17_TCS_BOARD, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), + maxSet15Imtq(objects::RTD_15_IC18_IMTQ, EiveMax31855::RtdCommands::EXCHANGE_SET_ID), tmp1075SetTcs0(objects::TMP1075_HANDLER_TCS_0), tmp1075SetTcs1(objects::TMP1075_HANDLER_TCS_1), tmp1075SetPlPcdu0(objects::TMP1075_HANDLER_PLPCDU_0), @@ -64,8 +71,12 @@ ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater } ReturnValue_t ThermalController::initialize() { - auto result = ExtendedControllerBase::initialize(); - return result; + auto* camSwitcher = ObjectManager::instance()->get(objects::CAM_SWITCHER); + if (camSwitcher == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + camId = camSwitcher->getCommandQueue(); + return ExtendedControllerBase::initialize(); } ReturnValue_t ThermalController::handleCommandMessage(CommandMessage* message) { @@ -76,6 +87,7 @@ void ThermalController::performControlOperation() { #if OBSW_THREAD_TRACING == 1 trace::threadTrace(opCounter, "TCS Task"); #endif + switch (internalState) { case InternalState::STARTUP: { initialCountdown.resetTimer(); @@ -84,7 +96,9 @@ void ThermalController::performControlOperation() { } case InternalState::INITIAL_DELAY: { if (initialCountdown.hasTimedOut()) { + sif::info << "Starting thermal control operations" << std::endl; internalState = InternalState::READY; + break; } return; } @@ -95,26 +109,46 @@ void ThermalController::performControlOperation() { break; } - ReturnValue_t result = sensorTemperatures.read(); - if (result == returnvalue::OK) { - copySensors(); - sensorTemperatures.commit(); + if (cycles == 50) { + 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 } - result = susTemperatures.read(); - if (result == returnvalue::OK) { - copySus(); - susTemperatures.commit(); + { + PoolReadGuard pg(&sensorTemperatures); + if (pg.getReadResult() == returnvalue::OK) { + copySensors(); + } + } + { + PoolReadGuard pg(&susTemperatures); + if (pg.getReadResult() == returnvalue::OK) { + copySus(); + } + } + { + PoolReadGuard pg(&deviceTemperatures); + if (pg.getReadResult() == returnvalue::OK) { + copyDevices(); + } } - result = deviceTemperatures.read(); - if (result == returnvalue::OK) { - copyDevices(); - deviceTemperatures.commit(); - } - - std::array heaterStates; - heaterHandler.getAllSwitchStates(heaterStates); + HeaterSwitchStates heaterSwitchStateArray{}; + heaterHandler.getAllSwitchStates(heaterSwitchStateArray); { PoolReadGuard pg(&heaterInfo); std::memcpy(heaterInfo.heaterSwitchState.value, heaterStates.data(), 8); @@ -126,7 +160,26 @@ void ThermalController::performControlOperation() { } } - // performThermalModuleCtrl(); + 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(heaterSwitchStateArray); + } + cycles++; } ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, @@ -240,181 +293,179 @@ ReturnValue_t ThermalController::checkModeCommand(Mode_t mode, Submode_t submode void ThermalController::copySensors() { { - PoolReadGuard pg0(&max31865Set0, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg0(&maxSet0PlocHspd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg0.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_ploc_heatspreader.value = max31865Set0.temperatureCelcius.value; - sensorTemperatures.sensor_ploc_heatspreader.setValid( - max31865Set0.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_ploc_heatspreader.isValid()) { - sensorTemperatures.sensor_ploc_heatspreader.value = INVALID_TEMPERATURE; + sensorTemperatures.plocHeatspreader.value = maxSet0PlocHspd.temperatureCelcius.value; + sensorTemperatures.plocHeatspreader.setValid(maxSet0PlocHspd.temperatureCelcius.isValid()); + if (not sensorTemperatures.plocHeatspreader.isValid()) { + sensorTemperatures.plocHeatspreader.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg1(&max31865Set1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg1(&maxSet1PlocMissionBrd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg1.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_ploc_missionboard.value = max31865Set1.temperatureCelcius.value; - sensorTemperatures.sensor_ploc_missionboard.setValid( - max31865Set1.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_ploc_missionboard.isValid()) { - sensorTemperatures.sensor_ploc_missionboard.value = INVALID_TEMPERATURE; + sensorTemperatures.plocMissionboard.value = maxSet1PlocMissionBrd.temperatureCelcius.value; + sensorTemperatures.plocMissionboard.setValid( + maxSet1PlocMissionBrd.temperatureCelcius.isValid()); + if (not sensorTemperatures.plocMissionboard.isValid()) { + sensorTemperatures.plocMissionboard.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg2(&max31865Set2, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg2(&maxSet2PlCam, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg2.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_4k_camera.value = max31865Set2.temperatureCelcius.value; - sensorTemperatures.sensor_4k_camera.setValid(max31865Set2.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_4k_camera.isValid()) { - sensorTemperatures.sensor_4k_camera.value = INVALID_TEMPERATURE; + sensorTemperatures.payload4kCamera.value = maxSet2PlCam.temperatureCelcius.value; + sensorTemperatures.payload4kCamera.setValid(maxSet2PlCam.temperatureCelcius.isValid()); + if (not sensorTemperatures.payload4kCamera.isValid()) { + sensorTemperatures.payload4kCamera.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg3(&max31865Set3, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg3(&maxSet3DacHspd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg3.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_dac_heatspreader.value = max31865Set3.temperatureCelcius.value; - sensorTemperatures.sensor_dac_heatspreader.setValid( - max31865Set3.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_dac_heatspreader.isValid()) { - sensorTemperatures.sensor_dac_heatspreader.value = INVALID_TEMPERATURE; + sensorTemperatures.dacHeatspreader.value = maxSet3DacHspd.temperatureCelcius.value; + sensorTemperatures.dacHeatspreader.setValid(maxSet3DacHspd.temperatureCelcius.isValid()); + if (not sensorTemperatures.dacHeatspreader.isValid()) { + sensorTemperatures.dacHeatspreader.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg4(&max31865Set4, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg4(&maxSet4Str, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg4.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_startracker.value = max31865Set4.temperatureCelcius.value; - sensorTemperatures.sensor_startracker.setValid(max31865Set4.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_startracker.isValid()) { - sensorTemperatures.sensor_startracker.value = INVALID_TEMPERATURE; + sensorTemperatures.startracker.value = maxSet4Str.temperatureCelcius.value; + sensorTemperatures.startracker.setValid(maxSet4Str.temperatureCelcius.isValid()); + if (not sensorTemperatures.startracker.isValid()) { + sensorTemperatures.startracker.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg5(&max31865Set5, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg5(&maxSet5Rw1MxMy, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg5.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_rw1.value = max31865Set5.temperatureCelcius.value; - sensorTemperatures.sensor_rw1.setValid(max31865Set5.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_rw1.isValid()) { - sensorTemperatures.sensor_rw1.value = INVALID_TEMPERATURE; + sensorTemperatures.rw1.value = maxSet5Rw1MxMy.temperatureCelcius.value; + sensorTemperatures.rw1.setValid(maxSet5Rw1MxMy.temperatureCelcius.isValid()); + if (not sensorTemperatures.rw1.isValid()) { + sensorTemperatures.rw1.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg6(&max31865Set6, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg6(&maxSet6Dro, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg6.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_dro.value = max31865Set6.temperatureCelcius.value; - sensorTemperatures.sensor_dro.setValid(max31865Set6.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_dro.isValid()) { - sensorTemperatures.sensor_dro.value = INVALID_TEMPERATURE; + sensorTemperatures.dro.value = maxSet6Dro.temperatureCelcius.value; + sensorTemperatures.dro.setValid(maxSet6Dro.temperatureCelcius.isValid()); + if (not sensorTemperatures.dro.isValid()) { + sensorTemperatures.dro.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg7(&max31865Set7, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg7(&maxSet7Scex, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg7.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_scex.value = max31865Set7.temperatureCelcius.value; - sensorTemperatures.sensor_scex.setValid(max31865Set7.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_scex.isValid()) { - sensorTemperatures.sensor_scex.value = INVALID_TEMPERATURE; + sensorTemperatures.scex.value = maxSet7Scex.temperatureCelcius.value; + sensorTemperatures.scex.setValid(maxSet7Scex.temperatureCelcius.isValid()); + if (not sensorTemperatures.scex.isValid()) { + sensorTemperatures.scex.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg8(&max31865Set8, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg8(&maxSet8X8, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg8.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_x8.value = max31865Set8.temperatureCelcius.value; - sensorTemperatures.sensor_x8.setValid(max31865Set8.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_x8.isValid()) { - sensorTemperatures.sensor_x8.value = INVALID_TEMPERATURE; + sensorTemperatures.x8.value = maxSet8X8.temperatureCelcius.value; + sensorTemperatures.x8.setValid(maxSet8X8.temperatureCelcius.isValid()); + if (not sensorTemperatures.x8.isValid()) { + sensorTemperatures.x8.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg9(&max31865Set9, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg9(&maxSet9Hpa, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg9.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_hpa.value = max31865Set9.temperatureCelcius.value; - sensorTemperatures.sensor_hpa.setValid(max31865Set9.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_hpa.isValid()) { - sensorTemperatures.sensor_hpa.value = INVALID_TEMPERATURE; + sensorTemperatures.hpa.value = maxSet9Hpa.temperatureCelcius.value; + sensorTemperatures.hpa.setValid(maxSet9Hpa.temperatureCelcius.isValid()); + if (not sensorTemperatures.hpa.isValid()) { + sensorTemperatures.hpa.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg10(&max31865Set10, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg10(&maxSet10EbandTx, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg10.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_tx_modul.value = max31865Set10.temperatureCelcius.value; - sensorTemperatures.sensor_tx_modul.setValid(max31865Set10.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_tx_modul.isValid()) { - sensorTemperatures.sensor_tx_modul.value = INVALID_TEMPERATURE; + sensorTemperatures.eBandTx.value = maxSet10EbandTx.temperatureCelcius.value; + sensorTemperatures.eBandTx.setValid(maxSet10EbandTx.temperatureCelcius.isValid()); + if (not sensorTemperatures.eBandTx.isValid()) { + sensorTemperatures.eBandTx.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg11(&max31865Set11, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg11(&maxSet11Mpa, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg11.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_mpa.value = max31865Set11.temperatureCelcius.value; - sensorTemperatures.sensor_mpa.setValid(max31865Set11.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_mpa.isValid()) { - sensorTemperatures.sensor_mpa.value = INVALID_TEMPERATURE; + sensorTemperatures.mpa.value = maxSet11Mpa.temperatureCelcius.value; + sensorTemperatures.mpa.setValid(maxSet11Mpa.temperatureCelcius.isValid()); + if (not sensorTemperatures.mpa.isValid()) { + sensorTemperatures.mpa.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg12(&max31865Set12, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg12(&maxSet31865Set12, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg12.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_acu.value = max31865Set12.temperatureCelcius.value; - sensorTemperatures.sensor_acu.setValid(max31865Set12.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_acu.isValid()) { - sensorTemperatures.sensor_acu.value = INVALID_TEMPERATURE; + sensorTemperatures.acu.value = maxSet31865Set12.temperatureCelcius.value; + sensorTemperatures.acu.setValid(maxSet31865Set12.temperatureCelcius.isValid()); + if (not sensorTemperatures.acu.isValid()) { + sensorTemperatures.acu.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg13(&max31865Set13, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg13(&maxSet13PlPcduHspd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg13.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_plpcdu_heatspreader.value = max31865Set13.temperatureCelcius.value; - sensorTemperatures.sensor_plpcdu_heatspreader.setValid( - max31865Set13.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_plpcdu_heatspreader.isValid()) { - sensorTemperatures.sensor_plpcdu_heatspreader.value = INVALID_TEMPERATURE; + sensorTemperatures.plpcduHeatspreader.value = maxSet13PlPcduHspd.temperatureCelcius.value; + sensorTemperatures.plpcduHeatspreader.setValid( + maxSet13PlPcduHspd.temperatureCelcius.isValid()); + if (not sensorTemperatures.plpcduHeatspreader.isValid()) { + sensorTemperatures.plpcduHeatspreader.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg14(&max31865Set14, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg14(&maxSet14TcsBrd, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg14.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_tcs_board.value = max31865Set14.temperatureCelcius.value; - sensorTemperatures.sensor_tcs_board.setValid(max31865Set14.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_tcs_board.isValid()) { - sensorTemperatures.sensor_tcs_board.value = INVALID_TEMPERATURE; + sensorTemperatures.tcsBoard.value = maxSet14TcsBrd.temperatureCelcius.value; + sensorTemperatures.tcsBoard.setValid(maxSet14TcsBrd.temperatureCelcius.isValid()); + if (not sensorTemperatures.tcsBoard.isValid()) { + sensorTemperatures.tcsBoard.value = INVALID_TEMPERATURE; } } } { - PoolReadGuard pg15(&max31865Set15, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); + PoolReadGuard pg15(&maxSet15Imtq, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT); if (pg15.getReadResult() == returnvalue::OK) { - sensorTemperatures.sensor_magnettorquer.value = max31865Set15.temperatureCelcius.value; - sensorTemperatures.sensor_magnettorquer.setValid(max31865Set15.temperatureCelcius.isValid()); - if (not sensorTemperatures.sensor_magnettorquer.isValid()) { - sensorTemperatures.sensor_magnettorquer.value = INVALID_TEMPERATURE; + sensorTemperatures.mgt.value = maxSet15Imtq.temperatureCelcius.value; + sensorTemperatures.mgt.setValid(maxSet15Imtq.temperatureCelcius.isValid()); + if (not sensorTemperatures.mgt.isValid()) { + sensorTemperatures.mgt.value = INVALID_TEMPERATURE; } } } @@ -915,28 +966,31 @@ void ThermalController::copyDevices() { } void ThermalController::ctrlAcsBoard() { - // TODO: check heater::Switchers switchNr = heater::HEATER_2_ACS_BRD; heater::Switchers redSwitchNr = heater::HEATER_0_OBC_BRD; // A side + thermalComponent = ACS_BOARD; sensors[0].first = deviceTemperatures.gyro0SideA.isValid(); sensors[0].second = deviceTemperatures.gyro0SideA.value; - sensors[1].first = deviceTemperatures.mgm0SideA.isValid(); - sensors[1].second = deviceTemperatures.mgm0SideA.value; - sensors[2].first = deviceTemperatures.gyro1SideA.isValid(); - sensors[2].second = deviceTemperatures.gyro1SideA.value; - sensors[3].first = sensorTemperatures.sensor_tcs_board.isValid(); - sensors[3].second = sensorTemperatures.sensor_tcs_board.value; - numSensors = 4; + sensors[1].first = deviceTemperatures.gyro2SideB.isValid(); + sensors[1].second = deviceTemperatures.gyro2SideB.value; + sensors[2].first = deviceTemperatures.mgm0SideA.isValid(); + sensors[2].second = deviceTemperatures.mgm0SideA.value; + sensors[3].first = deviceTemperatures.mgm2SideB.isValid(); + sensors[3].second = deviceTemperatures.mgm2SideB.value; + sensors[4].first = sensorTemperatures.tcsBoard.isValid(); + sensors[4].second = sensorTemperatures.tcsBoard.value; + numSensors = 5; if (selectAndReadSensorTemp()) { if (chooseHeater(switchNr, redSwitchNr)) { - ctrlHeater(switchNr, redSwitchNr, acsBoardLimits); + HeaterContext htrCtx(switchNr, redSwitchNr, acsBoardLimits); + checkLimitsAndCtrlHeater(htrCtx); } resetSensorsArray(); return; } - + resetSensorsArray(); // B side sensors[0].first = deviceTemperatures.gyro2SideB.isValid(); sensors[0].second = deviceTemperatures.gyro2SideB.value; @@ -944,17 +998,18 @@ void ThermalController::ctrlAcsBoard() { sensors[1].second = deviceTemperatures.mgm2SideB.value; sensors[2].first = deviceTemperatures.gyro3SideB.isValid(); sensors[2].second = deviceTemperatures.gyro3SideB.value; - sensors[3].first = sensorTemperatures.sensor_tcs_board.isValid(); - sensors[3].second = sensorTemperatures.sensor_tcs_board.value; + sensors[3].first = sensorTemperatures.tcsBoard.isValid(); + sensors[3].second = sensorTemperatures.tcsBoard.value; + numSensors = 4; if (selectAndReadSensorTemp()) { if (chooseHeater(switchNr, redSwitchNr)) { - ctrlHeater(switchNr, redSwitchNr, acsBoardLimits); + HeaterContext htrCtx(switchNr, redSwitchNr, acsBoardLimits); + checkLimitsAndCtrlHeater(htrCtx); } } else { if (chooseHeater(switchNr, redSwitchNr)) { - if (heaterHandler.checkSwitchState(switchNr)) { + if (heaterHandler.getSwitchState(switchNr)) { heaterHandler.switchHeater(switchNr, HeaterHandler::SwitchState::OFF); - sif::info << "ThermalController::ctrlHeater: Heater" << switchNr << " OFF" << std::endl; } } } @@ -962,107 +1017,169 @@ void ThermalController::ctrlAcsBoard() { } void ThermalController::ctrlMgt() { - PoolReadGuard pg(&imtqThermalSet); - auto heaterReq = - static_cast(imtqThermalSet.heaterRequest.value); - - if (heaterReq == ThermalComponentIF::STATE_REQUEST_OPERATIONAL) { - sensors[0].first = sensorTemperatures.sensor_magnettorquer.isValid(); - sensors[0].second = sensorTemperatures.sensor_magnettorquer.value; - sensors[1].first = deviceTemperatures.mgt.isValid(); - sensors[1].second = deviceTemperatures.mgt.value; - sensors[2].first = sensorTemperatures.sensor_plpcdu_heatspreader.isValid(); - sensors[2].second = sensorTemperatures.sensor_plpcdu_heatspreader.value; - numSensors = 3; - ctrlComponentTemperature(heater::HEATER_2_ACS_BRD, heater::HEATER_3_PCDU_PDU, mgtLimits); - } + thermalComponent = MGT; + sensors[0].first = sensorTemperatures.mgt.isValid(); + sensors[0].second = sensorTemperatures.mgt.value; + sensors[1].first = deviceTemperatures.mgt.isValid(); + sensors[1].second = deviceTemperatures.mgt.value; + sensors[2].first = sensorTemperatures.plpcduHeatspreader.isValid(); + sensors[2].second = sensorTemperatures.plpcduHeatspreader.value; + numSensors = 3; + HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_3_PCDU_PDU, mgtLimits); + ctrlComponentTemperature(htrCtx); + // TODO: trigger special event } void ThermalController::ctrlRw() { - // TODO: better solution? + Event eventToTrigger = 0; + bool oneIsAboveLimit = false; + + std::array sensorTemps{}; + // RW1 - sensors[0].first = sensorTemperatures.sensor_rw1.isValid(); - sensors[0].second = sensorTemperatures.sensor_rw1.value; + thermalComponent = RW; + sensors[0].first = sensorTemperatures.rw1.isValid(); + sensors[0].second = sensorTemperatures.rw1.value; sensors[1].first = deviceTemperatures.rw1.isValid(); sensors[1].second = deviceTemperatures.rw1.value; sensors[2].first = deviceTemperatures.rw4.isValid(); sensors[2].second = deviceTemperatures.rw4.value; - sensors[3].first = sensorTemperatures.sensor_dro.isValid(); - sensors[3].second = sensorTemperatures.sensor_dro.value; + sensors[3].first = sensorTemperatures.dro.isValid(); + sensors[3].second = sensorTemperatures.dro.value; numSensors = 4; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); + { + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); + ctrlComponentTemperature(htrCtx); + sensorTemps[0] = tempFloatToU32(); + if (componentAboveUpperLimit) { + oneIsAboveLimit = true; + eventToTrigger = overHeatEventToTrigger; + } + } // RW2 + thermalComponent = RW; sensors[0].first = deviceTemperatures.rw2.isValid(); sensors[0].second = deviceTemperatures.rw2.value; sensors[1].first = deviceTemperatures.rw3.isValid(); sensors[1].second = deviceTemperatures.rw3.value; - sensors[2].first = sensorTemperatures.sensor_rw1.isValid(); - sensors[2].second = sensorTemperatures.sensor_rw1.value; - sensors[3].first = sensorTemperatures.sensor_dro.isValid(); - sensors[3].second = sensorTemperatures.sensor_dro.value; + sensors[2].first = sensorTemperatures.rw1.isValid(); + sensors[2].second = sensorTemperatures.rw1.value; + sensors[3].first = sensorTemperatures.dro.isValid(); + sensors[3].second = sensorTemperatures.dro.value; numSensors = 4; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); - + { + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); + ctrlComponentTemperature(htrCtx); + sensorTemps[1] = tempFloatToU32(); + if (componentAboveUpperLimit) { + oneIsAboveLimit = true; + if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) { + eventToTrigger = overHeatEventToTrigger; + } + } + } // RW3 + thermalComponent = RW; sensors[0].first = deviceTemperatures.rw3.isValid(); sensors[0].second = deviceTemperatures.rw3.value; sensors[1].first = deviceTemperatures.rw4.isValid(); sensors[1].second = deviceTemperatures.rw4.value; - sensors[2].first = sensorTemperatures.sensor_rw1.isValid(); - sensors[2].second = sensorTemperatures.sensor_rw1.value; - sensors[3].first = sensorTemperatures.sensor_dro.isValid(); - sensors[3].second = sensorTemperatures.sensor_dro.value; + sensors[2].first = sensorTemperatures.rw1.isValid(); + sensors[2].second = sensorTemperatures.rw1.value; + sensors[3].first = sensorTemperatures.dro.isValid(); + sensors[3].second = sensorTemperatures.dro.value; numSensors = 4; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); + { + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); + ctrlComponentTemperature(htrCtx); + sensorTemps[2] = tempFloatToU32(); + if (componentAboveUpperLimit) { + oneIsAboveLimit = true; + if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) { + eventToTrigger = overHeatEventToTrigger; + } + } + } // RW4 + thermalComponent = RW; sensors[0].first = deviceTemperatures.rw4.isValid(); sensors[0].second = deviceTemperatures.rw4.value; sensors[1].first = deviceTemperatures.rw1.isValid(); sensors[1].second = deviceTemperatures.rw1.value; - sensors[2].first = sensorTemperatures.sensor_rw1.isValid(); - sensors[2].second = sensorTemperatures.sensor_rw1.value; - sensors[3].first = sensorTemperatures.sensor_dro.isValid(); - sensors[3].second = sensorTemperatures.sensor_dro.value; + sensors[2].first = sensorTemperatures.rw1.isValid(); + sensors[2].second = sensorTemperatures.rw1.value; + sensors[3].first = sensorTemperatures.dro.isValid(); + sensors[3].second = sensorTemperatures.dro.value; numSensors = 4; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); + { + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits); + ctrlComponentTemperature(htrCtx); + sensorTemps[3] = tempFloatToU32(); + if (componentAboveUpperLimit) { + oneIsAboveLimit = true; + if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) { + eventToTrigger = overHeatEventToTrigger; + } + } + } + + if (oneIsAboveLimit and not rwTooHotFlag) { + EventManagerIF::triggerEvent(objects::RW1, eventToTrigger, sensorTemps[0]); + EventManagerIF::triggerEvent(objects::RW2, eventToTrigger, sensorTemps[1]); + EventManagerIF::triggerEvent(objects::RW3, eventToTrigger, sensorTemps[2]); + EventManagerIF::triggerEvent(objects::RW4, eventToTrigger, sensorTemps[3]); + rwTooHotFlag = true; + } else if (not oneIsAboveLimit) { + rwTooHotFlag = false; + } } void ThermalController::ctrlStr() { - sensors[0].first = sensorTemperatures.sensor_startracker.isValid(); - sensors[0].second = sensorTemperatures.sensor_startracker.value; + thermalComponent = STR; + sensors[0].first = sensorTemperatures.startracker.isValid(); + sensors[0].second = sensorTemperatures.startracker.value; sensors[1].first = deviceTemperatures.startracker.isValid(); sensors[1].second = deviceTemperatures.startracker.value; - sensors[2].first = sensorTemperatures.sensor_dro.isValid(); - sensors[2].second = sensorTemperatures.sensor_dro.value; + sensors[2].first = sensorTemperatures.dro.isValid(); + sensors[2].second = sensorTemperatures.dro.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_5_STR, heater::HEATER_6_DRO, strLimits); + HeaterContext htrCtx(heater::HEATER_5_STR, heater::HEATER_6_DRO, strLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandlerWhichClearsOneShotFlag(objects::STAR_TRACKER, strTooHotFlag); } void ThermalController::ctrlIfBoard() { + thermalComponent = IF_BOARD; sensors[0].first = sensorTemperatures.tmp1075IfBrd.isValid(); sensors[0].second = sensorTemperatures.tmp1075IfBrd.value; - sensors[1].first = sensorTemperatures.sensor_magnettorquer.isValid(); - sensors[1].second = sensorTemperatures.sensor_magnettorquer.value; + sensors[1].first = sensorTemperatures.mgt.isValid(); + sensors[1].second = sensorTemperatures.mgt.value; sensors[2].first = deviceTemperatures.mgm2SideB.isValid(); sensors[2].second = deviceTemperatures.mgm2SideB.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_2_ACS_BRD, heater::HEATER_3_PCDU_PDU, ifBoardLimits); + HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_3_PCDU_PDU, ifBoardLimits); + ctrlComponentTemperature(htrCtx); + // TODO: special event overheating + could go back to safe mode } void ThermalController::ctrlTcsBoard() { - sensors[0].first = sensorTemperatures.sensor_tcs_board.isValid(); - sensors[0].second = sensorTemperatures.sensor_tcs_board.value; + thermalComponent = TCS_BOARD; + sensors[0].first = sensorTemperatures.tcsBoard.isValid(); + sensors[0].second = sensorTemperatures.tcsBoard.value; sensors[1].first = sensorTemperatures.tmp1075Tcs0.isValid(); sensors[1].second = sensorTemperatures.tmp1075Tcs0.value; sensors[2].first = sensorTemperatures.tmp1075Tcs1.isValid(); sensors[2].second = sensorTemperatures.tmp1075Tcs1.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_0_OBC_BRD, heater::HEATER_2_ACS_BRD, tcsBoardLimits); + HeaterContext htrCtx(heater::HEATER_0_OBC_BRD, heater::HEATER_2_ACS_BRD, tcsBoardLimits); + ctrlComponentTemperature(htrCtx); + // TODO: special event overheating + could go back to safe mode } void ThermalController::ctrlObc() { + thermalComponent = OBC; sensors[0].first = deviceTemperatures.q7s.isValid(); sensors[0].second = deviceTemperatures.q7s.value; sensors[1].first = sensorTemperatures.tmp1075Tcs1.isValid(); @@ -1070,13 +1187,18 @@ void ThermalController::ctrlObc() { sensors[2].first = sensorTemperatures.tmp1075Tcs0.isValid(); sensors[2].second = sensorTemperatures.tmp1075Tcs0.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_0_OBC_BRD, heater::HEATER_2_ACS_BRD, obcLimits); - if (componentAboveCutOffLimit) { - triggerEvent(OBC_OVERHEATING); + HeaterContext htrCtx(heater::HEATER_0_OBC_BRD, heater::HEATER_2_ACS_BRD, obcLimits); + ctrlComponentTemperature(htrCtx); + if (componentAboveUpperLimit and not obcTooHotFlag) { + triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32()); + obcTooHotFlag = true; + } else if (not componentAboveUpperLimit) { + obcTooHotFlag = false; } } void ThermalController::ctrlObcIfBoard() { + thermalComponent = OBCIF_BOARD; sensors[0].first = deviceTemperatures.q7s.isValid(); sensors[0].second = deviceTemperatures.q7s.value; sensors[1].first = sensorTemperatures.tmp1075Tcs0.isValid(); @@ -1084,255 +1206,376 @@ void ThermalController::ctrlObcIfBoard() { sensors[2].first = sensorTemperatures.tmp1075Tcs1.isValid(); sensors[2].second = sensorTemperatures.tmp1075Tcs1.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_0_OBC_BRD, heater::HEATER_2_ACS_BRD, obcIfBoardLimits); + HeaterContext htrCtx(heater::HEATER_0_OBC_BRD, heater::HEATER_2_ACS_BRD, obcIfBoardLimits); + ctrlComponentTemperature(htrCtx); + if (componentAboveUpperLimit and not obcTooHotFlag) { + triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32()); + obcTooHotFlag = true; + } else if (not componentAboveUpperLimit) { + obcTooHotFlag = false; // TODO: !! + } } void ThermalController::ctrlSBandTransceiver() { + thermalComponent = SBAND_TRANSCEIVER; sensors[0].first = deviceTemperatures.syrlinksPowerAmplifier.isValid(); sensors[0].second = deviceTemperatures.syrlinksPowerAmplifier.value; sensors[1].first = deviceTemperatures.syrlinksBasebandBoard.isValid(); sensors[1].second = deviceTemperatures.syrlinksBasebandBoard.value; - sensors[2].first = sensorTemperatures.sensor_4k_camera.isValid(); - sensors[2].second = sensorTemperatures.sensor_4k_camera.value; + sensors[2].first = sensorTemperatures.payload4kCamera.isValid(); + sensors[2].second = sensorTemperatures.payload4kCamera.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_7_S_BAND, heater::HEATER_4_CAMERA, - sBandTransceiverLimits); - if (componentAboveCutOffLimit) { - triggerEvent(SYRLINKS_OVERHEATING); + HeaterContext htrCtx(heater::HEATER_7_S_BAND, heater::HEATER_4_CAMERA, sBandTransceiverLimits); + ctrlComponentTemperature(htrCtx); + if (componentAboveUpperLimit and not syrlinksTooHotFlag) { + triggerEvent(tcsCtrl::SYRLINKS_OVERHEATING, tempFloatToU32()); + syrlinksTooHotFlag = true; + } else if (not componentAboveUpperLimit) { + syrlinksTooHotFlag = false; } } void ThermalController::ctrlPcduP60Board() { + thermalComponent = PCDUP60_BOARD; sensors[0].first = deviceTemperatures.temp1P60dock.isValid(); sensors[0].second = deviceTemperatures.temp1P60dock.value; sensors[1].first = deviceTemperatures.temp2P60dock.isValid(); sensors[1].second = deviceTemperatures.temp2P60dock.value; numSensors = 2; - ctrlComponentTemperature(heater::HEATER_3_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduP60BoardLimits); + HeaterContext htrCtx(heater::HEATER_3_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduP60BoardLimits); + ctrlComponentTemperature(htrCtx); + if (componentAboveUpperLimit and not pcduSystemTooHotFlag) { + triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32()); + pcduSystemTooHotFlag = true; + } else if (not componentAboveUpperLimit) { + pcduSystemTooHotFlag = false; + } // TODO: ! } void ThermalController::ctrlPcduAcu() { + thermalComponent = PCDUACU; heater::Switchers switchNr = heater::HEATER_3_PCDU_PDU; heater::Switchers redSwitchNr = heater::HEATER_2_ACS_BRD; if (chooseHeater(switchNr, redSwitchNr)) { bool sensorTempAvailable = true; - + // TODO: check if (deviceTemperatures.acu.value[0] != INVALID_TEMPERATURE) { sensorTemp = deviceTemperatures.acu.value[0]; } else if (deviceTemperatures.acu.value[1] != INVALID_TEMPERATURE) { sensorTemp = deviceTemperatures.acu.value[1]; } else if (deviceTemperatures.acu.value[2] != INVALID_TEMPERATURE) { sensorTemp = deviceTemperatures.acu.value[2]; - } else if (sensorTemperatures.sensor_acu.isValid()) { - sensorTemp = sensorTemperatures.sensor_acu.value; + } else if (sensorTemperatures.acu.isValid()) { + sensorTemp = sensorTemperatures.acu.value; } else { - triggerEvent(NO_VALID_SENSOR_TEMPERATURE, switchNr); + triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, thermalComponent); sensorTempAvailable = false; } if (sensorTempAvailable) { - ctrlHeater(switchNr, redSwitchNr, pcduAcuLimits); + HeaterContext htrCtx(switchNr, redSwitchNr, pcduAcuLimits); + checkLimitsAndCtrlHeater(htrCtx); } } + if (componentAboveUpperLimit and not pcduSystemTooHotFlag) { + triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32()); + pcduSystemTooHotFlag = true; + } else if (not componentAboveUpperLimit) { + pcduSystemTooHotFlag = false; + } } void ThermalController::ctrlPcduPdu() { + thermalComponent = PCDUPDU; sensors[0].first = deviceTemperatures.pdu1.isValid(); sensors[0].second = deviceTemperatures.pdu1.value; sensors[1].first = deviceTemperatures.pdu2.isValid(); sensors[1].second = deviceTemperatures.pdu2.value; sensors[2].first = sensorTemperatures.tmp1075Tcs0.isValid(); sensors[2].second = sensorTemperatures.tmp1075Tcs0.value; - numSensors = 2; - ctrlComponentTemperature(heater::HEATER_3_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduPduLimits); + numSensors = 3; + HeaterContext htrCtx(heater::HEATER_3_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduPduLimits); + ctrlComponentTemperature(htrCtx); + if (componentAboveUpperLimit and not pcduSystemTooHotFlag) { + triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32()); + pcduSystemTooHotFlag = true; + } else if (not componentAboveUpperLimit) { + pcduSystemTooHotFlag = false; + } } void ThermalController::ctrlPlPcduBoard() { + thermalComponent = PLPCDU_BOARD; sensors[0].first = sensorTemperatures.tmp1075PlPcdu0.isValid(); sensors[0].second = sensorTemperatures.tmp1075PlPcdu0.value; sensors[1].first = sensorTemperatures.tmp1075PlPcdu1.isValid(); sensors[1].second = sensorTemperatures.tmp1075PlPcdu1.value; sensors[2].first = deviceTemperatures.adcPayloadPcdu.isValid(); sensors[2].second = deviceTemperatures.adcPayloadPcdu.value; - sensors[3].first = sensorTemperatures.sensor_plpcdu_heatspreader.isValid(); - sensors[3].second = sensorTemperatures.sensor_plpcdu_heatspreader.value; + sensors[3].first = sensorTemperatures.plpcduHeatspreader.isValid(); + sensors[3].second = sensorTemperatures.plpcduHeatspreader.value; numSensors = 4; - ctrlComponentTemperature(heater::HEATER_3_PCDU_PDU, heater::HEATER_2_ACS_BRD, plPcduBoardLimits); - if (componentAboveCutOffLimit) { - triggerEvent(PLPCDU_OVERHEATING); - } + HeaterContext htrCtx(heater::HEATER_3_PCDU_PDU, heater::HEATER_2_ACS_BRD, plPcduBoardLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); } void ThermalController::ctrlPlocMissionBoard() { - sensors[0].first = sensorTemperatures.sensor_ploc_heatspreader.isValid(); - sensors[0].second = sensorTemperatures.sensor_ploc_heatspreader.value; - sensors[1].first = sensorTemperatures.sensor_ploc_missionboard.isValid(); - sensors[1].second = sensorTemperatures.sensor_ploc_missionboard.value; - sensors[2].first = sensorTemperatures.sensor_dac_heatspreader.isValid(); - sensors[2].second = sensorTemperatures.sensor_dac_heatspreader.value; + thermalComponent = PLOCMISSION_BOARD; + sensors[0].first = sensorTemperatures.plocHeatspreader.isValid(); + sensors[0].second = sensorTemperatures.plocHeatspreader.value; + sensors[1].first = sensorTemperatures.plocMissionboard.isValid(); + sensors[1].second = sensorTemperatures.plocMissionboard.value; + sensors[2].first = sensorTemperatures.dacHeatspreader.isValid(); + sensors[2].second = sensorTemperatures.dacHeatspreader.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_1_PLOC_PROC_BRD, heater::HEATER_0_OBC_BRD, - plocMissionBoardLimits); - if (componentAboveCutOffLimit) { - triggerEvent(PLOC_OVERHEATING); - } + HeaterContext htrCtx(heater::HEATER_1_PLOC_PROC_BRD, heater::HEATER_0_OBC_BRD, + plocMissionBoardLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, plocTooHotFlag); } void ThermalController::ctrlPlocProcessingBoard() { - sensors[0].first = sensorTemperatures.sensor_ploc_missionboard.isValid(); - sensors[0].second = sensorTemperatures.sensor_ploc_missionboard.value; - sensors[1].first = sensorTemperatures.sensor_ploc_heatspreader.isValid(); - sensors[1].second = sensorTemperatures.sensor_ploc_heatspreader.value; - sensors[2].first = sensorTemperatures.sensor_dac_heatspreader.isValid(); - sensors[2].second = sensorTemperatures.sensor_dac_heatspreader.value; + thermalComponent = PLOCPROCESSING_BOARD; + sensors[0].first = sensorTemperatures.plocMissionboard.isValid(); + sensors[0].second = sensorTemperatures.plocMissionboard.value; + sensors[1].first = sensorTemperatures.plocHeatspreader.isValid(); + sensors[1].second = sensorTemperatures.plocHeatspreader.value; + sensors[2].first = sensorTemperatures.dacHeatspreader.isValid(); + sensors[2].second = sensorTemperatures.dacHeatspreader.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_1_PLOC_PROC_BRD, heater::HEATER_0_OBC_BRD, - plocProcessingBoardLimits); + HeaterContext htrCtx(heater::HEATER_1_PLOC_PROC_BRD, heater::HEATER_0_OBC_BRD, + plocProcessingBoardLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, plocTooHotFlag); } void ThermalController::ctrlDac() { - sensors[0].first = sensorTemperatures.sensor_dac_heatspreader.isValid(); - sensors[0].second = sensorTemperatures.sensor_dac_heatspreader.value; - sensors[1].first = sensorTemperatures.sensor_ploc_missionboard.isValid(); - sensors[1].second = sensorTemperatures.sensor_ploc_missionboard.value; - sensors[2].first = sensorTemperatures.sensor_ploc_heatspreader.isValid(); - sensors[2].second = sensorTemperatures.sensor_ploc_heatspreader.value; + thermalComponent = DAC; + sensors[0].first = sensorTemperatures.dacHeatspreader.isValid(); + sensors[0].second = sensorTemperatures.dacHeatspreader.value; + sensors[1].first = sensorTemperatures.plocMissionboard.isValid(); + sensors[1].second = sensorTemperatures.plocMissionboard.value; + sensors[2].first = sensorTemperatures.plocHeatspreader.isValid(); + sensors[2].second = sensorTemperatures.plocHeatspreader.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_1_PLOC_PROC_BRD, heater::HEATER_0_OBC_BRD, dacLimits); + HeaterContext htrCtx(heater::HEATER_1_PLOC_PROC_BRD, heater::HEATER_0_OBC_BRD, dacLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); } void ThermalController::ctrlCameraBody() { - sensors[0].first = sensorTemperatures.sensor_4k_camera.isValid(); - sensors[0].second = sensorTemperatures.sensor_4k_camera.value; - sensors[1].first = sensorTemperatures.sensor_dro.isValid(); - sensors[1].second = sensorTemperatures.sensor_dro.value; - sensors[2].first = sensorTemperatures.sensor_mpa.isValid(); - sensors[2].second = sensorTemperatures.sensor_mpa.value; + thermalComponent = CAMERA; + sensors[0].first = sensorTemperatures.payload4kCamera.isValid(); + sensors[0].second = sensorTemperatures.payload4kCamera.value; + sensors[1].first = sensorTemperatures.dro.isValid(); + sensors[1].second = sensorTemperatures.dro.value; + sensors[2].first = sensorTemperatures.mpa.isValid(); + sensors[2].second = sensorTemperatures.mpa.value; numSensors = 3; - ctrlComponentTemperature(heater::HEATER_4_CAMERA, heater::HEATER_6_DRO, cameraLimits); -} - -void ThermalController::ctrlDro() { - sensors[0].first = sensorTemperatures.sensor_dro.isValid(); - sensors[0].second = sensorTemperatures.sensor_dro.value; - sensors[1].first = sensorTemperatures.sensor_4k_camera.isValid(); - sensors[1].second = sensorTemperatures.sensor_4k_camera.value; - sensors[2].first = sensorTemperatures.sensor_mpa.isValid(); - sensors[2].second = sensorTemperatures.sensor_mpa.value; - numSensors = 3; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, droLimits); -} - -void ThermalController::ctrlX8() { - sensors[0].first = sensorTemperatures.sensor_x8.isValid(); - sensors[0].second = sensorTemperatures.sensor_x8.value; - sensors[1].first = sensorTemperatures.sensor_hpa.isValid(); - sensors[1].second = sensorTemperatures.sensor_hpa.value; - sensors[2].first = sensorTemperatures.sensor_tx_modul.isValid(); - sensors[2].second = sensorTemperatures.sensor_tx_modul.value; - numSensors = 3; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, x8Limits); -} - -void ThermalController::ctrlTx() { - sensors[0].first = sensorTemperatures.sensor_tx_modul.isValid(); - sensors[0].second = sensorTemperatures.sensor_tx_modul.value; - sensors[1].first = sensorTemperatures.sensor_x8.isValid(); - sensors[1].second = sensorTemperatures.sensor_x8.value; - sensors[2].first = sensorTemperatures.sensor_mpa.isValid(); - sensors[2].second = sensorTemperatures.sensor_mpa.value; - numSensors = 3; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, txLimits); -} - -void ThermalController::ctrlMpa() { - sensors[0].first = sensorTemperatures.sensor_mpa.isValid(); - sensors[0].second = sensorTemperatures.sensor_mpa.value; - sensors[1].first = sensorTemperatures.sensor_hpa.isValid(); - sensors[1].second = sensorTemperatures.sensor_hpa.value; - sensors[2].first = sensorTemperatures.sensor_tx_modul.isValid(); - sensors[2].second = sensorTemperatures.sensor_tx_modul.value; - numSensors = 3; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, mpaLimits); -} - -void ThermalController::ctrlHpa() { - sensors[0].first = sensorTemperatures.sensor_hpa.isValid(); - sensors[0].second = sensorTemperatures.sensor_hpa.value; - sensors[1].first = sensorTemperatures.sensor_x8.isValid(); - sensors[1].second = sensorTemperatures.sensor_x8.value; - sensors[2].first = sensorTemperatures.sensor_mpa.isValid(); - sensors[2].second = sensorTemperatures.sensor_mpa.value; - numSensors = 3; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, hpaLimits); - if (componentAboveCutOffLimit) { - triggerEvent(HPA_OVERHEATING); + HeaterContext htrCtx(heater::HEATER_4_CAMERA, heater::HEATER_6_DRO, cameraLimits); + ctrlComponentTemperature(htrCtx); + if (componentAboveUpperLimit and not camTooHotOneShotFlag) { + triggerEvent(tcsCtrl::CAMERA_OVERHEATING, tempFloatToU32()); + CommandMessage msg; + HealthMessage::setHealthMessage(&msg, HealthMessage::HEALTH_SET, HealthState::FAULTY); + ReturnValue_t result = commandQueue->sendMessage(camId, &msg); + if (result != returnvalue::OK) { + sif::error << "ThermalController::ctrlCameraBody(): Sending health message failed" + << std::endl; + } + camTooHotOneShotFlag = true; + } else if (not componentAboveUpperLimit) { + camTooHotOneShotFlag = false; } } -void ThermalController::performThermalModuleCtrl() { - ctrlCameraBody(); +void ThermalController::ctrlDro() { + thermalComponent = DRO; + sensors[0].first = sensorTemperatures.dro.isValid(); + sensors[0].second = sensorTemperatures.dro.value; + sensors[1].first = sensorTemperatures.payload4kCamera.isValid(); + sensors[1].second = sensorTemperatures.payload4kCamera.value; + sensors[2].first = sensorTemperatures.mpa.isValid(); + sensors[2].second = sensorTemperatures.mpa.value; + numSensors = 3; + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, droLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); +} + +void ThermalController::ctrlX8() { + thermalComponent = X8; + sensors[0].first = sensorTemperatures.x8.isValid(); + sensors[0].second = sensorTemperatures.x8.value; + sensors[1].first = sensorTemperatures.hpa.isValid(); + sensors[1].second = sensorTemperatures.hpa.value; + sensors[2].first = sensorTemperatures.eBandTx.isValid(); + sensors[2].second = sensorTemperatures.eBandTx.value; + numSensors = 3; + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, x8Limits); + ctrlComponentTemperature(htrCtx); + tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); +} + +void ThermalController::ctrlTx() { + thermalComponent = TX; + sensors[0].first = sensorTemperatures.eBandTx.isValid(); + sensors[0].second = sensorTemperatures.eBandTx.value; + sensors[1].first = sensorTemperatures.x8.isValid(); + sensors[1].second = sensorTemperatures.x8.value; + sensors[2].first = sensorTemperatures.mpa.isValid(); + sensors[2].second = sensorTemperatures.mpa.value; + numSensors = 3; + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, txLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); +} + +void ThermalController::ctrlMpa() { + thermalComponent = MPA; + sensors[0].first = sensorTemperatures.mpa.isValid(); + sensors[0].second = sensorTemperatures.mpa.value; + sensors[1].first = sensorTemperatures.hpa.isValid(); + sensors[1].second = sensorTemperatures.hpa.value; + sensors[2].first = sensorTemperatures.eBandTx.isValid(); + sensors[2].second = sensorTemperatures.eBandTx.value; + numSensors = 3; + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, mpaLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); +} + +void ThermalController::ctrlHpa() { + thermalComponent = HPA; + sensors[0].first = sensorTemperatures.hpa.isValid(); + sensors[0].second = sensorTemperatures.hpa.value; + sensors[1].first = sensorTemperatures.x8.isValid(); + sensors[1].second = sensorTemperatures.x8.value; + sensors[2].first = sensorTemperatures.mpa.isValid(); + sensors[2].second = sensorTemperatures.mpa.value; + numSensors = 3; + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, hpaLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag); +} + +void ThermalController::ctrlScexBoard() { + thermalComponent = SCEX_BOARD; + sensors[0].first = sensorTemperatures.scex.isValid(); + sensors[0].second = sensorTemperatures.scex.value; + sensors[1].first = sensorTemperatures.x8.isValid(); + sensors[1].second = sensorTemperatures.x8.value; + sensors[2].first = sensorTemperatures.hpa.isValid(); + sensors[2].second = sensorTemperatures.hpa.value; + numSensors = 3; + HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_5_STR, scexBoardLimits); + ctrlComponentTemperature(htrCtx); + tooHotHandlerWhichClearsOneShotFlag(objects::SCEX, scexTooHotFlag); +} + +void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates) { ctrlAcsBoard(); ctrlMgt(); ctrlRw(); ctrlStr(); ctrlIfBoard(); - ctrlAcsBoard(); + ctrlTcsBoard(); ctrlObc(); ctrlObcIfBoard(); ctrlSBandTransceiver(); ctrlPcduP60Board(); ctrlPcduAcu(); ctrlPcduPdu(); - ctrlPlPcduBoard(); + + // Payload components + std::array plocInAllowedRange{}; ctrlPlocMissionBoard(); + plocInAllowedRange.at(0) = not componentAboveUpperLimit; ctrlPlocProcessingBoard(); - ctrlDac(); + plocInAllowedRange.at(1) = not componentAboveUpperLimit; - ctrlDro(); - ctrlX8(); - ctrlHpa(); - ctrlTx(); - ctrlMpa(); + if (plocTooHotFlag) { + bool clearFlag = true; + for (const auto& inRange : plocInAllowedRange) { + if (not inRange) { + clearFlag = false; + } + } + if (clearFlag) { + plocTooHotFlag = false; + } + } + ctrlCameraBody(); ctrlScexBoard(); -} -void ThermalController::ctrlScexBoard() { - sensors[0].first = sensorTemperatures.sensor_scex.isValid(); - sensors[0].second = sensorTemperatures.sensor_scex.value; - sensors[1].first = sensorTemperatures.sensor_x8.isValid(); - sensors[1].second = sensorTemperatures.sensor_x8.value; - sensors[2].first = sensorTemperatures.sensor_hpa.isValid(); - sensors[2].second = sensorTemperatures.sensor_hpa.value; - numSensors = 3; - ctrlComponentTemperature(heater::HEATER_6_DRO, heater::HEATER_5_STR, scexBoardLimits); -} + // 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; -void ThermalController::ctrlHeater(heater::Switchers switchNr, heater::Switchers redSwitchNr, - struct TempLimits& tempLimit) { - componentAboveCutOffLimit = false; - // Heater off - if (not heaterHandler.checkSwitchState(switchNr)) { - if (sensorTemp < tempLimit.opLowerLimit) { - heaterHandler.switchHeater(switchNr, HeaterHandler::SwitchState::ON); - sif::info << "ThermalController::ctrlHeater: Heater" << switchNr << " ON" << std::endl; + if (eBandTooHotFlag) { + bool clearFlag = true; + for (const auto& inRange : eBandInAllowedRange) { + if (not inRange) { + clearFlag = false; + } } - // Heater on - } else if (heaterHandler.checkSwitchState(switchNr)) { - if (sensorTemp >= tempLimit.opLowerLimit + TEMP_OFFSET) { - heaterHandler.switchHeater(switchNr, HeaterHandler::SwitchState::OFF); - sif::info << "ThermalController::ctrlHeater: Heater" << switchNr << " OFF" << std::endl; + if (clearFlag) { + eBandTooHotFlag = false; } - } else if (not redSwitchNrInUse) { - if (heaterHandler.checkSwitchState(redSwitchNr)) { - if (sensorTemp >= tempLimit.cutOffLimit) { - componentAboveCutOffLimit = true; - heaterHandler.switchHeater(redSwitchNr, HeaterHandler::SwitchState::OFF); - sif::info << "ThermalController::ctrlHeater: Heater" << redSwitchNr << " OFF" << std::endl; + } + + heaterTransitionControl(heaterSwitchStates); +} +void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) { + if (selectAndReadSensorTemp()) { + if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) { + checkLimitsAndCtrlHeater(htrCtx); + } + } else { + // TODO: muss der Heater dann wirklich abgeschalten werden? + if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) { + if (heaterHandler.getSwitchState(htrCtx.switchNr)) { + heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::OFF); } } } + resetSensorsArray(); } +bool ThermalController::selectAndReadSensorTemp() { + for (unsigned i = 0; i < numSensors; i++) { + if (sensors[i].first and sensors[i].second != INVALID_TEMPERATURE) { + sensorTemp = sensors[i].second; + thermalStates[thermalComponent].errorCounter = 0; + return true; + } + } + thermalStates[thermalComponent].errorCounter++; + if (thermalComponent != RW and thermalComponent != ACS_BOARD) { + if (thermalStates[thermalComponent].errorCounter <= 3) { + triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, thermalComponent); + } + } else { + if (thermalStates[thermalComponent].errorCounter <= 8) { + triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, thermalComponent); + } + } + + return false; +} bool ThermalController::chooseHeater(heater::Switchers& switchNr, heater::Switchers redSwitchNr) { bool heaterAvailable = true; @@ -1342,7 +1585,7 @@ bool ThermalController::chooseHeater(heater::Switchers& switchNr, heater::Switch redSwitchNrInUse = true; } else { heaterAvailable = false; - triggerEvent(NO_HEALTHY_HEATER_AVAILABLE, switchNr, redSwitchNr); + triggerEvent(tcsCtrl::NO_HEALTHY_HEATER_AVAILABLE, switchNr, redSwitchNr); } } else { redSwitchNrInUse = false; @@ -1350,40 +1593,159 @@ bool ThermalController::chooseHeater(heater::Switchers& switchNr, heater::Switch return heaterAvailable; } -bool ThermalController::selectAndReadSensorTemp() { - for (unsigned i = 0; i < numSensors; i++) { - if (sensors[i].first and sensors[i].second != INVALID_TEMPERATURE) { - sensorTemp = sensors[i].second; - return true; - } +void ThermalController::heaterCtrlTempTooHighHandler(HeaterContext& htrCtx, const char* whatLimit) { + if (htrCtx.switchState == HeaterHandler::SwitchState::ON) { + sif::info << "TCS: Component " << static_cast(thermalComponent) << " too warm, above " + << whatLimit << ", switching off heater" << std::endl; + heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::OFF); + heaterStates[htrCtx.switchNr].switchTransition = true; + heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF; + } + if (heaterHandler.getSwitchState(htrCtx.redSwitchNr) == HeaterHandler::SwitchState::ON) { + heaterHandler.switchHeater(htrCtx.redSwitchNr, HeaterHandler::SwitchState::OFF); + heaterStates[htrCtx.redSwitchNr].switchTransition = true; + heaterStates[htrCtx.redSwitchNr].target = HeaterHandler::SwitchState::OFF; } - triggerEvent(NO_VALID_SENSOR_TEMPERATURE); - return false; } -void ThermalController::ctrlComponentTemperature(heater::Switchers switchNr, - heater::Switchers redSwitchNr, - TempLimits& tempLimit) { - if (selectAndReadSensorTemp()) { - if (chooseHeater(switchNr, redSwitchNr)) { - ctrlHeater(switchNr, redSwitchNr, tempLimit); - } +void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) { + componentAboveCutOffLimit = false; + componentAboveUpperLimit = false; + // Stay passive during switch transitions, wait for heater switching to complete. Otherwise, + // still check whether components are out of range, which might be important information for the + // top level control loop. + if (heaterStates[htrCtx.switchNr].switchTransition) { + htrCtx.doHeaterHandling = false; + heaterCtrlCheckUpperLimits(htrCtx); } else { - if (chooseHeater(switchNr, - redSwitchNr)) { // TODO: muss der Heater dann wirklich abgeschalten werden? - if (heaterHandler.checkSwitchState(switchNr)) { - heaterHandler.switchHeater(switchNr, HeaterHandler::SwitchState::OFF); - sif::info << "ThermalController::ctrlHeater: Heater" << switchNr << " OFF" << std::endl; + // Heater off + htrCtx.switchState = heaterHandler.getSwitchState(htrCtx.switchNr); + if (htrCtx.switchState == HeaterHandler::SwitchState::OFF) { + if (sensorTemp < htrCtx.tempLimit.opLowerLimit) { + heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::ON); + sif::info << "ThermalController::checkLimitsAndCtrlHeater: Heater " + << static_cast(thermalComponent) << " ON" << std::endl; + heaterStates[htrCtx.switchNr].switchTransition = true; + thermalStates[thermalComponent].heating = true; + heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::ON; + } else { + thermalStates[thermalComponent].heating = false; + } + heaterCtrlCheckUpperLimits(htrCtx); + // Heater on + } else if (heaterHandler.getSwitchState(htrCtx.switchNr) == HeaterHandler::SwitchState::ON) { + if (thermalStates[thermalComponent].heating) { + // We are already in a heating cycle, so need to check whether heating task is complete. + if (sensorTemp >= htrCtx.tempLimit.opLowerLimit + TEMP_OFFSET) { + heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::OFF); + sif::info << "ThermalController::checkLimitsAndCtrlHeater: Heater " + << static_cast(thermalComponent) << " OFF" << std::endl; + heaterStates[htrCtx.switchNr].switchTransition = true; + heaterStates[htrCtx.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 = heaterCtrlCheckUpperLimits(htrCtx); + if (sensorTemp >= htrCtx.tempLimit.cutOffLimit) { + componentAboveCutOffLimit = true; + if (not tooHighHandlerAlreadyCalled) { + heaterCtrlTempTooHighHandler(htrCtx, "CutOff-Limit"); + } + } } } } - resetSensorsArray(); +} + +bool ThermalController::heaterCtrlCheckUpperLimits(HeaterContext& htrCtx) { + if (sensorTemp >= htrCtx.tempLimit.nopUpperLimit) { + componentAboveUpperLimit = true; + if (htrCtx.doHeaterHandling) { + heaterCtrlTempTooHighHandler(htrCtx, "NOP-Limit"); + } + overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH; + return true; + } else if (sensorTemp >= htrCtx.tempLimit.opUpperLimit) { + componentAboveUpperLimit = true; + if (htrCtx.doHeaterHandling) { + heaterCtrlTempTooHighHandler(htrCtx, "OP-Limit"); + } + overHeatEventToTrigger = ThermalComponentIF::COMPONENT_TEMP_HIGH; + return true; + } + return false; } void ThermalController::resetSensorsArray() { - // TODO: müssen auch andere Variablen resettet werden? senstemp? for (auto& validValuePair : sensors) { validValuePair.first = false; validValuePair.second = INVALID_TEMPERATURE; } + thermalComponent = NONE; +} +void ThermalController::heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates) { + // TODO: Test + for (unsigned i = 0; i < 7; i++) { + if (heaterStates[i].switchTransition) { + if (currentHeaterStates[i] == heaterStates[i].target) { + heaterStates[i].switchTransition = false; + continue; + } + if (heaterStates[i].heaterSwitchControlCycles > 3) { + heaterStates[i].switchTransition = false; + heaterStates[i].heaterSwitchControlCycles = 0; + } + heaterStates[i].heaterSwitchControlCycles++; + } + } +} +uint32_t ThermalController::tempFloatToU32() const { + auto sensorTempAsFloat = static_cast(sensorTemp); + uint32_t tempRaw = 0; + size_t dummyLen = 0; + SerializeAdapter::serialize(&sensorTempAsFloat, reinterpret_cast(&tempRaw), &dummyLen, + sizeof(tempRaw), SerializeIF::Endianness::NETWORK); + return tempRaw; +} + +void ThermalController::setMode(Mode_t mode) { + if (mode == MODE_OFF) { + transitionToOff = false; + } + this->mode = mode; + modeHelper.modeChanged(mode, submode); + announceMode(false); +} + +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; + 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) { + 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 4624c411..0ceb9cae 100644 --- a/mission/controller/ThermalController.h +++ b/mission/controller/ThermalController.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -45,6 +45,48 @@ struct TempLimits { float nopUpperLimit; }; +struct ThermalState { + uint8_t errorCounter; + bool heating; + uint32_t heaterStartTime; +}; + +struct HeaterState { + bool switchTransition; + HeaterHandler::SwitchState target; + uint8_t heaterSwitchControlCycles; +}; + +using HeaterSwitchStates = std::array; + +enum ThermalComponents : uint8_t { + NONE = 0, + ACS_BOARD = 1, + MGT = 2, + RW = 3, + STR = 4, + IF_BOARD = 5, + TCS_BOARD = 6, + OBC = 7, + 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 { public: static const uint16_t INVALID_TEMPERATURE = 999; @@ -55,7 +97,19 @@ class ThermalController : public ExtendedControllerBase { ReturnValue_t initialize() override; protected: - void performThermalModuleCtrl(); + struct HeaterContext { + public: + HeaterContext(heater::Switchers switchNr, heater::Switchers redundantSwitchNr, + const TempLimits& tempLimit) + : switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {} + bool doHeaterHandling = true; + heater::Switchers switchNr; + HeaterHandler::SwitchState switchState = HeaterHandler::SwitchState::OFF; + heater::Switchers redSwitchNr; + const TempLimits& tempLimit; + }; + + void performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates); ReturnValue_t handleCommandMessage(CommandMessage* message) override; void performControlOperation() override; ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, @@ -67,16 +121,7 @@ class ThermalController : public ExtendedControllerBase { uint32_t* msToReachTheMode) override; private: - 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_HEALTHY_HEATER_AVAILABLE = MAKE_EVENT(1, severity::MEDIUM); - static constexpr Event SYRLINKS_OVERHEATING = MAKE_EVENT(2, severity::HIGH); - static constexpr Event PLOC_OVERHEATING = MAKE_EVENT(3, severity::HIGH); - static constexpr Event OBC_OVERHEATING = MAKE_EVENT(4, severity::HIGH); - static constexpr Event HPA_OVERHEATING = MAKE_EVENT(5, severity::HIGH); - static constexpr Event PLPCDU_OVERHEATING = MAKE_EVENT(6, severity::HIGH); - - static const uint32_t DELAY = 500; + static const uint32_t INIT_DELAY = 1500; static const uint32_t TEMP_OFFSET = 5; @@ -96,22 +141,22 @@ class ThermalController : public ExtendedControllerBase { DeviceHandlerThermalSet imtqThermalSet; // Temperature Sensors - MAX31865::PrimarySet max31865Set0; - MAX31865::PrimarySet max31865Set1; - MAX31865::PrimarySet max31865Set2; - MAX31865::PrimarySet max31865Set3; - MAX31865::PrimarySet max31865Set4; - MAX31865::PrimarySet max31865Set5; - MAX31865::PrimarySet max31865Set6; - MAX31865::PrimarySet max31865Set7; - MAX31865::PrimarySet max31865Set8; - MAX31865::PrimarySet max31865Set9; - MAX31865::PrimarySet max31865Set10; - MAX31865::PrimarySet max31865Set11; - MAX31865::PrimarySet max31865Set12; - MAX31865::PrimarySet max31865Set13; - MAX31865::PrimarySet max31865Set14; - MAX31865::PrimarySet max31865Set15; + MAX31865::PrimarySet maxSet0PlocHspd; + MAX31865::PrimarySet maxSet1PlocMissionBrd; + MAX31865::PrimarySet maxSet2PlCam; + MAX31865::PrimarySet maxSet3DacHspd; + MAX31865::PrimarySet maxSet4Str; + MAX31865::PrimarySet maxSet5Rw1MxMy; + MAX31865::PrimarySet maxSet6Dro; + MAX31865::PrimarySet maxSet7Scex; + MAX31865::PrimarySet maxSet8X8; + MAX31865::PrimarySet maxSet9Hpa; + MAX31865::PrimarySet maxSet10EbandTx; + MAX31865::PrimarySet maxSet11Mpa; + MAX31865::PrimarySet maxSet31865Set12; + MAX31865::PrimarySet maxSet13PlPcduHspd; + MAX31865::PrimarySet maxSet14TcsBrd; + MAX31865::PrimarySet maxSet15Imtq; TMP1075::Tmp1075Dataset tmp1075SetTcs0; TMP1075::Tmp1075Dataset tmp1075SetTcs1; @@ -191,18 +236,38 @@ class ThermalController : public ExtendedControllerBase { TempLimits dacLimits = TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0); TempLimits cameraLimits = TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0); TempLimits droLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); - TempLimits x8Limits = TempLimits(-40.0, -30.0, -75.0, 80.0, 90.0); - TempLimits hpaLimits = TempLimits(-40.0, -30.0, -75.0, 80.0, 90.0); - TempLimits txLimits = TempLimits(-40.0, -30.0, -75.0, 80.0, 90.0); - TempLimits mpaLimits = TempLimits(-40.0, -30.0, -75.0, 80.0, 90.0); + TempLimits x8Limits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); + TempLimits hpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); + TempLimits txLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); + TempLimits mpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0); TempLimits scexBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0); double sensorTemp = INVALID_TEMPERATURE; + ThermalComponents thermalComponent = NONE; bool redSwitchNrInUse = false; + MessageQueueId_t camId = MessageQueueIF::NO_QUEUE; bool componentAboveCutOffLimit = false; + bool componentAboveUpperLimit = false; + Event overHeatEventToTrigger; + bool eBandTooHotFlag = false; + bool camTooHotOneShotFlag = false; + bool scexTooHotFlag = false; + bool plocTooHotFlag = false; + bool pcduSystemTooHotFlag = false; + bool syrlinksTooHotFlag = false; + bool obcTooHotFlag = false; + bool strTooHotFlag = false; + bool rwTooHotFlag = false; - // Initial delay to make sure all pool variables have been initialized their owners - Countdown initialCountdown = Countdown(DELAY); + bool transitionToOff = false; + uint32_t transitionToOffCycles = 0; + uint32_t cycles = 0; + std::array thermalStates{}; + std::array heaterStates{}; + + // Initial delay to make sure all pool variables have been initialized their owners. + // Also, wait for system initialization to complete. + Countdown initialCountdown = Countdown(INIT_DELAY); #if OBSW_THREAD_TRACING == 1 uint32_t opCounter = 0; @@ -221,14 +286,18 @@ class ThermalController : public ExtendedControllerBase { static constexpr dur_millis_t MUTEX_TIMEOUT = 50; + void startTransition(Mode_t mode, Submode_t submode) override; + void resetSensorsArray(); void copySensors(); void copySus(); void copyDevices(); - void ctrlComponentTemperature(heater::Switchers switchNr, heater::Switchers redSwitchNr, - TempLimits& tempLimit); - void ctrlHeater(heater::Switchers switchNr, heater::Switchers redSwitchNr, TempLimits& tempLimit); + void ctrlComponentTemperature(HeaterContext& heaterContext); + void checkLimitsAndCtrlHeater(HeaterContext& heaterContext); + bool heaterCtrlCheckUpperLimits(HeaterContext& heaterContext); + void heaterCtrlTempTooHighHandler(HeaterContext& heaterContext, const char* whatLimit); + bool chooseHeater(heater::Switchers& switchNr, heater::Switchers redSwitchNr); bool selectAndReadSensorTemp(); @@ -255,6 +324,11 @@ class ThermalController : public ExtendedControllerBase { void ctrlTx(); void ctrlMpa(); void ctrlScexBoard(); + void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates); + void setMode(Mode_t mode); + uint32_t tempFloatToU32() const; + 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/controllerdefinitions/ThermalControllerDefinitions.h b/mission/controller/tcsDefs.h similarity index 77% rename from mission/controller/controllerdefinitions/ThermalControllerDefinitions.h rename to mission/controller/tcsDefs.h index e7c95218..e187091b 100644 --- a/mission/controller/controllerdefinitions/ThermalControllerDefinitions.h +++ b/mission/controller/tcsDefs.h @@ -5,9 +5,19 @@ #include #include "devices/heaterSwitcherList.h" +#include "eive/eventSubsystemIds.h" namespace tcsCtrl { +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_HEALTHY_HEATER_AVAILABLE = MAKE_EVENT(1, severity::MEDIUM); +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, DEVICE_TEMPERATURES = 1, @@ -93,34 +103,33 @@ static const uint8_t ENTRIES_SUS_TEMPERATURE_SET = 12; */ class SensorTemperatures : public StaticLocalDataSet { public: - SensorTemperatures(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, SENSOR_TEMPERATURES) {} + explicit SensorTemperatures(HasLocalDataPoolIF* owner) + : StaticLocalDataSet(owner, SENSOR_TEMPERATURES) {} - SensorTemperatures(object_id_t objectId) + explicit SensorTemperatures(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, SENSOR_TEMPERATURES)) {} - lp_var_t sensor_ploc_heatspreader = + lp_var_t plocHeatspreader = lp_var_t(sid.objectId, PoolIds::SENSOR_PLOC_HEATSPREADER, this); - lp_var_t sensor_ploc_missionboard = + lp_var_t plocMissionboard = lp_var_t(sid.objectId, PoolIds::SENSOR_PLOC_MISSIONBOARD, this); - lp_var_t sensor_4k_camera = lp_var_t(sid.objectId, PoolIds::SENSOR_4K_CAMERA, this); - lp_var_t sensor_dac_heatspreader = + lp_var_t payload4kCamera = lp_var_t(sid.objectId, PoolIds::SENSOR_4K_CAMERA, this); + lp_var_t dacHeatspreader = lp_var_t(sid.objectId, PoolIds::SENSOR_DAC_HEATSPREADER, this); - lp_var_t sensor_startracker = - lp_var_t(sid.objectId, PoolIds::SENSOR_STARTRACKER, this); - lp_var_t sensor_rw1 = lp_var_t(sid.objectId, PoolIds::SENSOR_RW1, this); - lp_var_t sensor_scex = lp_var_t(sid.objectId, PoolIds::SENSOR_SCEX, this); - lp_var_t sensor_tx_modul = lp_var_t(sid.objectId, PoolIds::SENSOR_TX_MODUL, this); + lp_var_t startracker = lp_var_t(sid.objectId, PoolIds::SENSOR_STARTRACKER, this); + lp_var_t rw1 = lp_var_t(sid.objectId, PoolIds::SENSOR_RW1, this); + lp_var_t scex = lp_var_t(sid.objectId, PoolIds::SENSOR_SCEX, this); + lp_var_t eBandTx = lp_var_t(sid.objectId, PoolIds::SENSOR_TX_MODUL, this); // E-Band module - lp_var_t sensor_dro = lp_var_t(sid.objectId, PoolIds::SENSOR_DRO, this); - lp_var_t sensor_mpa = lp_var_t(sid.objectId, PoolIds::SENSOR_MPA, this); - lp_var_t sensor_x8 = lp_var_t(sid.objectId, PoolIds::SENSOR_X8, this); - lp_var_t sensor_hpa = lp_var_t(sid.objectId, PoolIds::SENSOR_HPA, this); - lp_var_t sensor_acu = lp_var_t(sid.objectId, PoolIds::SENSOR_ACU, this); - lp_var_t sensor_plpcdu_heatspreader = + lp_var_t dro = lp_var_t(sid.objectId, PoolIds::SENSOR_DRO, this); + lp_var_t mpa = lp_var_t(sid.objectId, PoolIds::SENSOR_MPA, this); + lp_var_t x8 = lp_var_t(sid.objectId, PoolIds::SENSOR_X8, this); + lp_var_t hpa = lp_var_t(sid.objectId, PoolIds::SENSOR_HPA, this); + lp_var_t acu = lp_var_t(sid.objectId, PoolIds::SENSOR_ACU, this); + lp_var_t plpcduHeatspreader = lp_var_t(sid.objectId, PoolIds::SENSOR_PLPCDU_HEATSPREADER, this); - lp_var_t sensor_tcs_board = lp_var_t(sid.objectId, PoolIds::SENSOR_TCS_BOARD, this); - lp_var_t sensor_magnettorquer = - lp_var_t(sid.objectId, PoolIds::SENSOR_MAGNETTORQUER, this); + lp_var_t tcsBoard = lp_var_t(sid.objectId, PoolIds::SENSOR_TCS_BOARD, this); + lp_var_t mgt = lp_var_t(sid.objectId, PoolIds::SENSOR_MAGNETTORQUER, this); lp_var_t tmp1075Tcs0 = lp_var_t(sid.objectId, PoolIds::SENSOR_TMP1075_TCS_0, this); lp_var_t tmp1075Tcs1 = lp_var_t(sid.objectId, PoolIds::SENSOR_TMP1075_TCS_1, this); lp_var_t tmp1075PlPcdu0 = @@ -137,9 +146,10 @@ class SensorTemperatures : public StaticLocalDataSet { public: - DeviceTemperatures(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, DEVICE_TEMPERATURES) {} + explicit DeviceTemperatures(HasLocalDataPoolIF* owner) + : StaticLocalDataSet(owner, DEVICE_TEMPERATURES) {} - DeviceTemperatures(object_id_t objectId) + explicit DeviceTemperatures(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, DEVICE_TEMPERATURES)) {} lp_var_t q7s = lp_var_t(sid.objectId, PoolIds::TEMP_Q7S, this); @@ -178,9 +188,11 @@ class DeviceTemperatures : public StaticLocalDataSet { public: - SusTemperatures(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, SUS_TEMPERATURES) {} + explicit SusTemperatures(HasLocalDataPoolIF* owner) + : StaticLocalDataSet(owner, SUS_TEMPERATURES) {} - SusTemperatures(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, SUS_TEMPERATURES)) {} + explicit SusTemperatures(object_id_t objectId) + : StaticLocalDataSet(sid_t(objectId, SUS_TEMPERATURES)) {} lp_var_t sus_0_n_loc_xfyfzm_pt_xf = lp_var_t(sid.objectId, PoolIds::SUS_0_N_LOC_XFYFZM_PT_XF, this); diff --git a/mission/genericFactory.cpp b/mission/genericFactory.cpp index d2c2bd6d..ca05a309 100644 --- a/mission/genericFactory.cpp +++ b/mission/genericFactory.cpp @@ -295,7 +295,7 @@ void ObjectFactory::createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& {new HealthDevice(objects::HEATER_7_SYRLINKS, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_7}, }}); heaterHandler = new HeaterHandler(objects::HEATER_HANDLER, &gpioIF, helper, &pwrSwitcher, - pcdu::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V); + power::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V); heaterHandler->connectModeTreeParent(satsystem::tcs::SUBSYSTEM); } @@ -365,7 +365,7 @@ void ObjectFactory::createAcsBoardAssy(PowerSwitchIF& pwrSwitcher, TcsBoardAssembly* ObjectFactory::createTcsBoardAssy(PowerSwitchIF& pwrSwitcher) { TcsBoardHelper helper(RTD_INFOS); auto* tcsBoardAss = new TcsBoardAssembly(objects::TCS_BOARD_ASS, &pwrSwitcher, - pcdu::Switches::PDU1_CH0_TCS_BOARD_3V3, helper); + power::Switches::PDU1_CH0_TCS_BOARD_3V3, helper); tcsBoardAss->connectModeTreeParent(satsystem::tcs::SUBSYSTEM); return tcsBoardAss; } diff --git a/mission/power/PcduHandler.cpp b/mission/power/PcduHandler.cpp index 8968110e..63f583f4 100644 --- a/mission/power/PcduHandler.cpp +++ b/mission/power/PcduHandler.cpp @@ -41,9 +41,9 @@ ReturnValue_t PcduHandler::performOperation(uint8_t counter) { PoolReadGuard pg(&switcherSet.p60Dock5VStack); if (pg.getReadResult() == returnvalue::OK) { if (switcherSet.p60Dock5VStack.value != switchState) { - triggerEvent(power::SWITCH_HAS_CHANGED, switchState, pcdu::Switches::P60_DOCK_5V_STACK); + triggerEvent(power::SWITCH_HAS_CHANGED, switchState, power::Switches::P60_DOCK_5V_STACK); MutexGuard mg(pwrLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); - switchStates[pcdu::P60_DOCK_5V_STACK] = switchState; + switchStates[power::P60_DOCK_5V_STACK] = switchState; } switcherSet.p60Dock5VStack.setValid(true); switcherSet.p60Dock5VStack.value = switchState; @@ -103,7 +103,7 @@ ReturnValue_t PcduHandler::initialize() { void PcduHandler::initializeSwitchStates() { using namespace pcdu; try { - for (uint8_t idx = 0; idx < NUMBER_OF_SWITCHES; idx++) { + for (uint8_t idx = 0; idx < power::NUMBER_OF_SWITCHES; idx++) { if (idx < PDU::CHANNELS_LEN) { switchStates[idx] = INIT_SWITCHES_PDU1.at(idx); } else if (idx < PDU::CHANNELS_LEN * 2) { @@ -181,22 +181,23 @@ void PcduHandler::updatePdu2SwitchStates() { } switcherSet.pdu2Switches.setValid(true); MutexGuard mg(pwrLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); - checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH0_Q7S, pdu2CoreHk.outputEnables[Channels::Q7S]); + checkAndUpdatePduSwitch(pdu, power::PDU2_CH0_Q7S, pdu2CoreHk.outputEnables[Channels::Q7S]); - checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8, pdu2CoreHk.outputEnables[Channels::PAYLOAD_PCDU_CH1]); - checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH2_RW_5V, pdu2CoreHk.outputEnables[Channels::RW]); - checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU2_CH2_RW_5V, + pdu2CoreHk.outputEnables[Channels::RW]); + checkAndUpdatePduSwitch(pdu, power::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V, pdu2CoreHk.outputEnables[Channels::TCS_HEATER_IN]); - checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH4_SUS_REDUNDANT_3V3, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU2_CH4_SUS_REDUNDANT_3V3, pdu2CoreHk.outputEnables[Channels::SUS_REDUNDANT]); - checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V, pdu2CoreHk.outputEnables[Channels::DEPY_MECHANISM]); - checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8, pdu2CoreHk.outputEnables[Channels::PAYLOAD_PCDU_CH6]); - checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3, pdu2CoreHk.outputEnables[Channels::ACS_B_SIDE]); - checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH8_PAYLOAD_CAMERA, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU2_CH8_PAYLOAD_CAMERA, pdu2CoreHk.outputEnables[Channels::PAYLOAD_CAMERA]); if (firstSwitchInfoPdu2) { firstSwitchInfoPdu2 = false; @@ -218,23 +219,23 @@ void PcduHandler::updatePdu1SwitchStates() { } switcherSet.pdu1Switches.setValid(true); MutexGuard mg(pwrLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); - checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH0_TCS_BOARD_3V3, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU1_CH0_TCS_BOARD_3V3, pdu1CoreHk.outputEnables[Channels::TCS_BOARD_3V3]); - checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH1_SYRLINKS_12V, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU1_CH1_SYRLINKS_12V, pdu1CoreHk.outputEnables[Channels::SYRLINKS]); - checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH2_STAR_TRACKER_5V, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU1_CH2_STAR_TRACKER_5V, pdu1CoreHk.outputEnables[Channels::STR]); - checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH3_MGT_5V, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU1_CH3_MGT_5V, pdu1CoreHk.outputEnables[Channels::MGT]); - checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH4_SUS_NOMINAL_3V3, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU1_CH4_SUS_NOMINAL_3V3, pdu1CoreHk.outputEnables[Channels::SUS_NOMINAL]); - checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH5_SOLAR_CELL_EXP_5V, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V, pdu1CoreHk.outputEnables[Channels::SOL_CELL_EXPERIMENT]); - checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH6_PLOC_12V, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU1_CH6_PLOC_12V, pdu1CoreHk.outputEnables[Channels::PLOC]); - checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH7_ACS_A_SIDE_3V3, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU1_CH7_ACS_A_SIDE_3V3, pdu1CoreHk.outputEnables[Channels::ACS_A_SIDE]); - checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH8_UNOCCUPIED, + checkAndUpdatePduSwitch(pdu, power::Switches::PDU1_CH8_UNOCCUPIED, pdu1CoreHk.outputEnables[Channels::UNUSED]); if (firstSwitchInfoPdu1) { firstSwitchInfoPdu1 = false; @@ -255,99 +256,99 @@ ReturnValue_t PcduHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onO GomspaceDeviceHandler* module = nullptr; switch (switchNr) { - case pcdu::PDU1_CH0_TCS_BOARD_3V3: { + case power::PDU1_CH0_TCS_BOARD_3V3: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_TCS_BOARD_3V3; module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } - case pcdu::PDU1_CH1_SYRLINKS_12V: { + case power::PDU1_CH1_SYRLINKS_12V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SYRLINKS; module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } - case pcdu::PDU1_CH2_STAR_TRACKER_5V: { + case power::PDU1_CH2_STAR_TRACKER_5V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_STAR_TRACKER; module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } - case pcdu::PDU1_CH3_MGT_5V: { + case power::PDU1_CH3_MGT_5V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_MGT; module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } - case pcdu::PDU1_CH4_SUS_NOMINAL_3V3: { + case power::PDU1_CH4_SUS_NOMINAL_3V3: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SUS_NOMINAL; module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } - case pcdu::PDU1_CH5_SOLAR_CELL_EXP_5V: { + case power::PDU1_CH5_SOLAR_CELL_EXP_5V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SOLAR_CELL_EXP; module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } - case pcdu::PDU1_CH6_PLOC_12V: { + case power::PDU1_CH6_PLOC_12V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_PLOC; module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } - case pcdu::PDU1_CH7_ACS_A_SIDE_3V3: { + case power::PDU1_CH7_ACS_A_SIDE_3V3: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_ACS_BOARD_SIDE_A; module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } - case pcdu::PDU1_CH8_UNOCCUPIED: { + case power::PDU1_CH8_UNOCCUPIED: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_CHANNEL8; module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } // This is a dangerous command. Reject/Igore it for now - case pcdu::PDU2_CH0_Q7S: { + case power::PDU2_CH0_Q7S: { return returnvalue::FAILED; // memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_Q7S; // pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); // break; } - case pcdu::PDU2_CH1_PL_PCDU_BATT_0_14V8: { + case power::PDU2_CH1_PL_PCDU_BATT_0_14V8: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH1; module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } - case pcdu::PDU2_CH2_RW_5V: { + case power::PDU2_CH2_RW_5V: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_RW; module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } - case pcdu::PDU2_CH3_TCS_BOARD_HEATER_IN_8V: { + case power::PDU2_CH3_TCS_BOARD_HEATER_IN_8V: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_TCS_BOARD_HEATER_IN; module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } - case pcdu::PDU2_CH4_SUS_REDUNDANT_3V3: { + case power::PDU2_CH4_SUS_REDUNDANT_3V3: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_SUS_REDUNDANT; module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } - case pcdu::PDU2_CH5_DEPLOYMENT_MECHANISM_8V: { + case power::PDU2_CH5_DEPLOYMENT_MECHANISM_8V: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_DEPLOYMENT_MECHANISM; module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } - case pcdu::PDU2_CH6_PL_PCDU_BATT_1_14V8: { + case power::PDU2_CH6_PL_PCDU_BATT_1_14V8: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH6; module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } - case pcdu::PDU2_CH7_ACS_BOARD_SIDE_B_3V3: { + case power::PDU2_CH7_ACS_BOARD_SIDE_B_3V3: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_ACS_BOARD_SIDE_B; module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } - case pcdu::PDU2_CH8_PAYLOAD_CAMERA: { + case power::PDU2_CH8_PAYLOAD_CAMERA: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_CAMERA; module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } - case pcdu::P60_DOCK_5V_STACK: { + case power::P60_DOCK_5V_STACK: { memoryAddress = P60Dock::CONFIG_ADDRESS_OUT_EN_5V_STACK; module = ObjectManager::instance()->get(objects::P60DOCK_HANDLER); break; @@ -399,7 +400,7 @@ ReturnValue_t PcduHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onO ReturnValue_t PcduHandler::sendFuseOnCommand(uint8_t fuseNr) { return returnvalue::OK; } ReturnValue_t PcduHandler::getSwitchState(uint8_t switchNr) const { - if (switchNr >= pcdu::NUMBER_OF_SWITCHES) { + if (switchNr >= power::NUMBER_OF_SWITCHES) { sif::debug << "PCDUHandler::getSwitchState: Invalid switch number" << std::endl; return returnvalue::FAILED; } @@ -459,7 +460,7 @@ LocalPoolDataSetBase* PcduHandler::getDataSetHandle(sid_t sid) { } } -void PcduHandler::checkAndUpdatePduSwitch(GOMSPACE::Pdu pdu, pcdu::Switches switchIdx, +void PcduHandler::checkAndUpdatePduSwitch(GOMSPACE::Pdu pdu, power::Switches switchIdx, uint8_t setValue) { using namespace pcdu; if (switchStates[switchIdx] != setValue) { diff --git a/mission/power/PcduHandler.h b/mission/power/PcduHandler.h index dd7c235a..a59ae3da 100644 --- a/mission/power/PcduHandler.h +++ b/mission/power/PcduHandler.h @@ -88,7 +88,7 @@ class PcduHandler : public PowerSwitchIF, CCSDSTime::CDS_short timeStampPdu1HkDataset; uint8_t SWITCH_STATE_UNKNOWN = 2; - uint8_t switchStates[pcdu::NUMBER_OF_SWITCHES]; + uint8_t switchStates[power::NUMBER_OF_SWITCHES]; /** * Pointer to the IPCStore. * This caches the pointer received from the objectManager in the constructor. @@ -137,7 +137,7 @@ class PcduHandler : public PowerSwitchIF, */ void updateHkTableDataset(store_address_t storeId, LocalPoolDataSetBase* dataset, CCSDSTime::CDS_short* datasetTimeStamp); - void checkAndUpdatePduSwitch(GOMSPACE::Pdu pdu, pcdu::Switches switchIdx, uint8_t setValue); + void checkAndUpdatePduSwitch(GOMSPACE::Pdu pdu, power::Switches switchIdx, uint8_t setValue); }; #endif /* MISSION_POWER_PCDUHANDLER_H_ */ diff --git a/mission/power/defs.h b/mission/power/defs.h index 70e155a6..6cb1d16b 100644 --- a/mission/power/defs.h +++ b/mission/power/defs.h @@ -3,11 +3,38 @@ #include #include +#include #include "eive/eventSubsystemIds.h" namespace power { +/* Switches are uint8_t datatype and go from 0 to 255 */ +enum Switches : power::Switch_t { + PDU1_CH0_TCS_BOARD_3V3, + PDU1_CH1_SYRLINKS_12V, + PDU1_CH2_STAR_TRACKER_5V, + PDU1_CH3_MGT_5V, + PDU1_CH4_SUS_NOMINAL_3V3, + PDU1_CH5_SOLAR_CELL_EXP_5V, + PDU1_CH6_PLOC_12V, + PDU1_CH7_ACS_A_SIDE_3V3, + PDU1_CH8_UNOCCUPIED, + + PDU2_CH0_Q7S, + PDU2_CH1_PL_PCDU_BATT_0_14V8, + PDU2_CH2_RW_5V, + PDU2_CH3_TCS_BOARD_HEATER_IN_8V, + PDU2_CH4_SUS_REDUNDANT_3V3, + PDU2_CH5_DEPLOYMENT_MECHANISM_8V, + PDU2_CH6_PL_PCDU_BATT_1_14V8, + PDU2_CH7_ACS_BOARD_SIDE_B_3V3, + PDU2_CH8_PAYLOAD_CAMERA, + + P60_DOCK_5V_STACK, + NUMBER_OF_SWITCHES +}; + static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_HANDLER; //! [EXPORT] : [COMMENT] Indicates that a FSFW object requested setting a switch //! P1: 1 if on was requested, 0 for off | P2: Switch Index diff --git a/mission/power/gsDefs.h b/mission/power/gsDefs.h index e1ffe6d3..d155bb54 100644 --- a/mission/power/gsDefs.h +++ b/mission/power/gsDefs.h @@ -11,6 +11,7 @@ #include "devices/powerSwitcherList.h" #include "fsfw/platform.h" +#include "mission/power/defs.h" namespace GOMSPACE { @@ -715,32 +716,6 @@ namespace pcdu { enum PoolIds : uint32_t { PDU1_SWITCHES, PDU2_SWITCHES, P60DOCK_SWITCHES }; -/* Switches are uint8_t datatype and go from 0 to 255 */ -enum Switches : power::Switch_t { - PDU1_CH0_TCS_BOARD_3V3, - PDU1_CH1_SYRLINKS_12V, - PDU1_CH2_STAR_TRACKER_5V, - PDU1_CH3_MGT_5V, - PDU1_CH4_SUS_NOMINAL_3V3, - PDU1_CH5_SOLAR_CELL_EXP_5V, - PDU1_CH6_PLOC_12V, - PDU1_CH7_ACS_A_SIDE_3V3, - PDU1_CH8_UNOCCUPIED, - - PDU2_CH0_Q7S, - PDU2_CH1_PL_PCDU_BATT_0_14V8, - PDU2_CH2_RW_5V, - PDU2_CH3_TCS_BOARD_HEATER_IN_8V, - PDU2_CH4_SUS_REDUNDANT_3V3, - PDU2_CH5_DEPLOYMENT_MECHANISM_8V, - PDU2_CH6_PL_PCDU_BATT_1_14V8, - PDU2_CH7_ACS_BOARD_SIDE_B_3V3, - PDU2_CH8_PAYLOAD_CAMERA, - - P60_DOCK_5V_STACK, - NUMBER_OF_SWITCHES -}; - static const uint8_t ON = 1; static const uint8_t OFF = 0; @@ -760,7 +735,7 @@ const std::array INIT_SWITCHES_PDU2 = {ON, OFF, OFF static constexpr uint32_t SWITCHER_SET_ID = 0; -class SwitcherStates : public StaticLocalDataSet { +class SwitcherStates : public StaticLocalDataSet { public: SwitcherStates(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, SWITCHER_SET_ID) {} diff --git a/mission/system/acs/AcsBoardAssembly.h b/mission/system/acs/AcsBoardAssembly.h index b9255704..6619dadb 100644 --- a/mission/system/acs/AcsBoardAssembly.h +++ b/mission/system/acs/AcsBoardAssembly.h @@ -113,8 +113,8 @@ class AcsBoardAssembly : public DualLaneAssemblyBase { void selectGpsInDualMode(duallane::Submodes side); private: - static constexpr pcdu::Switches SWITCH_A = pcdu::Switches::PDU1_CH7_ACS_A_SIDE_3V3; - static constexpr pcdu::Switches SWITCH_B = pcdu::Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3; + static constexpr power::Switches SWITCH_A = power::Switches::PDU1_CH7_ACS_A_SIDE_3V3; + static constexpr power::Switches SWITCH_B = power::Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3; AcsBoardHelper helper; GpioIF* gpioIF = nullptr; diff --git a/mission/system/acs/DualLaneAssemblyBase.cpp b/mission/system/acs/DualLaneAssemblyBase.cpp index 6c5fab89..858e6892 100644 --- a/mission/system/acs/DualLaneAssemblyBase.cpp +++ b/mission/system/acs/DualLaneAssemblyBase.cpp @@ -5,7 +5,7 @@ #include "OBSWConfig.h" DualLaneAssemblyBase::DualLaneAssemblyBase(object_id_t objectId, PowerSwitchIF* pwrSwitcher, - pcdu::Switches switch1, pcdu::Switches switch2, + power::Switches switch1, power::Switches switch2, Event pwrTimeoutEvent, Event sideSwitchNotAllowedEvent, Event transitionOtherSideFailedEvent) : AssemblyBase(objectId, 20), diff --git a/mission/system/acs/DualLaneAssemblyBase.h b/mission/system/acs/DualLaneAssemblyBase.h index 2269fd2a..d15a2f30 100644 --- a/mission/system/acs/DualLaneAssemblyBase.h +++ b/mission/system/acs/DualLaneAssemblyBase.h @@ -18,8 +18,8 @@ class DualLaneAssemblyBase : public AssemblyBase, public ConfirmsFailuresIF { static constexpr UniqueEventId_t POWER_STATE_MACHINE_TIMEOUT_ID = 2; static constexpr UniqueEventId_t SIDE_SWITCH_TRANSITION_NOT_ALLOWED_ID = 3; - DualLaneAssemblyBase(object_id_t objectId, PowerSwitchIF* pwrSwitcher, pcdu::Switches switch1, - pcdu::Switches switch2, Event pwrSwitchTimeoutEvent, + DualLaneAssemblyBase(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switches switch1, + power::Switches switch2, Event pwrSwitchTimeoutEvent, Event sideSwitchNotAllowedEvent, Event transitionOtherSideFailedEvent); protected: diff --git a/mission/system/acs/SusAssembly.h b/mission/system/acs/SusAssembly.h index e993bee4..15f347dd 100644 --- a/mission/system/acs/SusAssembly.h +++ b/mission/system/acs/SusAssembly.h @@ -44,8 +44,8 @@ class SusAssembly : public DualLaneAssemblyBase { private: enum class States { IDLE, SWITCHING_POWER, MODE_COMMANDING } state = States::IDLE; - static constexpr pcdu::Switches SWITCH_NOM = pcdu::Switches::PDU1_CH4_SUS_NOMINAL_3V3; - static constexpr pcdu::Switches SWITCH_RED = pcdu::Switches::PDU2_CH4_SUS_REDUNDANT_3V3; + static constexpr power::Switches SWITCH_NOM = power::Switches::PDU1_CH4_SUS_NOMINAL_3V3; + static constexpr power::Switches SWITCH_RED = power::Switches::PDU2_CH4_SUS_REDUNDANT_3V3; FixedArrayList modeTable; SusAssHelper helper; diff --git a/mission/system/com/ComSubsystem.cpp b/mission/system/com/ComSubsystem.cpp index 759ace4a..5001dbe5 100644 --- a/mission/system/com/ComSubsystem.cpp +++ b/mission/system/com/ComSubsystem.cpp @@ -1,5 +1,6 @@ #include "ComSubsystem.h" +#include #include #include #include @@ -7,6 +8,7 @@ #include #include #include +#include #include @@ -21,7 +23,13 @@ ComSubsystem::ComSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequence } void ComSubsystem::performChildOperation() { + Subsystem::performChildOperation(); readEventQueue(); + if (performRecoveryToRxOnly and not isInTransition) { + startRxOnlyRecovery(true); + // To avoid immediately enabling TX after falling back. + rememberBitLock = false; + } // Execute default rate sequence after transition has been completed if (rememberBitLock and not isInTransition) { startRxAndTxLowRateSeq(); @@ -30,8 +38,6 @@ void ComSubsystem::performChildOperation() { if (countdownActive) { checkTransmitterCountdown(); } - - Subsystem::performChildOperation(); } MessageQueueId_t ComSubsystem::getCommandQueue() const { return Subsystem::getCommandQueue(); } @@ -93,7 +99,11 @@ ReturnValue_t ComSubsystem::initialize() { "listener" << std::endl; #endif - return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->subscribeToEvent(eventQueue->getId(), + event::getEventId(tcsCtrl::SYRLINKS_OVERHEATING)); + if (result != returnvalue::OK) { + return ObjectManager::CHILD_INIT_FAILED; } result = manager->subscribeToEventRange(eventQueue->getId(), event::getEventId(PdecHandler::CARRIER_LOCK), @@ -144,6 +154,19 @@ void ComSubsystem::readEventQueue() { void ComSubsystem::handleEventMessage(EventMessage *eventMessage) { Event event = eventMessage->getEvent(); switch (event) { + case tcsCtrl::SYRLINKS_OVERHEATING: { + // This event overrides the bit lock. + rememberBitLock = false; + if (mode == com::RX_ONLY) { + return; + } + if (isInTransition) { + performRecoveryToRxOnly = true; + return; + } + startRxOnlyRecovery(true); + break; + } case PdecHandler::BIT_LOCK_PDEC: { handleBitLockEvent(); break; @@ -191,6 +214,12 @@ void ComSubsystem::checkTransmitterCountdown() { } } +void ComSubsystem::startRxOnlyRecovery(bool forced) { + modeHelper.setForced(forced); + startTransition(com::RX_ONLY, 0); + performRecoveryToRxOnly = false; +} + bool ComSubsystem::isTxMode(Mode_t mode) { if ((mode == com::Submode::RX_AND_TX_DEFAULT_DATARATE) || (mode == com::Submode::RX_AND_TX_LOW_DATARATE) || diff --git a/mission/system/com/ComSubsystem.h b/mission/system/com/ComSubsystem.h index 6a887d30..476bf646 100644 --- a/mission/system/com/ComSubsystem.h +++ b/mission/system/com/ComSubsystem.h @@ -57,6 +57,7 @@ class ComSubsystem : public Subsystem, public ReceivesParameterMessagesIF { * @brief Enables transmitter in low rate mode */ void startRxAndTxLowRateSeq(); + void startRxOnlyRecovery(bool forced); /** * @brief Returns true if mode is a mode where the transmitter is on @@ -73,6 +74,7 @@ class ComSubsystem : public Subsystem, public ReceivesParameterMessagesIF { MessageQueueIF *eventQueue = nullptr; bool enableTxWhenCarrierLock = false; + bool performRecoveryToRxOnly = false; // Countdown will be started as soon as the transmitter was enabled Countdown transmitterCountdown; diff --git a/mission/system/objects/CamSwitcher.cpp b/mission/system/objects/CamSwitcher.cpp index b995e211..90a78945 100644 --- a/mission/system/objects/CamSwitcher.cpp +++ b/mission/system/objects/CamSwitcher.cpp @@ -3,3 +3,8 @@ CamSwitcher::CamSwitcher(object_id_t objectId, PowerSwitchIF &pwrSwitcher, power::Switch_t pwrSwitch) : PowerSwitcherComponent(objectId, &pwrSwitcher, pwrSwitch) {} +void CamSwitcher::performFaultyOperation() { + if (not switcher.active() and switcher.getState() != PowerSwitcher::SWITCH_IS_OFF) { + switcher.turnOff(); + } +} diff --git a/mission/system/objects/CamSwitcher.h b/mission/system/objects/CamSwitcher.h index 672b884b..57f371ce 100644 --- a/mission/system/objects/CamSwitcher.h +++ b/mission/system/objects/CamSwitcher.h @@ -8,6 +8,7 @@ class CamSwitcher : public PowerSwitcherComponent { CamSwitcher(object_id_t objectId, PowerSwitchIF &pwrSwitcher, power::Switch_t pwrSwitch); private: + void performFaultyOperation() override; }; #endif /* MISSION_SYSTEM_OBJECTS_CAMSWITCHER_H_ */ diff --git a/mission/system/objects/EiveSystem.cpp b/mission/system/objects/EiveSystem.cpp index 22af5fb2..f6b99b1e 100644 --- a/mission/system/objects/EiveSystem.cpp +++ b/mission/system/objects/EiveSystem.cpp @@ -4,11 +4,15 @@ #include #include #include +#include +#include + +#include "mission/sysDefs.h" EiveSystem::EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables) : Subsystem(setObjectId, maxNumberOfSequences, maxNumberOfTables) { - auto mqArgs = MqArgs(getObjectId(), static_cast(this)); + auto mqArgs = MqArgs(SubsystemBase::getObjectId(), static_cast(this)); eventQueue = QueueFactory::instance()->createMessageQueue(10, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs); } @@ -16,15 +20,15 @@ EiveSystem::EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, void EiveSystem::announceMode(bool recursive) { const char* modeStr = "UNKNOWN"; switch (mode) { - case (acs::AcsMode::OFF): { - modeStr = "OFF"; + case (satsystem::Mode::BOOT): { + modeStr = "OFF/BOOT"; break; } - case (acs::AcsMode::SAFE): { + case (satsystem::Mode::SAFE): { modeStr = "SAFE"; break; } - case (acs::AcsMode::PTG_IDLE): { + case (satsystem::Mode::PTG_IDLE): { modeStr = "POINTING IDLE"; break; } @@ -46,12 +50,16 @@ void EiveSystem::announceMode(bool recursive) { } void EiveSystem::performChildOperation() { + Subsystem::performChildOperation(); handleEventMessages(); - return Subsystem::performChildOperation(); + if (not isInTransition and performSafeRecovery) { + commandSelfToSafe(); + performSafeRecovery = false; + } } ReturnValue_t EiveSystem::initialize() { - EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); + auto* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); if (manager == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "AcsSubsystem::initialize: Invalid event manager" << std::endl; @@ -67,21 +75,37 @@ ReturnValue_t EiveSystem::initialize() { #endif return ObjectManagerIF::CHILD_INIT_FAILED; } + manager->subscribeToEvent(eventQueue->getId(), + event::getEventId(tcsCtrl::PCDU_SYSTEM_OVERHEATING)); + manager->subscribeToEvent(eventQueue->getId(), event::getEventId(tcsCtrl::OBC_OVERHEATING)); + return Subsystem::initialize(); } void EiveSystem::handleEventMessages() { EventMessage event; - for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; - result = eventQueue->receiveMessage(&event)) { + for (ReturnValue_t status = eventQueue->receiveMessage(&event); status == returnvalue::OK; + status = eventQueue->receiveMessage(&event)) { switch (event.getMessageId()) { case EventMessage::EVENT_MESSAGE: + switch (event.getEvent()) { + case tcsCtrl::OBC_OVERHEATING: + case tcsCtrl::PCDU_SYSTEM_OVERHEATING: { + if (isInTransition) { + performSafeRecovery = true; + return; + } + + commandSelfToSafe(); + break; + } + } break; default: - sif::debug << "AcsSubsystem::performChildOperation: Did not subscribe " - "to this event message" - << std::endl; + sif::debug << "EiveSystem: Did not subscribe to event " << event.getEvent() << std::endl; break; } } } + +void EiveSystem::commandSelfToSafe() { startTransition(satsystem::Mode::SAFE, 0); } diff --git a/mission/system/objects/EiveSystem.h b/mission/system/objects/EiveSystem.h index 0d75b31a..06110775 100644 --- a/mission/system/objects/EiveSystem.h +++ b/mission/system/objects/EiveSystem.h @@ -8,12 +8,14 @@ class EiveSystem : public Subsystem { EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables); private: + MessageQueueIF* eventQueue = nullptr; + bool performSafeRecovery = false; + ReturnValue_t initialize() override; void performChildOperation() override; void announceMode(bool recursive) override; void handleEventMessages(); - - MessageQueueIF* eventQueue = nullptr; + void commandSelfToSafe(); }; #endif /* MISSION_SYSTEM_EIVESYSTEM_H_ */ diff --git a/mission/system/objects/Stack5VHandler.h b/mission/system/objects/Stack5VHandler.h index 17b9ed1e..8781fc55 100644 --- a/mission/system/objects/Stack5VHandler.h +++ b/mission/system/objects/Stack5VHandler.h @@ -31,7 +31,7 @@ class Stack5VHandler { HandlerState handlerState = HandlerState::IDLE; bool radSensorIsOn = false; bool plPcduIsOn = false; - pcdu::Switches stackSwitch = pcdu::Switches::P60_DOCK_5V_STACK; + power::Switches stackSwitch = power::Switches::P60_DOCK_5V_STACK; bool updateInternalStates(); }; diff --git a/mission/tcs/HeaterHandler.cpp b/mission/tcs/HeaterHandler.cpp index 4ceaa4ee..529fe698 100644 --- a/mission/tcs/HeaterHandler.cpp +++ b/mission/tcs/HeaterHandler.cpp @@ -38,7 +38,7 @@ HeaterHandler::HeaterHandler(object_id_t setObjectId_, GpioIF* gpioInterface_, H cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); } -HeaterHandler::~HeaterHandler() {} +HeaterHandler::~HeaterHandler() = default; ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) { try { @@ -259,7 +259,7 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switchers heaterIdx) { // Check state of main line switch ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch); if (mainSwitchState == PowerSwitchIF::SWITCH_ON) { - if (checkSwitchState(heaterIdx) == SwitchState::OFF) { + if (getSwitchState(heaterIdx) == SwitchState::OFF) { gpioId_t gpioId = heater.gpioId; result = gpioInterface->pullHigh(gpioId); if (result != returnvalue::OK) { @@ -292,12 +292,13 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switchers heaterIdx) { } else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF && heater.waitMainSwitchOn) { // Just waiting for the main switch being set on return; - } else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF) { + } else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF or + mainSwitchState == PowerSwitchIF::SWITCH_UNKNOWN) { mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_ON); heater.mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs()); heater.waitMainSwitchOn = true; } else { - sif::debug << "HeaterHandler::handleSwitchHandling: Failed to get state of" + sif::debug << "HeaterHandler::handleSwitchOnCommand: Failed to get state of" << " main line switch" << std::endl; if (heater.replyQueue != commandQueue->getId()) { actionHelper.finish(false, heater.replyQueue, heater.action, mainSwitchState); @@ -310,7 +311,7 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switchers heaterIdx) { ReturnValue_t result = returnvalue::OK; auto& heater = heaterVec.at(heaterIdx); // Check whether switch is already off - if (checkSwitchState(heaterIdx)) { + if (getSwitchState(heaterIdx)) { gpioId_t gpioId = heater.gpioId; result = gpioInterface->pullLow(gpioId); if (result != returnvalue::OK) { @@ -344,7 +345,7 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switchers heaterIdx) { heater.cmdActive = false; } -HeaterHandler::SwitchState HeaterHandler::checkSwitchState(heater::Switchers switchNr) const { +HeaterHandler::SwitchState HeaterHandler::getSwitchState(heater::Switchers switchNr) const { MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); return heaterVec.at(switchNr).switchState; } @@ -428,7 +429,7 @@ ReturnValue_t HeaterHandler::getSwitchState(uint8_t switchNr) const { if (switchNr > 7) { return returnvalue::FAILED; } - if (checkSwitchState(static_cast(switchNr)) == SwitchState::ON) { + if (getSwitchState(static_cast(switchNr)) == SwitchState::ON) { return PowerSwitchIF::SWITCH_ON; } return PowerSwitchIF::SWITCH_OFF; diff --git a/mission/tcs/HeaterHandler.h b/mission/tcs/HeaterHandler.h index 05e7e5d8..6787b660 100644 --- a/mission/tcs/HeaterHandler.h +++ b/mission/tcs/HeaterHandler.h @@ -174,7 +174,7 @@ class HeaterHandler : public ExecutableObjectIF, * @brief Returns the state of a switch (ON - true, or OFF - false). * @param switchNr The number of the switch to check. */ - SwitchState checkSwitchState(heater::Switchers switchNr) const; + SwitchState getSwitchState(heater::Switchers switchNr) const; /** * @brief This function runs commands waiting for execution. diff --git a/tmtc b/tmtc index 0f2daf94..cef8d623 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 0f2daf94dfaf3651330275ce5e5868fab263b56f +Subproject commit cef8d623c9fa11237fc8e51e5fd4dab750a5602b diff --git a/unittest/controller/testThermalController.cpp b/unittest/controller/testThermalController.cpp index 85e81a71..623c6d52 100644 --- a/unittest/controller/testThermalController.cpp +++ b/unittest/controller/testThermalController.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -19,7 +20,8 @@ TEST_CASE("Thermal Controller", "[ThermalController]") { TemperatureSensorInserter::Tmp1075DummyMap map1; new TemperatureSensorInserter(objects::THERMAL_TEMP_INSERTER, map0, map1); auto dummyGpioIF = new DummyGpioIF(); - auto dummySwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0); + auto* dummySwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0); + new CamSwitcher(objects::CAM_SWITCHER, *dummySwitcher, power::Switches::PDU2_CH8_PAYLOAD_CAMERA); // TODO: Create dummy heater handler HeaterHandler* heaterHandler = nullptr; // new ThermalController(objects::THERMAL_CONTROLLER);