diff --git a/src/logic/command_base.cpp b/src/logic/command_base.cpp index 17d9121..7294d20 100644 --- a/src/logic/command_base.cpp +++ b/src/logic/command_base.cpp @@ -13,11 +13,11 @@ namespace logic { -inline ErrorCode &operator|=(ErrorCode &a, ErrorCode b) { +constexpr ErrorCode &operator|=(ErrorCode &a, ErrorCode b) { return a = (ErrorCode)((uint16_t)a | (uint16_t)b); } -static ErrorCode TMC2130ToErrorCode(const hal::tmc2130::ErrorFlags &ef) { +constexpr ErrorCode TMC2130ToErrorCode(const hal::tmc2130::ErrorFlags &ef) { ErrorCode e = ErrorCode::RUNNING; if (ef.reset_flag) { @@ -39,7 +39,7 @@ static ErrorCode TMC2130ToErrorCode(const hal::tmc2130::ErrorFlags &ef) { return e; } -static ErrorCode AddErrorAxisBit(ErrorCode ec, uint8_t tmcIndex) { +constexpr ErrorCode AddErrorAxisBit(ErrorCode ec, uint8_t tmcIndex) { switch (tmcIndex) { case config::Axis::Pulley: ec |= ErrorCode::TMC_PULLEY_BIT; @@ -61,12 +61,14 @@ ErrorCode CheckMovable(mm::MovableBase &m) { case mm::MovableBase::TMCFailed: return AddErrorAxisBit(TMC2130ToErrorCode(m.TMCErrorFlags()), m.Axis()); case mm::MovableBase::HomingFailed: - return AddErrorAxisBit(ErrorCode::HOMING_FAILED, m.Axis()); + return m.SupportsHoming() ? AddErrorAxisBit(ErrorCode::HOMING_FAILED, m.Axis()) : ErrorCode::RUNNING; + case mm::MovableBase::MoveFailed: + return m.SupportsHoming() ? AddErrorAxisBit(ErrorCode::MOVE_FAILED, m.Axis()) : ErrorCode::RUNNING; } return ErrorCode::RUNNING; } -static inline ErrorCode WithoutAxisBits(ErrorCode ec) { +constexpr ErrorCode WithoutAxisBits(ErrorCode ec) { return static_cast( static_cast(ec) & (~(static_cast(ErrorCode::TMC_SELECTOR_BIT) @@ -93,19 +95,35 @@ bool CommandBase::WaitForOneModuleErrorRecovery(ErrorCode ec, modules::motion::M } switch (state) { - case ProgressCode::ERRWaitingForUser: // waiting for a recovery - mask axis bits: - if (WithoutAxisBits(ec) == ErrorCode::HOMING_FAILED) { - // homing can be recovered - mui::Event ev = mui::userInput.ConsumeEvent(); - if (ev == mui::Event::Middle) { - recoveringMovableErrorAxisMask |= axisMask; - m.PlanHome(); // force initiate a new homing attempt + case ProgressCode::ERRWaitingForUser: { // waiting for a recovery - mask axis bits: + mui::Event ev = mui::userInput.ConsumeEvent(); + if (ev == mui::Event::Middle) { + switch (WithoutAxisBits(ec)) { + case ErrorCode::MOVE_FAILED: + // A failed move can be recovered for Idler and Selector (doesn't make sense on the Pulley). + // But - force initiate a new homing attempt of BOTH Idler and Selector (that's the main difference from HomingFailed) + // because we expect the user disassembled the whole MMU to remove a stuck piece of filament + // and therefore we cannot rely on Idler's and Selector's position + recoveringMovableErrorAxisMask |= 0x3; // @@TODO better axis masks + mi::idler.PlanHome(); + ms::selector.PlanHome(); state = ProgressCode::Homing; error = ErrorCode::RUNNING; + break; + case ErrorCode::HOMING_FAILED: + // A failed homing can be recovered + recoveringMovableErrorAxisMask |= axisMask; + m.PlanHome(); // force initiate a new homing attempt just on the failed axis + state = ProgressCode::Homing; + error = ErrorCode::RUNNING; + break; + default: + break; } } // TMC errors cannot be recovered safely, waiting for power cycling the MMU return true; + } default: return true; // prevent descendant from taking over while in an error state } diff --git a/src/logic/error_codes.h b/src/logic/error_codes.h index 66734a7..385690a 100644 --- a/src/logic/error_codes.h +++ b/src/logic/error_codes.h @@ -46,6 +46,11 @@ enum class ErrorCode : uint_fast16_t { ///< - a piece of filament was left inside - pushed in front of the loaded filament causing the fsensor trigger too early ///< - fsensor is faulty producing bogus triggers + MOVE_FAILED = 0x800a, ///< generic move failed error - always reported with the corresponding axis bit set (Idler or Selector) as follows: + MOVE_SELECTOR_FAILED = MOVE_FAILED | TMC_SELECTOR_BIT, ///< E32905 the Selector was unable to move to desired position properly - that means something is blocking its movement, e.g. a piece of filament got out of pulley body + MOVE_IDLER_FAILED = MOVE_FAILED | TMC_IDLER_BIT, ///< E33033 the Idler was unable to move - unused at the time of creation, but added for completeness + MOVE_PULLEY_FAILED = MOVE_FAILED | TMC_PULLEY_BIT, ///< E32841 the Pulley was unable to move - unused at the time of creation, but added for completeness + QUEUE_FULL = 0x802b, ///< E32811 internal logic error - attempt to move with a full queue VERSION_MISMATCH = 0x802c, ///< E32812 internal error of the printer - incompatible version of the MMU FW diff --git a/src/modules/idler.h b/src/modules/idler.h index 17a89b4..e1cb2f3 100644 --- a/src/modules/idler.h +++ b/src/modules/idler.h @@ -51,6 +51,8 @@ public: /// - blocked -> set idler's position according to the active filament slot void Init(); + virtual bool SupportsHoming() override { return true; } + protected: virtual void PrepareMoveToPlannedSlot() override; virtual void PlanHomingMoveForward() override; diff --git a/src/modules/movable_base.cpp b/src/modules/movable_base.cpp index 25099db..47e9b5a 100644 --- a/src/modules/movable_base.cpp +++ b/src/modules/movable_base.cpp @@ -36,6 +36,13 @@ void MovableBase::PerformMove() { // TMC2130 entered some error state, the planned move couldn't have been finished - result of operation is Failed tmcErrorFlags = mm::motion.DriverForAxis(axis).GetErrorFlags(); // save the failed state state = TMCFailed; + } else if (mm::motion.StallGuard(axis) && SupportsHoming()) { + // Axis stalled while moving - dangerous especially with the Selector + // Checked only for axes which support homing (because we plan a homing move after the error is resolved to regain precise position) + mm::motion.StallGuardReset(axis); + mm::motion.AbortPlannedMoves(axis, true); + // @@TODO move a bit back from where it came from to enable easier removal of whatever is blocking the axis + state = MoveFailed; } else if (mm::motion.QueueEmpty(axis)) { // move finished currentSlot = plannedSlot; diff --git a/src/modules/movable_base.h b/src/modules/movable_base.h index 990f1e1..facb597 100644 --- a/src/modules/movable_base.h +++ b/src/modules/movable_base.h @@ -17,7 +17,8 @@ public: HomeForward, HomeBack, TMCFailed, - HomingFailed + HomingFailed, + MoveFailed, }; /// Operation (Engage/Disengage/MoveToSlot) return values @@ -67,6 +68,8 @@ public: inline config::Axis Axis() const { return axis; } + virtual bool SupportsHoming() = 0; + protected: /// internal state of the automaton uint8_t state; diff --git a/src/modules/pulley.h b/src/modules/pulley.h index 73a2f0b..48a13a7 100644 --- a/src/modules/pulley.h +++ b/src/modules/pulley.h @@ -34,6 +34,8 @@ public: void InitAxis(); void Disable(); + virtual bool SupportsHoming() override { return false; } + protected: virtual void PrepareMoveToPlannedSlot() override {} virtual void PlanHomingMoveForward() override {} diff --git a/src/modules/selector.h b/src/modules/selector.h index fd6a272..9f002db 100644 --- a/src/modules/selector.h +++ b/src/modules/selector.h @@ -40,6 +40,8 @@ public: /// - blocked -> set selector's position according to the active filament slot void Init(); + virtual bool SupportsHoming() override { return true; } + protected: virtual void PrepareMoveToPlannedSlot() override; virtual void PlanHomingMoveForward() override;