Hold/Resume Idler+Selector even after their homing errors

MMU-222
pull/270/head
D.R.racer 2023-03-13 09:15:12 +01:00 committed by DRracer
parent bafad408b7
commit f07e206398
9 changed files with 41 additions and 33 deletions

View File

@ -56,8 +56,8 @@ static ErrorCode __attribute__((noinline)) AddErrorAxisBit(ErrorCode ec, uint8_t
return ec; return ec;
} }
ErrorCode CheckMovable(mm::MovableBase &m) { ErrorCode CheckMovable(const mm::MovableBase &m) {
switch (m.State()) { switch (m.State() & (~mm::MovableBase::OnHold)) { // clear the on-hold bit from the state check
case mm::MovableBase::TMCFailed: case mm::MovableBase::TMCFailed:
return AddErrorAxisBit(TMC2130ToErrorCode(m.TMCErrorFlags()), m.Axis()); return AddErrorAxisBit(TMC2130ToErrorCode(m.TMCErrorFlags()), m.Axis());
case mm::MovableBase::HomingFailed: case mm::MovableBase::HomingFailed:
@ -84,12 +84,14 @@ bool CommandBase::WaitForOneModuleErrorRecovery(ErrorCode ec, modules::motion::M
errorBeforeModuleFailed = error; errorBeforeModuleFailed = error;
error = ec; error = ec;
state = ProgressCode::ERRWaitingForUser; // such a situation always requires user's attention -> let the printer display an error screen state = ProgressCode::ERRWaitingForUser; // such a situation always requires user's attention -> let the printer display an error screen
HoldIdlerSelector();
} }
// are we already recovering an error - that would mean we got another one // are we already recovering an error - that would mean we got another one
if (recoveringMovableErrorAxisMask) { if (recoveringMovableErrorAxisMask) {
error = ec; error = ec;
state = ProgressCode::ERRWaitingForUser; // such a situation always requires user's attention -> let the printer display an error screen state = ProgressCode::ERRWaitingForUser; // such a situation always requires user's attention -> let the printer display an error screen
HoldIdlerSelector();
} }
switch (state) { switch (state) {
@ -99,6 +101,7 @@ bool CommandBase::WaitForOneModuleErrorRecovery(ErrorCode ec, modules::motion::M
mui::Event ev = mui::userInput.ConsumeEvent(); mui::Event ev = mui::userInput.ConsumeEvent();
if (ev == mui::Event::Middle) { if (ev == mui::Event::Middle) {
recoveringMovableErrorAxisMask |= axisMask; recoveringMovableErrorAxisMask |= axisMask;
ResumeIdlerSelector();
m.PlanHome(); // force initiate a new homing attempt m.PlanHome(); // force initiate a new homing attempt
state = ProgressCode::Homing; state = ProgressCode::Homing;
error = ErrorCode::RUNNING; error = ErrorCode::RUNNING;

View File

@ -69,7 +69,7 @@ bool Idler::StallGuardAllowed(bool forward) const {
} }
Idler::OperationResult Idler::Disengage() { Idler::OperationResult Idler::Disengage() {
if (state == Moving || state == OnHold) { if (state == Moving || IsOnHold()) {
dbg_logic_P(PSTR("Moving --> Disengage refused")); dbg_logic_P(PSTR("Moving --> Disengage refused"));
return OperationResult::Refused; return OperationResult::Refused;
} }
@ -101,7 +101,7 @@ Idler::OperationResult Idler::Engage(uint8_t slot) {
} }
Idler::OperationResult Idler::PlanMoveInner(uint8_t slot, Operation plannedOp) { Idler::OperationResult Idler::PlanMoveInner(uint8_t slot, Operation plannedOp) {
if (state == Moving || state == OnHold) { if (state == Moving || IsOnHold()) {
dbg_logic_P(PSTR("Moving --> Engage refused")); dbg_logic_P(PSTR("Moving --> Engage refused"));
return OperationResult::Refused; return OperationResult::Refused;
} }
@ -132,6 +132,10 @@ Idler::OperationResult Idler::PlanMoveInner(uint8_t slot, Operation plannedOp) {
} }
bool Idler::Step() { bool Idler::Step() {
if (IsOnHold()) {
return true; // just wait, do nothing!
}
if (state != TMCFailed) { if (state != TMCFailed) {
CheckTMC(); CheckTMC();
} }
@ -155,10 +159,7 @@ bool Idler::Step() {
return false; return false;
} }
return true; return true;
case OnHold:
return true; // just wait, do nothing!
case TMCFailed: case TMCFailed:
dbg_logic_P(PSTR("Idler Failed"));
default: default:
return true; return true;
} }

View File

@ -8,7 +8,7 @@ namespace motion {
MovableBase::OperationResult MovableBase::PlanHome() { MovableBase::OperationResult MovableBase::PlanHome() {
InvalidateHoming(); InvalidateHoming();
if (state == OnHold) if (IsOnHold())
return OperationResult::Refused; return OperationResult::Refused;
// switch to normal mode on this axis // switch to normal mode on this axis
@ -32,7 +32,7 @@ void __attribute__((noinline)) MovableBase::SetCurrents(uint8_t iRun, uint8_t iH
} }
void MovableBase::HoldOn() { void MovableBase::HoldOn() {
state = OnHold; state |= OnHold; // set the on-hold bit
mm::motion.AbortPlannedMoves(axis); mm::motion.AbortPlannedMoves(axis);
// Force turn off motors - prevent overheating and allow servicing during an error state. // Force turn off motors - prevent overheating and allow servicing during an error state.
// And don't worry about TMC2130 creep after axis enabled - we'll rehome both axes later when needed. // And don't worry about TMC2130 creep after axis enabled - we'll rehome both axes later when needed.

View File

@ -13,13 +13,13 @@ public:
/// Internal states of the state machine /// Internal states of the state machine
enum { enum {
Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code
Moving, Moving = 1,
PlannedHome, PlannedHome = 2,
HomeForward, HomeForward = 3,
HomeBack, HomeBack = 4,
TMCFailed, TMCFailed = 5,
HomingFailed, HomingFailed = 6,
OnHold, OnHold = 0x80, ///< needs to be a separate bit due to homing recovery infrastructure
}; };
/// Operation (Engage/Disengage/MoveToSlot) return values /// Operation (Engage/Disengage/MoveToSlot) return values
@ -78,8 +78,11 @@ public:
/// Also, disables the axis /// Also, disables the axis
void HoldOn(); void HoldOn();
/// @returns true if the movable is on-hold
bool IsOnHold() const { return state & OnHold; }
/// Allows the movable to move/home again after begin suspended by HoldOn /// Allows the movable to move/home again after begin suspended by HoldOn
void Resume() { state = Ready; } void Resume() { state &= ~OnHold; }
#ifndef UNITTEST #ifndef UNITTEST
protected: protected:

View File

@ -17,6 +17,9 @@ bool __attribute__((noinline)) Pulley::FinishHomingAndPlanMoveToParkPos() {
} }
bool Pulley::Step() { bool Pulley::Step() {
if (IsOnHold()) {
return true; // just wait, do nothing!
}
if (state != TMCFailed) { if (state != TMCFailed) {
CheckTMC(); CheckTMC();
} }
@ -31,8 +34,6 @@ bool Pulley::Step() {
return true; return true;
case Ready: case Ready:
return true; return true;
case OnHold:
return true;
case TMCFailed: case TMCFailed:
default: default:
return true; return true;

View File

@ -89,6 +89,9 @@ Selector::OperationResult Selector::MoveToSlot(uint8_t slot) {
} }
bool Selector::Step() { bool Selector::Step() {
if (IsOnHold()) {
return true; // just wait, do nothing!
}
if (state != TMCFailed) { if (state != TMCFailed) {
CheckTMC(); CheckTMC();
} }
@ -123,10 +126,7 @@ bool Selector::Step() {
return false; return false;
} }
return true; return true;
case OnHold:
return true; // just wait, do nothing!
case TMCFailed: case TMCFailed:
dbg_logic_P(PSTR("Selector Failed"));
default: default:
return true; return true;
} }

View File

@ -168,25 +168,25 @@ bool OnHold(uint8_t slot) {
// now put movables on hold // now put movables on hold
logic::CommandBase::HoldIdlerSelector(); logic::CommandBase::HoldIdlerSelector();
REQUIRE(mi::idler.state == mi::Idler::OnHold); REQUIRE(mi::idler.IsOnHold());
REQUIRE(ms::selector.state == ms::Selector::OnHold); REQUIRE(ms::selector.IsOnHold());
// both movables should ignore all attempts to perform moves // both movables should ignore all attempts to perform moves
REQUIRE(mi::idler.PlanHome() == mi::Idler::OperationResult::Refused); REQUIRE(mi::idler.PlanHome() == mi::Idler::OperationResult::Refused);
REQUIRE(mi::idler.state == mi::Idler::OnHold); REQUIRE(mi::idler.IsOnHold());
REQUIRE(mi::idler.Disengaged()); REQUIRE(mi::idler.Disengaged());
REQUIRE(ms::selector.PlanHome() == ms::Selector::OperationResult::Refused); REQUIRE(ms::selector.PlanHome() == ms::Selector::OperationResult::Refused);
REQUIRE(ms::selector.state == ms::Selector::OnHold); REQUIRE(ms::selector.IsOnHold());
REQUIRE(mi::idler.Disengage() == mi::Idler::OperationResult::Refused); REQUIRE(mi::idler.Disengage() == mi::Idler::OperationResult::Refused);
REQUIRE(mi::idler.state == mi::Idler::OnHold); REQUIRE(mi::idler.IsOnHold());
REQUIRE(mi::idler.Engage(slot) == mi::Idler::OperationResult::Refused); REQUIRE(mi::idler.Engage(slot) == mi::Idler::OperationResult::Refused);
REQUIRE(mi::idler.state == mi::Idler::OnHold); REQUIRE(mi::idler.IsOnHold());
REQUIRE(mi::idler.Disengaged()); REQUIRE(mi::idler.Disengaged());
REQUIRE(ms::selector.MoveToSlot((slot + 1) % config::toolCount) == ms::Selector::OperationResult::Refused); REQUIRE(ms::selector.MoveToSlot((slot + 1) % config::toolCount) == ms::Selector::OperationResult::Refused);
REQUIRE(ms::selector.state == ms::Selector::OnHold); REQUIRE(ms::selector.IsOnHold());
return true; return true;
} }

View File

@ -209,7 +209,7 @@ bool SimulateFailedHomeFirstTime(logic::CommandBase &cb) {
} }
} }
while (ms::selector.State() != mm::MovableBase::HomingFailed) { while (!(ms::selector.State() & mm::MovableBase::OnHold)) {
main_loop(); main_loop();
cb.Step(); cb.Step();
} }
@ -250,7 +250,7 @@ bool SimulateFailedHomeSelectorRepeated(logic::CommandBase &cb) {
} }
} }
while (ms::selector.State() != mm::MovableBase::HomingFailed) { while (!(ms::selector.State() & mm::MovableBase::OnHold)) {
main_loop(); main_loop();
cb.Step(); cb.Step();
} }

View File

@ -434,8 +434,8 @@ void ToolChangeWithFlickeringFINDA(logic::ToolChange &tc, uint8_t fromSlot, uint
tc.Step(); tc.Step();
// now both Idler and Selector are on hold again // now both Idler and Selector are on hold again
REQUIRE(mi::idler.state == mi::Idler::OnHold); REQUIRE(mi::idler.IsOnHold());
REQUIRE(ms::selector.state == ms::Selector::OnHold); REQUIRE(ms::selector.IsOnHold());
REQUIRE(VerifyState2(tc, mg::FilamentLoadState::AtPulley, mi::idler.IdleSlotIndex(), fromSlot, true, false, toSlot, ml::off, ml::blink0, ErrorCode::FINDA_FLICKERS, ProgressCode::ERRWaitingForUser)); REQUIRE(VerifyState2(tc, mg::FilamentLoadState::AtPulley, mi::idler.IdleSlotIndex(), fromSlot, true, false, toSlot, ml::off, ml::blink0, ErrorCode::FINDA_FLICKERS, ProgressCode::ERRWaitingForUser));