Introduce UnloadingFromFSensor

To allow tighter cooperation with the printer - after the printer thinks it unloaded the filament from the drive gear,
we'll still rotate the drive gear as long as the MMU reports progress state UnloadingFromFSensor.
After those 40mm of slow unload distance, the MMU checks the fsensor (like is has been doing before).
If FSensor is off at this moment, everything is fine a the unload will continue at full speed.
pull/271/head
D.R.racer 2023-04-11 21:50:42 +02:00
parent 113f71330e
commit 33edba66ee
6 changed files with 50 additions and 21 deletions

View File

@ -50,5 +50,7 @@ enum class ProgressCode : uint_fast8_t {
HWTestDisplay, // P35 HWTestDisplay, // P35
ErrHwTestFailed, // P36 ErrHwTestFailed, // P36
UnloadingFilamentSlowly, // P37
Empty = 0xff // dummy empty state Empty = 0xff // dummy empty state
}; };

View File

@ -133,4 +133,20 @@ bool UnloadFilament::StepInner() {
return false; return false;
} }
ProgressCode UnloadFilament::State() const {
switch (state) {
case ProgressCode::UnloadingToFinda:
switch (unl.State()) {
case UnloadToFinda::EngagingIdler:
return ProgressCode::EngagingIdler;
case UnloadToFinda::UnloadingFromFSensor:
return ProgressCode::UnloadingFilamentSlowly;
// the rest should be reported as UnloadingFilament
}
[[fallthrough]];
default:
return state;
}
}
} // namespace logic } // namespace logic

View File

@ -21,6 +21,8 @@ public:
/// @returns true if the state machine finished its job, false otherwise /// @returns true if the state machine finished its job, false otherwise
bool StepInner() override; bool StepInner() override;
ProgressCode State() const override;
private: private:
constexpr static const uint8_t maxRetries = 1; constexpr static const uint8_t maxRetries = 1;

View File

@ -20,37 +20,46 @@ void UnloadToFinda::Reset(uint8_t maxTries) {
// FINDA is sensing the filament, plan moves to unload it // FINDA is sensing the filament, plan moves to unload it
state = EngagingIdler; state = EngagingIdler;
mi::idler.Engage(mg::globals.ActiveSlot()); mi::idler.Engage(mg::globals.ActiveSlot());
if (mg::globals.FilamentLoaded() >= mg::FilamentLoadState::InSelector) {
state = UnloadingFromFSensor;
mpu::pulley.InitAxis();
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::blink0);
} else {
state = FailedFINDA;
}
} }
} }
bool UnloadToFinda::Step() { bool UnloadToFinda::Step() {
switch (state) { switch (state) {
case EngagingIdler: case EngagingIdler:
if (mg::globals.FilamentLoaded() >= mg::FilamentLoadState::InSelector) {
state = UnloadingToFinda;
mpu::pulley.InitAxis();
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::blink0);
} else {
state = FailedFINDA;
}
return false;
case UnloadingToFinda:
if (mi::idler.Engaged()) { if (mi::idler.Engaged()) {
state = WaitingForFINDA; state = UnloadingFromFSensor;
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InSelector); mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InSelector);
unloadStart_mm = mpu::pulley.CurrentPosition_mm(); unloadStart_mm = mpu::pulley.CurrentPosition_mm();
// plan both moves to keep the unload smooth
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, mg::globals.PulleyUnloadFeedrate_mm_s());
} }
return false; return false;
case UnloadingFromFSensor:
if ((abs(unloadStart_mm - mpu::pulley.CurrentPosition_mm()) > 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
// This scenario should not be tried again - repeating it may cause more damage to filament + potentially more collateral damage
state = FailedFSensor;
mm::motion.AbortPlannedMoves(); // stop rotating the pulley
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
} else {
// fsensor turned correctly off, seamlessly transfer to fast unloading -> waiting for FINDA
// the move has already been planned when idler engaged
state = WaitingForFINDA;
}
}
return false;
case WaitingForFINDA: { case WaitingForFINDA: {
int32_t currentPulley_mm = mpu::pulley.CurrentPosition_mm(); if (!mf::finda.Pressed()) {
if ((abs(unloadStart_mm - currentPulley_mm) > mm::truncatedUnit(mg::globals.FSensorUnloadCheck_mm())) && mfs::fsensor.Pressed()) {
// fsensor didn't trigger within the first fsensorUnloadCheckDistance mm -> stop pulling, something failed, report an error
// This scenario should not be tried again - repeating it may cause more damage to filament + potentially more collateral damage
state = FailedFSensor;
mm::motion.AbortPlannedMoves(); // stop rotating the pulley
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
} else if (!mf::finda.Pressed()) {
// detected end of filament // detected end of filament
state = OK; state = OK;
mm::motion.AbortPlannedMoves(); // stop rotating the pulley mm::motion.AbortPlannedMoves(); // stop rotating the pulley

View File

@ -15,7 +15,7 @@ struct UnloadToFinda {
/// internal states of the state machine /// internal states of the state machine
enum { enum {
EngagingIdler, EngagingIdler,
UnloadingToFinda, UnloadingFromFSensor,
WaitingForFINDA, WaitingForFINDA,
OK, OK,
FailedFINDA, FailedFINDA,

View File

@ -57,7 +57,7 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
CHECK(mm::axes[mm::Pulley].enabled == true); CHECK(mm::axes[mm::Pulley].enabled == true);
// now pulling the filament until finda triggers // now pulling the filament until finda triggers
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA); REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingFromFSensor);
REQUIRE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1, 10, 1000), 1100)); REQUIRE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1, 10, 1000), 1100));
REQUIRE(ff.State() == logic::UnloadToFinda::OK); REQUIRE(ff.State() == logic::UnloadToFinda::OK);
@ -209,7 +209,7 @@ TEST_CASE("unload_to_finda::unload_repeated", "[unload_to_finda]") {
main_loop(); main_loop();
ff.Step(); ff.Step();
REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingToFinda); REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingFromFSensor);
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InSelector); REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InSelector);
// make arbitrary amount of steps // make arbitrary amount of steps