From fbb46e5951d0d78f0cd106fd2d47bd4d9b9099bf Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Sat, 21 May 2022 13:47:03 +0200 Subject: [PATCH] Distinguish fast and slow feed stage Originally, only FeedingToBondtech was reported to the printer. With PR#173 we have this operation separated into a fast and a slow stage (for MK3S with the chimney). It looks like the printer could benefit from knowing if the MMU is still pushing fast or when it entered the slow stage (to prevent ramming hard the Bondtech gears) Along with this new state being reported, we also introduce a new ErrorCode::FSENSOR_TOO_EARLY which basically means that the fsensor triggered in the fast feeding stage. --- src/logic/error_codes.h | 5 +++++ src/logic/feed_to_bondtech.cpp | 22 +++++++++++++++---- src/logic/feed_to_bondtech.h | 5 ++++- src/logic/progress_codes.h | 2 ++ src/logic/tool_change.cpp | 18 +++++++++++++-- .../test_feed_to_bondtech.cpp | 11 ++++++++-- .../logic/tool_change/test_tool_change.cpp | 12 ++++++---- 7 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/logic/error_codes.h b/src/logic/error_codes.h index bc495f9..66734a7 100644 --- a/src/logic/error_codes.h +++ b/src/logic/error_codes.h @@ -41,6 +41,11 @@ enum class ErrorCode : uint_fast16_t { FINDA_VS_EEPROM_DISREPANCY = 0x8008, ///< E32776 FINDA is pressed but we have no such record in EEPROM - this can only happen at the start of the MMU and can be resolved by issuing an Unload command + FSENSOR_TOO_EARLY = 0x8009, ///< E32777 FSensor triggered while doing FastFeedToBondtech - that means either: + ///< - the PTFE is too short + ///< - 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 + 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/logic/feed_to_bondtech.cpp b/src/logic/feed_to_bondtech.cpp index 28e36ce..7f71b79 100644 --- a/src/logic/feed_to_bondtech.cpp +++ b/src/logic/feed_to_bondtech.cpp @@ -34,7 +34,7 @@ bool FeedToBondtech::Step() { if (mi::idler.Engaged()) { dbg_logic_P(PSTR("Feed to Bondtech --> Idler engaged")); dbg_logic_fP(PSTR("Pulley start steps %u"), mpu::pulley.CurrentPosition_mm()); - state = PushingFilamentToFSensor; + state = PushingFilamentFast; mpu::pulley.InitAxis(); // plan a fast move while in the safe minimal length mpu::pulley.PlanMove(config::minimumBowdenLength, config::pulleyLoadFeedrate, config::pulleySlowFeedrate); @@ -42,14 +42,26 @@ bool FeedToBondtech::Step() { mpu::pulley.PlanMove(config::maximumBowdenLength - config::minimumBowdenLength, config::pulleySlowFeedrate, config::pulleySlowFeedrate); } return false; + case PushingFilamentFast: + if (mfs::fsensor.Pressed()) { + // Safety precaution - if the fsensor triggers while pushing the filament fast, we must stop pushing immediately + // With a correctly set-up MMU this shouldn't happen + mm::motion.AbortPlannedMoves(); // stop pushing filament + state = FSensorTooEarly; + } else if (mm::motion.PlannedMoves(mm::Pulley) == 1) { + // a bit of a hack - the fast (already planned) move has finished, doing the slow part + // -> just switch to FeedingToFSensor + state = PushingFilamentToFSensor; + } + return false; case PushingFilamentToFSensor: //dbg_logic_P(PSTR("Feed to Bondtech --> Pushing")); if (mfs::fsensor.Pressed()) { mm::motion.AbortPlannedMoves(); // stop pushing filament GoToPushToNozzle(); - } else if (mm::motion.StallGuard(mm::Pulley)) { - // stall guard occurred during movement - the filament got stuck - state = Failed; // @@TODO may be even report why it failed + // } else if (mm::motion.StallGuard(mm::Pulley)) { + // // stall guard occurred during movement - the filament got stuck + // state = PulleyStalled; } else if (mm::motion.QueueEmpty()) { // all moves have been finished and the fsensor didn't switch on state = Failed; } @@ -76,6 +88,8 @@ bool FeedToBondtech::Step() { dbg_logic_P(PSTR("Feed to Bondtech OK")); return true; case Failed: + case FSensorTooEarly: + // case PulleyStalled: dbg_logic_P(PSTR("Feed to Bondtech FAILED")); return true; default: diff --git a/src/logic/feed_to_bondtech.h b/src/logic/feed_to_bondtech.h index b4a28bc..146c48a 100644 --- a/src/logic/feed_to_bondtech.h +++ b/src/logic/feed_to_bondtech.h @@ -14,11 +14,14 @@ struct FeedToBondtech { /// internal states of the state machine enum { EngagingIdler, + PushingFilamentFast, PushingFilamentToFSensor, PushingFilamentIntoNozzle, DisengagingIdler, OK, - Failed + Failed, + FSensorTooEarly, + // PulleyStalled }; inline FeedToBondtech() diff --git a/src/logic/progress_codes.h b/src/logic/progress_codes.h index 6b37ce4..7dd2e19 100644 --- a/src/logic/progress_codes.h +++ b/src/logic/progress_codes.h @@ -39,5 +39,7 @@ enum class ProgressCode : uint_fast8_t { Homing, // P26 MovingSelector, // P27 + FeedingToFSensor, // P28 + Empty = 0xff // dummy empty state }; diff --git a/src/logic/tool_change.cpp b/src/logic/tool_change.cpp index 62438bf..c524486 100644 --- a/src/logic/tool_change.cpp +++ b/src/logic/tool_change.cpp @@ -81,9 +81,14 @@ bool ToolChange::StepInner() { break; case ProgressCode::FeedingToBondtech: if (james.Step()) { - if (james.State() == FeedToBondtech::Failed) { + switch (james.State()) { + case FeedToBondtech::Failed: GoToErrDisengagingIdler(ErrorCode::FSENSOR_DIDNT_SWITCH_ON); // signal loading error - } else { + break; + case FeedToBondtech::FSensorTooEarly: + GoToErrDisengagingIdler(ErrorCode::FSENSOR_TOO_EARLY); // signal loading error + break; + default: ToolChangeFinishedCorrectly(); } } @@ -163,6 +168,15 @@ ProgressCode ToolChange::State() const { switch (state) { case ProgressCode::UnloadingFilament: return unl.State(); // report sub-automaton states properly + case ProgressCode::FeedingToBondtech: + // only process the important states + switch (james.State()) { + case FeedToBondtech::PushingFilamentToFSensor: + return ProgressCode::FeedingToFSensor; + case FeedToBondtech::PushingFilamentIntoNozzle: + return ProgressCode::FeedingToNozzle; + } + // [[fallthrough]] // everything else is reported as FeedingToBondtech default: return state; } diff --git a/tests/unit/logic/feed_to_bondtech/test_feed_to_bondtech.cpp b/tests/unit/logic/feed_to_bondtech/test_feed_to_bondtech.cpp index e8e61eb..65424ee 100644 --- a/tests/unit/logic/feed_to_bondtech/test_feed_to_bondtech.cpp +++ b/tests/unit/logic/feed_to_bondtech/test_feed_to_bondtech.cpp @@ -52,14 +52,21 @@ TEST_CASE("feed_to_bondtech::feed_phase_unlimited", "[feed_to_bondtech]") { CHECK(mm::axes[mm::Pulley].enabled); // idler engaged, selector in position, we'll start pushing filament - REQUIRE(fb.State() == FeedToBondtech::PushingFilamentToFSensor); + REQUIRE(fb.State() == FeedToBondtech::PushingFilamentFast); // at least at the beginning the LED should shine green (it should be blinking, but this mode has been already verified in the LED's unit test) REQUIRE(ml::leds.Mode(mg::globals.ActiveSlot(), ml::green) == ml::blink0); + // fast load - no fsensor trigger + REQUIRE(WhileCondition( + fb, + [&](uint32_t) { return fb.State() == FeedToBondtech::PushingFilamentFast; }, + mm::unitToSteps(config::minimumBowdenLength) + 2)); + + // slow load - expecting fsensor trigger REQUIRE(WhileCondition( fb, [&](uint32_t step) { - if( step == 1000 ){ + if( step == 100 ){ mfs::fsensor.ProcessMessage(true); } return fb.State() == FeedToBondtech::PushingFilamentToFSensor; }, diff --git a/tests/unit/logic/tool_change/test_tool_change.cpp b/tests/unit/logic/tool_change/test_tool_change.cpp index 3f56490..1145c86 100644 --- a/tests/unit/logic/tool_change/test_tool_change.cpp +++ b/tests/unit/logic/tool_change/test_tool_change.cpp @@ -42,15 +42,17 @@ void FeedingToFinda(logic::ToolChange &tc, uint8_t toSlot, uint32_t triggerAt = } void FeedingToBondtech(logic::ToolChange &tc, uint8_t toSlot) { - // james is feeding + // james is feeding fast and then slowly + // FSensor must not trigger too early + REQUIRE_FALSE(mfs::fsensor.Pressed()); REQUIRE(WhileCondition( tc, [&](uint32_t step) -> bool { - if(step == 2000){ // on 2000th step make filament sensor trigger + if(step == mm::unitToSteps(config::minimumBowdenLength)+10){ // on the correct step make filament sensor trigger mfs::fsensor.ProcessMessage(true); } return tc.TopLevelState() == ProgressCode::FeedingToBondtech; }, - 20000UL)); + mm::unitToSteps(config::minimumBowdenLength) + 10000)); REQUIRE(VerifyState(tc, mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), toSlot, true, false, ml::on, ml::off, ErrorCode::OK, ProgressCode::OK)); } @@ -73,7 +75,9 @@ void ToolChange(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) { REQUIRE(WhileCondition( tc, [&](uint32_t step) -> bool { - if(step == 2000){ // on 2000th step make FINDA trigger + if(step == 20){ // on 20th step make FSensor switch off + mfs::fsensor.ProcessMessage(false); + } else if(step == mm::unitToSteps(config::minimumBowdenLength)){ // on 2000th step make FINDA trigger hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low); } return tc.TopLevelState() == ProgressCode::UnloadingFilament; },