Greatly improve unload filament unit test
+ relevant changes for other unit tests -> prepare for improving of the other unit tests as wellpull/37/head
parent
807eda7db3
commit
ce20f0b001
|
|
@ -12,9 +12,6 @@ namespace logic {
|
|||
|
||||
ToolChange toolChange;
|
||||
|
||||
namespace mm = modules::motion;
|
||||
namespace mi = modules::idler;
|
||||
namespace ms = modules::selector;
|
||||
namespace mg = modules::globals;
|
||||
|
||||
void ToolChange::Reset(uint8_t param) {
|
||||
|
|
@ -36,35 +33,51 @@ bool ToolChange::Step() {
|
|||
switch (state) {
|
||||
case ProgressCode::UnloadingFilament:
|
||||
if (unl.Step()) {
|
||||
// unloading sequence finished
|
||||
switch (unl.Error()) {
|
||||
case ErrorCode::OK: // finished successfully
|
||||
// unloading sequence finished - basically, no errors can occurr here
|
||||
// as UnloadFilament should handle all the possible error states on its own
|
||||
// There is no way the UnloadFilament to finish in an error state
|
||||
state = ProgressCode::LoadingFilament;
|
||||
load.Reset(plannedSlot);
|
||||
break;
|
||||
case ErrorCode::UNLOAD_ERROR2: // @@TODO what shall we do in case of this error?
|
||||
case ErrorCode::FINDA_DIDNT_TRIGGER:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ProgressCode::LoadingFilament:
|
||||
if (load.Step()) {
|
||||
// unloading sequence finished
|
||||
switch (load.Error()) {
|
||||
case ErrorCode::OK: // finished successfully
|
||||
// loading sequence finished - basically, no errors can occurr here
|
||||
// as LoadFilament should handle all the possible error states on its own
|
||||
// There is no way the LoadFilament to finish in an error state
|
||||
state = ProgressCode::OK;
|
||||
break;
|
||||
// case ErrorCode::LOAD_ERROR2: // @@TODO load errors?
|
||||
// case ErrorCode::LOAD_FINDA_DIDNT_TRIGGER:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ProgressCode::OK:
|
||||
return true;
|
||||
default: // we got into an unhandled state, better report it
|
||||
state = ProgressCode::ERRInternal;
|
||||
error = ErrorCode::INTERNAL;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ProgressCode ToolChange::State() const {
|
||||
switch (state) {
|
||||
case ProgressCode::UnloadingFilament:
|
||||
return unl.State(); // report sub-automaton states properly
|
||||
case ProgressCode::LoadingFilament:
|
||||
return load.State(); // report sub-automaton states properly
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorCode ToolChange::Error() const {
|
||||
switch (state) {
|
||||
case ProgressCode::UnloadingFilament:
|
||||
return unl.Error(); // report sub-automaton errors properly
|
||||
case ProgressCode::LoadingFilament:
|
||||
return load.Error(); // report sub-automaton errors properly
|
||||
default:
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace logic
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ public:
|
|||
/// @returns true if the state machine finished its job, false otherwise
|
||||
bool Step() override;
|
||||
|
||||
ProgressCode State() const override;
|
||||
|
||||
ErrorCode Error() const override;
|
||||
|
||||
private:
|
||||
UnloadFilament unl; ///< a high-level command/operation may be used as a building block of other operations as well
|
||||
LoadFilament load;
|
||||
|
|
|
|||
|
|
@ -17,12 +17,14 @@ namespace mi = modules::idler;
|
|||
namespace ml = modules::leds;
|
||||
namespace mg = modules::globals;
|
||||
|
||||
void UnloadFilament::Reset(uint8_t param) {
|
||||
void UnloadFilament::Reset(uint8_t /*param*/) {
|
||||
// unloads filament from extruder - filament is above Bondtech gears
|
||||
mm::motion.InitAxis(mm::Pulley);
|
||||
state = ProgressCode::UnloadingToFinda;
|
||||
error = ErrorCode::OK;
|
||||
unl.Reset(maxRetries);
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::blink0);
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::off);
|
||||
}
|
||||
|
||||
bool UnloadFilament::Step() {
|
||||
|
|
@ -33,7 +35,9 @@ bool UnloadFilament::Step() {
|
|||
if (unl.State() == UnloadToFinda::Failed) {
|
||||
// couldn't unload to FINDA, report error and wait for user to resolve it
|
||||
state = ProgressCode::ERR1DisengagingIdler;
|
||||
error = ErrorCode::FINDA_DIDNT_TRIGGER;
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0);
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
||||
} else {
|
||||
state = ProgressCode::DisengagingIdler;
|
||||
}
|
||||
|
|
@ -59,10 +63,11 @@ bool UnloadFilament::Step() {
|
|||
if (mm::motion.QueueEmpty()) {
|
||||
state = ProgressCode::OK;
|
||||
mm::motion.DisableAxis(mm::Pulley);
|
||||
mg::globals.SetFilamentLoaded(false); // filament unloaded
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::on);
|
||||
}
|
||||
return false;
|
||||
case ProgressCode::ERR1DisengagingIdler: // couldn't unload to FINDA
|
||||
error = ErrorCode::FINDA_DIDNT_TRIGGER;
|
||||
if (!mi::idler.Engaged()) {
|
||||
state = ProgressCode::ERR1WaitingForUser;
|
||||
}
|
||||
|
|
@ -88,7 +93,6 @@ bool UnloadFilament::Step() {
|
|||
return false;
|
||||
}
|
||||
case ProgressCode::OK:
|
||||
mg::globals.SetFilamentLoaded(false); // filament unloaded
|
||||
return true; // successfully finished
|
||||
default: // we got into an unhandled state, better report it
|
||||
state = ProgressCode::ERRInternal;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ public:
|
|||
: CommandBase() {}
|
||||
|
||||
/// Restart the automaton
|
||||
void Reset(uint8_t param) override;
|
||||
/// @param param is not used, always unloads from the active slot
|
||||
void Reset(uint8_t /*param*/) override;
|
||||
|
||||
/// @returns true if the state machine finished its job, false otherwise
|
||||
bool Step() override;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ void Debouncer::Step(uint16_t time, bool press) {
|
|||
break;
|
||||
case State::Detected:
|
||||
if (f.tmp == press) {
|
||||
if (time - timeLastChange > debounceTimeout) {
|
||||
if (time - timeLastChange >= debounceTimeout) {
|
||||
f.state = State::WaitForRelease;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7,16 +7,15 @@ namespace finda {
|
|||
|
||||
class FINDA : protected debounce::Debouncer {
|
||||
public:
|
||||
inline constexpr FINDA()
|
||||
: debounce::Debouncer(debounce) {};
|
||||
void Step();
|
||||
using debounce::Debouncer::Pressed;
|
||||
|
||||
private:
|
||||
/// time interval for debouncing @@TODO specify units
|
||||
constexpr static const uint16_t debounce = 100;
|
||||
/// ADC decision level when a FINDA is considered pressed/not pressed
|
||||
constexpr static const uint16_t adcDecisionLevel = 512;
|
||||
|
||||
inline constexpr FINDA()
|
||||
: debounce::Debouncer(debounce) {};
|
||||
void Step();
|
||||
using debounce::Debouncer::Pressed;
|
||||
};
|
||||
|
||||
extern FINDA finda;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ TEST_CASE("cut_filament::cut0", "[cut_filament]") {
|
|||
|
||||
CutFilament cf;
|
||||
// restart the automaton
|
||||
currentCommand = &cf;
|
||||
cf.Reset(0);
|
||||
|
||||
main_loop();
|
||||
|
|
@ -45,7 +44,7 @@ TEST_CASE("cut_filament::cut0", "[cut_filament]") {
|
|||
CHECK(modules::motion::axes[modules::motion::Selector].targetPos == ms::Selector::SlotPosition(0));
|
||||
|
||||
// now cycle at most some number of cycles (to be determined yet) and then verify, that the idler and selector reached their target positions
|
||||
REQUIRE(WhileCondition([&]() { return cf.TopLevelState() == ProgressCode::SelectingFilamentSlot; }, 5000));
|
||||
REQUIRE(WhileTopState(cf, ProgressCode::SelectingFilamentSlot, 5000));
|
||||
|
||||
CHECK(modules::motion::axes[modules::motion::Idler].pos == mi::Idler::SlotPosition(0));
|
||||
CHECK(modules::motion::axes[modules::motion::Selector].pos == ms::Selector::SlotPosition(0));
|
||||
|
|
@ -53,27 +52,32 @@ TEST_CASE("cut_filament::cut0", "[cut_filament]") {
|
|||
// idler and selector reached their target positions and the CF automaton will start feeding to FINDA as the next step
|
||||
REQUIRE(cf.TopLevelState() == ProgressCode::FeedingToFinda);
|
||||
// prepare for simulated finda trigger
|
||||
hal::adc::ReinitADC(1, hal::adc::TADCData({ 0, 0, 0, 0, 600, 700, 800, 900 }), 10);
|
||||
REQUIRE(WhileCondition([&]() { return cf.TopLevelState() == ProgressCode::FeedingToFinda; }, 5000));
|
||||
REQUIRE(WhileCondition(
|
||||
cf,
|
||||
[&](int step) -> bool {
|
||||
if( step == 1000 ){ // simulate FINDA trigger - will get pressed in 100 steps (due to debouncing)
|
||||
hal::adc::SetADC(1, 900);
|
||||
}
|
||||
return cf.TopLevelState() == ProgressCode::FeedingToFinda; }, 5000));
|
||||
|
||||
// filament fed into FINDA, cutting...
|
||||
REQUIRE(cf.TopLevelState() == ProgressCode::PreparingBlade);
|
||||
REQUIRE(WhileCondition([&]() { return cf.TopLevelState() == ProgressCode::PreparingBlade; }, 5000));
|
||||
REQUIRE(WhileTopState(cf, ProgressCode::PreparingBlade, 5000));
|
||||
|
||||
REQUIRE(cf.TopLevelState() == ProgressCode::EngagingIdler);
|
||||
REQUIRE(WhileCondition([&]() { return cf.TopLevelState() == ProgressCode::EngagingIdler; }, 5000));
|
||||
REQUIRE(WhileTopState(cf, ProgressCode::EngagingIdler, 5000));
|
||||
|
||||
// the idler should be at the active slot @@TODO
|
||||
REQUIRE(cf.TopLevelState() == ProgressCode::PushingFilament);
|
||||
REQUIRE(WhileCondition([&]() { return cf.TopLevelState() == ProgressCode::PushingFilament; }, 5000));
|
||||
REQUIRE(WhileTopState(cf, ProgressCode::PushingFilament, 5000));
|
||||
|
||||
// filament pushed - performing cut
|
||||
REQUIRE(cf.TopLevelState() == ProgressCode::PerformingCut);
|
||||
REQUIRE(WhileCondition([&]() { return cf.TopLevelState() == ProgressCode::PerformingCut; }, 5000));
|
||||
REQUIRE(WhileTopState(cf, ProgressCode::PerformingCut, 5000));
|
||||
|
||||
// returning selector
|
||||
REQUIRE(cf.TopLevelState() == ProgressCode::ReturningSelector);
|
||||
REQUIRE(WhileCondition([&]() { return cf.TopLevelState() == ProgressCode::ReturningSelector; }, 5000));
|
||||
REQUIRE(WhileTopState(cf, ProgressCode::ReturningSelector, 5000));
|
||||
|
||||
// the next states are still @@TODO
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ TEST_CASE("eject_filament::eject0", "[eject_filament]") {
|
|||
|
||||
EjectFilament ef;
|
||||
// restart the automaton
|
||||
currentCommand = &ef;
|
||||
ef.Reset(0);
|
||||
|
||||
main_loop();
|
||||
|
|
@ -45,32 +44,32 @@ TEST_CASE("eject_filament::eject0", "[eject_filament]") {
|
|||
CHECK(modules::motion::axes[modules::motion::Selector].targetPos == ms::Selector::SlotPosition(4));
|
||||
|
||||
// now cycle at most some number of cycles (to be determined yet) and then verify, that the idler and selector reached their target positions
|
||||
REQUIRE(WhileCondition([&]() { return ef.TopLevelState() == ProgressCode::SelectingFilamentSlot; }, 5000));
|
||||
REQUIRE(WhileTopState(ef, ProgressCode::SelectingFilamentSlot, 5000));
|
||||
|
||||
// idler and selector reached their target positions and the CF automaton will start feeding to FINDA as the next step
|
||||
REQUIRE(ef.TopLevelState() == ProgressCode::FeedingToFinda);
|
||||
// prepare for simulated finda trigger
|
||||
hal::adc::ReinitADC(1, hal::adc::TADCData({ 0, 0, 0, 0, 600, 700, 800, 900 }), 10);
|
||||
REQUIRE(WhileCondition([&]() { return ef.TopLevelState() == ProgressCode::FeedingToFinda; }, 50000));
|
||||
REQUIRE(WhileTopState(ef, ProgressCode::FeedingToFinda, 50000));
|
||||
|
||||
// filament fed into FINDA, cutting...
|
||||
REQUIRE(ef.TopLevelState() == ProgressCode::PreparingBlade);
|
||||
REQUIRE(WhileCondition([&]() { return ef.TopLevelState() == ProgressCode::PreparingBlade; }, 5000));
|
||||
REQUIRE(WhileTopState(ef, ProgressCode::PreparingBlade, 5000));
|
||||
|
||||
REQUIRE(ef.TopLevelState() == ProgressCode::EngagingIdler);
|
||||
REQUIRE(WhileCondition([&]() { return ef.TopLevelState() == ProgressCode::EngagingIdler; }, 5000));
|
||||
REQUIRE(WhileTopState(ef, ProgressCode::EngagingIdler, 5000));
|
||||
|
||||
// the idler should be at the active slot @@TODO
|
||||
REQUIRE(ef.TopLevelState() == ProgressCode::PushingFilament);
|
||||
REQUIRE(WhileCondition([&]() { return ef.TopLevelState() == ProgressCode::PushingFilament; }, 5000));
|
||||
REQUIRE(WhileTopState(ef, ProgressCode::PushingFilament, 5000));
|
||||
|
||||
// filament pushed - performing cut
|
||||
REQUIRE(ef.TopLevelState() == ProgressCode::PerformingCut);
|
||||
REQUIRE(WhileCondition([&]() { return ef.TopLevelState() == ProgressCode::PerformingCut; }, 5000));
|
||||
REQUIRE(WhileTopState(ef, ProgressCode::PerformingCut, 5000));
|
||||
|
||||
// returning selector
|
||||
REQUIRE(ef.TopLevelState() == ProgressCode::ReturningSelector);
|
||||
REQUIRE(WhileCondition([&]() { return ef.TopLevelState() == ProgressCode::ReturningSelector; }, 5000));
|
||||
REQUIRE(WhileTopState(ef, ProgressCode::ReturningSelector, 5000));
|
||||
|
||||
// the next states are still @@TODO
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,15 +29,6 @@ namespace ms = modules::selector;
|
|||
|
||||
namespace ha = hal::adc;
|
||||
|
||||
template <typename COND>
|
||||
bool WhileCondition(logic::FeedToBondtech &ff, COND cond, uint32_t maxLoops = 5000) {
|
||||
while (cond() && --maxLoops) {
|
||||
main_loop();
|
||||
ff.Step();
|
||||
}
|
||||
return maxLoops > 0;
|
||||
}
|
||||
|
||||
TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
||||
using namespace logic;
|
||||
|
||||
|
|
@ -47,108 +38,50 @@ TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
|||
main_loop();
|
||||
|
||||
// restart the automaton
|
||||
fb.Reset(false);
|
||||
fb.Reset(1);
|
||||
|
||||
// REQUIRE(ff.State() == FeedToBondtech::EngagingIdler);
|
||||
REQUIRE(fb.State() == FeedToBondtech::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::axes[mm::Idler].targetPos == mi::Idler::SlotPosition(0));
|
||||
// CHECK(mm::axes[mm::Selector].targetPos == ms::Selector::SlotPosition(0));
|
||||
// CHECK(mm::axes[mm::Idler].enabled == true);
|
||||
// it should have instructed the selector and idler to move to slot 0
|
||||
// check if the idler and selector have the right command
|
||||
CHECK(mm::axes[mm::Idler].targetPos == mi::Idler::SlotPosition(0));
|
||||
CHECK(mm::axes[mm::Selector].targetPos == ms::Selector::SlotPosition(0));
|
||||
CHECK(mm::axes[mm::Idler].enabled == true);
|
||||
|
||||
// // engaging idler
|
||||
// REQUIRE(WhileCondition(
|
||||
// ff,
|
||||
// [&]() { return !mi::idler.Engaged(); },
|
||||
// 5000));
|
||||
// engaging idler
|
||||
REQUIRE(WhileCondition(
|
||||
fb,
|
||||
[&](int) { return !mi::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
// CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(0));
|
||||
// CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0));
|
||||
CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(0));
|
||||
CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0));
|
||||
|
||||
// // idler engaged, selector in position, we'll start pushing filament
|
||||
// REQUIRE(ff.State() == FeedToBondtech::PushingFilament);
|
||||
// // 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));
|
||||
// idler engaged, selector in position, we'll start pushing filament
|
||||
REQUIRE(fb.State() == FeedToBondtech::PushingFilament);
|
||||
// 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));
|
||||
|
||||
// // now let the filament be pushed into the FINDA - do 500 steps without triggering the condition
|
||||
// // and then let the simulated ADC channel 1 create a FINDA switch
|
||||
// ha::ReinitADC(1, ha::TADCData({ 600, 700, 800, 900 }), 1);
|
||||
// @@TODO simulate incoming message from the printer - fsensor triggered
|
||||
|
||||
// REQUIRE(WhileCondition(
|
||||
// ff,
|
||||
// [&]() { return ff.State() == FeedToBondtech::PushingFilament; },
|
||||
// 1500));
|
||||
// // From now on the FINDA is reported as ON
|
||||
REQUIRE(WhileCondition(
|
||||
fb,
|
||||
[&](int) { return fb.State() == FeedToBondtech::PushingFilament; },
|
||||
1500));
|
||||
|
||||
// // unloading back to PTFE
|
||||
// REQUIRE(ff.State() == FeedToBondtech::UnloadBackToPTFE);
|
||||
// REQUIRE(WhileCondition(
|
||||
// ff,
|
||||
// [&]() { return ff.State() == FeedToBondtech::UnloadBackToPTFE; },
|
||||
// 5000));
|
||||
// disengaging idler
|
||||
REQUIRE(fb.State() == FeedToBondtech::DisengagingIdler);
|
||||
REQUIRE(WhileCondition(
|
||||
fb,
|
||||
[&](int) { return fb.State() == FeedToBondtech::DisengagingIdler; },
|
||||
5000));
|
||||
|
||||
// // disengaging idler
|
||||
// REQUIRE(ff.State() == FeedToBondtech::DisengagingIdler);
|
||||
// REQUIRE(WhileCondition(
|
||||
// ff,
|
||||
// [&]() { return mi::idler.Engaged(); },
|
||||
// 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::Idler].pos == mi::Idler::SlotPosition(5)); // @@TODO constants
|
||||
// CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0));
|
||||
// state machine finished ok, the green LED should be on
|
||||
REQUIRE(fb.State() == FeedToBondtech::OK);
|
||||
REQUIRE(ml::leds.LedOn(mg::globals.ActiveSlot(), ml::Color::green));
|
||||
|
||||
// // state machine finished ok, the green LED should be on
|
||||
// REQUIRE(ff.State() == FeedToBondtech::OK);
|
||||
// REQUIRE(ml::leds.LedOn(mg::globals.ActiveSlot(), ml::Color::green));
|
||||
|
||||
// REQUIRE(ff.Step() == true); // the automaton finished its work, any consecutive calls to Step must return true
|
||||
//}
|
||||
|
||||
//TEST_CASE("feed_to_finda::FINDA_failed", "[feed_to_finda]") {
|
||||
// using namespace logic;
|
||||
|
||||
// ForceReinitAllAutomata();
|
||||
|
||||
// FeedToBondtech ff;
|
||||
// main_loop();
|
||||
|
||||
// // restart the automaton - we want the limited version of the feed
|
||||
// ff.Reset(true);
|
||||
|
||||
// REQUIRE(ff.State() == FeedToBondtech::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::axes[mm::Idler].targetPos == mi::Idler::SlotPosition(0));
|
||||
// CHECK(mm::axes[mm::Selector].targetPos == ms::Selector::SlotPosition(0));
|
||||
|
||||
// // engaging idler
|
||||
// REQUIRE(WhileCondition(
|
||||
// ff,
|
||||
// [&]() { return !mi::idler.Engaged(); },
|
||||
// 5000));
|
||||
|
||||
// CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(0));
|
||||
// CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0));
|
||||
|
||||
// // idler engaged, we'll start pushing filament
|
||||
// REQUIRE(ff.State() == FeedToBondtech::PushingFilament);
|
||||
// // 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.Mode(mg::globals.ActiveSlot(), ml::Color::green) == ml::blink0);
|
||||
|
||||
// // now let the filament be pushed into the FINDA - but we make sure the FINDA doesn't trigger at all
|
||||
// ha::ReinitADC(1, ha::TADCData({ 0 }), 100);
|
||||
|
||||
// REQUIRE(WhileCondition(
|
||||
// ff, // boo, this formatting is UGLY!
|
||||
// [&]() { return ff.State() == FeedToBondtech::PushingFilament; },
|
||||
// 5000));
|
||||
|
||||
// // the FINDA didn't trigger, we should be in the Failed state
|
||||
// REQUIRE(ff.State() == FeedToBondtech::Failed);
|
||||
// REQUIRE(ml::leds.Mode(mg::globals.ActiveSlot(), ml::Color::green) == ml::off);
|
||||
// REQUIRE(ml::leds.Mode(mg::globals.ActiveSlot(), ml::Color::red) == ml::blink0);
|
||||
|
||||
// REQUIRE(ff.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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,15 +29,6 @@ namespace ms = modules::selector;
|
|||
|
||||
namespace ha = hal::adc;
|
||||
|
||||
template <typename COND>
|
||||
bool WhileCondition(logic::FeedToFinda &ff, COND cond, uint32_t maxLoops = 5000) {
|
||||
while (cond() && --maxLoops) {
|
||||
main_loop();
|
||||
ff.Step();
|
||||
}
|
||||
return maxLoops > 0;
|
||||
}
|
||||
|
||||
TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
||||
using namespace logic;
|
||||
|
||||
|
|
@ -60,7 +51,7 @@ TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
|||
// engaging idler
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return !mi::idler.Engaged(); },
|
||||
[&](int) { return !mi::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(0));
|
||||
|
|
@ -77,7 +68,7 @@ TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
|||
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return ff.State() == FeedToFinda::PushingFilament; },
|
||||
[&](int) { return ff.State() == FeedToFinda::PushingFilament; },
|
||||
1500));
|
||||
// From now on the FINDA is reported as ON
|
||||
|
||||
|
|
@ -85,14 +76,14 @@ TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
|||
REQUIRE(ff.State() == FeedToFinda::UnloadBackToPTFE);
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return ff.State() == FeedToFinda::UnloadBackToPTFE; },
|
||||
[&](int) { return ff.State() == FeedToFinda::UnloadBackToPTFE; },
|
||||
5000));
|
||||
|
||||
// disengaging idler
|
||||
REQUIRE(ff.State() == FeedToFinda::DisengagingIdler);
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return mi::idler.Engaged(); },
|
||||
[&](int) { return mi::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // @@TODO constants
|
||||
|
|
@ -126,7 +117,7 @@ TEST_CASE("feed_to_finda::FINDA_failed", "[feed_to_finda]") {
|
|||
// engaging idler
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return !mi::idler.Engaged(); },
|
||||
[&](int) { return !mi::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(0));
|
||||
|
|
@ -141,8 +132,8 @@ TEST_CASE("feed_to_finda::FINDA_failed", "[feed_to_finda]") {
|
|||
ha::ReinitADC(1, ha::TADCData({ 0 }), 100);
|
||||
|
||||
REQUIRE(WhileCondition(
|
||||
ff, // boo, this formatting is UGLY!
|
||||
[&]() { return ff.State() == FeedToFinda::PushingFilament; },
|
||||
ff,
|
||||
[&](int) { return ff.State() == FeedToFinda::PushingFilament; },
|
||||
5000));
|
||||
|
||||
// the FINDA didn't trigger, we should be in the Failed state
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ TEST_CASE("unload_filament::unload0", "[unload_filament]") {
|
|||
|
||||
LoadFilament lf;
|
||||
// restart the automaton
|
||||
currentCommand = &lf;
|
||||
lf.Reset(0);
|
||||
|
||||
main_loop();
|
||||
|
|
@ -53,4 +52,5 @@ TEST_CASE("unload_filament::unload0", "[unload_filament]") {
|
|||
// REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::FinishingMoves; }, 5000));
|
||||
|
||||
// REQUIRE(uf.TopLevelState() == ProgressCode::OK);
|
||||
REQUIRE(modules::globals::globals.FilamentLoaded() == true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@
|
|||
#include "../../../../src/modules/permanent_storage.h"
|
||||
#include "../../../../src/modules/selector.h"
|
||||
|
||||
#include <new> // bring in placement new
|
||||
#include "../stubs/stub_motion.h"
|
||||
|
||||
logic::CommandBase *currentCommand = nullptr;
|
||||
#include <new> // bring in placement new
|
||||
|
||||
void main_loop() {
|
||||
modules::buttons::buttons.Step();
|
||||
|
|
@ -25,8 +25,6 @@ void main_loop() {
|
|||
modules::idler::idler.Step();
|
||||
modules::selector::selector.Step();
|
||||
modules::motion::motion.Step();
|
||||
if (currentCommand)
|
||||
currentCommand->Step();
|
||||
|
||||
modules::time::IncMillis();
|
||||
}
|
||||
|
|
@ -57,8 +55,12 @@ void ForceReinitAllAutomata() {
|
|||
// finda OFF
|
||||
hal::adc::ReinitADC(1, hal::adc::TADCData({ 0 }), 1);
|
||||
|
||||
// reinit timing
|
||||
modules::time::ReinitTimebase();
|
||||
|
||||
// reinit axes positions
|
||||
modules::motion::ReinitMotion();
|
||||
|
||||
// let's assume we have the filament NOT loaded and active slot 0
|
||||
modules::globals::globals.SetFilamentLoaded(false);
|
||||
modules::globals::globals.SetActiveSlot(0);
|
||||
|
|
|
|||
|
|
@ -4,12 +4,17 @@
|
|||
extern void main_loop();
|
||||
extern void ForceReinitAllAutomata();
|
||||
|
||||
extern logic::CommandBase *currentCommand;
|
||||
|
||||
template <typename COND>
|
||||
bool WhileCondition(COND cond, uint32_t maxLoops = 5000) {
|
||||
while (cond() && --maxLoops) {
|
||||
template <typename SM, typename COND>
|
||||
bool WhileCondition(SM &sm, COND cond, uint32_t maxLoops = 5000) {
|
||||
while (cond(maxLoops) && --maxLoops) {
|
||||
main_loop();
|
||||
sm.Step();
|
||||
}
|
||||
return maxLoops > 0;
|
||||
}
|
||||
|
||||
template <typename SM>
|
||||
bool WhileTopState(SM &sm, ProgressCode state, uint32_t maxLoops = 5000) {
|
||||
return WhileCondition(
|
||||
sm, [&](int) { return sm.TopLevelState() == state; }, maxLoops);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,13 @@ namespace modules {
|
|||
namespace motion {
|
||||
|
||||
Motion motion;
|
||||
|
||||
// Intentionally inited with strange values
|
||||
// Need to call ReinitMotion() each time we start some unit test
|
||||
AxisSim axes[3] = {
|
||||
{ 0, 0, false, false, false }, // pulley
|
||||
{ 1, 1, false, false, false }, // selector //@@TODO proper selector positions once defined
|
||||
{ 0, 0, false, false, false }, // idler
|
||||
{ -32767, -32767, false, false, false }, // pulley
|
||||
{ -32767, -32767, false, false, false }, // selector //@@TODO proper selector positions once defined
|
||||
{ -32767, -32767, false, false, false }, // idler
|
||||
};
|
||||
|
||||
void Motion::InitAxis(Axis axis) {
|
||||
|
|
@ -72,6 +75,13 @@ void Motion::AbortPlannedMoves() {
|
|||
}
|
||||
}
|
||||
|
||||
void ReinitMotion() {
|
||||
// reset the simulation data to defaults
|
||||
axes[0] = AxisSim({ 0, 0, false, false, false }); // pulley
|
||||
axes[1] = AxisSim({ 1, 1, false, false, false }); // selector //@@TODO proper selector positions once defined
|
||||
axes[2] = AxisSim({ 0, 0, false, false, false }); // idler
|
||||
}
|
||||
|
||||
/// probably higher-level operations knowing the semantic meaning of axes
|
||||
|
||||
} // namespace motion
|
||||
|
|
|
|||
|
|
@ -14,5 +14,7 @@ struct AxisSim {
|
|||
|
||||
extern AxisSim axes[3];
|
||||
|
||||
extern void ReinitMotion();
|
||||
|
||||
} // namespace motion
|
||||
} // namespace modules
|
||||
|
|
|
|||
|
|
@ -34,23 +34,16 @@ TEST_CASE("tool_change::test0", "[tool_change]") {
|
|||
|
||||
ToolChange tc;
|
||||
// restart the automaton
|
||||
currentCommand = &tc;
|
||||
tc.Reset(0);
|
||||
|
||||
main_loop();
|
||||
|
||||
// REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::UnloadingToFinda; }, 5000));
|
||||
REQUIRE(WhileTopState(tc, ProgressCode::UnloadingFilament, 5000));
|
||||
REQUIRE(modules::globals::globals.FilamentLoaded() == false);
|
||||
|
||||
// REQUIRE(uf.TopLevelState() == ProgressCode::DisengagingIdler);
|
||||
// REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::DisengagingIdler; }, 5000));
|
||||
REQUIRE(tc.TopLevelState() == ProgressCode::LoadingFilament);
|
||||
REQUIRE(WhileTopState(tc, ProgressCode::LoadingFilament, 5000));
|
||||
|
||||
// CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5));
|
||||
|
||||
// REQUIRE(uf.TopLevelState() == ProgressCode::AvoidingGrind);
|
||||
// REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::AvoidingGrind; }, 5000));
|
||||
|
||||
// REQUIRE(uf.TopLevelState() == ProgressCode::FinishingMoves);
|
||||
// REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::FinishingMoves; }, 5000));
|
||||
|
||||
// REQUIRE(uf.TopLevelState() == ProgressCode::OK);
|
||||
REQUIRE(tc.TopLevelState() == ProgressCode::OK);
|
||||
REQUIRE(modules::globals::globals.FilamentLoaded() == true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,30 +27,198 @@ namespace mb = modules::buttons;
|
|||
namespace mg = modules::globals;
|
||||
namespace ms = modules::selector;
|
||||
|
||||
TEST_CASE("unload_filament::unload0", "[unload_filament]") {
|
||||
using namespace logic;
|
||||
|
||||
void RegularUnloadFromSlot04(uint8_t slot) {
|
||||
// prepare startup conditions
|
||||
ForceReinitAllAutomata();
|
||||
|
||||
UnloadFilament uf;
|
||||
// restart the automaton
|
||||
currentCommand = &uf;
|
||||
uf.Reset(0);
|
||||
|
||||
// change the startup to what we need here
|
||||
// move selector to the right spot
|
||||
ms::selector.MoveToSlot(slot);
|
||||
while (ms::selector.Slot() != slot)
|
||||
main_loop();
|
||||
|
||||
REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::UnloadingToFinda; }, 5000));
|
||||
mg::globals.SetActiveSlot(slot);
|
||||
mg::globals.SetFilamentLoaded(true);
|
||||
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::DisengagingIdler);
|
||||
REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::DisengagingIdler; }, 5000));
|
||||
// set FINDA ON + debounce
|
||||
hal::adc::SetADC(1, mf::FINDA::adcDecisionLevel + 1);
|
||||
for (size_t i = 0; i < mf::FINDA::debounce + 1; ++i)
|
||||
main_loop();
|
||||
|
||||
CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5));
|
||||
// verify startup conditions
|
||||
REQUIRE(mg::globals.FilamentLoaded() == true);
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5));
|
||||
REQUIRE(!mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot));
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == true);
|
||||
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::AvoidingGrind);
|
||||
REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::AvoidingGrind; }, 5000));
|
||||
// restart the automaton
|
||||
logic::UnloadFilament uf;
|
||||
uf.Reset(slot);
|
||||
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::FinishingMoves);
|
||||
REQUIRE(WhileCondition([&]() { return uf.TopLevelState() == ProgressCode::FinishingMoves; }, 5000));
|
||||
// Stage 0 - verify state just after Reset()
|
||||
REQUIRE(mg::globals.FilamentLoaded() == true); // we still think we have filament loaded at this stage
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // idler should have been activated by the underlying automaton
|
||||
REQUIRE(!mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot)); // no change in selector's position
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == true); // FINDA triggered off
|
||||
REQUIRE(ml::leds.Mode(slot, ml::green) == ml::blink0); // green LED should blink
|
||||
REQUIRE(uf.Error() == ErrorCode::OK); // no error so far
|
||||
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::OK);
|
||||
// run the automaton
|
||||
// Stage 1 - unloading to FINDA
|
||||
REQUIRE(WhileCondition(
|
||||
uf,
|
||||
[&](int step) -> bool {
|
||||
if(step == 100){ // on 100th step make FINDA trigger
|
||||
hal::adc::SetADC(1, 0);
|
||||
}
|
||||
return uf.TopLevelState() == ProgressCode::UnloadingToFinda; },
|
||||
5000));
|
||||
|
||||
REQUIRE(mg::globals.FilamentLoaded() == true); // we still think we have filament loaded at this stage
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(slot)); // idler should have been activated by the underlying automaton
|
||||
REQUIRE(mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot)); // no change in selector's position
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == false); // FINDA triggered off
|
||||
REQUIRE(ml::leds.Mode(slot, ml::green) == ml::blink0); // green LED should blink
|
||||
REQUIRE(uf.Error() == ErrorCode::OK); // no error so far
|
||||
|
||||
// Stage 2 - idler was engaged, disengage it
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::DisengagingIdler);
|
||||
REQUIRE(WhileTopState(uf, ProgressCode::DisengagingIdler, 5000));
|
||||
|
||||
REQUIRE(mg::globals.FilamentLoaded() == true); // we still think we have filament loaded at this stage
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // idler should have been disengaged
|
||||
REQUIRE(!mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot)); // no change in selector's position
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == false); // FINDA still triggered off
|
||||
REQUIRE(ml::leds.Mode(slot, ml::green) == ml::blink0); // green LED should blink
|
||||
REQUIRE(uf.Error() == ErrorCode::OK); // no error so far
|
||||
|
||||
// Stage 3 - avoiding grind (whatever is that @@TODO)
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::AvoidingGrind);
|
||||
REQUIRE(WhileTopState(uf, ProgressCode::AvoidingGrind, 5000));
|
||||
|
||||
REQUIRE(mg::globals.FilamentLoaded() == true); // we still think we have filament loaded at this stage
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // idler should have been disengaged
|
||||
REQUIRE(!mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot)); // no change in selector's position
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == false); // FINDA still triggered off
|
||||
REQUIRE(ml::leds.Mode(slot, ml::green) == ml::blink0); // green LED should blink
|
||||
REQUIRE(uf.Error() == ErrorCode::OK); // no error so far
|
||||
|
||||
// Stage 4 - finishing moves and setting global state correctly
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::FinishingMoves);
|
||||
REQUIRE(WhileTopState(uf, ProgressCode::FinishingMoves, 5000));
|
||||
|
||||
REQUIRE(mg::globals.FilamentLoaded() == false); // filament unloaded
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // idler should have been disengaged
|
||||
REQUIRE(!mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot)); // no change in selector's position
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == false); // FINDA still triggered off
|
||||
REQUIRE(ml::leds.Mode(slot, ml::green) == ml::on); // green LED should be ON
|
||||
REQUIRE(uf.Error() == ErrorCode::OK); // no error so far
|
||||
|
||||
// Stage 5 - repeated calls to TopLevelState should return "OK"
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::OK);
|
||||
REQUIRE(mg::globals.FilamentLoaded() == false);
|
||||
REQUIRE(mf::finda.Pressed() == false);
|
||||
REQUIRE(uf.Error() == ErrorCode::OK); // no error
|
||||
}
|
||||
|
||||
TEST_CASE("unload_filament::regular_unload_from_slot_0-4", "[unload_filament]") {
|
||||
for (uint8_t slot = 0; slot < 5; ++slot) {
|
||||
RegularUnloadFromSlot04(slot);
|
||||
}
|
||||
}
|
||||
|
||||
void FindaDidntTrigger(uint8_t slot) {
|
||||
// prepare startup conditions
|
||||
ForceReinitAllAutomata();
|
||||
|
||||
// change the startup to what we need here
|
||||
|
||||
// move selector to the right spot
|
||||
ms::selector.MoveToSlot(slot);
|
||||
while (ms::selector.Slot() != slot)
|
||||
main_loop();
|
||||
|
||||
// set FINDA ON + debounce
|
||||
hal::adc::SetADC(1, mf::FINDA::adcDecisionLevel + 1);
|
||||
for (size_t i = 0; i < mf::FINDA::debounce + 1; ++i)
|
||||
main_loop();
|
||||
|
||||
mg::globals.SetActiveSlot(slot);
|
||||
mg::globals.SetFilamentLoaded(true);
|
||||
|
||||
// verify startup conditions
|
||||
REQUIRE(mg::globals.FilamentLoaded() == true);
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5));
|
||||
REQUIRE(!mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot));
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == true);
|
||||
|
||||
// restart the automaton
|
||||
logic::UnloadFilament uf;
|
||||
uf.Reset(slot);
|
||||
|
||||
// Stage 0 - verify state just after Reset()
|
||||
REQUIRE(mg::globals.FilamentLoaded() == true); // we still think we have filament loaded at this stage
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // idler should have been activated by the underlying automaton
|
||||
REQUIRE(!mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot)); // no change in selector's position
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == true); // FINDA triggered off
|
||||
REQUIRE(ml::leds.Mode(slot, ml::green) == ml::blink0); // green LED should blink
|
||||
REQUIRE(uf.Error() == ErrorCode::OK); // no error so far
|
||||
|
||||
// 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
|
||||
// without reaching the FINDA and report an error
|
||||
REQUIRE(WhileTopState(uf, ProgressCode::UnloadingToFinda, 50000));
|
||||
|
||||
REQUIRE(mg::globals.FilamentLoaded() == true); // we still think we have filament loaded at this stage
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(slot)); // idler should have been activated by the underlying automaton
|
||||
REQUIRE(mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot)); // no change in selector's position
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == true); // FINDA still on
|
||||
REQUIRE(ml::leds.Mode(slot, ml::red) == ml::blink0); // red LED should blink
|
||||
REQUIRE(ml::leds.Mode(slot, ml::green) == ml::off); // green LED should be off
|
||||
REQUIRE(uf.Error() == ErrorCode::FINDA_DIDNT_TRIGGER); // didn't get any response from FINDA
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::ERR1DisengagingIdler);
|
||||
|
||||
// Stage 2 - idler should get disengaged
|
||||
REQUIRE(WhileTopState(uf, ProgressCode::ERR1DisengagingIdler, 5000));
|
||||
|
||||
REQUIRE(mg::globals.FilamentLoaded() == true); // we still think we have filament loaded at this stage
|
||||
REQUIRE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5)); // idler should have been disengaged
|
||||
REQUIRE(!mi::idler.Engaged());
|
||||
REQUIRE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(slot)); // no change in selector's position
|
||||
REQUIRE(ms::selector.Slot() == slot);
|
||||
REQUIRE(mf::finda.Pressed() == true); // FINDA still on
|
||||
REQUIRE(ml::leds.Mode(slot, ml::red) == ml::blink0); // red LED should blink
|
||||
REQUIRE(ml::leds.Mode(slot, ml::green) == ml::off); // green LED should be off
|
||||
REQUIRE(uf.Error() == ErrorCode::FINDA_DIDNT_TRIGGER);
|
||||
REQUIRE(uf.TopLevelState() == ProgressCode::ERR1WaitingForUser);
|
||||
|
||||
// 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?
|
||||
}
|
||||
|
||||
TEST_CASE("unload_filament::finda_didnt_trigger", "[unload_filament]") {
|
||||
for (uint8_t slot = 0; slot < 5; ++slot) {
|
||||
FindaDidntTrigger(slot);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,15 +29,6 @@ namespace ms = modules::selector;
|
|||
|
||||
namespace ha = hal::adc;
|
||||
|
||||
template <typename COND>
|
||||
bool WhileConditionFF(logic::UnloadToFinda &ff, COND cond, uint32_t maxLoops = 5000) {
|
||||
while (cond() && --maxLoops) {
|
||||
main_loop();
|
||||
ff.Step();
|
||||
}
|
||||
return maxLoops > 0;
|
||||
}
|
||||
|
||||
TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
||||
using namespace logic;
|
||||
|
||||
|
|
@ -50,7 +41,8 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
|||
|
||||
// wait for FINDA to debounce
|
||||
REQUIRE(WhileCondition(
|
||||
[&]() { return !mf::finda.Pressed(); },
|
||||
ff,
|
||||
[&](int) { return !mf::finda.Pressed(); },
|
||||
5000));
|
||||
|
||||
// restart the automaton - just 1 attempt
|
||||
|
|
@ -65,17 +57,17 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
|||
CHECK(mm::axes[mm::Idler].enabled == true);
|
||||
|
||||
// engaging idler
|
||||
REQUIRE(WhileConditionFF(
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return !mi::idler.Engaged(); },
|
||||
[&](int) { return !mi::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == UnloadToFinda::WaitingForFINDA);
|
||||
hal::adc::ReinitADC(1, hal::adc::TADCData({ 1023, 900, 800, 500, 0 }), 10);
|
||||
REQUIRE(WhileConditionFF(
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return mf::finda.Pressed(); },
|
||||
[&](int) { return mf::finda.Pressed(); },
|
||||
50000));
|
||||
|
||||
REQUIRE(ff.State() == UnloadToFinda::OK);
|
||||
|
|
@ -108,7 +100,8 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]")
|
|||
|
||||
// wait for FINDA to debounce
|
||||
REQUIRE(WhileCondition(
|
||||
[&]() { return !mf::finda.Pressed(); },
|
||||
ff,
|
||||
[&](int) { return !mf::finda.Pressed(); },
|
||||
5000));
|
||||
|
||||
// restart the automaton - just 1 attempt
|
||||
|
|
@ -123,18 +116,18 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]")
|
|||
CHECK(mm::axes[mm::Idler].enabled == true);
|
||||
|
||||
// engaging idler
|
||||
REQUIRE(WhileConditionFF(
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return !mi::idler.Engaged(); },
|
||||
[&](int) { return !mi::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
// now pulling the filament until finda triggers
|
||||
REQUIRE(ff.State() == UnloadToFinda::WaitingForFINDA);
|
||||
|
||||
// no changes to FINDA during unload - we'll pretend it never triggers
|
||||
REQUIRE(!WhileConditionFF(
|
||||
REQUIRE(!WhileCondition(
|
||||
ff,
|
||||
[&]() { return mf::finda.Pressed(); },
|
||||
[&](int) { return mf::finda.Pressed(); },
|
||||
50000));
|
||||
|
||||
REQUIRE(ff.State() == UnloadToFinda::Failed);
|
||||
|
|
|
|||
|
|
@ -29,5 +29,9 @@ uint16_t ReadADC(uint8_t adc) {
|
|||
return rdptr[adc] != values2Return[adc].end() ? *rdptr[adc] : values2Return[adc].back();
|
||||
}
|
||||
|
||||
void SetADC(uint8_t channel, uint16_t value) {
|
||||
ReinitADC(channel, TADCData({ value }), 1);
|
||||
}
|
||||
|
||||
} // namespace adc
|
||||
} // namespace hal
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@ namespace adc {
|
|||
|
||||
using TADCData = std::vector<uint16_t>;
|
||||
|
||||
/// plan a vector of ADC values for the next steps
|
||||
void ReinitADC(uint8_t channel, TADCData &&d, uint8_t ovsmpl);
|
||||
|
||||
/// set ADC value on a channel to some fixed value from now on
|
||||
void SetADC(uint8_t channel, uint16_t value);
|
||||
|
||||
} // namespace adc
|
||||
} // namespace hal
|
||||
|
|
|
|||
Loading…
Reference in New Issue