Improve and verify Load filament alg and unit tests
parent
46a40f7488
commit
f6e5d4ae76
|
|
@ -37,7 +37,8 @@ bool FeedToBondtech::Step() {
|
||||||
case PushingFilament:
|
case PushingFilament:
|
||||||
if (mfs::fsensor.Pressed()) {
|
if (mfs::fsensor.Pressed()) {
|
||||||
mm::motion.AbortPlannedMoves(); // stop pushing filament
|
mm::motion.AbortPlannedMoves(); // stop pushing filament
|
||||||
state = DisengagingIdler;
|
// mi::idler.Disengage();
|
||||||
|
state = OK;
|
||||||
} 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
|
||||||
|
|
@ -45,12 +46,12 @@ bool FeedToBondtech::Step() {
|
||||||
state = Failed;
|
state = Failed;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case DisengagingIdler:
|
// case DisengagingIdler:
|
||||||
if (!mi::idler.Engaged()) {
|
// if (!mi::idler.Engaged()) {
|
||||||
state = OK;
|
// state = OK;
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::on);
|
// ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::on);
|
||||||
}
|
// }
|
||||||
return false;
|
// return false;
|
||||||
case OK:
|
case OK:
|
||||||
case Failed:
|
case Failed:
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -51,14 +51,14 @@ bool FeedToFinda::Step() {
|
||||||
return false;
|
return false;
|
||||||
case UnloadBackToPTFE:
|
case UnloadBackToPTFE:
|
||||||
if (mm::motion.QueueEmpty()) { // all moves have been finished
|
if (mm::motion.QueueEmpty()) { // all moves have been finished
|
||||||
state = DisengagingIdler;
|
// state = DisengagingIdler;
|
||||||
mi::idler.Disengage();
|
// mi::idler.Disengage();
|
||||||
}
|
// }
|
||||||
return false;
|
// return false;
|
||||||
case DisengagingIdler:
|
// case DisengagingIdler:
|
||||||
if (!mi::idler.Engaged()) {
|
// if (!mi::idler.Engaged()) {
|
||||||
state = OK;
|
state = OK;
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::on);
|
// ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::on);
|
||||||
}
|
}
|
||||||
// @@TODO FINDA must be reported as OFF again as we are pulling the filament from it - is this correct?
|
// @@TODO FINDA must be reported as OFF again as we are pulling the filament from it - is this correct?
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ void LoadFilament::Reset(uint8_t param) {
|
||||||
error = ErrorCode::OK;
|
error = ErrorCode::OK;
|
||||||
mg::globals.SetActiveSlot(param);
|
mg::globals.SetActiveSlot(param);
|
||||||
mi::idler.Engage(mg::globals.ActiveSlot());
|
mi::idler.Engage(mg::globals.ActiveSlot());
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::blink0);
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::off);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadFilament::Step() {
|
bool LoadFilament::Step() {
|
||||||
|
|
@ -40,7 +42,9 @@ bool LoadFilament::Step() {
|
||||||
if (feed.State() == FeedToFinda::Failed) {
|
if (feed.State() == FeedToFinda::Failed) {
|
||||||
// @@TODO - try to repeat 6x - push/pull sequence - probably something to put into feed_to_finda as an option
|
// @@TODO - try to repeat 6x - push/pull sequence - probably something to put into feed_to_finda as an option
|
||||||
state = ProgressCode::ERR1DisengagingIdler;
|
state = ProgressCode::ERR1DisengagingIdler;
|
||||||
|
error = ErrorCode::FINDA_DIDNT_TRIGGER;
|
||||||
mi::idler.Disengage();
|
mi::idler.Disengage();
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::Mode::off);
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::red, ml::Mode::blink0); // signal loading error
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::red, ml::Mode::blink0); // signal loading error
|
||||||
} else {
|
} else {
|
||||||
state = ProgressCode::FeedingToBondtech;
|
state = ProgressCode::FeedingToBondtech;
|
||||||
|
|
@ -62,13 +66,14 @@ bool LoadFilament::Step() {
|
||||||
case ProgressCode::DisengagingIdler:
|
case ProgressCode::DisengagingIdler:
|
||||||
if (!mi::idler.Engaged()) {
|
if (!mi::idler.Engaged()) {
|
||||||
state = ProgressCode::OK;
|
state = ProgressCode::OK;
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::off);
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::on);
|
||||||
|
mg::globals.SetFilamentLoaded(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProgressCode::OK:
|
case ProgressCode::OK:
|
||||||
mg::globals.SetFilamentLoaded(true);
|
|
||||||
return true;
|
return true;
|
||||||
case ProgressCode::ERR1DisengagingIdler: // couldn't unload to FINDA
|
case ProgressCode::ERR1DisengagingIdler: // couldn't unload to FINDA
|
||||||
error = ErrorCode::FINDA_DIDNT_TRIGGER;
|
|
||||||
if (!mi::idler.Engaged()) {
|
if (!mi::idler.Engaged()) {
|
||||||
state = ProgressCode::ERR1WaitingForUser;
|
state = ProgressCode::ERR1WaitingForUser;
|
||||||
}
|
}
|
||||||
|
|
@ -80,12 +85,13 @@ bool LoadFilament::Step() {
|
||||||
bool userResolved = modules::buttons::buttons.ButtonPressed(modules::buttons::Right) /*|| command_userResolved()*/;
|
bool userResolved = modules::buttons::buttons.ButtonPressed(modules::buttons::Right) /*|| command_userResolved()*/;
|
||||||
if (help) {
|
if (help) {
|
||||||
// try to manually load just a tiny bit - help the filament with the pulley
|
// try to manually load just a tiny bit - help the filament with the pulley
|
||||||
//@@TODO
|
state = ProgressCode::ERR1EngagingIdler;
|
||||||
|
mi::idler.Engage(mg::globals.ActiveSlot());
|
||||||
} else if (tryAgain) {
|
} else if (tryAgain) {
|
||||||
// try again the whole sequence
|
// try again the whole sequence
|
||||||
Reset(0); // @@TODO param
|
Reset(mg::globals.ActiveSlot());
|
||||||
} else if (userResolved) {
|
} else if (userResolved) {
|
||||||
// problem resolved - the user pulled the fillament by hand
|
// problem resolved - the user pushed the fillament by hand?
|
||||||
modules::leds::leds.SetMode(mg::globals.ActiveSlot(), modules::leds::red, modules::leds::off);
|
modules::leds::leds.SetMode(mg::globals.ActiveSlot(), modules::leds::red, modules::leds::off);
|
||||||
modules::leds::leds.SetMode(mg::globals.ActiveSlot(), modules::leds::green, modules::leds::on);
|
modules::leds::leds.SetMode(mg::globals.ActiveSlot(), modules::leds::green, modules::leds::on);
|
||||||
// mm::motion.PlanMove(mm::Pulley, 450, 5000); // @@TODO constants
|
// mm::motion.PlanMove(mm::Pulley, 450, 5000); // @@TODO constants
|
||||||
|
|
@ -93,6 +99,26 @@ bool LoadFilament::Step() {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
case ProgressCode::ERR1EngagingIdler:
|
||||||
|
if (mi::idler.Engaged()) {
|
||||||
|
state = ProgressCode::ERR1HelpingFilament;
|
||||||
|
mm::motion.PlanMove(mm::Pulley, 450, 5000); //@@TODO constants
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case ProgressCode::ERR1HelpingFilament:
|
||||||
|
if (mf::finda.Pressed()) {
|
||||||
|
// the help was enough to press the FINDA, we are ok, continue normally
|
||||||
|
state = ProgressCode::FeedingToBondtech;
|
||||||
|
error = ErrorCode::OK;
|
||||||
|
} else if (mm::motion.QueueEmpty()) {
|
||||||
|
// helped a bit, but FINDA didn't trigger, return to the main error state
|
||||||
|
state = ProgressCode::ERR1DisengagingIdler;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default: // we got into an unhandled state, better report it
|
||||||
|
state = ProgressCode::ERRInternal;
|
||||||
|
error = ErrorCode::INTERNAL;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ bool UnloadFilament::Step() {
|
||||||
mi::idler.Engage(mg::globals.ActiveSlot());
|
mi::idler.Engage(mg::globals.ActiveSlot());
|
||||||
} else if (tryAgain) {
|
} else if (tryAgain) {
|
||||||
// try again the whole sequence
|
// try again the whole sequence
|
||||||
Reset(0);
|
Reset(0); //@@TODO validate the reset parameter
|
||||||
} else if (userResolved) {
|
} else if (userResolved) {
|
||||||
// problem resolved - the user pulled the fillament by hand
|
// problem resolved - the user pulled the fillament by hand
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::off);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::off);
|
||||||
|
|
|
||||||
|
|
@ -62,26 +62,30 @@ TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
||||||
// 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::Color::green));
|
REQUIRE(ml::leds.LedOn(mg::globals.ActiveSlot(), ml::Color::green));
|
||||||
|
|
||||||
// @@TODO simulate incoming message from the printer - fsensor triggered
|
|
||||||
|
|
||||||
REQUIRE(WhileCondition(
|
REQUIRE(WhileCondition(
|
||||||
fb,
|
fb,
|
||||||
[&](int) { return fb.State() == FeedToBondtech::PushingFilament; },
|
[&](int step) {
|
||||||
|
if( step == 1000 ){
|
||||||
|
modules::fsensor::fsensor.ProcessMessage(true);
|
||||||
|
}
|
||||||
|
return fb.State() == FeedToBondtech::PushingFilament; },
|
||||||
1500));
|
1500));
|
||||||
|
|
||||||
// disengaging idler
|
REQUIRE(modules::fsensor::fsensor.Pressed());
|
||||||
REQUIRE(fb.State() == FeedToBondtech::DisengagingIdler);
|
|
||||||
REQUIRE(WhileCondition(
|
|
||||||
fb,
|
|
||||||
[&](int) { return fb.State() == FeedToBondtech::DisengagingIdler; },
|
|
||||||
5000));
|
|
||||||
|
|
||||||
CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // @@TODO constants
|
// // disengaging idler
|
||||||
|
// REQUIRE(fb.State() == FeedToBondtech::DisengagingIdler);
|
||||||
|
// REQUIRE(WhileCondition(
|
||||||
|
// fb,
|
||||||
|
// [&](int) { return fb.State() == FeedToBondtech::DisengagingIdler; },
|
||||||
|
// 5000));
|
||||||
|
|
||||||
|
// CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // @@TODO constants
|
||||||
CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0));
|
CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0));
|
||||||
|
|
||||||
// state machine finished ok, the green LED should be on
|
// state machine finished ok, the green LED should be on
|
||||||
REQUIRE(fb.State() == FeedToBondtech::OK);
|
REQUIRE(fb.State() == FeedToBondtech::OK);
|
||||||
REQUIRE(ml::leds.LedOn(mg::globals.ActiveSlot(), ml::Color::green));
|
// REQUIRE(ml::leds.LedOn(mg::globals.ActiveSlot(), ml::Color::green));
|
||||||
|
|
||||||
REQUIRE(fb.Step() == true); // the automaton finished its work, any consecutive calls to Step must return true
|
REQUIRE(fb.Step() == true); // the automaton finished its work, any consecutive calls to Step must return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,19 +79,19 @@ TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
||||||
[&](int) { return ff.State() == FeedToFinda::UnloadBackToPTFE; },
|
[&](int) { return ff.State() == FeedToFinda::UnloadBackToPTFE; },
|
||||||
5000));
|
5000));
|
||||||
|
|
||||||
// disengaging idler
|
// // disengaging idler
|
||||||
REQUIRE(ff.State() == FeedToFinda::DisengagingIdler);
|
// REQUIRE(ff.State() == FeedToFinda::DisengagingIdler);
|
||||||
REQUIRE(WhileCondition(
|
// REQUIRE(WhileCondition(
|
||||||
ff,
|
// ff,
|
||||||
[&](int) { return mi::idler.Engaged(); },
|
// [&](int) { return mi::idler.Engaged(); },
|
||||||
5000));
|
// 5000));
|
||||||
|
|
||||||
CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // @@TODO constants
|
CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(0)); // @@TODO constants
|
||||||
CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0));
|
CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0));
|
||||||
|
|
||||||
// state machine finished ok, the green LED should be on
|
// state machine finished ok, the green LED should be on
|
||||||
REQUIRE(ff.State() == FeedToFinda::OK);
|
REQUIRE(ff.State() == FeedToFinda::OK);
|
||||||
REQUIRE(ml::leds.LedOn(mg::globals.ActiveSlot(), ml::Color::green));
|
REQUIRE(ml::leds.Mode(mg::globals.ActiveSlot(), ml::green) == ml::blink0);
|
||||||
|
|
||||||
REQUIRE(ff.Step() == true); // the automaton finished its work, any consecutive calls to Step must return true
|
REQUIRE(ff.Step() == true); // the automaton finished its work, any consecutive calls to Step must return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
template<typename SM>
|
||||||
|
bool VerifyState(SM &uf, bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t selectorSlotIndex,
|
||||||
|
bool findaPressed, ml::Mode greenLEDMode, ml::Mode redLEDMode, ErrorCode err, ProgressCode topLevelProgress) {
|
||||||
|
CHECKED_ELSE(mg::globals.FilamentLoaded() == filamentLoaded) { return false; }
|
||||||
|
CHECKED_ELSE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(idlerSlotIndex)) { return false; }
|
||||||
|
CHECKED_ELSE(mi::idler.Engaged() == (idlerSlotIndex < 5)) { return false; }
|
||||||
|
CHECKED_ELSE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(selectorSlotIndex)) { return false; }
|
||||||
|
CHECKED_ELSE(ms::selector.Slot() == selectorSlotIndex) { return false; }
|
||||||
|
CHECKED_ELSE(mf::finda.Pressed() == findaPressed) { return false; }
|
||||||
|
CHECKED_ELSE(ml::leds.Mode(selectorSlotIndex, ml::red) == redLEDMode) { return false; }
|
||||||
|
CHECKED_ELSE(ml::leds.Mode(selectorSlotIndex, ml::green) == greenLEDMode) { return false; }
|
||||||
|
CHECKED_ELSE(uf.Error() == err) { return false; }
|
||||||
|
CHECKED_ELSE(uf.TopLevelState() == topLevelProgress) { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -27,30 +27,143 @@ namespace mb = modules::buttons;
|
||||||
namespace mg = modules::globals;
|
namespace mg = modules::globals;
|
||||||
namespace ms = modules::selector;
|
namespace ms = modules::selector;
|
||||||
|
|
||||||
TEST_CASE("unload_filament::unload0", "[unload_filament]") {
|
#include "../helpers/helpers.ipp"
|
||||||
using namespace logic;
|
|
||||||
|
|
||||||
|
void LoadFilamentCommonSetup(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
ForceReinitAllAutomata();
|
ForceReinitAllAutomata();
|
||||||
|
|
||||||
LoadFilament lf;
|
// change the startup to what we need here
|
||||||
|
EnsureActiveSlotIndex(slot);
|
||||||
|
|
||||||
|
// verify startup conditions
|
||||||
|
REQUIRE(VerifyState(lf, false, 5, slot, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
|
||||||
|
|
||||||
// restart the automaton
|
// restart the automaton
|
||||||
lf.Reset(0);
|
lf.Reset(slot);
|
||||||
|
|
||||||
main_loop();
|
// Stage 0 - verify state just after Reset()
|
||||||
|
// we assume the filament is not loaded
|
||||||
|
// idler should have been activated by the underlying automaton
|
||||||
|
// no change in selector's position
|
||||||
|
// FINDA off
|
||||||
|
// green LED should blink, red off
|
||||||
|
REQUIRE(VerifyState(lf, false, 5, slot, false, ml::blink0, ml::off, ErrorCode::OK, ProgressCode::EngagingIdler));
|
||||||
|
|
||||||
// REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::UnloadingToFinda; }, 5000));
|
// Stage 1 - engaging idler
|
||||||
|
REQUIRE(WhileTopState(lf, ProgressCode::EngagingIdler, 5000));
|
||||||
// REQUIRE(uf.TopLevelState() == ProgressCode::DisengagingIdler);
|
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::blink0, ml::off, ErrorCode::OK, ProgressCode::FeedingToFinda));
|
||||||
// REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::DisengagingIdler; }, 5000));
|
}
|
||||||
|
|
||||||
// CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5));
|
void LoadFilamentSuccessful(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
// Stage 2 - feeding to finda
|
||||||
// REQUIRE(uf.TopLevelState() == ProgressCode::AvoidingGrind);
|
// we'll assume the finda is working correctly here
|
||||||
// REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::AvoidingGrind; }, 5000));
|
REQUIRE(WhileCondition(
|
||||||
|
lf,
|
||||||
// REQUIRE(uf.TopLevelState() == ProgressCode::FinishingMoves);
|
[&](int step) -> bool {
|
||||||
// REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::FinishingMoves; }, 5000));
|
if(step == 100){ // on 100th step make FINDA trigger
|
||||||
|
hal::adc::SetADC(1, 1023);
|
||||||
// REQUIRE(uf.TopLevelState() == ProgressCode::OK);
|
}
|
||||||
REQUIRE(modules::globals::globals.FilamentLoaded() == true);
|
return lf.TopLevelState() == ProgressCode::FeedingToFinda; },
|
||||||
|
5000));
|
||||||
|
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::blink0, ml::off, ErrorCode::OK, ProgressCode::FeedingToBondtech));
|
||||||
|
|
||||||
|
// Stage 3 - feeding to bondtech
|
||||||
|
// we'll make a fsensor switch during the process
|
||||||
|
REQUIRE(WhileCondition(
|
||||||
|
lf,
|
||||||
|
[&](int step) -> bool {
|
||||||
|
if(step == 100){ // on 100th step make fsensor trigger
|
||||||
|
modules::fsensor::fsensor.ProcessMessage(true);
|
||||||
|
}
|
||||||
|
return lf.TopLevelState() == ProgressCode::FeedingToBondtech; },
|
||||||
|
5000));
|
||||||
|
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::blink0, ml::off, ErrorCode::OK, ProgressCode::DisengagingIdler));
|
||||||
|
|
||||||
|
// Stage 4 - disengaging idler
|
||||||
|
REQUIRE(WhileTopState(lf, ProgressCode::DisengagingIdler, 5000));
|
||||||
|
REQUIRE(VerifyState(lf, true, 5, slot, true, ml::on, ml::off, ErrorCode::OK, ProgressCode::OK));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("load_filament::regular_load_to_slot_0-4", "[load_filament]") {
|
||||||
|
for (uint8_t slot = 0; slot < 5; ++slot) {
|
||||||
|
logic::LoadFilament lf;
|
||||||
|
LoadFilamentCommonSetup(slot, lf);
|
||||||
|
LoadFilamentSuccessful(slot, lf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FailedLoadToFinda(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
// Stage 2 - feeding to finda
|
||||||
|
// we'll assume the finda is defective here and does not trigger
|
||||||
|
REQUIRE(WhileTopState(lf, ProgressCode::FeedingToFinda, 5000));
|
||||||
|
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_TRIGGER, ProgressCode::ERR1DisengagingIdler));
|
||||||
|
|
||||||
|
// Stage 3 - disengaging idler in error mode
|
||||||
|
REQUIRE(WhileTopState(lf, ProgressCode::ERR1DisengagingIdler, 5000));
|
||||||
|
REQUIRE(VerifyState(lf, false, 5, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_TRIGGER, ProgressCode::ERR1WaitingForUser));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FailedLoadToFindaResolveHelp(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
// Stage 3 - the user has to do something
|
||||||
|
// there are 3 options:
|
||||||
|
// - help the filament a bit
|
||||||
|
// - try again the whole sequence
|
||||||
|
// - resolve the problem by hand - after pressing the button we shall check, that FINDA is off and we should do what?
|
||||||
|
|
||||||
|
// In this case we check the first option
|
||||||
|
|
||||||
|
// Perform press on button 1 + debounce
|
||||||
|
hal::adc::SetADC(0, 0);
|
||||||
|
while (!mb::buttons.ButtonPressed(0)) {
|
||||||
|
main_loop();
|
||||||
|
lf.Step();
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(VerifyState(lf, false, 5, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_TRIGGER, ProgressCode::ERR1EngagingIdler));
|
||||||
|
|
||||||
|
// Stage 4 - engage the idler
|
||||||
|
REQUIRE(WhileTopState(lf, ProgressCode::ERR1EngagingIdler, 5000));
|
||||||
|
|
||||||
|
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_TRIGGER, ProgressCode::ERR1HelpingFilament));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FailedLoadToFindaResolveHelpFindaTriggered(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
// Stage 5 - move the pulley a bit - simulate FINDA depress
|
||||||
|
REQUIRE(WhileCondition(
|
||||||
|
lf,
|
||||||
|
[&](int step) -> bool {
|
||||||
|
if(step == 100){ // on 100th step make FINDA trigger
|
||||||
|
hal::adc::SetADC(1, 1023);
|
||||||
|
}
|
||||||
|
return lf.TopLevelState() == ProgressCode::ERR1HelpingFilament; },
|
||||||
|
5000));
|
||||||
|
|
||||||
|
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::off, ml::blink0, ErrorCode::OK, ProgressCode::FeedingToBondtech));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FailedLoadToFindaResolveHelpFindaDidntTrigger(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
// Stage 5 - move the pulley a bit - no FINDA change
|
||||||
|
REQUIRE(WhileTopState(lf, ProgressCode::ERR1HelpingFilament, 5000));
|
||||||
|
|
||||||
|
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_TRIGGER, ProgressCode::ERR1DisengagingIdler));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_ok", "[load_filament]") {
|
||||||
|
for (uint8_t slot = 0; slot < 5; ++slot) {
|
||||||
|
logic::LoadFilament lf;
|
||||||
|
LoadFilamentCommonSetup(slot, lf);
|
||||||
|
FailedLoadToFinda(slot, lf);
|
||||||
|
FailedLoadToFindaResolveHelp(slot, lf);
|
||||||
|
FailedLoadToFindaResolveHelpFindaTriggered(slot, lf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_fail", "[load_filament]") {
|
||||||
|
for (uint8_t slot = 0; slot < 5; ++slot) {
|
||||||
|
logic::LoadFilament lf;
|
||||||
|
LoadFilamentCommonSetup(slot, lf);
|
||||||
|
FailedLoadToFinda(slot, lf);
|
||||||
|
FailedLoadToFindaResolveHelp(slot, lf);
|
||||||
|
FailedLoadToFindaResolveHelpFindaDidntTrigger(slot, lf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,20 +27,7 @@ namespace mb = modules::buttons;
|
||||||
namespace mg = modules::globals;
|
namespace mg = modules::globals;
|
||||||
namespace ms = modules::selector;
|
namespace ms = modules::selector;
|
||||||
|
|
||||||
bool VerifyState(logic::UnloadFilament &uf, bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t selectorSlotIndex,
|
#include "../helpers/helpers.ipp"
|
||||||
bool findaPressed, ml::Mode greenLEDMode, ml::Mode redLEDMode, ErrorCode err, ProgressCode topLevelProgress) {
|
|
||||||
CHECKED_ELSE(mg::globals.FilamentLoaded() == filamentLoaded) { return false; }
|
|
||||||
CHECKED_ELSE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(idlerSlotIndex)) { return false; }
|
|
||||||
CHECKED_ELSE(mi::idler.Engaged() == (idlerSlotIndex < 5)) { return false; }
|
|
||||||
CHECKED_ELSE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(selectorSlotIndex)) { return false; }
|
|
||||||
CHECKED_ELSE(ms::selector.Slot() == selectorSlotIndex) { return false; }
|
|
||||||
CHECKED_ELSE(mf::finda.Pressed() == findaPressed) { return false; }
|
|
||||||
CHECKED_ELSE(ml::leds.Mode(selectorSlotIndex, ml::red) == redLEDMode) { return false; }
|
|
||||||
CHECKED_ELSE(ml::leds.Mode(selectorSlotIndex, ml::green) == greenLEDMode) { return false; }
|
|
||||||
CHECKED_ELSE(uf.Error() == err) { return false; }
|
|
||||||
CHECKED_ELSE(uf.TopLevelState() == topLevelProgress) { return false; }
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegularUnloadFromSlot04Init(uint8_t slot, logic::UnloadFilament &uf) {
|
void RegularUnloadFromSlot04Init(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
// prepare startup conditions
|
// prepare startup conditions
|
||||||
|
|
@ -251,14 +238,16 @@ void FindaDidntTriggerResolveHelpFindaDidntTrigger(uint8_t slot, logic::UnloadFi
|
||||||
REQUIRE(VerifyState(uf, true, slot, slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_TRIGGER, ProgressCode::ERR1DisengagingIdler));
|
REQUIRE(VerifyState(uf, true, slot, slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_TRIGGER, ProgressCode::ERR1DisengagingIdler));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("unload_filament::finda_didnt_trigger_resolve_help", "[unload_filament]") {
|
TEST_CASE("unload_filament::finda_didnt_trigger_resolve_help_second_ok", "[unload_filament]") {
|
||||||
for (uint8_t slot = 0; slot < 5; ++slot) {
|
for (uint8_t slot = 0; slot < 5; ++slot) {
|
||||||
logic::UnloadFilament uf;
|
logic::UnloadFilament uf;
|
||||||
FindaDidntTriggerCommonSetup(slot, uf);
|
FindaDidntTriggerCommonSetup(slot, uf);
|
||||||
FindaDidntTriggerResolveHelp(slot, uf);
|
FindaDidntTriggerResolveHelp(slot, uf);
|
||||||
FindaDidntTriggerResolveHelpFindaTriggered(slot, uf);
|
FindaDidntTriggerResolveHelpFindaTriggered(slot, uf);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("unload_filament::finda_didnt_trigger_resolve_help_second_fail", "[unload_filament]") {
|
||||||
// the same with different end scenario
|
// the same with different end scenario
|
||||||
for (uint8_t slot = 0; slot < 5; ++slot) {
|
for (uint8_t slot = 0; slot < 5; ++slot) {
|
||||||
logic::UnloadFilament uf;
|
logic::UnloadFilament uf;
|
||||||
|
|
|
||||||
|
|
@ -30,25 +30,17 @@ namespace ms = modules::selector;
|
||||||
namespace ha = hal::adc;
|
namespace ha = hal::adc;
|
||||||
|
|
||||||
TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
||||||
using namespace logic;
|
|
||||||
|
|
||||||
ForceReinitAllAutomata();
|
ForceReinitAllAutomata();
|
||||||
|
|
||||||
// we need finda ON
|
// we need finda ON
|
||||||
hal::adc::ReinitADC(1, hal::adc::TADCData({ 1023 }), 1);
|
SetFINDAStateAndDebounce(true);
|
||||||
|
|
||||||
UnloadToFinda ff;
|
logic::UnloadToFinda ff;
|
||||||
|
|
||||||
// wait for FINDA to debounce
|
|
||||||
REQUIRE(WhileCondition(
|
|
||||||
ff,
|
|
||||||
[&](int) { return !mf::finda.Pressed(); },
|
|
||||||
5000));
|
|
||||||
|
|
||||||
// restart the automaton - just 1 attempt
|
// restart the automaton - just 1 attempt
|
||||||
ff.Reset(1);
|
ff.Reset(1);
|
||||||
|
|
||||||
REQUIRE(ff.State() == UnloadToFinda::EngagingIdler);
|
REQUIRE(ff.State() == logic::UnloadToFinda::EngagingIdler);
|
||||||
|
|
||||||
// it should have instructed the selector and idler to move to slot 1
|
// it should have instructed the selector and idler to move to slot 1
|
||||||
// check if the idler and selector have the right command
|
// check if the idler and selector have the right command
|
||||||
|
|
@ -63,51 +55,41 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
||||||
5000));
|
5000));
|
||||||
|
|
||||||
// now pulling the filament until finda triggers
|
// now pulling the filament until finda triggers
|
||||||
REQUIRE(ff.State() == UnloadToFinda::WaitingForFINDA);
|
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||||
hal::adc::ReinitADC(1, hal::adc::TADCData({ 1023, 900, 800, 500, 0 }), 10);
|
hal::adc::ReinitADC(1, hal::adc::TADCData({ 1023, 900, 800, 500, 0 }), 10);
|
||||||
REQUIRE(WhileCondition(
|
REQUIRE(WhileCondition(
|
||||||
ff,
|
ff,
|
||||||
[&](int) { return mf::finda.Pressed(); },
|
[&](int) { return mf::finda.Pressed(); },
|
||||||
50000));
|
50000));
|
||||||
|
|
||||||
REQUIRE(ff.State() == UnloadToFinda::OK);
|
REQUIRE(ff.State() == logic::UnloadToFinda::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("unload_to_finda::no_sense_FINDA_upon_start", "[unload_to_finda]") {
|
TEST_CASE("unload_to_finda::no_sense_FINDA_upon_start", "[unload_to_finda]") {
|
||||||
using namespace logic;
|
|
||||||
|
|
||||||
ForceReinitAllAutomata(); // that implies FINDA OFF which should really not happen for an unload call
|
ForceReinitAllAutomata(); // that implies FINDA OFF which should really not happen for an unload call
|
||||||
|
|
||||||
UnloadToFinda ff;
|
logic::UnloadToFinda ff;
|
||||||
|
|
||||||
// restart the automaton - just 1 attempt
|
// restart the automaton - just 1 attempt
|
||||||
ff.Reset(1);
|
ff.Reset(1);
|
||||||
|
|
||||||
// the state machine should accept the unpressed FINDA as no-fillament-loaded
|
// the state machine should accept the unpressed FINDA as no-fillament-loaded
|
||||||
// thus should immediately end in the OK state
|
// thus should immediately end in the OK state
|
||||||
REQUIRE(ff.State() == UnloadToFinda::OK);
|
REQUIRE(ff.State() == logic::UnloadToFinda::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]") {
|
TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]") {
|
||||||
using namespace logic;
|
|
||||||
|
|
||||||
ForceReinitAllAutomata();
|
ForceReinitAllAutomata();
|
||||||
|
|
||||||
// we need finda ON
|
// we need finda ON
|
||||||
hal::adc::ReinitADC(1, hal::adc::TADCData({ 1023 }), 1);
|
SetFINDAStateAndDebounce(true);
|
||||||
|
|
||||||
UnloadToFinda ff;
|
logic::UnloadToFinda ff;
|
||||||
|
|
||||||
// wait for FINDA to debounce
|
|
||||||
REQUIRE(WhileCondition(
|
|
||||||
ff,
|
|
||||||
[&](int) { return !mf::finda.Pressed(); },
|
|
||||||
5000));
|
|
||||||
|
|
||||||
// restart the automaton - just 1 attempt
|
// restart the automaton - just 1 attempt
|
||||||
ff.Reset(1);
|
ff.Reset(1);
|
||||||
|
|
||||||
REQUIRE(ff.State() == UnloadToFinda::EngagingIdler);
|
REQUIRE(ff.State() == logic::UnloadToFinda::EngagingIdler);
|
||||||
|
|
||||||
// it should have instructed the selector and idler to move to slot 1
|
// it should have instructed the selector and idler to move to slot 1
|
||||||
// check if the idler and selector have the right command
|
// check if the idler and selector have the right command
|
||||||
|
|
@ -122,7 +104,7 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]")
|
||||||
5000));
|
5000));
|
||||||
|
|
||||||
// now pulling the filament until finda triggers
|
// now pulling the filament until finda triggers
|
||||||
REQUIRE(ff.State() == UnloadToFinda::WaitingForFINDA);
|
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||||
|
|
||||||
// no changes to FINDA during unload - we'll pretend it never triggers
|
// no changes to FINDA during unload - we'll pretend it never triggers
|
||||||
REQUIRE(!WhileCondition(
|
REQUIRE(!WhileCondition(
|
||||||
|
|
@ -130,5 +112,5 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]")
|
||||||
[&](int) { return mf::finda.Pressed(); },
|
[&](int) { return mf::finda.Pressed(); },
|
||||||
50000));
|
50000));
|
||||||
|
|
||||||
REQUIRE(ff.State() == UnloadToFinda::Failed);
|
REQUIRE(ff.State() == logic::UnloadToFinda::Failed);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue