Selector: add timeout to PlannedHome to prevent deadlock

Add a plannedHomeTimer counter that increments each main-loop
iteration while the selector is in PlannedHome waiting for the
idler to become HomingValid. If 30 000 iterations elapse without
the idler becoming valid, HomeFailed() is called, transitioning
to HomingFailed which surfaces an error screen to the user.

This prevents an indefinite deadlock when the idler is stuck in
a non-error state (e.g. Ready with homingValid==false) that
WaitForModulesErrorRecovery cannot detect.
pull/359/head
Marcelo Brigato 2026-03-29 23:19:57 -03:00
parent 48d4d920be
commit 65251c47b8
2 changed files with 14 additions and 1 deletions

View File

@ -21,6 +21,7 @@ void Selector::PrepareMoveToPlannedSlot() {
void Selector::PlanHomingMoveForward() {
state = PlannedHome;
plannedHomeTimer = 0; // reset timeout counter when entering PlannedHome
dbg_logic_P(PSTR("Plan Homing Selector Forward"));
}
@ -110,6 +111,13 @@ bool Selector::Step() {
state = HomeForward;
mm::motion.PlanMove<mm::Selector>(mm::unitToAxisUnit<mm::S_pos_t>(-config::selectorLimits.lenght * 2),
mm::unitToAxisUnit<mm::S_speed_t>(mg::globals.SelectorHomingFeedrate_mm_s()));
} else if (++plannedHomeTimer >= 30000U) {
// Idler did not become homing-valid within ~30 000 main-loop iterations.
// This breaks a potential deadlock where the idler is stuck in a non-error
// state (e.g. Ready with homingValid==false) that WaitForModulesErrorRecovery
// cannot detect. HomeFailed() transitions selector to HomingFailed, which IS
// detected and surfaces an error screen to the user.
HomeFailed();
}
return false;
case HomeForward:

View File

@ -15,7 +15,8 @@ namespace mm = modules::motion;
class Selector : public mm::MovableBase {
public:
inline constexpr Selector()
: MovableBase(mm::Selector) {}
: MovableBase(mm::Selector)
, plannedHomeTimer(0) {}
/// Plan move of the selector to a specific filament slot
/// @param slot index to move to
@ -49,6 +50,10 @@ protected:
virtual void FinishMove() override;
private:
/// Counts main-loop iterations spent in PlannedHome while waiting for the idler to become HomingValid.
/// Guards against indefinite deadlock: if the idler never becomes valid, HomeFailed() fires and the
/// WaitForModulesErrorRecovery path surfaces the error to the user.
uint16_t plannedHomeTimer;
};
/// The one and only instance of Selector in the FW