diff --git a/src/modules/idler.cpp b/src/modules/idler.cpp index 4c05073..5d2bb62 100644 --- a/src/modules/idler.cpp +++ b/src/modules/idler.cpp @@ -62,7 +62,7 @@ void Idler::FinishMove() { } Idler::OperationResult Idler::Disengage() { - if (state == Moving) { + if (state == Moving || state == OnHold) { dbg_logic_P(PSTR("Moving --> Disengage refused")); return OperationResult::Refused; } @@ -94,7 +94,7 @@ Idler::OperationResult Idler::Engage(uint8_t slot) { } Idler::OperationResult Idler::PlanMoveInner(uint8_t slot, Operation plannedOp) { - if (state == Moving) { + if (state == Moving || state == OnHold) { dbg_logic_P(PSTR("Moving --> Engage refused")); return OperationResult::Refused; } diff --git a/src/modules/idler.h b/src/modules/idler.h index c0b6a0c..18a8ec4 100644 --- a/src/modules/idler.h +++ b/src/modules/idler.h @@ -22,10 +22,12 @@ public: /// Plan engaging of the idler to a specific filament slot /// @param slot index to be activated /// @returns #OperationResult + /// @note if(state==OnHold) all attempts to Engage are rejected with OperationResult::Rejected OperationResult Engage(uint8_t slot); /// Plan disengaging of the idler, i.e. parking the idler /// @returns #OperationResult + /// @note if(state==OnHold) all attempts to Disengage are rejected with OperationResult::Rejected OperationResult Disengage(); /// Plan partial disengaging of the idler diff --git a/src/modules/movable_base.cpp b/src/modules/movable_base.cpp index 2f14fdd..7a91e7c 100644 --- a/src/modules/movable_base.cpp +++ b/src/modules/movable_base.cpp @@ -6,8 +6,10 @@ namespace modules { namespace motion { -void MovableBase::PlanHome() { +MovableBase::OperationResult MovableBase::PlanHome() { InvalidateHoming(); + if (state == OnHold) + return OperationResult::Refused; // switch to normal mode on this axis @@ -21,6 +23,7 @@ void MovableBase::PlanHome() { state = HomeForward; // beware - the derived class may change the state if necessary currentSlot = -1; // important - other state machines may be waiting for a valid Slot() which is not yet correct while homing in progress PlanHomingMoveForward(); + return OperationResult::Accepted; } void __attribute__((noinline)) MovableBase::SetCurrents(uint8_t iRun, uint8_t iHold) { diff --git a/src/modules/movable_base.h b/src/modules/movable_base.h index 6d03a39..273e850 100644 --- a/src/modules/movable_base.h +++ b/src/modules/movable_base.h @@ -63,7 +63,8 @@ public: inline void InvalidateHoming() { homingValid = false; } /// Prepare a homing move of the axis - void PlanHome(); + /// @returns true if the move has been planned successfully (i.e. movable is NOT on-hold) + OperationResult PlanHome(); inline bool HomingValid() const { return homingValid; } diff --git a/src/modules/selector.h b/src/modules/selector.h index fd6a272..0fd247c 100644 --- a/src/modules/selector.h +++ b/src/modules/selector.h @@ -20,6 +20,7 @@ public: /// Plan move of the selector to a specific filament slot /// @param slot index to move to /// @returns false in case an operation is already underway + /// @note if(state==OnHold) all attempts to move the selector are rejected with OperationResult::Rejected OperationResult MoveToSlot(uint8_t slot); /// Performs one step of the state machine according to currently planned operation. diff --git a/tests/unit/logic/homing/test_homing.cpp b/tests/unit/logic/homing/test_homing.cpp index 88913c9..9de4a33 100644 --- a/tests/unit/logic/homing/test_homing.cpp +++ b/tests/unit/logic/homing/test_homing.cpp @@ -153,3 +153,45 @@ TEST_CASE("homing::refused_home", "[homing]") { REQUIRE(RefusedHome(slot)); } } + +bool OnHold(uint8_t slot) { + // prepare startup conditions + ForceReinitAllAutomata(); + + // change the startup to what we need here + HomeIdlerAndSelector(); + + SetFINDAStateAndDebounce(true); + mg::globals.SetFilamentLoaded(slot, mg::FilamentLoadState::InSelector); + + // now put movables on hold + logic::CommandBase::HoldIdlerSelector(); + + REQUIRE(mi::idler.state == mi::Idler::OnHold); + REQUIRE(ms::selector.state == ms::Selector::OnHold); + + // both movables should ignore all attempts to perform moves + REQUIRE(mi::idler.PlanHome() == mi::Idler::OperationResult::Refused); + REQUIRE(mi::idler.state == mi::Idler::OnHold); + REQUIRE(mi::idler.Disengaged()); + + REQUIRE(ms::selector.PlanHome() == ms::Selector::OperationResult::Refused); + REQUIRE(ms::selector.state == ms::Selector::OnHold); + + REQUIRE(mi::idler.Disengage() == mi::Idler::OperationResult::Refused); + REQUIRE(mi::idler.state == mi::Idler::OnHold); + REQUIRE(mi::idler.Engage(slot) == mi::Idler::OperationResult::Refused); + REQUIRE(mi::idler.state == mi::Idler::OnHold); + REQUIRE(mi::idler.Disengaged()); + + REQUIRE(ms::selector.MoveToSlot((slot + 1) % config::toolCount) == ms::Selector::OperationResult::Refused); + REQUIRE(ms::selector.state == ms::Selector::OnHold); + + return true; +} + +TEST_CASE("homing::on-hold", "[homing]") { + for (uint8_t slot = 0; slot < config::toolCount; ++slot) { + REQUIRE(OnHold(slot)); + } +} diff --git a/tests/unit/logic/load_filament/test_load_filament.cpp b/tests/unit/logic/load_filament/test_load_filament.cpp index 86ffc2f..28d8ea5 100644 --- a/tests/unit/logic/load_filament/test_load_filament.cpp +++ b/tests/unit/logic/load_filament/test_load_filament.cpp @@ -170,18 +170,6 @@ void FailedLoadToFindaResolveManual(uint8_t slot, logic::LoadFilament &lf) { REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK)); } -void FailedLoadToFindaResolveManualNoFINDA(uint8_t slot, logic::LoadFilament &lf) { - // Perform press on button 2 + debounce + keep FINDA OFF (i.e. the user didn't solve anything) - PressButtonAndDebounce(lf, mb::Right, false); - - SimulateIdlerHoming(lf); - - ClearButtons(lf); - - // pulling filament back - REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERRWaitingForUser)); -} - void FailedLoadToFindaResolveTryAgain(uint8_t slot, logic::LoadFilament &lf) { PressButtonAndDebounce(lf, mb::Middle, false); @@ -218,15 +206,6 @@ TEST_CASE("load_filament::state_machine_reusal", "[load_filament]") { } } -TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_manual_no_FINDA", "[load_filament]") { - for (uint8_t slot = 0; slot < config::toolCount; ++slot) { - logic::LoadFilament lf; - LoadFilamentCommonSetup(slot, lf, true); - FailedLoadToFinda(slot, lf); - FailedLoadToFindaResolveManualNoFINDA(slot, lf); - } -} - TEST_CASE("load_filament::failed_load_to_finda_0-4_try_again", "[load_filament]") { for (uint8_t slot = 0; slot < config::toolCount; ++slot) { logic::LoadFilament lf; diff --git a/tests/unit/logic/tool_change/test_tool_change.cpp b/tests/unit/logic/tool_change/test_tool_change.cpp index 0e4c119..7cdd933 100644 --- a/tests/unit/logic/tool_change/test_tool_change.cpp +++ b/tests/unit/logic/tool_change/test_tool_change.cpp @@ -426,8 +426,17 @@ void ToolChangeWithFlickeringFINDA(logic::ToolChange &tc, uint8_t fromSlot, uint // we should remain in the same error state REQUIRE(VerifyState2(tc, mg::FilamentLoadState::AtPulley, mi::idler.IdleSlotIndex(), fromSlot, true, false, toSlot, ml::off, ml::blink0, ErrorCode::RUNNING, ProgressCode::ERRDisengagingIdler)); - // Idler will try to rehome, allow it - SimulateIdlerHoming(tc); + // Idler would like to rehome at this spot - theoretically it is free to do so and actually will have the homing move planned. + // In reality, one main cycle of the FW takes ~1ms so the Idler will never really move - which is exactly what we want to leverage + + // perform just one step to fall into the same error again + main_loop(); + tc.Step(); + + // now both Idler and Selector are on hold again + REQUIRE(mi::idler.state == mi::Idler::OnHold); + REQUIRE(ms::selector.state == ms::Selector::OnHold); + REQUIRE(VerifyState2(tc, mg::FilamentLoadState::AtPulley, mi::idler.IdleSlotIndex(), fromSlot, true, false, toSlot, ml::off, ml::blink0, ErrorCode::FINDA_FLICKERS, ProgressCode::ERRWaitingForUser)); // now "fix" FINDA and the command shall finish correctly