Change the semantics of load filament
Load filament performs feed to FINDA and retract: - engage idler - feed normal to FINDA with config::feedToFinda distance until FINDA triggers - retract normal and as soon FINDA un-triggers move back to PTFE config::cuttingEdgeToFindaMidpoint - disengage the idler That implied introducing another substate machine - RetractFromFinda, which does the opposite of FeedToFinda while also checking for the FINDA switching off while retracting filament. Still, ToolChange and CutFilament need fixing with this changepull/126/head
parent
01b2280ea6
commit
6426295e32
|
|
@ -7,6 +7,7 @@ target_sources(
|
||||||
feed_to_finda.cpp
|
feed_to_finda.cpp
|
||||||
load_filament.cpp
|
load_filament.cpp
|
||||||
no_command.cpp
|
no_command.cpp
|
||||||
|
retract_from_finda.cpp
|
||||||
set_mode.cpp
|
set_mode.cpp
|
||||||
tool_change.cpp
|
tool_change.cpp
|
||||||
unload_filament.cpp
|
unload_filament.cpp
|
||||||
|
|
|
||||||
|
|
@ -32,29 +32,14 @@ bool FeedToFinda::Step() {
|
||||||
if (mf::finda.Pressed() || (feedPhaseLimited && mui::userInput.AnyEvent())) { // @@TODO probably also a command from the printer
|
if (mf::finda.Pressed() || (feedPhaseLimited && mui::userInput.AnyEvent())) { // @@TODO probably also a command from the printer
|
||||||
mm::motion.AbortPlannedMoves(); // stop pushing filament
|
mm::motion.AbortPlannedMoves(); // stop pushing filament
|
||||||
// FINDA triggered - that means it works and detected the filament tip
|
// FINDA triggered - that means it works and detected the filament tip
|
||||||
state = UnloadBackToPTFE;
|
state = OK;
|
||||||
mm::motion.PlanMove<mm::Pulley>(-config::cuttingEdgeToFindaMidpoint, config::pulleyFeedrate);
|
|
||||||
} else if (mm::motion.QueueEmpty()) { // all moves have been finished and FINDA didn't switch on
|
} else if (mm::motion.QueueEmpty()) { // all moves have been finished and FINDA didn't switch on
|
||||||
state = Failed;
|
state = Failed;
|
||||||
// @@TODO - shall we disengage the idler?
|
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case UnloadBackToPTFE:
|
|
||||||
if (mm::motion.QueueEmpty()) { // all moves have been finished
|
|
||||||
state = DisengagingIdler;
|
|
||||||
mi::idler.Disengage();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case DisengagingIdler:
|
|
||||||
if (!mi::idler.Engaged()) {
|
|
||||||
state = OK;
|
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
|
||||||
}
|
|
||||||
// @@TODO FINDA must be reported as OFF again as we are pulling the filament from it - is this correct?
|
|
||||||
return false;
|
|
||||||
case OK:
|
case OK:
|
||||||
case Failed:
|
case Failed:
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -51,20 +51,22 @@ bool LoadFilament::StepInner() {
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error
|
||||||
} else {
|
} else {
|
||||||
state = ProgressCode::FeedingToBondtech;
|
state = ProgressCode::RetractingFromFinda;
|
||||||
james.Reset(config::feedToBondtechMaxRetries);
|
retract.Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProgressCode::FeedingToBondtech:
|
case ProgressCode::RetractingFromFinda:
|
||||||
if (james.Step()) { // No, Mr. Bond, I expect you to FEED
|
if (retract.Step()) {
|
||||||
switch (james.State()) {
|
if (retract.State() == RetractFromFinda::Failed) {
|
||||||
case FeedToBondtech::Failed:
|
state = ProgressCode::ERRDisengagingIdler;
|
||||||
|
error = ErrorCode::FINDA_DIDNT_SWITCH_OFF;
|
||||||
case FeedToBondtech::OK:
|
|
||||||
mm::motion.Disable(mm::Pulley);
|
|
||||||
mi::idler.Disengage();
|
mi::idler.Disengage();
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0); // signal loading error
|
||||||
|
} else {
|
||||||
state = ProgressCode::DisengagingIdler;
|
state = ProgressCode::DisengagingIdler;
|
||||||
|
mi::idler.Disengage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "command_base.h"
|
#include "command_base.h"
|
||||||
#include "feed_to_finda.h"
|
#include "feed_to_finda.h"
|
||||||
#include "feed_to_bondtech.h"
|
#include "retract_from_finda.h"
|
||||||
|
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FeedToFinda feed;
|
FeedToFinda feed;
|
||||||
FeedToBondtech james; // bond ;)
|
RetractFromFinda retract;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The one and only instance of LoadFilament state machine in the FW
|
/// The one and only instance of LoadFilament state machine in the FW
|
||||||
|
|
|
||||||
|
|
@ -33,4 +33,5 @@ enum class ProgressCode : uint_fast8_t {
|
||||||
ReturningSelector, // P21
|
ReturningSelector, // P21
|
||||||
ParkingSelector, // P22
|
ParkingSelector, // P22
|
||||||
EjectingFilament, // P23
|
EjectingFilament, // P23
|
||||||
|
RetractingFromFinda, // P24
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include "retract_from_finda.h"
|
||||||
|
#include "../modules/finda.h"
|
||||||
|
#include "../modules/globals.h"
|
||||||
|
#include "../modules/idler.h"
|
||||||
|
#include "../modules/leds.h"
|
||||||
|
#include "../modules/motion.h"
|
||||||
|
|
||||||
|
namespace logic {
|
||||||
|
|
||||||
|
void RetractFromFinda::Reset() {
|
||||||
|
state = EngagingIdler;
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::blink0);
|
||||||
|
mi::idler.Engage(mg::globals.ActiveSlot());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RetractFromFinda::Step() {
|
||||||
|
switch (state) {
|
||||||
|
case EngagingIdler:
|
||||||
|
if (mi::idler.Engaged()) {
|
||||||
|
state = UnloadBackToPTFE;
|
||||||
|
mm::motion.PlanMove<mm::Pulley>(-config::cuttingEdgeToFindaMidpoint, config::pulleyFeedrate);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case UnloadBackToPTFE:
|
||||||
|
if (mm::motion.QueueEmpty()) { // all moves have been finished
|
||||||
|
if (!mf::finda.Pressed()) { // FINDA switched off correctly
|
||||||
|
state = OK;
|
||||||
|
} else { // FINDA didn't switch off
|
||||||
|
state = Failed;
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
||||||
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case OK:
|
||||||
|
case Failed:
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace logic
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace logic {
|
||||||
|
|
||||||
|
/// @brief Retract filament from FINDA to PTFE
|
||||||
|
///
|
||||||
|
/// Continuously pull filament by a fixed length (originally 600 steps) + verify FINDA is switched OFF
|
||||||
|
struct RetractFromFinda {
|
||||||
|
/// internal states of the state machine
|
||||||
|
enum {
|
||||||
|
EngagingIdler,
|
||||||
|
UnloadBackToPTFE,
|
||||||
|
OK,
|
||||||
|
Failed
|
||||||
|
};
|
||||||
|
|
||||||
|
inline RetractFromFinda()
|
||||||
|
: state(OK) {}
|
||||||
|
|
||||||
|
/// Restart the automaton
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
/// @returns true if the state machine finished its job, false otherwise
|
||||||
|
bool Step();
|
||||||
|
|
||||||
|
/// This method may be used to check the result of the automaton
|
||||||
|
/// @returns OK if everything went OK and FINDA triggered
|
||||||
|
/// @returns Failed if the FINDA didn't trigger
|
||||||
|
inline uint8_t State() const { return state; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t state;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace logic
|
||||||
|
|
@ -63,26 +63,26 @@ TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
||||||
1500));
|
1500));
|
||||||
// From now on the FINDA is reported as ON
|
// From now on the FINDA is reported as ON
|
||||||
|
|
||||||
// unloading back to PTFE
|
// // unloading back to PTFE
|
||||||
REQUIRE(ff.State() == FeedToFinda::UnloadBackToPTFE);
|
// REQUIRE(ff.State() == FeedToFinda::UnloadBackToPTFE);
|
||||||
REQUIRE(WhileCondition(
|
// REQUIRE(WhileCondition(
|
||||||
ff,
|
// ff,
|
||||||
[&](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).v); // @@TODO constants
|
// CHECK(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(5).v); // @@TODO constants
|
||||||
CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0).v);
|
CHECK(mm::axes[mm::Selector].pos == ms::Selector::SlotPosition(0).v);
|
||||||
|
|
||||||
// state machine finished ok, the green LED should be on
|
// state machine finished ok, the green LED should be blinking
|
||||||
REQUIRE(ff.State() == FeedToFinda::OK);
|
REQUIRE(ff.State() == FeedToFinda::OK);
|
||||||
REQUIRE(ml::leds.Mode(mg::globals.ActiveSlot(), ml::green) == ml::off);
|
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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/feed_to_bondtech.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/feed_to_bondtech.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/load_filament.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/load_filament.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/logic/retract_from_finda.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/debouncer.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/debouncer.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/finda.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/finda.cpp
|
||||||
|
|
|
||||||
|
|
@ -57,23 +57,23 @@ void LoadFilamentSuccessful(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
}
|
}
|
||||||
return lf.TopLevelState() == ProgressCode::FeedingToFinda; },
|
return lf.TopLevelState() == ProgressCode::FeedingToFinda; },
|
||||||
5000));
|
5000));
|
||||||
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToBondtech));
|
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::RetractingFromFinda));
|
||||||
|
|
||||||
// Stage 3 - feeding to bondtech
|
// Stage 3 - retracting from finda
|
||||||
// we'll make a fsensor switch during the process
|
// we'll assume the finda is working correctly here
|
||||||
REQUIRE(WhileCondition(
|
REQUIRE(WhileCondition(
|
||||||
lf,
|
lf,
|
||||||
[&](int step) -> bool {
|
[&](int step) -> bool {
|
||||||
if(step == 100){ // on 100th step make fsensor trigger
|
if(step == 50){ // on 50th step make FINDA trigger
|
||||||
mfs::fsensor.ProcessMessage(true);
|
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
|
||||||
}
|
}
|
||||||
return lf.TopLevelState() == ProgressCode::FeedingToBondtech; },
|
return lf.TopLevelState() == ProgressCode::RetractingFromFinda; },
|
||||||
5000));
|
5000));
|
||||||
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::DisengagingIdler));
|
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::DisengagingIdler));
|
||||||
|
|
||||||
// Stage 4 - disengaging idler
|
// Stage 4 - disengaging idler
|
||||||
REQUIRE(WhileTopState(lf, ProgressCode::DisengagingIdler, idlerEngageDisengageMaxSteps));
|
REQUIRE(WhileTopState(lf, ProgressCode::DisengagingIdler, idlerEngageDisengageMaxSteps));
|
||||||
REQUIRE(VerifyState(lf, true, mi::Idler::IdleSlotIndex(), slot, true, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
|
REQUIRE(VerifyState(lf, true, mi::Idler::IdleSlotIndex(), slot, false, ml::on, ml::off, ErrorCode::OK, ProgressCode::OK));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("load_filament::regular_load_to_slot_0-4", "[load_filament]") {
|
TEST_CASE("load_filament::regular_load_to_slot_0-4", "[load_filament]") {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/feed_to_bondtech.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/feed_to_bondtech.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/load_filament.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/load_filament.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/logic/retract_from_finda.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/tool_change.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/tool_change.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/unload_filament.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/unload_filament.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue