TCS heater upper burn limit #732

Merged
muellerr merged 18 commits from tcs-heater-upper-limit into main 2023-07-11 10:56:44 +02:00
15 changed files with 163 additions and 29 deletions

View File

@ -51,6 +51,9 @@ will consitute of a breaking change warranting a new major release:
# Added # Added
- Two events for heaters being commanded ON and OFF by the TCS controller - Two events for heaters being commanded ON and OFF by the TCS controller
- Upper limit for burn time of TCS heaters. Currently set to 1 hour for each heater.
This mechanism will only track the burn time for heaters which were commanded by the
TCS controller.
# [v6.0.0] 2023-07-02 # [v6.0.0] 2023-07-02

View File

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 298 translations. * @brief Auto-generated event translation file. Contains 299 translations.
* @details * @details
* Generated on: 2023-07-06 19:00:21 * Generated on: 2023-07-07 12:06:06
*/ */
#include "translateEvents.h" #include "translateEvents.h"
@ -288,6 +288,7 @@ const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING"; const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON"; const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF"; const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED"; const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON"; const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION"; const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
@ -872,6 +873,8 @@ const char *translateEvents(Event event) {
return TCS_SWITCHING_HEATER_ON_STRING; return TCS_SWITCHING_HEATER_ON_STRING;
case (14110): case (14110):
return TCS_SWITCHING_HEATER_OFF_STRING; return TCS_SWITCHING_HEATER_OFF_STRING;
case (14111):
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
case (14201): case (14201):
return TX_TIMER_EXPIRED_STRING; return TX_TIMER_EXPIRED_STRING;
case (14202): case (14202):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 171 translations. * Contains 171 translations.
* Generated on: 2023-07-06 19:00:21 * Generated on: 2023-07-07 12:06:06
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@ -126,6 +126,21 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
sif::debug << "Setting CAM temperature back to normal" << std::endl; sif::debug << "Setting CAM temperature back to normal" << std::endl;
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(0, true); max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(0, true);
} }
break;
}
case (TestCase::COLD_PLOC_STAYS_COLD): {
if (cycles == 15) {
sif::debug << "Setting cold PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-40, true);
}
break;
}
case (TestCase::COLD_CAMERA_STAYS_COLD): {
if (cycles == 15) {
sif::debug << "Setting cold PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-40, true);
}
break;
} }
} }
cycles++; cycles++;

View File

@ -33,6 +33,8 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
COLD_STR_CONSECUTIVE = 5, COLD_STR_CONSECUTIVE = 5,
COLD_CAMERA = 6, COLD_CAMERA = 6,
COLD_PLOC_CONSECUTIVE = 7, COLD_PLOC_CONSECUTIVE = 7,
COLD_PLOC_STAYS_COLD = 8,
COLD_CAMERA_STAYS_COLD = 9
}; };
int iteration = 0; int iteration = 0;
uint32_t cycles = 0; uint32_t cycles = 0;

View File

@ -282,6 +282,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h 14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h 14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14111;0x371f;TCS_HEATER_MAX_BURN_TIME_REACHED;MEDIUM;P1: Heater index. P2: Maximum burn time for heater.;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 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 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 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

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
282 14108 0x371c MGT_OVERHEATING HIGH No description mission/controller/tcsDefs.h
283 14109 0x371d TCS_SWITCHING_HEATER_ON INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
284 14110 0x371e TCS_SWITCHING_HEATER_OFF INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
285 14111 0x371f TCS_HEATER_MAX_BURN_TIME_REACHED MEDIUM P1: Heater index. P2: Maximum burn time for heater. mission/controller/tcsDefs.h
286 14201 0x3779 TX_TIMER_EXPIRED INFO The transmit timer to protect the Syrlinks expired P1: The current timer value mission/system/com/ComSubsystem.h
287 14202 0x377a BIT_LOCK_TX_ON INFO Transmitter will be turned on due to detection of bitlock mission/system/com/ComSubsystem.h
288 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

View File

@ -282,6 +282,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h 14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h 14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14111;0x371f;TCS_HEATER_MAX_BURN_TIME_REACHED;MEDIUM;P1: Heater index. P2: Maximum burn time for heater.;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 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 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 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

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
282 14108 0x371c MGT_OVERHEATING HIGH No description mission/controller/tcsDefs.h
283 14109 0x371d TCS_SWITCHING_HEATER_ON INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
284 14110 0x371e TCS_SWITCHING_HEATER_OFF INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
285 14111 0x371f TCS_HEATER_MAX_BURN_TIME_REACHED MEDIUM P1: Heater index. P2: Maximum burn time for heater. mission/controller/tcsDefs.h
286 14201 0x3779 TX_TIMER_EXPIRED INFO The transmit timer to protect the Syrlinks expired P1: The current timer value mission/system/com/ComSubsystem.h
287 14202 0x377a BIT_LOCK_TX_ON INFO Transmitter will be turned on due to detection of bitlock mission/system/com/ComSubsystem.h
288 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

View File

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 298 translations. * @brief Auto-generated event translation file. Contains 299 translations.
* @details * @details
* Generated on: 2023-07-06 19:00:21 * Generated on: 2023-07-07 12:06:06
*/ */
#include "translateEvents.h" #include "translateEvents.h"
@ -288,6 +288,7 @@ const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING"; const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON"; const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF"; const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED"; const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON"; const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION"; const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
@ -872,6 +873,8 @@ const char *translateEvents(Event event) {
return TCS_SWITCHING_HEATER_ON_STRING; return TCS_SWITCHING_HEATER_ON_STRING;
case (14110): case (14110):
return TCS_SWITCHING_HEATER_OFF_STRING; return TCS_SWITCHING_HEATER_OFF_STRING;
case (14111):
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
case (14201): case (14201):
return TX_TIMER_EXPIRED_STRING; return TX_TIMER_EXPIRED_STRING;
case (14202): case (14202):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 175 translations. * Contains 175 translations.
* Generated on: 2023-07-06 19:00:21 * Generated on: 2023-07-07 12:06:06
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 298 translations. * @brief Auto-generated event translation file. Contains 299 translations.
* @details * @details
* Generated on: 2023-07-06 19:00:21 * Generated on: 2023-07-07 12:06:06
*/ */
#include "translateEvents.h" #include "translateEvents.h"
@ -288,6 +288,7 @@ const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING"; const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON"; const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF"; const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED"; const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON"; const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION"; const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
@ -872,6 +873,8 @@ const char *translateEvents(Event event) {
return TCS_SWITCHING_HEATER_ON_STRING; return TCS_SWITCHING_HEATER_ON_STRING;
case (14110): case (14110):
return TCS_SWITCHING_HEATER_OFF_STRING; return TCS_SWITCHING_HEATER_OFF_STRING;
case (14111):
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
case (14201): case (14201):
return TX_TIMER_EXPIRED_STRING; return TX_TIMER_EXPIRED_STRING;
case (14202): case (14202):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 175 translations. * Contains 175 translations.
* Generated on: 2023-07-06 19:00:21 * Generated on: 2023-07-07 12:06:06
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@ -209,9 +209,13 @@ void ThermalController::performControlOperation() {
} else { } else {
transitionWhenHeatersOffCycles++; transitionWhenHeatersOffCycles++;
} }
} else if (mode != MODE_OFF and not tcsBrdShortlyUnavailable) { } else if (mode != MODE_OFF) {
if (not tcsBrdShortlyUnavailable) {
performThermalModuleCtrl(heaterSwitchStateArray); performThermalModuleCtrl(heaterSwitchStateArray);
} }
heaterTransitionControl(heaterSwitchStateArray);
heaterMaxDurationControl(heaterSwitchStateArray);
}
} }
ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
@ -1566,9 +1570,8 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
eBandTooHotFlag = false; eBandTooHotFlag = false;
} }
} }
heaterTransitionControl(heaterSwitchStates);
} }
void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) { void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) {
if (selectAndReadSensorTemp(htrCtx)) { if (selectAndReadSensorTemp(htrCtx)) {
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) { if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
@ -1594,6 +1597,7 @@ bool ThermalController::selectAndReadSensorTemp(HeaterContext& htrCtx) {
sensors[i].second > SANITY_LIMIT_LOWER_TEMP and sensors[i].second > SANITY_LIMIT_LOWER_TEMP and
sensors[i].second < SANITY_LIMIT_UPPER_TEMP) { sensors[i].second < SANITY_LIMIT_UPPER_TEMP) {
sensorTemp = sensors[i].second; sensorTemp = sensors[i].second;
currentSensorIndex = i;
thermalStates[currThermalComponent].noSensorAvailableCounter = 0; thermalStates[currThermalComponent].noSensorAvailableCounter = 0;
return true; return true;
} }
@ -1672,8 +1676,6 @@ void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
sif::info << "TCS: Heater " << static_cast<int>(htrCtx.switchNr) << " for component " sif::info << "TCS: Heater " << static_cast<int>(htrCtx.switchNr) << " for component "
<< static_cast<int>(currThermalComponent) << " ON" << std::endl; << static_cast<int>(currThermalComponent) << " ON" << std::endl;
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::ON, currThermalComponent); heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::ON, currThermalComponent);
heaterStates[htrCtx.switchNr].switchTransition = true;
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::ON;
} else { } else {
// Even if heater control is now allowed, we can update the state. // Even if heater control is now allowed, we can update the state.
thermalStates[currThermalComponent].heating = false; thermalStates[currThermalComponent].heating = false;
@ -1738,6 +1740,17 @@ void ThermalController::heaterTransitionControl(const HeaterSwitchStates& curren
for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) { for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) {
if (heaterStates[i].switchTransition) { if (heaterStates[i].switchTransition) {
if (currentHeaterStates[i] == heaterStates[i].target) { if (currentHeaterStates[i] == heaterStates[i].target) {
// Required for max heater period control
if (currentHeaterStates[i] == HeaterHandler::SwitchState::ON) {
heaterStates[i].heaterOnPeriod.setTimeout(MAX_HEATER_ON_DURATIONS_MS[i]);
heaterStates[i].heaterOnPeriod.resetTimer();
heaterStates[i].trackHeaterMaxPeriod = true;
} else {
heaterStates[i].trackHeaterMaxPeriod = false;
// The heater might still be one for some thermal components, so cross-check
// those components
crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(static_cast<heater::Switch>(i));
}
heaterStates[i].switchTransition = false; heaterStates[i].switchTransition = false;
heaterStates[i].heaterSwitchControlCycles = 0; heaterStates[i].heaterSwitchControlCycles = 0;
continue; continue;
@ -1750,6 +1763,27 @@ void ThermalController::heaterTransitionControl(const HeaterSwitchStates& curren
} }
} }
} }
void ThermalController::heaterMaxDurationControl(const HeaterSwitchStates& currentHeaterStates) {
for (unsigned i = 0; i < heater::Switch::NUMBER_OF_SWITCHES; i++) {
// Right now, we only track the maximum duration for heater which were commanded by the TCS
// controller.
if (currentHeaterStates[i] == HeaterHandler::SwitchState::ON and
heaterStates[i].trackHeaterMaxPeriod and heaterStates[i].heaterOnPeriod.hasTimedOut()) {
heaterStates[i].switchTransition = false;
heaterStates[i].heaterSwitchControlCycles = 0;
heaterStates[i].trackHeaterMaxPeriod = false;
triggerEvent(tcsCtrl::TCS_HEATER_MAX_BURN_TIME_REACHED, static_cast<uint32_t>(i),
MAX_HEATER_ON_DURATIONS_MS[i]);
heaterSwitchHelper(static_cast<heater::Switch>(i), HeaterHandler::SwitchState::OFF,
std::nullopt);
// The heater might still be one for some thermal components, so cross-check
// those components
crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(static_cast<heater::Switch>(i));
}
}
}
uint32_t ThermalController::tempFloatToU32() const { uint32_t ThermalController::tempFloatToU32() const {
auto sensorTempAsFloat = static_cast<float>(sensorTemp); auto sensorTempAsFloat = static_cast<float>(sensorTemp);
uint32_t tempRaw = 0; uint32_t tempRaw = 0;
@ -1784,26 +1818,40 @@ bool ThermalController::heaterCtrlAllowed() const { return submode != SUBMODE_NO
void ThermalController::resetThermalStates() { void ThermalController::resetThermalStates() {
for (auto& thermalState : thermalStates) { for (auto& thermalState : thermalStates) {
thermalState.heating = false; thermalState.heating = false;
thermalState.noSensorAvailableCounter = 0;
thermalState.heaterStartTime = 0;
thermalState.heaterEndTime = 0;
thermalState.sensorIndex = 0;
thermalState.heaterSwitch = heater::Switch::NUMBER_OF_SWITCHES;
} }
} }
void ThermalController::heaterSwitchHelper(heater::Switch switchNr, void ThermalController::heaterSwitchHelper(heater::Switch switchNr,
HeaterHandler::SwitchState state, HeaterHandler::SwitchState targetState,
unsigned componentIdx) { std::optional<unsigned> componentIdx) {
timeval currentTime; timeval currentTime;
Clock::getClockMonotonic(&currentTime); Clock::getClockMonotonic(&currentTime);
if (state == HeaterHandler::SwitchState::ON) { if (targetState == HeaterHandler::SwitchState::ON) {
heaterHandler.switchHeater(switchNr, state); heaterHandler.switchHeater(switchNr, targetState);
heaterStates[switchNr].target = HeaterHandler::SwitchState::ON;
heaterStates[switchNr].switchTransition = true;
if (componentIdx.has_value()) {
unsigned componentIdxVal = componentIdx.value();
thermalStates[componentIdxVal].sensorIndex = currentSensorIndex;
thermalStates[componentIdxVal].heaterSwitch = switchNr;
thermalStates[componentIdxVal].heating = true;
thermalStates[componentIdxVal].heaterStartTime = currentTime.tv_sec;
}
triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_ON, static_cast<uint32_t>(currThermalComponent), triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_ON, static_cast<uint32_t>(currThermalComponent),
static_cast<uint32_t>(switchNr)); static_cast<uint32_t>(switchNr));
thermalStates[componentIdx].heating = true;
thermalStates[componentIdx].heaterStartTime = currentTime.tv_sec;
} else { } else {
heaterHandler.switchHeater(switchNr, state); heaterHandler.switchHeater(switchNr, targetState);
if (componentIdx.has_value()) {
thermalStates[componentIdx.value()].heating = false;
thermalStates[componentIdx.value()].heaterEndTime = currentTime.tv_sec;
}
triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_OFF, static_cast<uint32_t>(currThermalComponent), triggerEvent(tcsCtrl::TCS_SWITCHING_HEATER_OFF, static_cast<uint32_t>(currThermalComponent),
static_cast<uint32_t>(switchNr)); static_cast<uint32_t>(switchNr));
thermalStates[componentIdx].heating = false;
thermalStates[componentIdx].heaterEndTime = currentTime.tv_sec;
} }
} }
@ -1826,6 +1874,18 @@ ThermalController::~ThermalController() {
} }
} }
void ThermalController::crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(
heater::Switch switchIdx) {
for (unsigned j = 0; j < thermalStates.size(); j++) {
if (thermalStates[j].heating and thermalStates[j].heaterSwitch == switchIdx) {
timeval currentTime;
Clock::getClockMonotonic(&currentTime);
thermalStates[j].heating = false;
thermalStates[j].heaterEndTime = currentTime.tv_sec;
}
}
}
void ThermalController::tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag) { void ThermalController::tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag) {
// Clear the one shot flag is the component is in acceptable temperature range. // Clear the one shot flag is the component is in acceptable temperature range.
if (not tooHotHandler(object, oneShotFlag) and not componentAboveUpperLimit) { if (not tooHotHandler(object, oneShotFlag) and not componentAboveUpperLimit) {

View File

@ -24,6 +24,7 @@
#include <atomic> #include <atomic>
#include <list> #include <list>
#include <optional>
/** /**
* NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit * NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit
@ -48,8 +49,11 @@ struct TempLimits {
struct ThermalState { struct ThermalState {
uint8_t noSensorAvailableCounter; uint8_t noSensorAvailableCounter;
// Which sensor is used for this component?
uint8_t sensorIndex = 0;
// Is heating on for that thermal module? // Is heating on for that thermal module?
bool heating = false; bool heating = false;
// Which switch is being used for heating the component
heater::Switch heaterSwitch = heater::Switch::NUMBER_OF_SWITCHES; heater::Switch heaterSwitch = heater::Switch::NUMBER_OF_SWITCHES;
// Heater start time and end times as UNIX seconds. Please note that these times will be updated // 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. // when a switch command is sent, with no guarantess that the heater actually went on.
@ -58,9 +62,11 @@ struct ThermalState {
}; };
struct HeaterState { struct HeaterState {
bool switchTransition; bool switchTransition = false;
HeaterHandler::SwitchState target; HeaterHandler::SwitchState target = HeaterHandler::SwitchState::OFF;
uint8_t heaterSwitchControlCycles; uint8_t heaterSwitchControlCycles = 0;
bool trackHeaterMaxPeriod = false;
Countdown heaterOnPeriod;
}; };
using HeaterSwitchStates = std::array<HeaterHandler::SwitchState, heater::NUMBER_OF_SWITCHES>; using HeaterSwitchStates = std::array<HeaterHandler::SwitchState, heater::NUMBER_OF_SWITCHES>;
@ -103,6 +109,25 @@ class ThermalController : public ExtendedControllerBase {
static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80; static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80;
static constexpr int16_t SANITY_LIMIT_UPPER_TEMP = 160; static constexpr int16_t SANITY_LIMIT_UPPER_TEMP = 160;
// 1 hour
static constexpr uint32_t DEFAULT_MAX_HEATER_ON_DURATION_MS = 60 * 60 * 1000;
static constexpr uint32_t MAX_HEATER_ON_DURATIONS_MS[8] = {// PLOC PROC board
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// PCDU PDU
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// ACS Board
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// OBC Board
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// Camera
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// STR
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// DRO
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// S-Band
DEFAULT_MAX_HEATER_ON_DURATION_MS};
ThermalController(object_id_t objectId, HeaterHandler& heater, ThermalController(object_id_t objectId, HeaterHandler& heater,
const std::atomic_bool& tcsBoardShortUnavailable, bool pollPcdu1Tmp); const std::atomic_bool& tcsBoardShortUnavailable, bool pollPcdu1Tmp);
virtual ~ThermalController(); virtual ~ThermalController();
@ -257,6 +282,7 @@ class ThermalController : public ExtendedControllerBase {
TempLimits scexBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0); TempLimits scexBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0);
double sensorTemp = INVALID_TEMPERATURE; double sensorTemp = INVALID_TEMPERATURE;
uint8_t currentSensorIndex = 0;
ThermalComponents currThermalComponent = NONE; ThermalComponents currThermalComponent = NONE;
bool redSwitchNrInUse = false; bool redSwitchNrInUse = false;
MessageQueueId_t camId = MessageQueueIF::NO_QUEUE; MessageQueueId_t camId = MessageQueueIF::NO_QUEUE;
@ -323,7 +349,7 @@ class ThermalController : public ExtendedControllerBase {
void heaterSwitchHelperAllOff(); void heaterSwitchHelperAllOff();
void heaterSwitchHelper(heater::Switch switchNr, HeaterHandler::SwitchState state, void heaterSwitchHelper(heater::Switch switchNr, HeaterHandler::SwitchState state,
unsigned componentIdx); std::optional<unsigned> componentIdx);
void ctrlAcsBoard(); void ctrlAcsBoard();
void ctrlMgt(); void ctrlMgt();
@ -347,7 +373,22 @@ class ThermalController : public ExtendedControllerBase {
void ctrlTx(); void ctrlTx();
void ctrlMpa(); void ctrlMpa();
void ctrlScexBoard(); void ctrlScexBoard();
/**
* The transition of heaters might take some time. As long as a transition is
* going on, the TCS controller works in a reduced form. This function takes care
* of tracking transition and capturing their completion.
* @param currentHeaterStates
*/
void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates); void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates);
/**
* Control tasks to prevent heaters being on for prolonged periods. Ideally, this
* should never happen, but this task prevents bugs from causing heaters to stay on
* for a long time, which draws a lot of power.
* @param currentHeaterStates
*/
void heaterMaxDurationControl(const HeaterSwitchStates& currentHeaterStates);
void crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(heater::Switch switchIdx);
void setMode(Mode_t mode, Submode_t submode); void setMode(Mode_t mode, Submode_t submode);
uint32_t tempFloatToU32() const; uint32_t tempFloatToU32() const;
bool tooHotHandler(object_id_t object, bool& oneShotFlag); bool tooHotHandler(object_id_t object, bool& oneShotFlag);

View File

@ -22,6 +22,8 @@ static constexpr Event MGT_OVERHEATING = MAKE_EVENT(8, severity::HIGH);
static constexpr Event TCS_SWITCHING_HEATER_ON = MAKE_EVENT(9, severity::INFO); static constexpr Event TCS_SWITCHING_HEATER_ON = MAKE_EVENT(9, severity::INFO);
//! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index //! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index
static constexpr Event TCS_SWITCHING_HEATER_OFF = MAKE_EVENT(10, severity::INFO); 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 { enum SetId : uint32_t {
SENSOR_TEMPERATURES = 0, SENSOR_TEMPERATURES = 0,

2
tmtc

@ -1 +1 @@
Subproject commit 069f84d2207c03e8d334cfce3f7dd530babe17b0 Subproject commit 15d25b4c5b7ad21603a83a6c09835f5c97273b17