Fix waiting for homing of Selector after UnloadFilament

pull/154/head
D.R.racer 2022-02-09 12:56:27 +01:00 committed by DRracer
parent c95c6677b1
commit b685ec4aff
6 changed files with 133 additions and 32 deletions

View File

@ -25,7 +25,9 @@ public:
ErrorCode Error() const override;
#ifndef UNITTEST
private:
#endif
void GoToFeedingToBondtech();
/// Common code for a correct completion of UnloadFilament

View File

@ -79,7 +79,7 @@ bool UnloadFilament::StepInner() {
}
return false;
case ProgressCode::DisengagingIdler:
if (!mi::idler.Engaged()) {
if (!mi::idler.Engaged() && ms::selector.State() == ms::Selector::Ready) {
FinishedCorrectly();
}
return false;

View File

@ -87,17 +87,21 @@ bool VerifyState2(SM &uf, mg::FilamentLoadState fls, uint8_t idlerSlotIndex, uin
CHECKED_ELSE(mg::globals.FilamentLoaded() & fls) {
return false;
}
CHECKED_ELSE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(idlerSlotIndex).v) {
return false;
if( idlerSlotIndex < config::toolCount ){ // abusing invalid index to skip checking of slot and position
CHECKED_ELSE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(idlerSlotIndex).v) {
return false;
}
CHECKED_ELSE(mi::idler.Engaged() == (idlerSlotIndex < config::toolCount)) {
return false;
}
}
CHECKED_ELSE(mi::idler.Engaged() == (idlerSlotIndex < config::toolCount)) {
return false;
}
CHECKED_ELSE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(selectorSlotIndex).v) {
return false;
}
CHECKED_ELSE(ms::selector.Slot() == selectorSlotIndex) {
return false;
if( selectorSlotIndex < config::toolCount ){ // abusing invalid index to skip checking of slot and position
CHECKED_ELSE(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(selectorSlotIndex).v) {
return false;
}
CHECKED_ELSE(ms::selector.Slot() == selectorSlotIndex) {
return false;
}
}
CHECKED_ELSE(mf::finda.Pressed() == findaPressed) {
return false;
@ -116,10 +120,12 @@ bool VerifyState2(SM &uf, mg::FilamentLoadState fls, uint8_t idlerSlotIndex, uin
return false;
}
} else {
CHECKED_ELSE(ml::leds.Mode(ledCheckIndex, ml::red) == redLEDMode) {
auto lmr = ml::leds.Mode(ledCheckIndex, ml::red);
CHECKED_ELSE(lmr == redLEDMode) {
return false;
}
CHECKED_ELSE(ml::leds.Mode(ledCheckIndex, ml::green) == greenLEDMode) {
auto lmg = ml::leds.Mode(ledCheckIndex, ml::green);
CHECKED_ELSE(lmg == greenLEDMode) {
return false;
}
}

View File

@ -117,6 +117,20 @@ bool SimulateUnloadToFINDA(uint32_t step, uint32_t fsOff, uint32_t findaOff) {
return mf::finda.Pressed();
}
bool SimulateFeedToFINDA(uint32_t step, uint32_t findaOn) {
if (step == findaOn) {
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::high);
}
return !mf::finda.Pressed();
}
bool SimulateRetractFromFINDA(uint32_t step, uint32_t findaOff) {
if (step == findaOff) {
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
}
return mf::finda.Pressed();
}
void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex) {
hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCLimits[btnIndex][0] + 1);
while (!mb::buttons.ButtonPressed(btnIndex)) {

View File

@ -26,6 +26,8 @@ void EnsureActiveSlotIndex(uint8_t slot, modules::globals::FilamentLoadState loa
void SetFINDAStateAndDebounce(bool press);
bool SimulateUnloadToFINDA(uint32_t step, uint32_t fsOff, uint32_t findaOff);
bool SimulateFeedToFINDA(uint32_t step, uint32_t findaOn);
bool SimulateRetractFromFINDA(uint32_t step, uint32_t findaOff);
void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex);
void ClearButtons(logic::CommandBase &cb);

View File

@ -14,25 +14,30 @@
#include "../../modules/stubs/stub_adc.h"
#include "../stubs/homing.h"
#include "../stubs/main_loop_stub.h"
#include "../stubs/stub_motion.h"
#include <functional>
using Catch::Matchers::Equals;
using namespace std::placeholders;
#include "../helpers/helpers.ipp"
// needs to be a separate function otherwise gdb has issues setting breakpoints inside
bool FeedingToFindaStep(logic::CommandBase &tc, uint32_t step, uint32_t triggerAt) {
if (step == triggerAt) { // on specified stepNr make FINDA trigger
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::high);
} else if (step >= triggerAt + config::findaDebounceMs + 2) {
REQUIRE(mf::finda.Pressed() == true);
}
return tc.TopLevelState() == ProgressCode::FeedingToFinda;
}
void FeedingToFinda(logic::ToolChange &tc, uint8_t toSlot, uint32_t triggerAt = 1000) {
// feeding to finda
REQUIRE(WhileCondition(
tc,
[&](uint32_t step) -> bool {
if(step == triggerAt){ // on specified stepNr make FINDA trigger
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::high);
} else if(step >= triggerAt + config::findaDebounceMs + 1){
REQUIRE(mf::finda.Pressed() == true);
}
return tc.TopLevelState() == ProgressCode::FeedingToFinda; },
200000UL));
REQUIRE(WhileCondition(tc, std::bind(FeedingToFindaStep, std::ref(tc), _1, triggerAt), 200'000UL));
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, toSlot, toSlot, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToBondtech));
}
@ -58,6 +63,8 @@ void CheckFinishedCorrectly(logic::ToolChange &tc, uint8_t toSlot) {
void ToolChange(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) {
ForceReinitAllAutomata();
SetFINDAStateAndDebounce(true);
mfs::fsensor.ProcessMessage(true);
EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle);
// restart the automaton
@ -86,9 +93,11 @@ void NoToolChange(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) {
ForceReinitAllAutomata();
// the filament is LOADED
SetFINDAStateAndDebounce(true);
mfs::fsensor.ProcessMessage(true);
EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle);
REQUIRE(VerifyEnvironmentState(mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), toSlot, false, false, ml::off, ml::off));
REQUIRE(VerifyEnvironmentState(mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), toSlot, true, false, ml::off, ml::off));
// restart the automaton
tc.Reset(toSlot);
@ -162,19 +171,15 @@ TEST_CASE("tool_change::same_slot_just_unloaded_filament", "[tool_change]") {
void ToolChangeFailLoadToFinda(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) {
ForceReinitAllAutomata();
SetFINDAStateAndDebounce(true);
mfs::fsensor.ProcessMessage(true);
EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle);
// restart the automaton
tc.Reset(toSlot);
REQUIRE(WhileCondition(
tc,
[&](uint32_t step) -> bool {
if(step == 2000){ // on 2000th step make FINDA trigger
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
}
return tc.TopLevelState() == ProgressCode::UnloadingFilament; },
200000UL));
REQUIRE(WhileCondition(tc, std::bind(SimulateUnloadToFINDA, _1, 100, 2'000), 200'000));
REQUIRE(WhileTopState(tc, ProgressCode::UnloadingFilament, 5000));
REQUIRE(mg::globals.FilamentLoaded() == mg::FilamentLoadState::AtPulley);
@ -316,3 +321,75 @@ TEST_CASE("tool_change::load_fail_FINDA_resolve_btnR_FINDA", "[tool_change]") {
}
}
}
void ToolChangeFailFSensor(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) {
using namespace std::placeholders;
ForceReinitAllAutomata();
SetFINDAStateAndDebounce(true);
mfs::fsensor.ProcessMessage(true);
EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle);
// restart the automaton
tc.Reset(toSlot);
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InNozzle, mi::idler.IdleSlotIndex(), fromSlot, true, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
// simulate unload to finda but fail the fsensor test
REQUIRE(WhileCondition(tc, std::bind(SimulateUnloadToFINDA, _1, 500'000, 10'000), 200'000));
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::idler.IdleSlotIndex(), fromSlot, false, false, ml::off, ml::blink0, ErrorCode::FSENSOR_DIDNT_SWITCH_OFF, ProgressCode::UnloadingFilament));
REQUIRE(tc.unl.State() == ProgressCode::ERRWaitingForUser);
}
void ToolChangeFailFSensorMiddleBtn(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) {
using namespace std::placeholders;
// user pulls filament out from the fsensor and presses Retry
mfs::fsensor.ProcessMessage(false);
PressButtonAndDebounce(tc, mb::Middle);
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::idler.IdleSlotIndex(), fromSlot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
REQUIRE(tc.unl.State() == ProgressCode::FeedingToFinda); // MMU must find out where the filament is FS is OFF, FINDA is OFF
// both movables should have their homing flag invalidated
REQUIRE_FALSE(mi::idler.HomingValid());
REQUIRE_FALSE(ms::selector.HomingValid());
// make FINDA trigger - Idler will rehome in this step, Selector must remain at its place
SimulateIdlerHoming(tc);
REQUIRE(mi::idler.HomingValid());
REQUIRE_FALSE(ms::selector.HomingValid());
// now trigger the FINDA
REQUIRE(WhileCondition(tc, std::bind(SimulateFeedToFINDA, _1, 100), 5000));
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, fromSlot, fromSlot, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
REQUIRE(tc.unl.State() == ProgressCode::RetractingFromFinda);
// make FINDA switch off
REQUIRE(WhileCondition(tc, std::bind(SimulateRetractFromFINDA, _1, 100), 5000));
REQUIRE(WhileCondition(
tc, [&](uint32_t) { return tc.unl.State() == ProgressCode::RetractingFromFinda; }, 50000));
// Selector will start rehoming at this stage - that was the error this test was to find
REQUIRE(VerifyState(tc, mg::FilamentLoadState::AtPulley, fromSlot, config::toolCount, false, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
REQUIRE(tc.unl.State() == ProgressCode::DisengagingIdler);
SimulateSelectorHoming(tc);
// Idler has probably engaged meanwhile, ignore its position check
REQUIRE(WhileTopState(tc, ProgressCode::UnloadingFilament, 50000));
REQUIRE(VerifyState2(tc, mg::FilamentLoadState::AtPulley, config::toolCount, fromSlot, false, false, toSlot, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda));
// after that, perform a normal load
FeedingToFinda(tc, toSlot, 100);
FeedingToBondtech(tc, toSlot);
CheckFinishedCorrectly(tc, toSlot);
}
TEST_CASE("tool_change::load_fail_FSensor_resolve_btnM", "[tool_change]") {
logic::ToolChange tc;
for (uint8_t fromSlot = 0; fromSlot < config::toolCount; ++fromSlot) {
for (uint8_t toSlot = 0; toSlot < config::toolCount; ++toSlot) {
if (fromSlot != toSlot) {
ToolChangeFailFSensor(tc, fromSlot, toSlot);
ToolChangeFailFSensorMiddleBtn(tc, fromSlot, toSlot);
}
}
}
}