From 6bb4a7b4b8524c9708d23de1d29f834c11c02ed0 Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Wed, 22 Jun 2022 16:07:16 +0200 Subject: [PATCH] Make ToolChange retry 3x before throwing out an error --- src/config/config.h | 4 ++++ src/logic/tool_change.cpp | 23 ++++++++++++++++--- src/logic/tool_change.h | 8 +++++-- .../logic/tool_change/test_tool_change.cpp | 5 ++++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/config/config.h b/src/config/config.h index 1b090b7..f7ab136 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -67,6 +67,10 @@ static constexpr uint16_t stepTimerQuantum = 256; // 256 = 128us /// Max retries of FeedToBondtech used in LoadFilament static constexpr uint8_t feedToBondtechMaxRetries = 2; +/// Max attempts of ToolChange before throwing out an error - obviously, this has to be >= 1 +static constexpr uint8_t toolChangeAttempts = 3; +static_assert(toolChangeAttempts >= 1); + /// Distances static constexpr U_mm pulleyToCuttingEdge = 33.0_mm; /// 33.0_mm /// Pulley to cutting edge. /// Case 1: FINDA working: This should be the max retraction after FINDA un-triggers. diff --git a/src/logic/tool_change.cpp b/src/logic/tool_change.cpp index a599b8e..a55d40d 100644 --- a/src/logic/tool_change.cpp +++ b/src/logic/tool_change.cpp @@ -17,6 +17,10 @@ namespace logic { ToolChange toolChange; +ToolChange::ToolChange() + : CommandBase() + , attempts(config::toolChangeAttempts) {} + bool ToolChange::Reset(uint8_t param) { if (!CheckToolIndex(param)) { return false; @@ -28,6 +32,10 @@ bool ToolChange::Reset(uint8_t param) { return true; } + return Reset(param, config::toolChangeAttempts); +} + +bool ToolChange::Reset(uint8_t param, uint8_t att) { // @@TODO establish printer in charge of UI processing for the ToolChange command only. // We'll see how that works and then probably we'll introduce some kind of protocol settings to switch UI handling. mui::userInput.SetPrinterInCharge(true); @@ -35,6 +43,7 @@ bool ToolChange::Reset(uint8_t param) { // we are either already at the correct slot, just the filament is not loaded - load the filament directly // or we are standing at another slot ... plannedSlot = param; + attempts = att; if (mg::globals.FilamentLoaded() >= mg::FilamentLoadState::InSelector) { dbg_logic_P(PSTR("Filament is loaded --> unload")); @@ -50,6 +59,14 @@ bool ToolChange::Reset(uint8_t param) { return true; } +void ToolChange::GoToRetryIfPossible(ErrorCode ec) { + if (--attempts) { + Reset(mg::globals.ActiveSlot(), attempts); + } else { + GoToErrDisengagingIdler(ec); + } +} + void logic::ToolChange::GoToFeedingToBondtech() { ml::leds.SetPairButOffOthers(mg::globals.ActiveSlot(), ml::blink0, ml::off); james.Reset(3); @@ -83,7 +100,7 @@ bool ToolChange::StepInner() { case ProgressCode::FeedingToFinda: if (feed.Step()) { if (feed.State() == FeedToFinda::Failed) { - GoToErrDisengagingIdler(ErrorCode::FINDA_DIDNT_SWITCH_ON); // signal loading error + GoToRetryIfPossible(ErrorCode::FINDA_DIDNT_SWITCH_ON); // signal loading error } else { GoToFeedingToBondtech(); } @@ -93,10 +110,10 @@ bool ToolChange::StepInner() { if (james.Step()) { switch (james.State()) { case FeedToBondtech::Failed: - GoToErrDisengagingIdler(ErrorCode::FSENSOR_DIDNT_SWITCH_ON); // signal loading error + GoToRetryIfPossible(ErrorCode::FSENSOR_DIDNT_SWITCH_ON); // signal loading error break; case FeedToBondtech::FSensorTooEarly: - GoToErrDisengagingIdler(ErrorCode::FSENSOR_TOO_EARLY); // signal loading error + GoToRetryIfPossible(ErrorCode::FSENSOR_TOO_EARLY); // signal loading error break; default: ToolChangeFinishedCorrectly(); diff --git a/src/logic/tool_change.h b/src/logic/tool_change.h index 5e9b14a..f57bdee 100644 --- a/src/logic/tool_change.h +++ b/src/logic/tool_change.h @@ -11,8 +11,7 @@ namespace logic { /// @brief A high-level command state machine - handles the complex logic of tool change - which is basically a chain of an Unload and a Load operation. class ToolChange : public CommandBase { public: - inline ToolChange() - : CommandBase() {} + ToolChange(); /// Restart the automaton /// @param param index of filament slot to change to - i.e. to load @@ -27,9 +26,13 @@ public: #ifndef UNITTEST private: +#else + inline void SetAttempts(uint8_t att) { attempts = att; } #endif void GoToFeedingToBondtech(); void GoToFeedingToFinda(); + bool Reset(uint8_t param, uint8_t att); + void GoToRetryIfPossible(ErrorCode ec); /// Common code for a correct completion of UnloadFilament void ToolChangeFinishedCorrectly(); @@ -38,6 +41,7 @@ private: FeedToFinda feed; FeedToBondtech james; // bond ;) uint8_t plannedSlot; + uint8_t attempts; ///< how many attempts shall the state machine try before throwing out an error - obviously this has to be >= 1 }; /// The one and only instance of ToolChange state machine in the FW diff --git a/tests/unit/logic/tool_change/test_tool_change.cpp b/tests/unit/logic/tool_change/test_tool_change.cpp index d00c47b..ba28caf 100644 --- a/tests/unit/logic/tool_change/test_tool_change.cpp +++ b/tests/unit/logic/tool_change/test_tool_change.cpp @@ -72,6 +72,7 @@ void ToolChange(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) { // restart the automaton tc.Reset(toSlot); + tc.SetAttempts(1); REQUIRE(WhileCondition( tc, @@ -106,6 +107,7 @@ void NoToolChange(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) { // restart the automaton tc.Reset(toSlot); + tc.SetAttempts(1); // should not do anything REQUIRE(tc.TopLevelState() == ProgressCode::OK); @@ -122,6 +124,7 @@ void JustLoadFilament(logic::ToolChange &tc, uint8_t slot) { // restart the automaton tc.Reset(slot); + tc.SetAttempts(1); FeedingToFinda(tc, slot); @@ -182,6 +185,7 @@ void ToolChangeFailLoadToFinda(logic::ToolChange &tc, uint8_t fromSlot, uint8_t // restart the automaton tc.Reset(toSlot); + tc.SetAttempts(1); REQUIRE(WhileCondition(tc, std::bind(SimulateUnloadToFINDA, _1, 100, 2'000), 200'000)); REQUIRE(WhileTopState(tc, ProgressCode::UnloadingFilament, 5000)); @@ -346,6 +350,7 @@ void ToolChangeFailFSensor(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSl // restart the automaton tc.Reset(toSlot); + tc.SetAttempts(1); REQUIRE(VerifyState(tc, mg::FilamentLoadState::InNozzle, mi::idler.IdleSlotIndex(), fromSlot, true, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament)); // simulate unload to finda but fail the fsensor test