diff --git a/src/config/config.h b/src/config/config.h index 67905e3..63cd7e9 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -77,6 +77,7 @@ static constexpr U_mm minimumBowdenLength = 341.0_mm; /// ~341.0_mm /// Minimum static constexpr U_mm maximumBowdenLength = 792.0_mm; /// ~792.0_mm /// Maximum bowden length. @TODO Should be stored in EEPROM. static constexpr U_mm feedToFinda = cuttingEdgeToFindaMidpoint + filamentMinLoadedToMMU; static constexpr U_mm cutLength = 8.0_mm; +static constexpr U_mm fsensorToNozzle = 20.0_mm; /// ~20mm from MK4's filament sensor through extruder gears into nozzle /// Begin: Pulley axis configuration static constexpr AxisConfig pulley = { @@ -96,6 +97,7 @@ static constexpr PulleyLimits pulleyLimits = { .accel = 800.0_mm_s2, }; static constexpr U_mm_s pulleyFeedrate = 40._mm_s; +static constexpr U_mm_s pulleySlowFeedrate = 1._mm_s; /// End: Pulley axis configuration /// Begin: Selector configuration diff --git a/src/logic/feed_to_bondtech.cpp b/src/logic/feed_to_bondtech.cpp index 081c6b4..473e5e0 100644 --- a/src/logic/feed_to_bondtech.cpp +++ b/src/logic/feed_to_bondtech.cpp @@ -24,19 +24,21 @@ bool FeedToBondtech::Step() { if (mi::idler.Engaged()) { dbg_logic_P(PSTR("Feed to Bondtech --> Idler engaged")); dbg_logic_sprintf_P(PSTR("Pulley start steps %u"), mm::motion.CurPosition(mm::Pulley)); - state = PushingFilament; + state = PushingFilamentToFSensor; mm::motion.InitAxis(mm::Pulley); mm::motion.PlanMove(config::defaultBowdenLength, config::pulleyFeedrate); //@@TODO constants - there was some strange acceleration sequence in the original FW, // we can probably hand over some array of constants for hand-tuned acceleration + leverage some smoothing in the stepper as well } return false; - case PushingFilament: + case PushingFilamentToFSensor: //dbg_logic_P(PSTR("Feed to Bondtech --> Pushing")); if (mfs::fsensor.Pressed()) { mm::motion.AbortPlannedMoves(); // stop pushing filament - mi::idler.Disengage(); - mg::globals.SetFilamentLoaded(mg::FilamentLoadState::InNozzle); - state = DisengagingIdler; + mg::globals.SetFilamentLoaded(mg::FilamentLoadState::InFSensor); + // plan a slow move to help push filament into the nozzle + //@@TODO the speed in mm/s must correspond to printer's feeding speed! + mm::motion.PlanMove(config::fsensorToNozzle, config::pulleySlowFeedrate); + state = PushingFilamentIntoNozzle; } 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 @@ -44,6 +46,13 @@ bool FeedToBondtech::Step() { state = Failed; } return false; + case PushingFilamentIntoNozzle: + if (mm::motion.QueueEmpty()) { + mg::globals.SetFilamentLoaded(mg::FilamentLoadState::InNozzle); + mi::idler.Disengage(); + state = DisengagingIdler; + } + return false; case DisengagingIdler: if (!mi::idler.Engaged()) { dbg_logic_P(PSTR("Feed to Bondtech --> Idler disengaged")); diff --git a/src/logic/feed_to_bondtech.h b/src/logic/feed_to_bondtech.h index 8ebc59f..9fdcf96 100644 --- a/src/logic/feed_to_bondtech.h +++ b/src/logic/feed_to_bondtech.h @@ -6,14 +6,15 @@ namespace logic { /// @brief Feed filament to Bondtech gears of the printer /// /// Continuously feed filament until the printer detects the filament in its filament sensor. +/// Then it feeds a bit more very gently to push the filament into the nozzle /// Disengages the Idler after finishing the feed. /// Disables the Pulley axis after disengaging the idler. struct FeedToBondtech { /// internal states of the state machine enum { EngagingIdler, - PushingFilament, - UnloadBackToPTFE, + PushingFilamentToFSensor, + PushingFilamentIntoNozzle, DisengagingIdler, OK, Failed diff --git a/src/logic/load_filament.cpp b/src/logic/load_filament.cpp index 72fd653..a7d9de2 100644 --- a/src/logic/load_filament.cpp +++ b/src/logic/load_filament.cpp @@ -48,12 +48,12 @@ bool LoadFilament::StepInner() { if (retract.State() == RetractFromFinda::Failed) { state = ProgressCode::ERRDisengagingIdler; error = ErrorCode::FINDA_DIDNT_SWITCH_OFF; - mi::idler.Disengage(); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error } else { state = ProgressCode::DisengagingIdler; } + mi::idler.Disengage(); // disengage in both cases } break; case ProgressCode::DisengagingIdler: diff --git a/src/logic/progress_codes.h b/src/logic/progress_codes.h index d7f9357..e4f8070 100644 --- a/src/logic/progress_codes.h +++ b/src/logic/progress_codes.h @@ -14,24 +14,25 @@ enum class ProgressCode : uint_fast8_t { UnloadingToPulley, //P4 FeedingToFinda, // P5 FeedingToBondtech, // P6 - AvoidingGrind, // P7 - FinishingMoves, // P8 + FeedingToNozzle, // P7 + AvoidingGrind, // P8 + FinishingMoves, // P9 - ERRDisengagingIdler, // P9 - ERREngagingIdler, // P10 - ERRWaitingForUser, // P11 - ERRInternal, // P12 - ERRHelpingFilament, // P13 - ERRTMCFailed, // P14 + ERRDisengagingIdler, // P10 + ERREngagingIdler, // P11 + ERRWaitingForUser, // P12 + ERRInternal, // P13 + ERRHelpingFilament, // P14 + ERRTMCFailed, // P15 - UnloadingFilament, // P15 - LoadingFilament, // P16 - SelectingFilamentSlot, // P17 - PreparingBlade, // P18 - PushingFilament, // P19 - PerformingCut, // P20 - ReturningSelector, // P21 - ParkingSelector, // P22 - EjectingFilament, // P23 - RetractingFromFinda, // P24 + UnloadingFilament, // P16 + LoadingFilament, // P17 + SelectingFilamentSlot, // P18 + PreparingBlade, // P19 + PushingFilament, // P20 + PerformingCut, // P21 + ReturningSelector, // P22 + ParkingSelector, // P23 + EjectingFilament, // P24 + RetractingFromFinda, // P25 }; diff --git a/src/logic/retract_from_finda.cpp b/src/logic/retract_from_finda.cpp index b9246e0..dc84129 100644 --- a/src/logic/retract_from_finda.cpp +++ b/src/logic/retract_from_finda.cpp @@ -30,18 +30,14 @@ bool RetractFromFinda::Step() { if (!mf::finda.Pressed()) { // FINDA switched off correctly while the move was performed state = OK; mg::globals.SetFilamentLoaded(mg::FilamentLoadState::AtPulley); - mi::idler.Disengage(); + dbg_logic_sprintf_P(PSTR("Pulley end steps %u"), mm::motion.CurPosition(mm::Pulley)); + ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off); } else { // FINDA didn't switch off state = Failed; ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); } } - if (!mi::idler.Engaged()) { - dbg_logic_P(PSTR("Retract from FINDA --> Ider disengaged")); - dbg_logic_sprintf_P(PSTR("Pulley end steps %u"), mm::motion.CurPosition(mm::Pulley)); - ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off); - } return false; case OK: dbg_logic_P(PSTR("Retract from FINDA OK")); diff --git a/src/logic/retract_from_finda.h b/src/logic/retract_from_finda.h index a577946..391f741 100644 --- a/src/logic/retract_from_finda.h +++ b/src/logic/retract_from_finda.h @@ -5,7 +5,11 @@ namespace logic { /// @brief Retract filament from FINDA to PTFE /// -/// Continuously pull filament by a fixed length (originally 600 steps) + verify FINDA is switched OFF +/// Continuously pulls filament by a fixed length (originally 600 steps) + verifies FINDA is switched OFF while performing the move +/// Steps: +/// - engages idler (or makes sure the idler is engaged) +/// - pulls filament +/// - leaves idler engaged for chaining operations struct RetractFromFinda { /// internal states of the state machine enum { diff --git a/src/logic/tool_change.cpp b/src/logic/tool_change.cpp index 744c15b..ea15608 100644 --- a/src/logic/tool_change.cpp +++ b/src/logic/tool_change.cpp @@ -19,8 +19,8 @@ void ToolChange::Reset(uint8_t param) { return; } - if (param == mg::globals.ActiveSlot() && (mg::globals.FilamentLoaded() >= mg::FilamentLoadState::InSelector)) { - // we are already at the correct slot and the filament is loaded - nothing to do + if (param == mg::globals.ActiveSlot() && (mg::globals.FilamentLoaded() == mg::FilamentLoadState::InNozzle)) { + // we are already at the correct slot and the filament is loaded in the nozzle - nothing to do dbg_logic_P(PSTR("we are already at the correct slot and the filament is loaded - nothing to do\n")); return; } @@ -78,7 +78,6 @@ bool ToolChange::StepInner() { ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error } else { - mg::globals.SetFilamentLoaded(mg::FilamentLoadState::InFSensor); state = ProgressCode::OK; error = ErrorCode::OK; } diff --git a/src/logic/unload_filament.cpp b/src/logic/unload_filament.cpp index 1db3f4a..86e186e 100644 --- a/src/logic/unload_filament.cpp +++ b/src/logic/unload_filament.cpp @@ -45,16 +45,16 @@ bool UnloadFilament::StepInner() { if (retract.State() == RetractFromFinda::Failed) { state = ProgressCode::ERRDisengagingIdler; error = ErrorCode::FINDA_DIDNT_SWITCH_OFF; - mi::idler.Disengage(); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error } else { - state = ProgressCode::FinishingMoves; + state = ProgressCode::DisengagingIdler; } + mi::idler.Disengage(); } return false; - case ProgressCode::FinishingMoves: - if (mm::motion.QueueEmpty()) { + case ProgressCode::DisengagingIdler: + if (!mi::idler.Engaged()) { state = ProgressCode::OK; error = ErrorCode::OK; mm::motion.Disable(mm::Pulley); diff --git a/tests/unit/logic/cut_filament/CMakeLists.txt b/tests/unit/logic/cut_filament/CMakeLists.txt index b3b46d7..eda20ee 100644 --- a/tests/unit/logic/cut_filament/CMakeLists.txt +++ b/tests/unit/logic/cut_filament/CMakeLists.txt @@ -4,6 +4,7 @@ add_executable( ${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp ${CMAKE_SOURCE_DIR}/src/logic/cut_filament.cpp ${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.cpp + ${CMAKE_SOURCE_DIR}/src/logic/retract_from_finda.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_filament.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp diff --git a/tests/unit/logic/eject_filament/CMakeLists.txt b/tests/unit/logic/eject_filament/CMakeLists.txt index c105a92..5113b18 100644 --- a/tests/unit/logic/eject_filament/CMakeLists.txt +++ b/tests/unit/logic/eject_filament/CMakeLists.txt @@ -4,6 +4,7 @@ add_executable( ${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp ${CMAKE_SOURCE_DIR}/src/logic/eject_filament.cpp ${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.cpp + ${CMAKE_SOURCE_DIR}/src/logic/retract_from_finda.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_filament.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp diff --git a/tests/unit/logic/failing_tmc/CMakeLists.txt b/tests/unit/logic/failing_tmc/CMakeLists.txt index 8967899..0c7fa64 100644 --- a/tests/unit/logic/failing_tmc/CMakeLists.txt +++ b/tests/unit/logic/failing_tmc/CMakeLists.txt @@ -3,6 +3,7 @@ add_executable( failing_tmc_tests ${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp ${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.cpp + ${CMAKE_SOURCE_DIR}/src/logic/retract_from_finda.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_filament.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp 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 f33eba2..16ee255 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 @@ -51,7 +51,7 @@ 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::PushingFilament); + REQUIRE(fb.State() == FeedToBondtech::PushingFilamentToFSensor); // 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.LedOn(mg::globals.ActiveSlot(), ml::green)); @@ -61,11 +61,18 @@ TEST_CASE("feed_to_bondtech::feed_phase_unlimited", "[feed_to_bondtech]") { if( step == 1000 ){ mfs::fsensor.ProcessMessage(true); } - return fb.State() == FeedToBondtech::PushingFilament; }, + return fb.State() == FeedToBondtech::PushingFilamentToFSensor; }, 1500)); REQUIRE(mfs::fsensor.Pressed()); + // pushing filament from fsensor into the nozzle + REQUIRE(fb.State() == FeedToBondtech::PushingFilamentIntoNozzle); + REQUIRE(WhileCondition( + fb, + [&](int) { return fb.State() == FeedToBondtech::PushingFilamentIntoNozzle; }, + 5000)); + // disengaging idler REQUIRE(fb.State() == FeedToBondtech::DisengagingIdler); REQUIRE(WhileCondition( diff --git a/tests/unit/logic/load_filament/test_load_filament.cpp b/tests/unit/logic/load_filament/test_load_filament.cpp index 5160e0d..d9632c5 100644 --- a/tests/unit/logic/load_filament/test_load_filament.cpp +++ b/tests/unit/logic/load_filament/test_load_filament.cpp @@ -39,11 +39,7 @@ void LoadFilamentCommonSetup(uint8_t slot, logic::LoadFilament &lf) { // no change in selector's position // FINDA off // green LED should blink, red off - REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::EngagingIdler)); - - // Stage 1 - engaging idler - REQUIRE(WhileTopState(lf, ProgressCode::EngagingIdler, idlerEngageDisengageMaxSteps)); - REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, slot, slot, false, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda)); + REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda)); } void LoadFilamentSuccessful(uint8_t slot, logic::LoadFilament &lf) { @@ -69,7 +65,7 @@ void LoadFilamentSuccessful(uint8_t slot, logic::LoadFilament &lf) { } return lf.TopLevelState() == ProgressCode::RetractingFromFinda; }, 5000)); - REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, slot, slot, false, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::DisengagingIdler)); + REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, slot, slot, false, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::DisengagingIdler)); // Stage 4 - disengaging idler REQUIRE(WhileTopState(lf, ProgressCode::DisengagingIdler, idlerEngageDisengageMaxSteps)); diff --git a/tests/unit/logic/unload_filament/CMakeLists.txt b/tests/unit/logic/unload_filament/CMakeLists.txt index 7f4b1da..b7fa33f 100644 --- a/tests/unit/logic/unload_filament/CMakeLists.txt +++ b/tests/unit/logic/unload_filament/CMakeLists.txt @@ -3,6 +3,7 @@ add_executable( unload_filament_tests ${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp ${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.cpp + ${CMAKE_SOURCE_DIR}/src/logic/retract_from_finda.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_filament.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp diff --git a/tests/unit/logic/unload_filament/test_unload_filament.cpp b/tests/unit/logic/unload_filament/test_unload_filament.cpp index e93b16d..e94a4e7 100644 --- a/tests/unit/logic/unload_filament/test_unload_filament.cpp +++ b/tests/unit/logic/unload_filament/test_unload_filament.cpp @@ -66,36 +66,19 @@ void RegularUnloadFromSlot04(uint8_t slot, logic::UnloadFilament &uf) { // no change in selector's position // FINDA triggered off // green LED should be off - REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, slot, slot, false, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::DisengagingIdler)); + REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, slot, slot, false, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::RetractingFromFinda)); - // Stage 2 - idler was engaged, disengage it + // Stage 2 - retracting from FINDA + REQUIRE(WhileTopState(uf, ProgressCode::RetractingFromFinda, idlerEngageDisengageMaxSteps)); + + // Stage 3 - idler was engaged, disengage it REQUIRE(WhileTopState(uf, ProgressCode::DisengagingIdler, idlerEngageDisengageMaxSteps)); - // we still think we have filament loaded at this stage - // idler should have been disengaged - // no change in selector's position - // FINDA still triggered off - // green LED should be off - REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::AvoidingGrind)); - - // Stage 3 - avoiding grind (whatever is that @@TODO) - REQUIRE(WhileTopState(uf, ProgressCode::AvoidingGrind, 5000)); - - // we still think we have filament loaded at this stage - // idler should have been disengaged - // no change in selector's position - // FINDA still triggered off - // green LED should be off - REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::FinishingMoves)); - - // Stage 4 - finishing moves and setting global state correctly - REQUIRE(WhileTopState(uf, ProgressCode::FinishingMoves, 5000)); - // filament unloaded // idler should have been disengaged // no change in selector's position // FINDA still triggered off - // green LED should be OFF + // green LED should be off REQUIRE(VerifyState(uf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK)); // Stage 5 - repeated calls to TopLevelState should return "OK"