Update unit tests to handle UnloadingFromFSensor
parent
33edba66ee
commit
f4274d1b16
|
|
@ -28,8 +28,8 @@ bool UnloadFilament::Reset(uint8_t /*param*/) {
|
|||
mpu::pulley.InitAxis();
|
||||
state = ProgressCode::UnloadingToFinda;
|
||||
error = ErrorCode::RUNNING;
|
||||
unl.Reset(maxRetries);
|
||||
ml::leds.SetPairButOffOthers(mg::globals.ActiveSlot(), ml::off, ml::off);
|
||||
unl.Reset(maxRetries);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,9 @@ void UnloadToFinda::Reset(uint8_t maxTries) {
|
|||
state = OK; // FINDA is already off, we assume the fillament is not there, i.e. already unloaded
|
||||
} else {
|
||||
// FINDA is sensing the filament, plan moves to unload it
|
||||
state = EngagingIdler;
|
||||
mi::idler.Engage(mg::globals.ActiveSlot());
|
||||
if (mg::globals.FilamentLoaded() >= mg::FilamentLoadState::InSelector) {
|
||||
state = UnloadingFromFSensor;
|
||||
mpu::pulley.InitAxis();
|
||||
state = EngagingIdler;
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::blink0);
|
||||
} else {
|
||||
state = FailedFINDA;
|
||||
|
|
@ -38,12 +36,16 @@ bool UnloadToFinda::Step() {
|
|||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InSelector);
|
||||
unloadStart_mm = mpu::pulley.CurrentPosition_mm();
|
||||
// plan both moves to keep the unload smooth
|
||||
mpu::pulley.InitAxis();
|
||||
mpu::pulley.PlanMove(-mg::globals.FSensorUnloadCheck_mm(), mg::globals.PulleySlowFeedrate_mm_s());
|
||||
mpu::pulley.PlanMove(-config::defaultBowdenLength - config::feedToFinda - config::filamentMinLoadedToMMU, mg::globals.PulleyUnloadFeedrate_mm_s());
|
||||
mpu::pulley.PlanMove(-config::defaultBowdenLength - config::feedToFinda - config::filamentMinLoadedToMMU // standard lenght where FINDA is expected to trigger
|
||||
+ mg::globals.FSensorUnloadCheck_mm(), // but subtract the slow unload phase distance
|
||||
mg::globals.PulleyUnloadFeedrate_mm_s());
|
||||
}
|
||||
return false;
|
||||
case UnloadingFromFSensor:
|
||||
if ((abs(unloadStart_mm - mpu::pulley.CurrentPosition_mm()) > mm::truncatedUnit(mg::globals.FSensorUnloadCheck_mm()))) {
|
||||
case UnloadingFromFSensor: {
|
||||
int32_t mpucp = mpu::pulley.CurrentPosition_mm();
|
||||
if ((abs(unloadStart_mm - mpucp) > mm::truncatedUnit(mg::globals.FSensorUnloadCheck_mm()))) {
|
||||
// passed the slow unload distance, check fsensor
|
||||
if (mfs::fsensor.Pressed()) {
|
||||
// fsensor didn't trigger within the first fsensorUnloadCheckDistance mm -> stop pulling, something failed, report an error
|
||||
|
|
@ -51,19 +53,24 @@ bool UnloadToFinda::Step() {
|
|||
state = FailedFSensor;
|
||||
mm::motion.AbortPlannedMoves(); // stop rotating the pulley
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
||||
return false; // avoid falling into WaitingForFINDA
|
||||
} else {
|
||||
// fsensor turned correctly off, seamlessly transfer to fast unloading -> waiting for FINDA
|
||||
// the move has already been planned when idler engaged
|
||||
state = WaitingForFINDA;
|
||||
// in this case we can safely fall into the WaitingForFINDA state as well
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
[[fallthrough]]; // while UnloadingFromFSensor also check for FINDA switch off
|
||||
// if that happens, filament has either broken (its tip reached finda before fsensor switched off)
|
||||
// or there is some other problem.
|
||||
case WaitingForFINDA: {
|
||||
if (!mf::finda.Pressed()) {
|
||||
// detected end of filament
|
||||
state = OK;
|
||||
mm::motion.AbortPlannedMoves(); // stop rotating the pulley
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
||||
// ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
||||
} else if (/*tmc2130_read_gstat() &&*/ mm::motion.QueueEmpty()) {
|
||||
// we reached the end of move queue, but the FINDA didn't switch off
|
||||
// two possible causes - grinded filament or malfunctioning FINDA
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ void FailingMovableUnload(hal::tmc2130::ErrorFlags ef, ErrorCode ec, config::Axi
|
|||
// UnloadFilament starts by engaging the idler (through the UnloadToFinda state machine)
|
||||
uf.Reset(0);
|
||||
|
||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), 0, true, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingToFinda));
|
||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), 0, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingToFinda));
|
||||
|
||||
REQUIRE(WhileCondition(
|
||||
uf,
|
||||
|
|
|
|||
|
|
@ -116,15 +116,18 @@ bool VerifyState(SM &uf, mg::FilamentLoadState fls, uint8_t idlerSlotIndex, uint
|
|||
bool findaPressed, bool pulleyEnabled, ml::Mode greenLEDMode, ml::Mode redLEDMode, ErrorCode err, ProgressCode topLevelProgress) {
|
||||
|
||||
CHECKED_ELSE(VerifyEnvironmentState(fls, idlerSlotIndex, selectorSlotIndex, findaPressed, pulleyEnabled, greenLEDMode, redLEDMode)) {
|
||||
WARN("VerifyEnvironmentState failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECKED_ELSE(uf.Error() == err) {
|
||||
WARN("uf.Error() != err");
|
||||
return false;
|
||||
}
|
||||
auto tls = uf.TopLevelState();
|
||||
CHECKED_ELSE(tls == topLevelProgress) {
|
||||
return false;
|
||||
WARN("tls == topLevelProgress");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -181,10 +184,12 @@ bool VerifyState2(SM &uf, mg::FilamentLoadState fls, uint8_t idlerSlotIndex, uin
|
|||
}
|
||||
|
||||
CHECKED_ELSE(uf.Error() == err) {
|
||||
return false;
|
||||
WARN("uf.Error() != err");
|
||||
return false;
|
||||
}
|
||||
CHECKED_ELSE(uf.TopLevelState() == topLevelProgress) {
|
||||
return false;
|
||||
WARN("tls == topLevelProgress");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ void ToolChangeFailFSensor(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSl
|
|||
// restart the automaton
|
||||
tc.Reset(toSlot);
|
||||
|
||||
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InNozzle, mi::idler.IdleSlotIndex(), fromSlot, true, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
|
||||
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InNozzle, mi::idler.IdleSlotIndex(), fromSlot, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
|
||||
// simulate unload to finda but fail the fsensor test
|
||||
REQUIRE(WhileCondition(tc, std::bind(SimulateUnloadToFINDA, _1, 500'000, 10'000), 200'000));
|
||||
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::idler.IdleSlotIndex(), fromSlot, false, false, ml::off, ml::blink0, ErrorCode::FSENSOR_DIDNT_SWITCH_OFF, ProgressCode::UnloadingFilament));
|
||||
|
|
@ -498,7 +498,7 @@ void ToolChangeFSENSOR_TOO_EARLY(logic::ToolChange &tc, uint8_t slot) {
|
|||
|
||||
// make AutoRetry
|
||||
PressButtonAndDebounce(tc, mb::Middle, true);
|
||||
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::idler.IdleSlotIndex(), slot, true, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
|
||||
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::idler.IdleSlotIndex(), slot, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
|
||||
|
||||
SimulateIdlerHoming(tc);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,14 +57,12 @@ void RegularUnloadFromSlot04(uint8_t slot, logic::UnloadFilament &uf, uint8_t en
|
|||
|
||||
// run the automaton
|
||||
// Stage 1 - unloading to FINDA
|
||||
REQUIRE(WhileCondition(
|
||||
uf,
|
||||
[&](uint32_t step) -> bool {
|
||||
if(step == 100){ // on 100th step make FINDA trigger
|
||||
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
|
||||
}
|
||||
return uf.TopLevelState() == ProgressCode::UnloadingToFinda; },
|
||||
50000));
|
||||
REQUIRE(WhileCondition(uf,
|
||||
std::bind(SimulateUnloadToFINDA, _1,
|
||||
mm::unitToSteps<mm::P_pos_t>(mg::globals.FSensorUnloadCheck_mm()) / 4, // make fsensor trigger roughly in the first 1/4 of the check distance
|
||||
mm::unitToSteps<mm::P_pos_t>(config::minimumBowdenLength)),
|
||||
200'000));
|
||||
uf.Step(); // make UnloadFilament do one more step to transfer to the correct state after finda pressed
|
||||
|
||||
// we still think we have filament loaded at this stage
|
||||
// idler should have been activated by the underlying automaton
|
||||
|
|
@ -102,7 +100,7 @@ TEST_CASE("unload_filament::regular_unload_from_slot_0-4", "[unload_filament]")
|
|||
for (uint8_t slot = 0; slot < config::toolCount; ++slot) {
|
||||
logic::UnloadFilament uf;
|
||||
RegularUnloadFromSlot04Init(slot, uf);
|
||||
RegularUnloadFromSlot04(slot, uf, mi::Idler::IdleSlotIndex(), false, ml::off);
|
||||
RegularUnloadFromSlot04(slot, uf, mi::Idler::IdleSlotIndex(), false, ml::blink0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +130,7 @@ void FindaDidntTriggerCommonSetup(uint8_t slot, logic::UnloadFilament &uf) {
|
|||
// FINDA triggered off
|
||||
// green LED should be off
|
||||
// no error so far
|
||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), slot, true, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingToFinda));
|
||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), slot, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingToFinda));
|
||||
|
||||
// run the automaton
|
||||
// Stage 1 - unloading to FINDA - do NOT let it trigger - keep it pressed, the automaton should finish all moves with the pulley
|
||||
|
|
@ -164,7 +162,6 @@ void FindaDidntTriggerCommonSetup(uint8_t slot, logic::UnloadFilament &uf) {
|
|||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, true, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERRWaitingForUser));
|
||||
}
|
||||
|
||||
|
||||
void FindaDidntTriggerResolveTryAgain(uint8_t slot, logic::UnloadFilament &uf) {
|
||||
// Stage 3 - the user has to do something
|
||||
// there are 3 options:
|
||||
|
|
@ -179,8 +176,8 @@ void FindaDidntTriggerResolveTryAgain(uint8_t slot, logic::UnloadFilament &uf) {
|
|||
// idler should have been disengaged
|
||||
// no change in selector's position
|
||||
// FINDA still on
|
||||
// red LED should blink, green LED should be off
|
||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, true, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingToFinda));
|
||||
// red LED should be off, green LED should be blinking
|
||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingToFinda));
|
||||
|
||||
ClearButtons(uf);
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,10 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
|||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingFromFSensor);
|
||||
REQUIRE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1, 10, 1000), 1100));
|
||||
REQUIRE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1,
|
||||
mm::unitToSteps<mm::P_pos_t>(mg::globals.FSensorUnloadCheck_mm()) / 4, // make fsensor trigger roughly in the first 1/4 of the check distance
|
||||
mm::unitToSteps<mm::P_pos_t>(config::minimumBowdenLength)),
|
||||
200'000));
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::OK);
|
||||
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InSelector);
|
||||
|
|
@ -109,11 +112,16 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]")
|
|||
5000));
|
||||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingFromFSensor);
|
||||
|
||||
// no changes to FINDA during unload - we'll pretend it never triggers
|
||||
// but set FSensor correctly
|
||||
REQUIRE_FALSE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1, 10, 150000), 50000));
|
||||
REQUIRE_FALSE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1,
|
||||
mm::unitToSteps<mm::P_pos_t>(mg::globals.FSensorUnloadCheck_mm()) / 4, // make fsensor trigger roughly in the first 1/4 of the check distance
|
||||
mm::unitToSteps<mm::P_pos_t>(config::maximumBowdenLength * 2) // set finda trigger beyond the total allowed number of steps (i.e. not trigger)
|
||||
),
|
||||
mm::unitToSteps<mm::P_pos_t>(config::maximumBowdenLength) // limit the number of loops to max bowden length steps
|
||||
));
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::FailedFINDA);
|
||||
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InSelector);
|
||||
|
|
@ -150,11 +158,16 @@ TEST_CASE("unload_to_finda::unload_without_FSensor_trigger", "[unload_to_finda]"
|
|||
5000));
|
||||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingFromFSensor);
|
||||
|
||||
// no changes to FSensor during unload - we'll pretend it never triggers
|
||||
// but set FINDA correctly
|
||||
REQUIRE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1, 150000, 10000), 50000));
|
||||
REQUIRE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1,
|
||||
mm::unitToSteps<mm::P_pos_t>(config::maximumBowdenLength * 2), // no changes to FSensor during unload - we'll pretend it never triggers
|
||||
mm::unitToSteps<mm::P_pos_t>(config::minimumBowdenLength) // trigger finda roughly at the expected distance (should never reach though)
|
||||
),
|
||||
mm::unitToSteps<mm::P_pos_t>(config::maximumBowdenLength) // limit the number of loops to max bowden length steps
|
||||
));
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::FailedFSensor);
|
||||
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InSelector);
|
||||
|
|
@ -191,14 +204,20 @@ TEST_CASE("unload_to_finda::unload_repeated", "[unload_to_finda]") {
|
|||
5000));
|
||||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingFromFSensor);
|
||||
|
||||
// no changes to FINDA during unload - we'll pretend it never triggers
|
||||
// but set FSensor correctly
|
||||
// In this case it is vital to correctly compute the amount of steps
|
||||
// to make the unload state machine restart after the 1st attempt
|
||||
uint32_t unlSteps = 1 + mm::unitToSteps<mm::P_pos_t>(config::defaultBowdenLength + config::feedToFinda + config::filamentMinLoadedToMMU);
|
||||
REQUIRE_FALSE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1, 10, 150000), unlSteps));
|
||||
uint32_t unlSteps = 2 + mm::unitToSteps<mm::P_pos_t>(config::defaultBowdenLength + config::feedToFinda + config::filamentMinLoadedToMMU - mg::globals.FSensorUnloadCheck_mm());
|
||||
REQUIRE_FALSE(WhileCondition(
|
||||
ff,
|
||||
std::bind(SimulateUnloadToFINDA, _1,
|
||||
mm::unitToSteps<mm::P_pos_t>(mg::globals.FSensorUnloadCheck_mm()) / 4, // make fsensor trigger roughly in the first 1/4 of the check distance
|
||||
mm::unitToSteps<mm::P_pos_t>(config::maximumBowdenLength * 2) // do not allow finda to trigger within the specified range
|
||||
),
|
||||
unlSteps));
|
||||
|
||||
main_loop();
|
||||
ff.Step();
|
||||
|
|
@ -219,7 +238,9 @@ TEST_CASE("unload_to_finda::unload_repeated", "[unload_to_finda]") {
|
|||
ff.Step();
|
||||
}
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||
// technically we are in the WaitingForFINDA state, but we want to tell the printer to rotate the E-motor after each unload retry
|
||||
// -> therefore we check for the UnloadingFromFSensor state
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingFromFSensor);
|
||||
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InSelector);
|
||||
|
||||
// now turn FINDA off - shall respond immediately
|
||||
|
|
|
|||
Loading…
Reference in New Issue