UnloadToFinda: update unit tests
parent
3bf5a1a0dc
commit
9aa9e0cc2b
|
|
@ -87,7 +87,10 @@ bool UnloadToFinda::Step() {
|
|||
// we reached the end of move queue, but the FINDA didn't switch off
|
||||
// two possible causes - grinded filament or malfunctioning FINDA
|
||||
if (--maxTries) {
|
||||
Reset(maxTries); // try again
|
||||
// Ideally, the Idler shall rehome and then try again.
|
||||
// That would auto-resolve errors caused by slipped or misaligned Idler
|
||||
mi::idler.InvalidateHoming();
|
||||
Reset(maxTries);
|
||||
} else {
|
||||
state = FailedFINDA;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,19 +79,27 @@ void ForceReinitAllAutomata() {
|
|||
mg::globals.Init();
|
||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::AtPulley);
|
||||
}
|
||||
void HomeIdler() {
|
||||
logic::NoCommand nc; // just a dummy instance which has an empty Step()
|
||||
SimulateIdlerHoming(nc);
|
||||
SimulateIdlerWaitForHomingValid(nc);
|
||||
SimulateIdlerMoveToParkingPosition(nc);
|
||||
}
|
||||
|
||||
void HomeSelector() {
|
||||
logic::NoCommand nc; // just a dummy instance which has an empty Step()
|
||||
SimulateSelectorHoming(nc);
|
||||
SimulateSelectorWaitForHomingValid(nc);
|
||||
SimulateSelectorWaitForReadyState(nc);
|
||||
}
|
||||
|
||||
void HomeIdlerAndSelector() {
|
||||
mi::idler.InvalidateHoming();
|
||||
ms::selector.InvalidateHoming();
|
||||
logic::NoCommand nc; // just a dummy instance which has an empty Step()
|
||||
|
||||
SimulateIdlerHoming(nc);
|
||||
SimulateIdlerWaitForHomingValid(nc);
|
||||
SimulateIdlerMoveToParkingPosition(nc);
|
||||
HomeIdler();
|
||||
|
||||
SimulateSelectorHoming(nc);
|
||||
SimulateSelectorWaitForHomingValid(nc);
|
||||
SimulateSelectorWaitForReadyState(nc);
|
||||
HomeSelector();
|
||||
}
|
||||
|
||||
bool EnsureActiveSlotIndex(uint8_t slot, mg::FilamentLoadState loadState) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "../../../../src/logic/command_base.h"
|
||||
#include "../../../../src/modules/globals.h"
|
||||
#include "../../../../src/modules/idler.h"
|
||||
|
||||
extern void main_loop();
|
||||
extern void ForceReinitAllAutomata();
|
||||
|
|
@ -44,3 +45,21 @@ static constexpr uint32_t selectorMoveMaxSteps = 40000UL;
|
|||
void HomeIdlerAndSelector();
|
||||
|
||||
void SimulateErrDisengagingIdler(logic::CommandBase &cb, ErrorCode deferredEC);
|
||||
|
||||
template <typename T>
|
||||
bool SimulateEngageIdlerFully(T &cb) {
|
||||
return WhileCondition(
|
||||
cb,
|
||||
[&](uint32_t) { return !mi::idler.Engaged(); },
|
||||
5000);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool SimulateEngageIdlerPartially(T &cb) {
|
||||
return WhileCondition(
|
||||
cb,
|
||||
[&](uint32_t) { return !mi::idler.PartiallyDisengaged(); },
|
||||
5000);
|
||||
}
|
||||
|
||||
void HomeIdler();
|
||||
|
|
|
|||
|
|
@ -12,10 +12,12 @@
|
|||
#include "../../../../src/modules/motion.h"
|
||||
#include "../../../../src/modules/permanent_storage.h"
|
||||
#include "../../../../src/modules/selector.h"
|
||||
#include "../../../../src/modules/timebase.h"
|
||||
|
||||
#include "../../../../src/logic/unload_to_finda.h"
|
||||
|
||||
#include "../../modules/stubs/stub_adc.h"
|
||||
#include "../../modules/stubs/stub_timebase.h"
|
||||
|
||||
#include "../stubs/main_loop_stub.h"
|
||||
#include "../stubs/stub_motion.h"
|
||||
|
|
@ -24,7 +26,7 @@ using namespace std::placeholders;
|
|||
|
||||
namespace ha = hal::adc;
|
||||
|
||||
TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
||||
void UnloadToFindaCommonSetup(logic::UnloadToFinda &ff, uint8_t retryAttempts) {
|
||||
ForceReinitAllAutomata();
|
||||
REQUIRE(EnsureActiveSlotIndex(0, mg::FilamentLoadState::AtPulley));
|
||||
|
||||
|
|
@ -35,10 +37,8 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
|||
// and MMU "thinks" it has the filament loaded
|
||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
||||
|
||||
logic::UnloadToFinda ff;
|
||||
|
||||
// restart the automaton - just 1 attempt
|
||||
ff.Reset(1);
|
||||
ff.Reset(retryAttempts);
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::EngagingIdler);
|
||||
|
||||
|
|
@ -47,12 +47,10 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
|||
CHECK(mm::AxisNearestTargetPos(mm::Idler) == mi::Idler::IntermediateSlotPosition(0).v);
|
||||
CHECK(mm::AxisNearestTargetPos(mm::Selector) == ms::Selector::SlotPosition(0).v);
|
||||
|
||||
// engaging idler partially
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&](uint32_t) { return !mi::idler.PartiallyDisengaged(); },
|
||||
5000));
|
||||
REQUIRE(SimulateEngageIdlerPartially(ff));
|
||||
}
|
||||
|
||||
void UnloadToFindaCommonTurnOffFSensor(logic::UnloadToFinda &ff) {
|
||||
// turn off fsensor - the printer freed the filament from the gears
|
||||
SetFSensorStateAndDebounce(false);
|
||||
|
||||
|
|
@ -63,14 +61,17 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
|||
CHECK(mm::axes[mm::Pulley].enabled == true);
|
||||
CHECK(mm::AxisNearestTargetPos(mm::Idler) == mi::Idler::SlotPosition(0).v);
|
||||
|
||||
// engaging idler fully
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&](uint32_t) { return !mi::idler.Engaged(); },
|
||||
5000));
|
||||
REQUIRE(SimulateEngageIdlerFully(ff));
|
||||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||
}
|
||||
|
||||
TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
||||
logic::UnloadToFinda ff;
|
||||
UnloadToFindaCommonSetup(ff, 1);
|
||||
UnloadToFindaCommonTurnOffFSensor(ff);
|
||||
|
||||
REQUIRE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1, 10, 1000), 1100));
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::OK);
|
||||
|
|
@ -92,37 +93,9 @@ TEST_CASE("unload_to_finda::no_sense_FINDA_upon_start", "[unload_to_finda]") {
|
|||
}
|
||||
|
||||
TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]") {
|
||||
ForceReinitAllAutomata();
|
||||
REQUIRE(EnsureActiveSlotIndex(0, mg::FilamentLoadState::AtPulley));
|
||||
|
||||
// we need finda ON
|
||||
SetFINDAStateAndDebounce(true);
|
||||
// fsensor should be ON
|
||||
SetFSensorStateAndDebounce(true);
|
||||
// and MMU "thinks" it has the filament loaded
|
||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
||||
|
||||
logic::UnloadToFinda ff;
|
||||
|
||||
// restart the automaton - just 1 attempt
|
||||
ff.Reset(1);
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::EngagingIdler);
|
||||
|
||||
// it should have instructed the selector and idler to move to slot 1
|
||||
// check if the idler and selector have the right command
|
||||
CHECK(mm::AxisNearestTargetPos(mm::Idler) == mi::Idler::SlotPosition(0).v);
|
||||
CHECK(mm::AxisNearestTargetPos(mm::Selector) == ms::Selector::SlotPosition(0).v);
|
||||
CHECK(mm::axes[mm::Idler].enabled == true);
|
||||
|
||||
// engaging idler
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&](uint32_t) { return !mi::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||
UnloadToFindaCommonSetup(ff, 1);
|
||||
UnloadToFindaCommonTurnOffFSensor(ff);
|
||||
|
||||
// no changes to FINDA during unload - we'll pretend it never triggers
|
||||
// but set FSensor correctly
|
||||
|
|
@ -134,96 +107,67 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]")
|
|||
}
|
||||
|
||||
TEST_CASE("unload_to_finda::unload_without_FSensor_trigger", "[unload_to_finda]") {
|
||||
ForceReinitAllAutomata();
|
||||
REQUIRE(EnsureActiveSlotIndex(0, mg::FilamentLoadState::AtPulley));
|
||||
|
||||
// we need finda ON
|
||||
SetFINDAStateAndDebounce(true);
|
||||
// fsensor should be ON
|
||||
SetFSensorStateAndDebounce(true);
|
||||
// and MMU "thinks" it has the filament loaded
|
||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
||||
|
||||
logic::UnloadToFinda ff;
|
||||
|
||||
// restart the automaton - just 1 attempt
|
||||
ff.Reset(1);
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::EngagingIdler);
|
||||
|
||||
// it should have instructed the selector and idler to move to slot 1
|
||||
// check if the idler and selector have the right command
|
||||
CHECK(mm::AxisNearestTargetPos(mm::Idler) == mi::Idler::SlotPosition(0).v);
|
||||
CHECK(mm::AxisNearestTargetPos(mm::Selector) == ms::Selector::SlotPosition(0).v);
|
||||
CHECK(mm::axes[mm::Idler].enabled == true);
|
||||
|
||||
// engaging idler
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&](uint32_t) { return !mi::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||
UnloadToFindaCommonSetup(ff, 1);
|
||||
|
||||
// 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));
|
||||
// time-out in 4 seconds
|
||||
mt::IncMillis(4000);
|
||||
|
||||
main_loop();
|
||||
ff.Step();
|
||||
|
||||
// no pulling actually starts, because the fsensor didn't turn off and the time-out elapsed
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::FailedFSensor);
|
||||
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InSelector);
|
||||
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InNozzle);
|
||||
}
|
||||
|
||||
TEST_CASE("unload_to_finda::unload_repeated", "[unload_to_finda]") {
|
||||
ForceReinitAllAutomata();
|
||||
REQUIRE(EnsureActiveSlotIndex(0, mg::FilamentLoadState::AtPulley));
|
||||
|
||||
// we need finda ON
|
||||
SetFINDAStateAndDebounce(true);
|
||||
// fsensor should be ON
|
||||
SetFSensorStateAndDebounce(true);
|
||||
// and MMU "thinks" it has the filament loaded
|
||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
||||
|
||||
logic::UnloadToFinda ff;
|
||||
UnloadToFindaCommonSetup(ff, 2);
|
||||
|
||||
// restart the automaton - 2 attempts
|
||||
ff.Reset(2);
|
||||
UnloadToFindaCommonTurnOffFSensor(ff);
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::EngagingIdler);
|
||||
|
||||
// it should have instructed the selector and idler to move to slot 1
|
||||
// check if the idler and selector have the right command
|
||||
CHECK(mm::AxisNearestTargetPos(mm::Idler) == mi::Idler::SlotPosition(0).v);
|
||||
CHECK(mm::AxisNearestTargetPos(mm::Selector) == ms::Selector::SlotPosition(0).v);
|
||||
CHECK(mm::axes[mm::Idler].enabled == true);
|
||||
|
||||
// engaging idler
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&](uint32_t) { return !mi::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||
// remember raw Pulley pos for tweaking the steps below
|
||||
// because a 20mm (config::fsensorToNozzleAvoidGrindUnload)
|
||||
// move is being executed while the Idler is fully engaging
|
||||
// It is roughly -90 steps
|
||||
// int32_t pulleySteppedAlready = mm::axes[config::Pulley].pos;
|
||||
|
||||
// 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::maximumBowdenLength + config::feedToFinda + config::filamentMinLoadedToMMU);
|
||||
// The number of steps must be more than what the state machine expects for FINDA to trigger.
|
||||
uint32_t unlSteps = 1 + mm::unitToSteps<mm::P_pos_t>(
|
||||
// standard fast move distance
|
||||
config::maximumBowdenLength + config::feedToFinda + config::filamentMinLoadedToMMU
|
||||
// slow start move distance
|
||||
+ config::fsensorToNozzleAvoidGrindUnload);
|
||||
// compensation
|
||||
// + pulleySteppedAlready;
|
||||
REQUIRE_FALSE(WhileCondition(ff, std::bind(SimulateUnloadToFINDA, _1, 10, 150000), unlSteps));
|
||||
|
||||
main_loop();
|
||||
ff.Step();
|
||||
|
||||
REQUIRE_FALSE(mi::idler.HomingValid());
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::EngagingIdler);
|
||||
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InSelector);
|
||||
|
||||
HomeIdler();
|
||||
|
||||
main_loop();
|
||||
ff.Step();
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingToFinda);
|
||||
|
||||
SimulateEngageIdlerPartially(ff);
|
||||
|
||||
main_loop();
|
||||
ff.Step();
|
||||
|
||||
REQUIRE(ff.State() == logic::UnloadToFinda::UnloadingToFinda);
|
||||
SimulateEngageIdlerFully(ff);
|
||||
|
||||
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::InSelector);
|
||||
|
||||
// make arbitrary amount of steps
|
||||
|
|
|
|||
Loading…
Reference in New Issue