#ifndef MISSION_CONTROLLER_CONTROLLERDEFINITIONS_THERMALCONTROLLERDEFINITIONS_H_ #define MISSION_CONTROLLER_CONTROLLERDEFINITIONS_THERMALCONTROLLERDEFINITIONS_H_ #include <fsfw/datapoollocal/LocalPoolVariable.h> #include <fsfw/datapoollocal/StaticLocalDataSet.h> #include "eive/eventSubsystemIds.h" #include "mission/tcs/defs.h" namespace tcsCtrl { /** * NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit * is exceeded. * OP Limit: Soft limit. Device should be switched off or TCS controller should take action if the * limit is exceeded to avoid reaching NOP limit */ struct TempLimits { TempLimits(float nopLowerLimit, float opLowerLimit, float cutOffLimit, float opUpperLimit, float nopUpperLimit) : opLowerLimit(opLowerLimit), opUpperLimit(opUpperLimit), cutOffLimit(cutOffLimit), nopLowerLimit(nopLowerLimit), nopUpperLimit(nopUpperLimit) {} float opLowerLimit; float opUpperLimit; float cutOffLimit; float nopLowerLimit; float nopUpperLimit; }; /** * Abstraction for the state of a single thermal component */ struct ThermalState { uint8_t noSensorAvailableCounter; // Which sensor is used for this component? uint8_t sensorIndex = 0; // Is heating on for that thermal module? bool heating = false; // Which switch is being used for heating the component heater::Switch heaterSwitch = heater::Switch::HEATER_NONE; // Heater start time and end times as UNIX seconds. Please note that these times will be updated // when a switch command is sent, with no guarantess that the heater actually went on. uint32_t heaterStartTime = 0; uint32_t heaterEndTime = 0; }; /** * Abstraction for the state of a single heater. */ struct HeaterState { bool switchTransition = false; heater::SwitchState target = heater::SwitchState::OFF; uint8_t heaterSwitchControlCycles = 0; bool trackHeaterMaxBurnTime = false; Countdown heaterOnMaxBurnTime; }; using HeaterSwitchStates = std::array<heater::SwitchState, heater::NUMBER_OF_SWITCHES>; enum ThermalComponents : uint8_t { NONE = 0, ACS_BOARD = 1, MGT = 2, RW = 3, STR = 4, IF_BOARD = 5, TCS_BOARD = 6, OBC = 7, LEGACY_OBCIF_BOARD = 8, SBAND_TRANSCEIVER = 9, PCDUP60_BOARD = 10, PCDUACU = 11, PCDUPDU = 12, PLPCDU_BOARD = 13, PLOCMISSION_BOARD = 14, PLOCPROCESSING_BOARD = 15, DAC = 16, CAMERA = 17, DRO = 18, X8 = 19, HPA = 20, TX = 21, MPA = 22, SCEX_BOARD = 23, NUM_THERMAL_COMPONENTS }; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_CONTROLLER; static 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); static constexpr Event MGT_OVERHEATING = MAKE_EVENT(8, severity::HIGH); //! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index static constexpr Event TCS_SWITCHING_HEATER_ON = MAKE_EVENT(9, severity::INFO); //! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index static constexpr Event TCS_SWITCHING_HEATER_OFF = MAKE_EVENT(10, severity::INFO); //! [EXPORT] : [COMMENT] P1: Heater index. P2: Maximum burn time for heater. static constexpr Event TCS_HEATER_MAX_BURN_TIME_REACHED = MAKE_EVENT(11, severity::MEDIUM); enum SetId : uint32_t { SENSOR_TEMPERATURES = 0, DEVICE_TEMPERATURES = 1, SUS_TEMPERATURES = 2, COMPONENT_TEMPERATURES = 3, HEATER_SET = 4, TCS_CTRL_INFO = 5 }; enum PoolIds : lp_id_t { SENSOR_PLOC_HEATSPREADER, SENSOR_PLOC_MISSIONBOARD, SENSOR_4K_CAMERA, SENSOR_DAC_HEATSPREADER, SENSOR_STARTRACKER, SENSOR_RW1, SENSOR_DRO, SENSOR_SCEX, SENSOR_X8, SENSOR_HPA, SENSOR_TX_MODUL, SENSOR_MPA, SENSOR_ACU, SENSOR_PLPCDU_HEATSPREADER, SENSOR_TCS_BOARD, SENSOR_MAGNETTORQUER, SENSOR_TMP1075_TCS_0, SENSOR_TMP1075_TCS_1, SENSOR_TMP1075_PLPCDU_0, SENSOR_TMP1075_PLPCDU_1, SENSOR_TMP1075_IF_BOARD, SUS_0_N_LOC_XFYFZM_PT_XF, SUS_6_R_LOC_XFYBZM_PT_XF, SUS_1_N_LOC_XBYFZM_PT_XB, SUS_7_R_LOC_XBYBZM_PT_XB, SUS_2_N_LOC_XFYBZB_PT_YB, SUS_8_R_LOC_XBYBZB_PT_YB, SUS_3_N_LOC_XFYBZF_PT_YF, SUS_9_R_LOC_XBYBZB_PT_YF, SUS_4_N_LOC_XMYFZF_PT_ZF, SUS_10_N_LOC_XMYBZF_PT_ZF, SUS_5_N_LOC_XFYMZB_PT_ZB, SUS_11_R_LOC_XBYMZB_PT_ZB, COMPONENT_RW, TEMP_Q7S, BATTERY_TEMP_1, BATTERY_TEMP_2, BATTERY_TEMP_3, BATTERY_TEMP_4, TEMP_RW1, TEMP_RW2, TEMP_RW3, TEMP_RW4, TEMP_STAR_TRACKER, TEMP_SYRLINKS_POWER_AMPLIFIER, TEMP_SYRLINKS_BASEBAND_BOARD, TEMP_MGT, TEMP_ACU, TEMP_PDU1, TEMP_PDU2, TEMP_1_P60DOCK, TEMP_2_P60DOCK, TEMP_GYRO_0_SIDE_A, TEMP_GYRO_1_SIDE_A, TEMP_GYRO_2_SIDE_B, TEMP_GYRO_3_SIDE_B, TEMP_MGM_0_SIDE_A, TEMP_MGM_2_SIDE_B, TEMP_ADC_PAYLOAD_PCDU, HEATER_SWITCH_LIST, HEATER_CURRENT, HEATER_ON_FOR_COMPONENT_VEC, SENSOR_USED_FOR_TCS_CTRL, HEATER_IDX_USED_FOR_TCS_CTRL, HEATER_START_TIME, HEATER_END_TIME }; static const uint8_t ENTRIES_SENSOR_TEMPERATURE_SET = 25; static const uint8_t ENTRIES_DEVICE_TEMPERATURE_SET = 25; static const uint8_t ENTRIES_SUS_TEMPERATURE_SET = 12; /** * @brief This dataset can be used to store the collected temperatures of all temperature sensors */ class SensorTemperatures : public StaticLocalDataSet<ENTRIES_SENSOR_TEMPERATURE_SET> { public: explicit SensorTemperatures(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, SENSOR_TEMPERATURES) {} explicit SensorTemperatures(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, SENSOR_TEMPERATURES)) {} lp_var_t<float> plocHeatspreader = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_PLOC_HEATSPREADER, this); lp_var_t<float> plocMissionboard = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_PLOC_MISSIONBOARD, this); lp_var_t<float> payload4kCamera = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_4K_CAMERA, this); lp_var_t<float> dacHeatspreader = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_DAC_HEATSPREADER, this); lp_var_t<float> startracker = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_STARTRACKER, this); lp_var_t<float> rw1 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_RW1, this); lp_var_t<float> scex = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_SCEX, this); lp_var_t<float> eBandTx = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TX_MODUL, this); // E-Band module lp_var_t<float> dro = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_DRO, this); lp_var_t<float> mpa = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_MPA, this); lp_var_t<float> x8 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_X8, this); lp_var_t<float> hpa = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_HPA, this); lp_var_t<float> acu = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_ACU, this); lp_var_t<float> plpcduHeatspreader = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_PLPCDU_HEATSPREADER, this); lp_var_t<float> tcsBoard = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TCS_BOARD, this); lp_var_t<float> mgt = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_MAGNETTORQUER, this); lp_var_t<float> tmp1075Tcs0 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TMP1075_TCS_0, this); lp_var_t<float> tmp1075Tcs1 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TMP1075_TCS_1, this); lp_var_t<float> tmp1075PlPcdu0 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TMP1075_PLPCDU_0, this); lp_var_t<float> tmp1075PlPcdu1 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TMP1075_PLPCDU_1, this); lp_var_t<float> tmp1075IfBrd = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TMP1075_IF_BOARD, this); }; /** * @brief This dataset can be used to store the collected temperatures of all device temperature * sensors */ class DeviceTemperatures : public StaticLocalDataSet<ENTRIES_DEVICE_TEMPERATURE_SET> { public: explicit DeviceTemperatures(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, DEVICE_TEMPERATURES) {} explicit DeviceTemperatures(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, DEVICE_TEMPERATURES)) {} lp_var_t<float> q7s = lp_var_t<float>(sid.objectId, PoolIds::TEMP_Q7S, this); lp_var_t<int16_t> batteryTemp1 = lp_var_t<int16_t>(sid.objectId, PoolIds::BATTERY_TEMP_1, this); lp_var_t<int16_t> batteryTemp2 = lp_var_t<int16_t>(sid.objectId, PoolIds::BATTERY_TEMP_2, this); lp_var_t<int16_t> batteryTemp3 = lp_var_t<int16_t>(sid.objectId, PoolIds::BATTERY_TEMP_3, this); lp_var_t<int16_t> batteryTemp4 = lp_var_t<int16_t>(sid.objectId, PoolIds::BATTERY_TEMP_4, this); lp_var_t<int32_t> rw1 = lp_var_t<int32_t>(sid.objectId, PoolIds::TEMP_RW1, this); lp_var_t<int32_t> rw2 = lp_var_t<int32_t>(sid.objectId, PoolIds::TEMP_RW2, this); lp_var_t<int32_t> rw3 = lp_var_t<int32_t>(sid.objectId, PoolIds::TEMP_RW3, this); lp_var_t<int32_t> rw4 = lp_var_t<int32_t>(sid.objectId, PoolIds::TEMP_RW4, this); lp_var_t<float> startracker = lp_var_t<float>(sid.objectId, PoolIds::TEMP_STAR_TRACKER, this); lp_var_t<float> syrlinksPowerAmplifier = lp_var_t<float>(sid.objectId, PoolIds::TEMP_SYRLINKS_POWER_AMPLIFIER, this); lp_var_t<float> syrlinksBasebandBoard = lp_var_t<float>(sid.objectId, PoolIds::TEMP_SYRLINKS_BASEBAND_BOARD, this); lp_var_t<int16_t> mgt = lp_var_t<int16_t>(sid.objectId, PoolIds::TEMP_MGT, this); lp_vec_t<float, 3> acu = lp_vec_t<float, 3>(sid.objectId, PoolIds::TEMP_ACU, this); lp_var_t<float> pdu1 = lp_var_t<float>(sid.objectId, PoolIds::TEMP_PDU1, this); lp_var_t<float> pdu2 = lp_var_t<float>(sid.objectId, PoolIds::TEMP_PDU2, this); lp_var_t<float> temp1P60dock = lp_var_t<float>(sid.objectId, PoolIds::TEMP_1_P60DOCK, this); lp_var_t<float> temp2P60dock = lp_var_t<float>(sid.objectId, PoolIds::TEMP_2_P60DOCK, this); lp_var_t<float> gyro0SideA = lp_var_t<float>(sid.objectId, PoolIds::TEMP_GYRO_0_SIDE_A, this); lp_var_t<float> gyro1SideA = lp_var_t<float>(sid.objectId, PoolIds::TEMP_GYRO_1_SIDE_A, this); lp_var_t<float> gyro2SideB = lp_var_t<float>(sid.objectId, PoolIds::TEMP_GYRO_2_SIDE_B, this); lp_var_t<float> gyro3SideB = lp_var_t<float>(sid.objectId, PoolIds::TEMP_GYRO_3_SIDE_B, this); lp_var_t<float> mgm0SideA = lp_var_t<float>(sid.objectId, PoolIds::TEMP_MGM_0_SIDE_A, this); lp_var_t<float> mgm2SideB = lp_var_t<float>(sid.objectId, PoolIds::TEMP_MGM_2_SIDE_B, this); lp_var_t<float> adcPayloadPcdu = lp_var_t<float>(sid.objectId, PoolIds::TEMP_ADC_PAYLOAD_PCDU, this); }; /** * @brief This dataset can be used to store the collected temperatures of all SUS temperature * sensors */ class SusTemperatures : public StaticLocalDataSet<ENTRIES_SUS_TEMPERATURE_SET> { public: explicit SusTemperatures(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, SUS_TEMPERATURES) {} explicit SusTemperatures(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, SUS_TEMPERATURES)) {} lp_var_t<float> sus_0_n_loc_xfyfzm_pt_xf = lp_var_t<float>(sid.objectId, PoolIds::SUS_0_N_LOC_XFYFZM_PT_XF, this); lp_var_t<float> sus_6_r_loc_xfybzm_pt_xf = lp_var_t<float>(sid.objectId, PoolIds::SUS_6_R_LOC_XFYBZM_PT_XF, this); lp_var_t<float> sus_1_n_loc_xbyfzm_pt_xb = lp_var_t<float>(sid.objectId, PoolIds::SUS_1_N_LOC_XBYFZM_PT_XB, this); lp_var_t<float> sus_7_r_loc_xbybzm_pt_xb = lp_var_t<float>(sid.objectId, PoolIds::SUS_7_R_LOC_XBYBZM_PT_XB, this); lp_var_t<float> sus_2_n_loc_xfybzb_pt_yb = lp_var_t<float>(sid.objectId, PoolIds::SUS_2_N_LOC_XFYBZB_PT_YB, this); lp_var_t<float> sus_8_r_loc_xbybzb_pt_yb = lp_var_t<float>(sid.objectId, PoolIds::SUS_8_R_LOC_XBYBZB_PT_YB, this); lp_var_t<float> sus_3_n_loc_xfybzf_pt_yf = lp_var_t<float>(sid.objectId, PoolIds::SUS_3_N_LOC_XFYBZF_PT_YF, this); lp_var_t<float> sus_9_r_loc_xbybzb_pt_yf = lp_var_t<float>(sid.objectId, PoolIds::SUS_9_R_LOC_XBYBZB_PT_YF, this); lp_var_t<float> sus_4_n_loc_xmyfzf_pt_zf = lp_var_t<float>(sid.objectId, PoolIds::SUS_4_N_LOC_XMYFZF_PT_ZF, this); lp_var_t<float> sus_10_n_loc_xmybzf_pt_zf = lp_var_t<float>(sid.objectId, PoolIds::SUS_10_N_LOC_XMYBZF_PT_ZF, this); lp_var_t<float> sus_5_n_loc_xfymzb_pt_zb = lp_var_t<float>(sid.objectId, PoolIds::SUS_5_N_LOC_XFYMZB_PT_ZB, this); lp_var_t<float> sus_11_r_loc_xbymzb_pt_zb = lp_var_t<float>(sid.objectId, PoolIds::SUS_11_R_LOC_XBYMZB_PT_ZB, this); }; class HeaterInfo : public StaticLocalDataSet<3> { public: HeaterInfo(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, HEATER_SET) {} HeaterInfo(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, HEATER_SET)) {} lp_vec_t<uint8_t, heater::NUMBER_OF_SWITCHES> heaterSwitchState = lp_vec_t<uint8_t, heater::NUMBER_OF_SWITCHES>(sid.objectId, PoolIds::HEATER_SWITCH_LIST, this); lp_var_t<int16_t> heaterCurrent = lp_var_t<int16_t>(sid.objectId, PoolIds::HEATER_CURRENT, this); }; class TcsCtrlInfo : public StaticLocalDataSet<6> { public: explicit TcsCtrlInfo(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, TCS_CTRL_INFO) {} explicit TcsCtrlInfo(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, TCS_CTRL_INFO)) {} lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heatingOnVec = lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>( sid.objectId, PoolIds::HEATER_ON_FOR_COMPONENT_VEC, this); lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> sensorIdxUsedForTcsCtrl = lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::SENSOR_USED_FOR_TCS_CTRL, this); lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterSwitchIdx = lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>( sid.objectId, PoolIds::HEATER_IDX_USED_FOR_TCS_CTRL, this); lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterStartTimes = lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_START_TIME, this); lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterEndTimes = lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_END_TIME, this); }; } // namespace tcsCtrl #endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_THERMALCONTROLLERDEFINITIONS_H_ */