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
2 changed files with 39 additions and 14 deletions
Showing only changes of commit c558a117b0 - Show all commits

View File

@ -1693,7 +1693,6 @@ void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
if (sensorTemp < htrCtx.tempLimit.opLowerLimit and heaterCtrlAllowed()) { if (sensorTemp < htrCtx.tempLimit.opLowerLimit and heaterCtrlAllowed()) {
sif::info << "TCS: Heater " << static_cast<int>(thermalComponent) << " ON" << std::endl; sif::info << "TCS: Heater " << static_cast<int>(thermalComponent) << " ON" << std::endl;
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::ON, thermalComponent); heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::ON, thermalComponent);
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[thermalComponent].heating = false; thermalStates[thermalComponent].heating = false;
@ -1757,10 +1756,14 @@ 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 heat period control // Required for max heater period control
if (currentHeaterStates[i] == HeaterHandler::SwitchState::ON) { if (currentHeaterStates[i] == HeaterHandler::SwitchState::ON) {
heaterStates[i].heaterOnPeriod.setTimeout(MAX_HEATER_ON_DURATIONS[i]); heaterStates[i].heaterOnPeriod.setTimeout(MAX_HEATER_ON_DURATIONS[i]);
heaterStates[i].heaterOnPeriod.resetTimer(); heaterStates[i].heaterOnPeriod.resetTimer();
} else {
// 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;
continue; continue;
@ -1781,14 +1784,9 @@ void ThermalController::heaterMaxDurationControl(const HeaterSwitchStates& curre
heaterStates[i].switchTransition = false; heaterStates[i].switchTransition = false;
heaterStates[i].heaterSwitchControlCycles = 0; heaterStates[i].heaterSwitchControlCycles = 0;
heaterHandler.switchHeater(static_cast<heater::Switch>(i), HeaterHandler::SwitchState::OFF); heaterHandler.switchHeater(static_cast<heater::Switch>(i), HeaterHandler::SwitchState::OFF);
for (unsigned j = 0; j < thermalStates.size(); j++) { // The heater might still be one for some thermal components, so cross-check
if (thermalStates[j].heating and thermalStates[j].heaterSwitch == i) { // those components
timeval currentTime; crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(static_cast<heater::Switch>(i));
Clock::getClockMonotonic(&currentTime);
thermalStates[j].heating = false;
thermalStates[j].heaterEndTime = currentTime.tv_sec;
}
}
} }
} }
} }
@ -1836,19 +1834,20 @@ void ThermalController::resetThermalStates() {
} }
void ThermalController::heaterSwitchHelper(heater::Switch switchNr, void ThermalController::heaterSwitchHelper(heater::Switch switchNr,
HeaterHandler::SwitchState state, HeaterHandler::SwitchState targetState,
unsigned componentIdx) { 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; heaterStates[switchNr].switchTransition = true;
thermalStates[componentIdx].sensorIndex = currentSensorIndex; thermalStates[componentIdx].sensorIndex = currentSensorIndex;
thermalStates[componentIdx].heaterSwitch = switchNr; thermalStates[componentIdx].heaterSwitch = switchNr;
thermalStates[componentIdx].heating = true; thermalStates[componentIdx].heating = true;
thermalStates[componentIdx].heaterStartTime = currentTime.tv_sec; thermalStates[componentIdx].heaterStartTime = currentTime.tv_sec;
} else { } else {
heaterHandler.switchHeater(switchNr, state); heaterHandler.switchHeater(switchNr, targetState);
thermalStates[componentIdx].heating = false; thermalStates[componentIdx].heating = false;
thermalStates[componentIdx].heaterEndTime = currentTime.tv_sec; thermalStates[componentIdx].heaterEndTime = currentTime.tv_sec;
} }
@ -1873,6 +1872,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

@ -371,8 +371,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 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);