Fix unit tests

That includes:
- introduce pulley slow feedrate and fsensor-to-nozzle distance
  in config necessary for slowly feeding the filament from fsensor into the nozzle.
  (the constant is subject to extraction into some other config as it has to be used in the printer as well).
- update FeedToBondtech accordingly to perform a gentle push into the nozzle
  after fsensor detects the filament + update its unit tests.
- slight cleanup of LoadFilament + fix its unit tests
- add FeedingToNozzle progress code, as it might be interesting
  to inform the printer about this task in the future
- revert non-clean changes from RetractFromFinda - it should not disengage the idler
- revert incorrect + fix ToolChange
- clean-up UnloadFilament
pull/126/head
D.R.racer 2021-10-01 09:18:04 +02:00 committed by DRracer
parent 94e6d1403e
commit e1af08b3d5
16 changed files with 73 additions and 71 deletions

View File

@ -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 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 feedToFinda = cuttingEdgeToFindaMidpoint + filamentMinLoadedToMMU;
static constexpr U_mm cutLength = 8.0_mm; 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 /// Begin: Pulley axis configuration
static constexpr AxisConfig pulley = { static constexpr AxisConfig pulley = {
@ -96,6 +97,7 @@ static constexpr PulleyLimits pulleyLimits = {
.accel = 800.0_mm_s2, .accel = 800.0_mm_s2,
}; };
static constexpr U_mm_s pulleyFeedrate = 40._mm_s; static constexpr U_mm_s pulleyFeedrate = 40._mm_s;
static constexpr U_mm_s pulleySlowFeedrate = 1._mm_s;
/// End: Pulley axis configuration /// End: Pulley axis configuration
/// Begin: Selector configuration /// Begin: Selector configuration

View File

@ -24,19 +24,21 @@ bool FeedToBondtech::Step() {
if (mi::idler.Engaged()) { if (mi::idler.Engaged()) {
dbg_logic_P(PSTR("Feed to Bondtech --> 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)); 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.InitAxis(mm::Pulley);
mm::motion.PlanMove<mm::Pulley>(config::defaultBowdenLength, config::pulleyFeedrate); //@@TODO constants - there was some strange acceleration sequence in the original FW, mm::motion.PlanMove<mm::Pulley>(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 // we can probably hand over some array of constants for hand-tuned acceleration + leverage some smoothing in the stepper as well
} }
return false; return false;
case PushingFilament: case PushingFilamentToFSensor:
//dbg_logic_P(PSTR("Feed to Bondtech --> Pushing")); //dbg_logic_P(PSTR("Feed to Bondtech --> Pushing"));
if (mfs::fsensor.Pressed()) { if (mfs::fsensor.Pressed()) {
mm::motion.AbortPlannedMoves(); // stop pushing filament mm::motion.AbortPlannedMoves(); // stop pushing filament
mi::idler.Disengage(); mg::globals.SetFilamentLoaded(mg::FilamentLoadState::InFSensor);
mg::globals.SetFilamentLoaded(mg::FilamentLoadState::InNozzle); // plan a slow move to help push filament into the nozzle
state = DisengagingIdler; //@@TODO the speed in mm/s must correspond to printer's feeding speed!
mm::motion.PlanMove<mm::Pulley>(config::fsensorToNozzle, config::pulleySlowFeedrate);
state = PushingFilamentIntoNozzle;
} else if (mm::motion.StallGuard(mm::Pulley)) { } else if (mm::motion.StallGuard(mm::Pulley)) {
// stall guard occurred during movement - the filament got stuck // stall guard occurred during movement - the filament got stuck
state = Failed; // @@TODO may be even report why it failed state = Failed; // @@TODO may be even report why it failed
@ -44,6 +46,13 @@ bool FeedToBondtech::Step() {
state = Failed; state = Failed;
} }
return false; return false;
case PushingFilamentIntoNozzle:
if (mm::motion.QueueEmpty()) {
mg::globals.SetFilamentLoaded(mg::FilamentLoadState::InNozzle);
mi::idler.Disengage();
state = DisengagingIdler;
}
return false;
case DisengagingIdler: case DisengagingIdler:
if (!mi::idler.Engaged()) { if (!mi::idler.Engaged()) {
dbg_logic_P(PSTR("Feed to Bondtech --> Idler disengaged")); dbg_logic_P(PSTR("Feed to Bondtech --> Idler disengaged"));

View File

@ -6,14 +6,15 @@ namespace logic {
/// @brief Feed filament to Bondtech gears of the printer /// @brief Feed filament to Bondtech gears of the printer
/// ///
/// Continuously feed filament until the printer detects the filament in its filament sensor. /// 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. /// Disengages the Idler after finishing the feed.
/// Disables the Pulley axis after disengaging the idler. /// Disables the Pulley axis after disengaging the idler.
struct FeedToBondtech { struct FeedToBondtech {
/// internal states of the state machine /// internal states of the state machine
enum { enum {
EngagingIdler, EngagingIdler,
PushingFilament, PushingFilamentToFSensor,
UnloadBackToPTFE, PushingFilamentIntoNozzle,
DisengagingIdler, DisengagingIdler,
OK, OK,
Failed Failed

View File

@ -48,12 +48,12 @@ bool LoadFilament::StepInner() {
if (retract.State() == RetractFromFinda::Failed) { if (retract.State() == RetractFromFinda::Failed) {
state = ProgressCode::ERRDisengagingIdler; state = ProgressCode::ERRDisengagingIdler;
error = ErrorCode::FINDA_DIDNT_SWITCH_OFF; 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::green, ml::off);
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error
} else { } else {
state = ProgressCode::DisengagingIdler; state = ProgressCode::DisengagingIdler;
} }
mi::idler.Disengage(); // disengage in both cases
} }
break; break;
case ProgressCode::DisengagingIdler: case ProgressCode::DisengagingIdler:

View File

@ -14,24 +14,25 @@ enum class ProgressCode : uint_fast8_t {
UnloadingToPulley, //P4 UnloadingToPulley, //P4
FeedingToFinda, // P5 FeedingToFinda, // P5
FeedingToBondtech, // P6 FeedingToBondtech, // P6
AvoidingGrind, // P7 FeedingToNozzle, // P7
FinishingMoves, // P8 AvoidingGrind, // P8
FinishingMoves, // P9
ERRDisengagingIdler, // P9 ERRDisengagingIdler, // P10
ERREngagingIdler, // P10 ERREngagingIdler, // P11
ERRWaitingForUser, // P11 ERRWaitingForUser, // P12
ERRInternal, // P12 ERRInternal, // P13
ERRHelpingFilament, // P13 ERRHelpingFilament, // P14
ERRTMCFailed, // P14 ERRTMCFailed, // P15
UnloadingFilament, // P15 UnloadingFilament, // P16
LoadingFilament, // P16 LoadingFilament, // P17
SelectingFilamentSlot, // P17 SelectingFilamentSlot, // P18
PreparingBlade, // P18 PreparingBlade, // P19
PushingFilament, // P19 PushingFilament, // P20
PerformingCut, // P20 PerformingCut, // P21
ReturningSelector, // P21 ReturningSelector, // P22
ParkingSelector, // P22 ParkingSelector, // P23
EjectingFilament, // P23 EjectingFilament, // P24
RetractingFromFinda, // P24 RetractingFromFinda, // P25
}; };

View File

@ -30,18 +30,14 @@ bool RetractFromFinda::Step() {
if (!mf::finda.Pressed()) { // FINDA switched off correctly while the move was performed if (!mf::finda.Pressed()) { // FINDA switched off correctly while the move was performed
state = OK; state = OK;
mg::globals.SetFilamentLoaded(mg::FilamentLoadState::AtPulley); 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 } else { // FINDA didn't switch off
state = Failed; state = Failed;
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); 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; return false;
case OK: case OK:
dbg_logic_P(PSTR("Retract from FINDA OK")); dbg_logic_P(PSTR("Retract from FINDA OK"));

View File

@ -5,7 +5,11 @@ namespace logic {
/// @brief Retract filament from FINDA to PTFE /// @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 { struct RetractFromFinda {
/// internal states of the state machine /// internal states of the state machine
enum { enum {

View File

@ -19,8 +19,8 @@ void ToolChange::Reset(uint8_t param) {
return; return;
} }
if (param == mg::globals.ActiveSlot() && (mg::globals.FilamentLoaded() >= mg::FilamentLoadState::InSelector)) { if (param == mg::globals.ActiveSlot() && (mg::globals.FilamentLoaded() == mg::FilamentLoadState::InNozzle)) {
// we are already at the correct slot and the filament is loaded - nothing to do // 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")); dbg_logic_P(PSTR("we are already at the correct slot and the filament is loaded - nothing to do\n"));
return; 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::green, ml::off);
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error
} else { } else {
mg::globals.SetFilamentLoaded(mg::FilamentLoadState::InFSensor);
state = ProgressCode::OK; state = ProgressCode::OK;
error = ErrorCode::OK; error = ErrorCode::OK;
} }

View File

@ -45,16 +45,16 @@ bool UnloadFilament::StepInner() {
if (retract.State() == RetractFromFinda::Failed) { if (retract.State() == RetractFromFinda::Failed) {
state = ProgressCode::ERRDisengagingIdler; state = ProgressCode::ERRDisengagingIdler;
error = ErrorCode::FINDA_DIDNT_SWITCH_OFF; 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::green, ml::off);
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error
} else { } else {
state = ProgressCode::FinishingMoves; state = ProgressCode::DisengagingIdler;
} }
mi::idler.Disengage();
} }
return false; return false;
case ProgressCode::FinishingMoves: case ProgressCode::DisengagingIdler:
if (mm::motion.QueueEmpty()) { if (!mi::idler.Engaged()) {
state = ProgressCode::OK; state = ProgressCode::OK;
error = ErrorCode::OK; error = ErrorCode::OK;
mm::motion.Disable(mm::Pulley); mm::motion.Disable(mm::Pulley);

View File

@ -4,6 +4,7 @@ add_executable(
${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp ${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp
${CMAKE_SOURCE_DIR}/src/logic/cut_filament.cpp ${CMAKE_SOURCE_DIR}/src/logic/cut_filament.cpp
${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.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_filament.cpp
${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp
${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp

View File

@ -4,6 +4,7 @@ add_executable(
${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp ${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp
${CMAKE_SOURCE_DIR}/src/logic/eject_filament.cpp ${CMAKE_SOURCE_DIR}/src/logic/eject_filament.cpp
${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.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_filament.cpp
${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp
${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp

View File

@ -3,6 +3,7 @@ add_executable(
failing_tmc_tests failing_tmc_tests
${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp ${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp
${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.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_filament.cpp
${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp
${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp

View File

@ -51,7 +51,7 @@ TEST_CASE("feed_to_bondtech::feed_phase_unlimited", "[feed_to_bondtech]") {
CHECK(mm::axes[mm::Pulley].enabled); CHECK(mm::axes[mm::Pulley].enabled);
// idler engaged, selector in position, we'll start pushing filament // 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) // 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)); 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 ){ if( step == 1000 ){
mfs::fsensor.ProcessMessage(true); mfs::fsensor.ProcessMessage(true);
} }
return fb.State() == FeedToBondtech::PushingFilament; }, return fb.State() == FeedToBondtech::PushingFilamentToFSensor; },
1500)); 1500));
REQUIRE(mfs::fsensor.Pressed()); 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 // disengaging idler
REQUIRE(fb.State() == FeedToBondtech::DisengagingIdler); REQUIRE(fb.State() == FeedToBondtech::DisengagingIdler);
REQUIRE(WhileCondition( REQUIRE(WhileCondition(

View File

@ -39,11 +39,7 @@ void LoadFilamentCommonSetup(uint8_t slot, logic::LoadFilament &lf) {
// no change in selector's position // no change in selector's position
// FINDA off // FINDA off
// green LED should blink, red 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)); REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda));
// 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));
} }
void LoadFilamentSuccessful(uint8_t slot, logic::LoadFilament &lf) { 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; }, return lf.TopLevelState() == ProgressCode::RetractingFromFinda; },
5000)); 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 // Stage 4 - disengaging idler
REQUIRE(WhileTopState(lf, ProgressCode::DisengagingIdler, idlerEngageDisengageMaxSteps)); REQUIRE(WhileTopState(lf, ProgressCode::DisengagingIdler, idlerEngageDisengageMaxSteps));

View File

@ -3,6 +3,7 @@ add_executable(
unload_filament_tests unload_filament_tests
${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp ${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp
${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.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_filament.cpp
${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp ${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp
${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp

View File

@ -66,36 +66,19 @@ void RegularUnloadFromSlot04(uint8_t slot, logic::UnloadFilament &uf) {
// no change in selector's position // no change in selector's position
// FINDA triggered off // FINDA triggered off
// green LED should be 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)); 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 // filament unloaded
// idler should have been disengaged // idler should have been disengaged
// no change in selector's position // no change in selector's position
// FINDA still triggered off // 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)); 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" // Stage 5 - repeated calls to TopLevelState should return "OK"