Add Pulley as a Movable module
This PR brings the following improvements: - unifies the error handling of TMC and Homing/Stallguard errors on all motorized modules (Idler, Selector, Pulley) - now we distinguish between Homing and TMC errors + we have a separate handling of these two kinds into CommandBase unified for all motorized modules - adds unit tests to verify the function - fixes SetFINDAStateAndDebounce (didn't obey the press parameter before)pull/154/head
parent
53d285280d
commit
b36e6b99a1
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../modules/finda.h"
|
#include "../modules/finda.h"
|
||||||
#include "../modules/fsensor.h"
|
#include "../modules/fsensor.h"
|
||||||
#include "../modules/idler.h"
|
#include "../modules/idler.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
#include "../modules/selector.h"
|
#include "../modules/selector.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
|
|
@ -15,7 +16,7 @@ inline ErrorCode &operator|=(ErrorCode &a, ErrorCode b) {
|
||||||
return a = (ErrorCode)((uint16_t)a | (uint16_t)b);
|
return a = (ErrorCode)((uint16_t)a | (uint16_t)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ErrorCode TMC2130ToErrorCode(const hal::tmc2130::ErrorFlags &ef, uint8_t tmcIndex) {
|
static ErrorCode TMC2130ToErrorCode(const hal::tmc2130::ErrorFlags &ef) {
|
||||||
ErrorCode e = ErrorCode::RUNNING;
|
ErrorCode e = ErrorCode::RUNNING;
|
||||||
|
|
||||||
if (ef.reset_flag) {
|
if (ef.reset_flag) {
|
||||||
|
|
@ -34,51 +35,101 @@ static ErrorCode TMC2130ToErrorCode(const hal::tmc2130::ErrorFlags &ef, uint8_t
|
||||||
e |= ErrorCode::TMC_OVER_TEMPERATURE_ERROR;
|
e |= ErrorCode::TMC_OVER_TEMPERATURE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e != ErrorCode::RUNNING) {
|
|
||||||
switch (tmcIndex) {
|
|
||||||
case config::Axis::Pulley:
|
|
||||||
e |= ErrorCode::TMC_PULLEY_BIT;
|
|
||||||
break;
|
|
||||||
case config::Axis::Selector:
|
|
||||||
e |= ErrorCode::TMC_SELECTOR_BIT;
|
|
||||||
break;
|
|
||||||
case config::Axis::Idler:
|
|
||||||
e |= ErrorCode::TMC_IDLER_BIT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBase::Step() {
|
static ErrorCode AddErrorAxisBit(ErrorCode ec, uint8_t tmcIndex) {
|
||||||
ErrorCode tmcErr = ErrorCode::RUNNING;
|
switch (tmcIndex) {
|
||||||
// check the global HW errors - may be we should avoid the modules layer and check for the HAL layer errors directly
|
case config::Axis::Pulley:
|
||||||
if (mi::idler.State() == mi::Idler::Failed) {
|
ec |= ErrorCode::TMC_PULLEY_BIT;
|
||||||
state = ProgressCode::ERRTMCFailed;
|
break;
|
||||||
tmcErr |= TMC2130ToErrorCode(mi::idler.TMCErrorFlags(), mm::Axis::Idler);
|
case config::Axis::Selector:
|
||||||
|
ec |= ErrorCode::TMC_SELECTOR_BIT;
|
||||||
|
break;
|
||||||
|
case config::Axis::Idler:
|
||||||
|
ec |= ErrorCode::TMC_IDLER_BIT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (ms::selector.State() == ms::Selector::Failed) {
|
return ec;
|
||||||
state = ProgressCode::ERRTMCFailed;
|
}
|
||||||
tmcErr |= TMC2130ToErrorCode(ms::selector.TMCErrorFlags(), mm::Axis::Selector);
|
|
||||||
}
|
|
||||||
// may be we should model the Pulley as well...
|
|
||||||
// if (ms::selector.State() == ms::Selector::Failed) {
|
|
||||||
// state = ProgressCode::ERRTMCFailed;
|
|
||||||
// error |= TMC2130ToErrorCode(mm::motion.DriverForAxis(mm::Axis::Selector), mm::Axis::Selector);
|
|
||||||
// return true; // the HW error prevents us from continuing with the state machine - the MMU must be restarted/fixed before continuing
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @@TODO not sure how to prevent losing the previously accumulated error ... or do I really need to do it?
|
ErrorCode CheckMovable(mm::MovableBase &m) {
|
||||||
// May be the TMC error word just gets updated with new flags as the motion proceeds
|
switch (m.State()) {
|
||||||
// And how about the logical errors like FINDA_DIDNT_SWITCH_ON?
|
case mm::MovableBase::TMCFailed:
|
||||||
if (tmcErr != ErrorCode::RUNNING) {
|
return AddErrorAxisBit(TMC2130ToErrorCode(m.TMCErrorFlags()), m.Axis());
|
||||||
error |= tmcErr;
|
case mm::MovableBase::HomingFailed:
|
||||||
|
return AddErrorAxisBit(ErrorCode::HOMING_FAILED, m.Axis());
|
||||||
|
}
|
||||||
|
return ErrorCode::RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ErrorCode WithoutAxisBits(ErrorCode ec) {
|
||||||
|
return static_cast<ErrorCode>(
|
||||||
|
static_cast<uint16_t>(ec)
|
||||||
|
& (~(static_cast<uint16_t>(ErrorCode::TMC_SELECTOR_BIT)
|
||||||
|
| static_cast<uint16_t>(ErrorCode::TMC_IDLER_BIT)
|
||||||
|
| static_cast<uint16_t>(ErrorCode::TMC_PULLEY_BIT))));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandBase::WaitForOneModuleErrorRecovery(ErrorCode ec, modules::motion::MovableBase &m) {
|
||||||
|
if (ec != ErrorCode::RUNNING) {
|
||||||
|
if (stateBeforeModuleFailed == ProgressCode::OK) {
|
||||||
|
// a new problem with the movable modules
|
||||||
|
// @@TODO not sure how to prevent losing the previously accumulated error ... or do I really need to do it?
|
||||||
|
// May be the TMC error word just gets updated with new flags as the motion proceeds
|
||||||
|
stateBeforeModuleFailed = state;
|
||||||
|
error = ec;
|
||||||
|
state = ProgressCode::ERRWaitingForUser; // such a situation always requires user's attention -> let the printer display an error screen
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
switch (state) {
|
||||||
|
case ProgressCode::ERRWaitingForUser: // waiting for a recovery - mask axis bits:
|
||||||
|
if (WithoutAxisBits(ec) == ErrorCode::HOMING_FAILED) {
|
||||||
|
// homing can be recovered
|
||||||
|
mui::Event ev = mui::userInput.ConsumeEvent();
|
||||||
|
if (ev == mui::Event::Middle) {
|
||||||
|
m.InvalidateHoming(); // @@TODO invalidate and force initiate a new homing attempt
|
||||||
|
state = ProgressCode::Homing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TMC errors cannot be recovered safely, waiting for power cycling the MMU
|
||||||
|
return true;
|
||||||
|
case ProgressCode::Homing:
|
||||||
|
if (m.HomingValid()) {
|
||||||
|
// managed to recover from a homing problem
|
||||||
|
state = stateBeforeModuleFailed;
|
||||||
|
stateBeforeModuleFailed = ProgressCode::OK;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return true; // no idea what to do in other states ... set internal fw error state?
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandBase::WaitForModulesErrorRecovery() {
|
||||||
|
if (WaitForOneModuleErrorRecovery(CheckMovable(mi::idler), mi::idler))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (WaitForOneModuleErrorRecovery(CheckMovable(ms::selector), ms::selector))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (WaitForOneModuleErrorRecovery(CheckMovable(mp::pulley), mp::pulley))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandBase::Step() {
|
||||||
|
if (WaitForModulesErrorRecovery()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return StepInner();
|
return StepInner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,7 +180,7 @@ bool CommandBase::CheckToolIndex(uint8_t index) {
|
||||||
void CommandBase::ErrDisengagingIdler() {
|
void CommandBase::ErrDisengagingIdler() {
|
||||||
if (!mi::idler.Engaged()) {
|
if (!mi::idler.Engaged()) {
|
||||||
state = ProgressCode::ERRWaitingForUser;
|
state = ProgressCode::ERRWaitingForUser;
|
||||||
mm::motion.Disable(mm::Pulley);
|
mp::pulley.Disable();
|
||||||
mui::userInput.Clear(); // remove all buffered events if any just before we wait for some input
|
mui::userInput.Clear(); // remove all buffered events if any just before we wait for some input
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,12 @@
|
||||||
#include "error_codes.h"
|
#include "error_codes.h"
|
||||||
#include "progress_codes.h"
|
#include "progress_codes.h"
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
namespace motion {
|
||||||
|
class MovableBase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The logic namespace handles the application logic on top of the modules.
|
/// The logic namespace handles the application logic on top of the modules.
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
||||||
|
|
@ -19,7 +25,8 @@ class CommandBase {
|
||||||
public:
|
public:
|
||||||
inline CommandBase()
|
inline CommandBase()
|
||||||
: state(ProgressCode::OK)
|
: state(ProgressCode::OK)
|
||||||
, error(ErrorCode::OK) {}
|
, error(ErrorCode::OK)
|
||||||
|
, stateBeforeModuleFailed(ProgressCode::OK) {}
|
||||||
|
|
||||||
// Normally, a base class should (must) have a virtual destructor to enable correct deallocation of superstructures.
|
// Normally, a base class should (must) have a virtual destructor to enable correct deallocation of superstructures.
|
||||||
// However, in our case we don't want ANY destruction of these objects and moreover - adding a destructor like this
|
// However, in our case we don't want ANY destruction of these objects and moreover - adding a destructor like this
|
||||||
|
|
@ -82,6 +89,15 @@ protected:
|
||||||
/// If not, it returns false and sets the error to ErrorCode::INVALID_TOOL
|
/// If not, it returns false and sets the error to ErrorCode::INVALID_TOOL
|
||||||
bool CheckToolIndex(uint8_t index);
|
bool CheckToolIndex(uint8_t index);
|
||||||
|
|
||||||
|
/// Checks for errors of modules - that includes TMC errors, Idler and Selector errors and possibly more.
|
||||||
|
/// The idea is to check blocking errors at one spot consistently.
|
||||||
|
/// Some of the detected errors can be irrecoverable (i.e. need power cycling the MMU).
|
||||||
|
/// @returns true if waiting for a recovery, false if the state machine can continue.
|
||||||
|
bool WaitForModulesErrorRecovery();
|
||||||
|
|
||||||
|
/// @returns true when still waiting for a module to recover, false otherwise.
|
||||||
|
bool WaitForOneModuleErrorRecovery(ErrorCode iState, modules::motion::MovableBase &m);
|
||||||
|
|
||||||
/// Perform disengaging idler in ErrDisengagingIdler state
|
/// Perform disengaging idler in ErrDisengagingIdler state
|
||||||
void ErrDisengagingIdler();
|
void ErrDisengagingIdler();
|
||||||
|
|
||||||
|
|
@ -93,6 +109,7 @@ protected:
|
||||||
|
|
||||||
ProgressCode state; ///< current progress state of the state machine
|
ProgressCode state; ///< current progress state of the state machine
|
||||||
ErrorCode error; ///< current error code
|
ErrorCode error; ///< current error code
|
||||||
|
ProgressCode stateBeforeModuleFailed; ///< saved state of the state machine before a common error happened
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace logic
|
} // namespace logic
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
#include "../modules/permanent_storage.h"
|
#include "../modules/permanent_storage.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
#include "../modules/selector.h"
|
#include "../modules/selector.h"
|
||||||
|
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
@ -60,7 +61,7 @@ bool CutFilament::StepInner() {
|
||||||
} else {
|
} else {
|
||||||
// unload back to the pulley
|
// unload back to the pulley
|
||||||
state = ProgressCode::UnloadingToPulley;
|
state = ProgressCode::UnloadingToPulley;
|
||||||
mm::motion.PlanMove<mm::Pulley>(-config::cutLength, config::pulleyUnloadFeedrate);
|
mp::pulley.PlanMove(-config::cutLength, config::pulleyUnloadFeedrate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -74,7 +75,7 @@ bool CutFilament::StepInner() {
|
||||||
case ProgressCode::PreparingBlade:
|
case ProgressCode::PreparingBlade:
|
||||||
if (ms::selector.Slot() == cutSlot + 1) {
|
if (ms::selector.Slot() == cutSlot + 1) {
|
||||||
state = ProgressCode::PushingFilament;
|
state = ProgressCode::PushingFilament;
|
||||||
mm::motion.PlanMove<mm::Pulley>(config::cutLength, config::pulleyUnloadFeedrate); //
|
mp::pulley.PlanMove(config::cutLength, config::pulleyUnloadFeedrate); //
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProgressCode::PushingFilament:
|
case ProgressCode::PushingFilament:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
#include "../modules/permanent_storage.h"
|
#include "../modules/permanent_storage.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
#include "../modules/selector.h"
|
#include "../modules/selector.h"
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
|
|
||||||
|
|
@ -53,8 +54,8 @@ bool EjectFilament::StepInner() {
|
||||||
case ProgressCode::ParkingSelector:
|
case ProgressCode::ParkingSelector:
|
||||||
if (mm::motion.QueueEmpty()) { // selector parked aside
|
if (mm::motion.QueueEmpty()) { // selector parked aside
|
||||||
state = ProgressCode::EjectingFilament;
|
state = ProgressCode::EjectingFilament;
|
||||||
mm::motion.InitAxis(mm::Pulley);
|
mp::pulley.InitAxis();
|
||||||
mm::motion.PlanMove<mm::Pulley>(-config::filamentMinLoadedToMMU, config::pulleySlowFeedrate);
|
mp::pulley.PlanMove(-config::filamentMinLoadedToMMU, config::pulleySlowFeedrate);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProgressCode::EjectingFilament:
|
case ProgressCode::EjectingFilament:
|
||||||
|
|
@ -65,7 +66,7 @@ bool EjectFilament::StepInner() {
|
||||||
break;
|
break;
|
||||||
case ProgressCode::DisengagingIdler:
|
case ProgressCode::DisengagingIdler:
|
||||||
if (!mi::idler.Engaged()) { // idler disengaged
|
if (!mi::idler.Engaged()) { // idler disengaged
|
||||||
mm::motion.Disable(mm::Pulley);
|
mp::pulley.Disable();
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::NotLoaded);
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::NotLoaded);
|
||||||
state = ProgressCode::OK;
|
state = ProgressCode::OK;
|
||||||
error = ErrorCode::OK;
|
error = ErrorCode::OK;
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,11 @@ enum class ErrorCode : uint_fast16_t {
|
||||||
|
|
||||||
QUEUE_FULL = 0x802b, ///< E32811 internal logic error - attempt to move with a full queue
|
QUEUE_FULL = 0x802b, ///< E32811 internal logic error - attempt to move with a full queue
|
||||||
|
|
||||||
|
HOMING_FAILED = 0x8007, ///< generic homing failed error - always reported with the corresponding axis bit set (Idler or Selector) as follows:
|
||||||
|
HOMING_SELECTOR_FAILED = HOMING_FAILED | TMC_SELECTOR_BIT, ///< E32903 the Selector was unable to home properly - that means something is blocking its movement
|
||||||
|
HOMING_IDLER_FAILED = HOMING_FAILED | TMC_IDLER_BIT, ///< E33031 the Idler was unable to home properly - that means something is blocking its movement
|
||||||
|
STALLED_PULLEY = HOMING_FAILED | TMC_PULLEY_BIT, ///< E32839 for the Pulley "homing" means just stallguard detected during Pulley's operation (Pulley doesn't home)
|
||||||
|
|
||||||
VERSION_MISMATCH = 0x802c, ///< E32812 internal error of the printer - incompatible version of the MMU FW
|
VERSION_MISMATCH = 0x802c, ///< E32812 internal error of the printer - incompatible version of the MMU FW
|
||||||
PROTOCOL_ERROR = 0x802d, ///< E32813 internal error of the printer - communication with the MMU got garbled - protocol decoder couldn't decode the incoming messages
|
PROTOCOL_ERROR = 0x802d, ///< E32813 internal error of the printer - communication with the MMU got garbled - protocol decoder couldn't decode the incoming messages
|
||||||
MMU_NOT_RESPONDING = 0x802e, ///< E32814 internal error of the printer - communication with the MMU is not working
|
MMU_NOT_RESPONDING = 0x802e, ///< E32814 internal error of the printer - communication with the MMU is not working
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
#include "../modules/permanent_storage.h"
|
#include "../modules/permanent_storage.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
|
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
@ -23,7 +24,7 @@ void logic::FeedToBondtech::GoToPushToNozzle() {
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InFSensor);
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InFSensor);
|
||||||
// plan a slow move to help push filament into the nozzle
|
// plan a slow move to help push filament into the nozzle
|
||||||
//@@TODO the speed in mm/s must correspond to printer's feeding speed!
|
//@@TODO the speed in mm/s must correspond to printer's feeding speed!
|
||||||
mm::motion.PlanMove<mm::Pulley>(config::fsensorToNozzle, config::pulleySlowFeedrate);
|
mp::pulley.PlanMove(config::fsensorToNozzle, config::pulleySlowFeedrate);
|
||||||
state = PushingFilamentIntoNozzle;
|
state = PushingFilamentIntoNozzle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,8 +35,8 @@ bool FeedToBondtech::Step() {
|
||||||
dbg_logic_P(PSTR("Feed to Bondtech --> Idler engaged"));
|
dbg_logic_P(PSTR("Feed to Bondtech --> Idler engaged"));
|
||||||
dbg_logic_fP(PSTR("Pulley start steps %u"), mm::motion.CurPosition(mm::Pulley));
|
dbg_logic_fP(PSTR("Pulley start steps %u"), mm::motion.CurPosition(mm::Pulley));
|
||||||
state = PushingFilamentToFSensor;
|
state = PushingFilamentToFSensor;
|
||||||
mm::motion.InitAxis(mm::Pulley);
|
mp::pulley.InitAxis();
|
||||||
mm::motion.PlanMove<mm::Pulley>(config::defaultBowdenLength, config::pulleyLoadFeedrate, config::pulleySlowFeedrate);
|
mp::pulley.PlanMove(config::defaultBowdenLength, config::pulleyLoadFeedrate, config::pulleySlowFeedrate);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case PushingFilamentToFSensor:
|
case PushingFilamentToFSensor:
|
||||||
|
|
@ -55,7 +56,7 @@ bool FeedToBondtech::Step() {
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
||||||
mi::idler.Disengage();
|
mi::idler.Disengage();
|
||||||
// while disengaging the idler, keep on moving with the pulley to avoid grinding while the printer is trying to grab the filament itself
|
// while disengaging the idler, keep on moving with the pulley to avoid grinding while the printer is trying to grab the filament itself
|
||||||
mm::motion.PlanMove<mm::Pulley>(config::fsensorToNozzleAvoidGrind, config::pulleySlowFeedrate);
|
mp::pulley.PlanMove(config::fsensorToNozzleAvoidGrind, config::pulleySlowFeedrate);
|
||||||
state = DisengagingIdler;
|
state = DisengagingIdler;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -64,7 +65,7 @@ bool FeedToBondtech::Step() {
|
||||||
dbg_logic_P(PSTR("Feed to Bondtech --> Idler disengaged"));
|
dbg_logic_P(PSTR("Feed to Bondtech --> Idler disengaged"));
|
||||||
dbg_logic_fP(PSTR("Pulley end steps %u"), mm::motion.CurPosition(mm::Pulley));
|
dbg_logic_fP(PSTR("Pulley end steps %u"), mm::motion.CurPosition(mm::Pulley));
|
||||||
state = OK;
|
state = OK;
|
||||||
mm::motion.Disable(mm::Pulley);
|
mp::pulley.Disable();
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::on);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::on);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
#include "../modules/permanent_storage.h"
|
#include "../modules/permanent_storage.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
#include "../modules/user_input.h"
|
#include "../modules/user_input.h"
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
@ -29,12 +30,12 @@ bool FeedToFinda::Step() {
|
||||||
dbg_logic_P(PSTR("Feed to Finda --> Idler engaged"));
|
dbg_logic_P(PSTR("Feed to Finda --> Idler engaged"));
|
||||||
dbg_logic_fP(PSTR("Pulley start steps %u"), mm::motion.CurPosition(mm::Pulley));
|
dbg_logic_fP(PSTR("Pulley start steps %u"), mm::motion.CurPosition(mm::Pulley));
|
||||||
state = PushingFilament;
|
state = PushingFilament;
|
||||||
mm::motion.InitAxis(mm::Pulley);
|
mp::pulley.InitAxis();
|
||||||
// @@TODO this may never happen as load filament always assumes the filament is at least at the pulley
|
// @@TODO this may never happen as load filament always assumes the filament is at least at the pulley
|
||||||
// if (mg::globals.FilamentLoaded() == mg::FilamentLoadState::NotLoaded) { // feed slowly filament to PTFE
|
// if (mg::globals.FilamentLoaded() == mg::FilamentLoadState::NotLoaded) { // feed slowly filament to PTFE
|
||||||
// mm::motion.PlanMove<mm::Pulley>(config::filamentMinLoadedToMMU, config::pulleySlowFeedrate);
|
// mp::pulley.PlanMove(config::filamentMinLoadedToMMU, config::pulleySlowFeedrate);
|
||||||
// }
|
// }
|
||||||
mm::motion.PlanMove<mm::Pulley>(config::maximumFeedToFinda, config::pulleySlowFeedrate);
|
mp::pulley.PlanMove(config::maximumFeedToFinda, config::pulleySlowFeedrate);
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InSelector);
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InSelector);
|
||||||
mui::userInput.Clear(); // remove all buffered events if any just before we wait for some input
|
mui::userInput.Clear(); // remove all buffered events if any just before we wait for some input
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
#include "../modules/permanent_storage.h"
|
#include "../modules/permanent_storage.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
#include "../modules/selector.h"
|
#include "../modules/selector.h"
|
||||||
#include "../modules/user_input.h"
|
#include "../modules/user_input.h"
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
|
|
@ -41,7 +42,7 @@ void logic::LoadFilament::FinishedCorrectly() {
|
||||||
state = ProgressCode::OK;
|
state = ProgressCode::OK;
|
||||||
error = ErrorCode::OK;
|
error = ErrorCode::OK;
|
||||||
ml::leds.SetPairButOffOthers(mg::globals.ActiveSlot(), ml::off, ml::off);
|
ml::leds.SetPairButOffOthers(mg::globals.ActiveSlot(), ml::off, ml::off);
|
||||||
mm::motion.Disable(mm::Pulley);
|
mp::pulley.Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadFilament::StepInner() {
|
bool LoadFilament::StepInner() {
|
||||||
|
|
@ -117,7 +118,7 @@ bool LoadFilament::StepInner() {
|
||||||
case ProgressCode::ERREngagingIdler:
|
case ProgressCode::ERREngagingIdler:
|
||||||
if (mi::idler.Engaged()) {
|
if (mi::idler.Engaged()) {
|
||||||
state = ProgressCode::ERRHelpingFilament;
|
state = ProgressCode::ERRHelpingFilament;
|
||||||
mm::motion.PlanMove<mm::Pulley>(config::pulleyHelperMove, config::pulleySlowFeedrate);
|
mp::pulley.PlanMove(config::pulleyHelperMove, config::pulleySlowFeedrate);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case ProgressCode::ERRHelpingFilament:
|
case ProgressCode::ERRHelpingFilament:
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "../modules/idler.h"
|
#include "../modules/idler.h"
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
|
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
@ -22,7 +23,7 @@ bool RetractFromFinda::Step() {
|
||||||
if (mi::idler.Engaged()) {
|
if (mi::idler.Engaged()) {
|
||||||
dbg_logic_fP(PSTR("Pulley start steps %u"), mm::motion.CurPosition(mm::Pulley));
|
dbg_logic_fP(PSTR("Pulley start steps %u"), mm::motion.CurPosition(mm::Pulley));
|
||||||
state = UnloadBackToPTFE;
|
state = UnloadBackToPTFE;
|
||||||
mm::motion.PlanMove<mm::Pulley>(-(config::cuttingEdgeToFindaMidpoint + config::cuttingEdgeRetract), config::pulleyUnloadFeedrate);
|
mp::pulley.PlanMove(-(config::cuttingEdgeToFindaMidpoint + config::cuttingEdgeRetract), config::pulleyUnloadFeedrate);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case UnloadBackToPTFE:
|
case UnloadBackToPTFE:
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
#include "../modules/permanent_storage.h"
|
#include "../modules/permanent_storage.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
#include "../modules/selector.h"
|
#include "../modules/selector.h"
|
||||||
#include "../modules/user_input.h"
|
#include "../modules/user_input.h"
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
|
|
@ -132,7 +133,7 @@ bool ToolChange::StepInner() {
|
||||||
case ProgressCode::ERREngagingIdler:
|
case ProgressCode::ERREngagingIdler:
|
||||||
if (mi::idler.Engaged()) {
|
if (mi::idler.Engaged()) {
|
||||||
state = ProgressCode::ERRHelpingFilament;
|
state = ProgressCode::ERRHelpingFilament;
|
||||||
mm::motion.PlanMove<mm::Pulley>(config::pulleyHelperMove, config::pulleySlowFeedrate);
|
mp::pulley.PlanMove(config::pulleyHelperMove, config::pulleySlowFeedrate);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case ProgressCode::ERRHelpingFilament:
|
case ProgressCode::ERRHelpingFilament:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
#include "../modules/permanent_storage.h"
|
#include "../modules/permanent_storage.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
#include "../modules/selector.h"
|
#include "../modules/selector.h"
|
||||||
#include "../modules/user_input.h"
|
#include "../modules/user_input.h"
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
|
|
@ -24,7 +25,7 @@ void UnloadFilament::Reset(uint8_t /*param*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// unloads filament from extruder - filament is above Bondtech gears
|
// unloads filament from extruder - filament is above Bondtech gears
|
||||||
mm::motion.InitAxis(mm::Pulley);
|
mp::pulley.InitAxis();
|
||||||
state = ProgressCode::UnloadingToFinda;
|
state = ProgressCode::UnloadingToFinda;
|
||||||
error = ErrorCode::RUNNING;
|
error = ErrorCode::RUNNING;
|
||||||
unl.Reset(maxRetries);
|
unl.Reset(maxRetries);
|
||||||
|
|
@ -34,7 +35,7 @@ void UnloadFilament::Reset(uint8_t /*param*/) {
|
||||||
void UnloadFilament::FinishedCorrectly() {
|
void UnloadFilament::FinishedCorrectly() {
|
||||||
state = ProgressCode::OK;
|
state = ProgressCode::OK;
|
||||||
error = ErrorCode::OK;
|
error = ErrorCode::OK;
|
||||||
mm::motion.Disable(mm::Pulley);
|
mp::pulley.Disable();
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::AtPulley); // filament unloaded
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::AtPulley); // filament unloaded
|
||||||
ml::leds.SetPairButOffOthers(mg::globals.ActiveSlot(), ml::off, ml::off);
|
ml::leds.SetPairButOffOthers(mg::globals.ActiveSlot(), ml::off, ml::off);
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +133,7 @@ bool UnloadFilament::StepInner() {
|
||||||
case ProgressCode::ERREngagingIdler:
|
case ProgressCode::ERREngagingIdler:
|
||||||
if (mi::idler.Engaged()) {
|
if (mi::idler.Engaged()) {
|
||||||
state = ProgressCode::ERRHelpingFilament;
|
state = ProgressCode::ERRHelpingFilament;
|
||||||
mm::motion.PlanMove<mm::Pulley>(-config::pulleyHelperMove, config::pulleySlowFeedrate);
|
mp::pulley.PlanMove(-config::pulleyHelperMove, config::pulleySlowFeedrate);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case ProgressCode::ERRHelpingFilament:
|
case ProgressCode::ERRHelpingFilament:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../modules/leds.h"
|
#include "../modules/leds.h"
|
||||||
#include "../modules/motion.h"
|
#include "../modules/motion.h"
|
||||||
#include "../modules/permanent_storage.h"
|
#include "../modules/permanent_storage.h"
|
||||||
|
#include "../modules/pulley.h"
|
||||||
|
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
||||||
|
|
@ -32,7 +33,7 @@ bool UnloadToFinda::Step() {
|
||||||
case EngagingIdler:
|
case EngagingIdler:
|
||||||
if (mg::globals.FilamentLoaded() >= mg::FilamentLoadState::InSelector) {
|
if (mg::globals.FilamentLoaded() >= mg::FilamentLoadState::InSelector) {
|
||||||
state = UnloadingToFinda;
|
state = UnloadingToFinda;
|
||||||
mm::motion.InitAxis(mm::Pulley);
|
mp::pulley.InitAxis();
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::blink0);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::blink0);
|
||||||
} else {
|
} else {
|
||||||
state = FailedFINDA;
|
state = FailedFINDA;
|
||||||
|
|
@ -42,8 +43,8 @@ bool UnloadToFinda::Step() {
|
||||||
if (mi::idler.Engaged()) {
|
if (mi::idler.Engaged()) {
|
||||||
state = WaitingForFINDA;
|
state = WaitingForFINDA;
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InSelector);
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InSelector);
|
||||||
unloadStart_mm = CurrentPositionPulley_mm();
|
unloadStart_mm = mp::pulley.CurrentPositionPulley_mm();
|
||||||
mm::motion.PlanMove<mm::Pulley>(-config::defaultBowdenLength - config::feedToFinda - config::filamentMinLoadedToMMU, config::pulleyUnloadFeedrate);
|
mp::pulley.PlanMove(-config::defaultBowdenLength - config::feedToFinda - config::filamentMinLoadedToMMU, config::pulleyUnloadFeedrate);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case WaitingForFINDA: {
|
case WaitingForFINDA: {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ target_sources(
|
||||||
motion.cpp
|
motion.cpp
|
||||||
movable_base.cpp
|
movable_base.cpp
|
||||||
permanent_storage.cpp
|
permanent_storage.cpp
|
||||||
|
pulley.cpp
|
||||||
pulse_gen.cpp
|
pulse_gen.cpp
|
||||||
selector.cpp
|
selector.cpp
|
||||||
speed_table.cpp
|
speed_table.cpp
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ void Idler::FinishHomingAndPlanMoveToParkPos() {
|
||||||
if (!plannedEngage) {
|
if (!plannedEngage) {
|
||||||
plannedSlot = IdleSlotIndex();
|
plannedSlot = IdleSlotIndex();
|
||||||
}
|
}
|
||||||
InitMovement(mm::Idler);
|
InitMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Idler::FinishMove() {
|
void Idler::FinishMove() {
|
||||||
|
|
@ -48,7 +48,7 @@ Idler::OperationResult Idler::Disengage() {
|
||||||
|
|
||||||
// coordinates invalid, first home, then disengage
|
// coordinates invalid, first home, then disengage
|
||||||
if (!homingValid) {
|
if (!homingValid) {
|
||||||
PerformHome(mm::Idler);
|
PerformHome();
|
||||||
return OperationResult::Accepted;
|
return OperationResult::Accepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ Idler::OperationResult Idler::Disengage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// disengaging
|
// disengaging
|
||||||
return InitMovement(mm::Idler);
|
return InitMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
Idler::OperationResult Idler::Engage(uint8_t slot) {
|
Idler::OperationResult Idler::Engage(uint8_t slot) {
|
||||||
|
|
@ -81,7 +81,7 @@ Idler::OperationResult Idler::Engage(uint8_t slot) {
|
||||||
// so rebooting the MMU while the printer is printing (and thus holding the filament by the moving Idler)
|
// so rebooting the MMU while the printer is printing (and thus holding the filament by the moving Idler)
|
||||||
// should not be an issue
|
// should not be an issue
|
||||||
if (!homingValid) {
|
if (!homingValid) {
|
||||||
PlanHome(mm::Idler);
|
PlanHome();
|
||||||
return OperationResult::Accepted;
|
return OperationResult::Accepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,26 +92,26 @@ Idler::OperationResult Idler::Engage(uint8_t slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// engaging
|
// engaging
|
||||||
return InitMovement(mm::Idler);
|
return InitMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Idler::Step() {
|
bool Idler::Step() {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Moving:
|
case Moving:
|
||||||
// dbg_logic_P(PSTR("Moving Idler"));
|
// dbg_logic_P(PSTR("Moving Idler"));
|
||||||
PerformMove(mm::Idler);
|
PerformMove();
|
||||||
return false;
|
return false;
|
||||||
case Homing:
|
case Homing:
|
||||||
dbg_logic_P(PSTR("Homing Idler"));
|
dbg_logic_P(PSTR("Homing Idler"));
|
||||||
PerformHome(mm::Idler);
|
PerformHome();
|
||||||
return false;
|
return false;
|
||||||
case Ready:
|
case Ready:
|
||||||
if (!homingValid && mg::globals.FilamentLoaded() < mg::InFSensor) {
|
if (!homingValid && mg::globals.FilamentLoaded() < mg::InFSensor) {
|
||||||
PlanHome(mm::Idler);
|
PlanHome();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case Failed:
|
case TMCFailed:
|
||||||
dbg_logic_P(PSTR("Idler Failed"));
|
dbg_logic_P(PSTR("Idler Failed"));
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -121,7 +121,7 @@ bool Idler::Step() {
|
||||||
void Idler::Init() {
|
void Idler::Init() {
|
||||||
if (mg::globals.FilamentLoaded() < mg::InFSensor) {
|
if (mg::globals.FilamentLoaded() < mg::InFSensor) {
|
||||||
// home the Idler only in case we don't have filament loaded in the printer (or at least we think we don't)
|
// home the Idler only in case we don't have filament loaded in the printer (or at least we think we don't)
|
||||||
PlanHome(mm::Idler);
|
PlanHome();
|
||||||
} else {
|
} else {
|
||||||
// otherwise assume the Idler is at its idle position (that's where it usually is)
|
// otherwise assume the Idler is at its idle position (that's where it usually is)
|
||||||
mm::motion.SetPosition(mm::Idler, SlotPosition(IdleSlotIndex()).v);
|
mm::motion.SetPosition(mm::Idler, SlotPosition(IdleSlotIndex()).v);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace mm = modules::motion;
|
||||||
class Idler : public motion::MovableBase {
|
class Idler : public motion::MovableBase {
|
||||||
public:
|
public:
|
||||||
inline constexpr Idler()
|
inline constexpr Idler()
|
||||||
: MovableBase()
|
: MovableBase(mm::Idler)
|
||||||
, plannedEngage(false)
|
, plannedEngage(false)
|
||||||
, currentlyEngaged(false) {}
|
, currentlyEngaged(false) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
namespace modules {
|
namespace modules {
|
||||||
namespace motion {
|
namespace motion {
|
||||||
|
|
||||||
void MovableBase::PlanHome(config::Axis axis) {
|
void MovableBase::PlanHome() {
|
||||||
// switch to normal mode on this axis
|
// switch to normal mode on this axis
|
||||||
mm::motion.InitAxis(axis);
|
mm::motion.InitAxis(axis);
|
||||||
mm::motion.SetMode(axis, mm::Normal);
|
mm::motion.SetMode(axis, mm::Normal);
|
||||||
|
|
@ -17,22 +17,22 @@ void MovableBase::PlanHome(config::Axis axis) {
|
||||||
state = Homing;
|
state = Homing;
|
||||||
}
|
}
|
||||||
|
|
||||||
MovableBase::OperationResult MovableBase::InitMovement(config::Axis axis) {
|
MovableBase::OperationResult MovableBase::InitMovement() {
|
||||||
if (motion.InitAxis(axis)) {
|
if (motion.InitAxis(axis)) {
|
||||||
PrepareMoveToPlannedSlot();
|
PrepareMoveToPlannedSlot();
|
||||||
state = Moving;
|
state = Moving;
|
||||||
return OperationResult::Accepted;
|
return OperationResult::Accepted;
|
||||||
} else {
|
} else {
|
||||||
state = Failed;
|
state = TMCFailed;
|
||||||
return OperationResult::Failed;
|
return OperationResult::Failed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovableBase::PerformMove(config::Axis axis) {
|
void MovableBase::PerformMove() {
|
||||||
if (!mm::motion.DriverForAxis(axis).GetErrorFlags().Good()) { // @@TODO check occasionally, i.e. not every time?
|
if (!mm::motion.DriverForAxis(axis).GetErrorFlags().Good()) { // @@TODO check occasionally, i.e. not every time?
|
||||||
// TMC2130 entered some error state, the planned move couldn't have been finished - result of operation is Failed
|
// TMC2130 entered some error state, the planned move couldn't have been finished - result of operation is Failed
|
||||||
tmcErrorFlags = mm::motion.DriverForAxis(axis).GetErrorFlags(); // save the failed state
|
tmcErrorFlags = mm::motion.DriverForAxis(axis).GetErrorFlags(); // save the failed state
|
||||||
state = Failed;
|
state = TMCFailed;
|
||||||
} else if (mm::motion.QueueEmpty(axis)) {
|
} else if (mm::motion.QueueEmpty(axis)) {
|
||||||
// move finished
|
// move finished
|
||||||
currentSlot = plannedSlot;
|
currentSlot = plannedSlot;
|
||||||
|
|
@ -41,7 +41,7 @@ void MovableBase::PerformMove(config::Axis axis) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovableBase::PerformHome(config::Axis axis) {
|
void MovableBase::PerformHome() {
|
||||||
if (mm::motion.StallGuard(axis)) {
|
if (mm::motion.StallGuard(axis)) {
|
||||||
// we have reached the end of the axis - homed ok
|
// we have reached the end of the axis - homed ok
|
||||||
mm::motion.AbortPlannedMoves(axis, true);
|
mm::motion.AbortPlannedMoves(axis, true);
|
||||||
|
|
@ -53,7 +53,7 @@ void MovableBase::PerformHome(config::Axis axis) {
|
||||||
// we ran out of planned moves but no StallGuard event has occurred - homing failed
|
// we ran out of planned moves but no StallGuard event has occurred - homing failed
|
||||||
homingValid = false;
|
homingValid = false;
|
||||||
mm::motion.SetMode(axis, mg::globals.MotorsStealth() ? mm::Stealth : mm::Normal);
|
mm::motion.SetMode(axis, mg::globals.MotorsStealth() ? mm::Stealth : mm::Normal);
|
||||||
state = Failed;
|
state = HomingFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ public:
|
||||||
Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code
|
Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code
|
||||||
Moving,
|
Moving,
|
||||||
Homing,
|
Homing,
|
||||||
Failed
|
TMCFailed,
|
||||||
|
HomingFailed
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Operation (Engage/Disengage/MoveToSlot) return values
|
/// Operation (Engage/Disengage/MoveToSlot) return values
|
||||||
|
|
@ -25,11 +26,12 @@ public:
|
||||||
Failed ///< the operation could not been started due to HW issues
|
Failed ///< the operation could not been started due to HW issues
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr MovableBase()
|
inline constexpr MovableBase(config::Axis axis)
|
||||||
: state(Ready)
|
: state(Ready)
|
||||||
, plannedSlot(-1)
|
, plannedSlot(-1)
|
||||||
, currentSlot(-1)
|
, currentSlot(-1)
|
||||||
, homingValid(false) {}
|
, homingValid(false)
|
||||||
|
, axis(axis) {}
|
||||||
|
|
||||||
/// virtual ~MovableBase(); intentionally disabled, see description in logic::CommandBase
|
/// virtual ~MovableBase(); intentionally disabled, see description in logic::CommandBase
|
||||||
|
|
||||||
|
|
@ -55,6 +57,10 @@ public:
|
||||||
/// (which makes homing completely transparent)
|
/// (which makes homing completely transparent)
|
||||||
inline void InvalidateHoming() { homingValid = false; }
|
inline void InvalidateHoming() { homingValid = false; }
|
||||||
|
|
||||||
|
inline bool HomingValid() const { return homingValid; }
|
||||||
|
|
||||||
|
inline config::Axis Axis() const { return axis; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// internal state of the automaton
|
/// internal state of the automaton
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
|
|
@ -71,19 +77,21 @@ protected:
|
||||||
/// cached TMC2130 error flags - being read only if the axis is enabled and doing something (moving)
|
/// cached TMC2130 error flags - being read only if the axis is enabled and doing something (moving)
|
||||||
hal::tmc2130::ErrorFlags tmcErrorFlags;
|
hal::tmc2130::ErrorFlags tmcErrorFlags;
|
||||||
|
|
||||||
|
config::Axis axis;
|
||||||
|
|
||||||
virtual void PrepareMoveToPlannedSlot() = 0;
|
virtual void PrepareMoveToPlannedSlot() = 0;
|
||||||
virtual void PlanHomingMove() = 0;
|
virtual void PlanHomingMove() = 0;
|
||||||
virtual void FinishHomingAndPlanMoveToParkPos() = 0;
|
virtual void FinishHomingAndPlanMoveToParkPos() = 0;
|
||||||
virtual void FinishMove() = 0;
|
virtual void FinishMove() = 0;
|
||||||
|
|
||||||
OperationResult InitMovement(config::Axis axis);
|
OperationResult InitMovement();
|
||||||
|
|
||||||
/// Prepare a homing move of the axis
|
/// Prepare a homing move of the axis
|
||||||
void PlanHome(config::Axis axis);
|
void PlanHome();
|
||||||
|
|
||||||
void PerformMove(config::Axis axis);
|
void PerformMove();
|
||||||
|
|
||||||
void PerformHome(config::Axis axis);
|
void PerformHome();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace motion
|
} // namespace motion
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/// @file pulley.cpp
|
||||||
|
#include "pulley.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
#include "globals.h"
|
||||||
|
#include "leds.h"
|
||||||
|
#include "motion.h"
|
||||||
|
#include "permanent_storage.h"
|
||||||
|
#include "../debug.h"
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
namespace pulley {
|
||||||
|
|
||||||
|
Pulley pulley;
|
||||||
|
|
||||||
|
void Pulley::FinishHomingAndPlanMoveToParkPos() {
|
||||||
|
mm::motion.SetPosition(mm::Pulley, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Pulley::Step() {
|
||||||
|
switch (state) {
|
||||||
|
case Moving:
|
||||||
|
PerformMove();
|
||||||
|
return false;
|
||||||
|
case Homing:
|
||||||
|
homingValid = true;
|
||||||
|
FinishHomingAndPlanMoveToParkPos();
|
||||||
|
return true;
|
||||||
|
case Ready:
|
||||||
|
return true;
|
||||||
|
case TMCFailed:
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pulley::PlanMove(unit::U_mm delta, unit::U_mm_s feed_rate, unit::U_mm_s end_rate) {
|
||||||
|
mm::motion.PlanMove<mm::Pulley>(delta, feed_rate, end_rate);
|
||||||
|
state = Moving;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Pulley::CurrentPositionPulley_mm() {
|
||||||
|
return mm::stepsToUnit<mm::P_pos_t>(mm::P_pos_t({ mm::motion.CurPosition(mm::Pulley) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pulley::InitAxis() {
|
||||||
|
mm::motion.InitAxis(mm::Pulley);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pulley::Disable() {
|
||||||
|
mm::motion.Disable(mm::Pulley);
|
||||||
|
state = Ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pulley
|
||||||
|
} // namespace modules
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/// @file pulley.h
|
||||||
|
#pragma once
|
||||||
|
#include "../config/config.h"
|
||||||
|
#include "axisunit.h"
|
||||||
|
#include "../unit.h"
|
||||||
|
#include "movable_base.h"
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
|
||||||
|
/// The pulley namespace provides all necessary facilities related to the logical model of the pulley device of the MMU unit.
|
||||||
|
namespace pulley {
|
||||||
|
|
||||||
|
namespace mm = modules::motion;
|
||||||
|
|
||||||
|
/// The Pulley model is an analogy to Idler and Selector.
|
||||||
|
/// It encapsulates the same error handling principles like the other two (motored) modules.
|
||||||
|
/// On the other hand - the Pulley is much simpler, there is no homing, engage/disengage and slots,
|
||||||
|
/// but it supports free rotation in either directions and some computation on top of it.
|
||||||
|
class Pulley : public motion::MovableBase {
|
||||||
|
public:
|
||||||
|
inline constexpr Pulley()
|
||||||
|
: MovableBase(mm::Pulley) {}
|
||||||
|
|
||||||
|
/// Performs one step of the state machine according to currently planned operation
|
||||||
|
/// @returns true if the pulley is ready to accept new commands (i.e. it has finished the last operation)
|
||||||
|
bool Step();
|
||||||
|
|
||||||
|
void PlanMove(unit::U_mm delta, unit::U_mm_s feed_rate, unit::U_mm_s end_rate = { 0 });
|
||||||
|
|
||||||
|
/// @returns rounded current position (rotation) of the Pulley
|
||||||
|
/// This exists purely to avoid expensive float (long double) computations of distance traveled by the filament
|
||||||
|
int32_t CurrentPositionPulley_mm();
|
||||||
|
|
||||||
|
void InitAxis();
|
||||||
|
void Disable();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void PrepareMoveToPlannedSlot() override {}
|
||||||
|
virtual void PlanHomingMove() override {}
|
||||||
|
virtual void FinishHomingAndPlanMoveToParkPos() override;
|
||||||
|
virtual void FinishMove() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The one and only instance of Pulley in the FW
|
||||||
|
extern Pulley pulley;
|
||||||
|
|
||||||
|
} // namespace pulley
|
||||||
|
} // namespace modules
|
||||||
|
|
||||||
|
namespace mp = modules::pulley;
|
||||||
|
|
@ -31,7 +31,7 @@ void Selector::FinishHomingAndPlanMoveToParkPos() {
|
||||||
if (plannedSlot > config::toolCount) {
|
if (plannedSlot > config::toolCount) {
|
||||||
plannedSlot = IdleSlotIndex();
|
plannedSlot = IdleSlotIndex();
|
||||||
}
|
}
|
||||||
InitMovement(mm::Selector);
|
InitMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Selector::FinishMove() {
|
void Selector::FinishMove() {
|
||||||
|
|
@ -52,7 +52,7 @@ Selector::OperationResult Selector::MoveToSlot(uint8_t slot) {
|
||||||
|
|
||||||
// coordinates invalid, first home, then engage
|
// coordinates invalid, first home, then engage
|
||||||
if (!homingValid && mg::globals.FilamentLoaded() < mg::FilamentLoadState::InSelector) {
|
if (!homingValid && mg::globals.FilamentLoaded() < mg::FilamentLoadState::InSelector) {
|
||||||
PlanHome(mm::Selector);
|
PlanHome();
|
||||||
return OperationResult::Accepted;
|
return OperationResult::Accepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,26 +63,26 @@ Selector::OperationResult Selector::MoveToSlot(uint8_t slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// do the move
|
// do the move
|
||||||
return InitMovement(mm::Selector);
|
return InitMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Selector::Step() {
|
bool Selector::Step() {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Moving:
|
case Moving:
|
||||||
PerformMove(mm::Selector);
|
PerformMove();
|
||||||
//dbg_logic_P(PSTR("Moving Selector"));
|
//dbg_logic_P(PSTR("Moving Selector"));
|
||||||
return false;
|
return false;
|
||||||
case Homing:
|
case Homing:
|
||||||
dbg_logic_P(PSTR("Homing Selector"));
|
dbg_logic_P(PSTR("Homing Selector"));
|
||||||
PerformHome(mm::Selector);
|
PerformHome();
|
||||||
return false;
|
return false;
|
||||||
case Ready:
|
case Ready:
|
||||||
if (!homingValid && mg::globals.FilamentLoaded() < mg::InSelector) {
|
if (!homingValid && mg::globals.FilamentLoaded() < mg::InSelector) {
|
||||||
PlanHome(mm::Selector);
|
PlanHome();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case Failed:
|
case TMCFailed:
|
||||||
dbg_logic_P(PSTR("Selector Failed"));
|
dbg_logic_P(PSTR("Selector Failed"));
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -92,7 +92,7 @@ bool Selector::Step() {
|
||||||
void Selector::Init() {
|
void Selector::Init() {
|
||||||
if (mg::globals.FilamentLoaded() < mg::FilamentLoadState::InSelector && (!mf::finda.Pressed())) {
|
if (mg::globals.FilamentLoaded() < mg::FilamentLoadState::InSelector && (!mf::finda.Pressed())) {
|
||||||
// home the Selector only in case we don't have filament loaded (or at least we think we don't)
|
// home the Selector only in case we don't have filament loaded (or at least we think we don't)
|
||||||
PlanHome(mm::Selector);
|
PlanHome();
|
||||||
} else {
|
} else {
|
||||||
// otherwise set selector's position according to know slot positions (and pretend it is correct)
|
// otherwise set selector's position according to know slot positions (and pretend it is correct)
|
||||||
mm::motion.SetPosition(mm::Selector, SlotPosition(mg::globals.ActiveSlot()).v);
|
mm::motion.SetPosition(mm::Selector, SlotPosition(mg::globals.ActiveSlot()).v);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace mm = modules::motion;
|
||||||
class Selector : public mm::MovableBase {
|
class Selector : public mm::MovableBase {
|
||||||
public:
|
public:
|
||||||
inline constexpr Selector()
|
inline constexpr Selector()
|
||||||
: MovableBase() {}
|
: MovableBase(mm::Selector) {}
|
||||||
|
|
||||||
/// Plan move of the selector to a specific filament slot
|
/// Plan move of the selector to a specific filament slot
|
||||||
/// @param slot index to move to
|
/// @param slot index to move to
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ add_executable(
|
||||||
failing_tmc_tests
|
failing_tmc_tests
|
||||||
${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/command_base.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/retract_from_finda.cpp
|
${CMAKE_SOURCE_DIR}/src/logic/retract_from_finda.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
|
||||||
|
|
@ -15,6 +16,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "../../../../src/modules/selector.h"
|
#include "../../../../src/modules/selector.h"
|
||||||
|
|
||||||
#include "../../../../src/logic/unload_filament.h"
|
#include "../../../../src/logic/unload_filament.h"
|
||||||
|
#include "../../../../src/logic/load_filament.h"
|
||||||
|
|
||||||
#include "../../modules/stubs/stub_adc.h"
|
#include "../../modules/stubs/stub_adc.h"
|
||||||
|
|
||||||
|
|
@ -34,7 +35,7 @@ inline ErrorCode operator|(ErrorCode a, ErrorCode b) {
|
||||||
return (ErrorCode)((uint16_t)a | (uint16_t)b);
|
return (ErrorCode)((uint16_t)a | (uint16_t)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FailingIdler(hal::tmc2130::ErrorFlags ef, ErrorCode ec) {
|
void FailingMovableUnload(hal::tmc2130::ErrorFlags ef, ErrorCode ec, config::Axis axis, uint32_t failingStep) {
|
||||||
// prepare startup conditions
|
// prepare startup conditions
|
||||||
ForceReinitAllAutomata();
|
ForceReinitAllAutomata();
|
||||||
|
|
||||||
|
|
@ -54,15 +55,14 @@ void FailingIdler(hal::tmc2130::ErrorFlags ef, ErrorCode ec) {
|
||||||
|
|
||||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), 0, true, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingToFinda));
|
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), 0, true, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingToFinda));
|
||||||
|
|
||||||
uint32_t failingStep = 5;
|
|
||||||
REQUIRE(WhileCondition(
|
REQUIRE(WhileCondition(
|
||||||
uf,
|
uf,
|
||||||
[&](uint32_t step) -> bool {
|
[&](uint32_t step) -> bool {
|
||||||
if(step == failingStep){ // on 5th step make the TMC report some error
|
if(step == failingStep){ // on 5th step make the TMC report some error
|
||||||
CauseTMCError(mm::Idler, ef);
|
CauseTMCError(axis, ef);
|
||||||
}
|
}
|
||||||
return uf.TopLevelState() == ProgressCode::UnloadingToFinda; },
|
return uf.TopLevelState() == ProgressCode::UnloadingToFinda; },
|
||||||
5000));
|
50000));
|
||||||
|
|
||||||
// the simulated motion may proceed, but I don't care here. In reality no one really knows what the TMC does
|
// the simulated motion may proceed, but I don't care here. In reality no one really knows what the TMC does
|
||||||
// The checked value is not really important here (just that it moves!), so with tuning of the constants it may break the unit test
|
// The checked value is not really important here (just that it moves!), so with tuning of the constants it may break the unit test
|
||||||
|
|
@ -78,15 +78,75 @@ void FailingIdler(hal::tmc2130::ErrorFlags ef, ErrorCode ec) {
|
||||||
REQUIRE(ml::leds.Mode(0, ml::red) == ml::off);
|
REQUIRE(ml::leds.Mode(0, ml::red) == ml::off);
|
||||||
REQUIRE(ml::leds.Mode(0, ml::green) == ml::blink0);
|
REQUIRE(ml::leds.Mode(0, ml::green) == ml::blink0);
|
||||||
REQUIRE(uf.Error() == ec);
|
REQUIRE(uf.Error() == ec);
|
||||||
REQUIRE(uf.TopLevelState() == ProgressCode::ERRTMCFailed);
|
REQUIRE(uf.TopLevelState() == ProgressCode::ERRWaitingForUser);
|
||||||
|
|
||||||
main_loop();
|
main_loop();
|
||||||
uf.Step();
|
uf.Step();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FailingMovableLoad(hal::tmc2130::ErrorFlags ef, ErrorCode ec, config::Axis axis, uint32_t failingStep, uint8_t slot) {
|
||||||
|
// prepare startup conditions
|
||||||
|
ForceReinitAllAutomata();
|
||||||
|
|
||||||
|
// change the startup to what we need here
|
||||||
|
EnsureActiveSlotIndex(5, mg::FilamentLoadState::AtPulley);
|
||||||
|
|
||||||
|
// set FINDA OFF + debounce
|
||||||
|
SetFINDAStateAndDebounce(false);
|
||||||
|
|
||||||
|
logic::LoadFilament lf;
|
||||||
|
|
||||||
|
// verify startup conditions
|
||||||
|
REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), ms::Selector::IdleSlotIndex(), false, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
|
||||||
|
|
||||||
|
// UnloadFilament starts by engaging the idler (through the UnloadToFinda state machine)
|
||||||
|
lf.Reset(slot);
|
||||||
|
|
||||||
|
REQUIRE(WhileCondition(
|
||||||
|
lf,
|
||||||
|
[&](uint32_t step) -> bool {
|
||||||
|
if(step == failingStep){ // on 5th step make the TMC report some error
|
||||||
|
CauseTMCError(axis, ef);
|
||||||
|
}
|
||||||
|
return lf.TopLevelState() == ProgressCode::FeedingToFinda; },
|
||||||
|
50000));
|
||||||
|
|
||||||
|
// the simulated motion may proceed, but I don't care here. In reality no one really knows what the TMC does
|
||||||
|
// The checked value is not really important here (just that it moves!), so with tuning of the constants it may break the unit test
|
||||||
|
// Therefore it is disabled by default
|
||||||
|
// REQUIRE(mm::axes[mm::Idler].pos == failingStep * config::pulleyToCuttingEdge.v + 1);
|
||||||
|
|
||||||
|
// repeated calls to step this logic automaton shall produce no change
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
// and this must cause the state machine to run into a TMC error state and report the error correctly
|
||||||
|
// Please note we are leaving the Idler in an intermediate position due to the TMC failure,
|
||||||
|
// so we cannot use the usual VerifyState(), but have to check the stuff manually
|
||||||
|
// REQUIRE(VerifyState(uf, true, raw_6, 0, false, ml::blink0, ml::blink0, ec, ProgressCode::ERRTMCFailed));
|
||||||
|
REQUIRE(ml::leds.Mode(0, ml::red) == ml::off);
|
||||||
|
REQUIRE(ml::leds.Mode(0, ml::green) == ml::blink0);
|
||||||
|
REQUIRE(lf.Error() == ec);
|
||||||
|
REQUIRE(lf.TopLevelState() == ProgressCode::ERRWaitingForUser);
|
||||||
|
|
||||||
|
main_loop();
|
||||||
|
lf.Step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("failing_tmc::failing_idler", "[failing_tmc]") {
|
TEST_CASE("failing_tmc::failing_idler", "[failing_tmc]") {
|
||||||
hal::tmc2130::ErrorFlags ef;
|
hal::tmc2130::ErrorFlags ef;
|
||||||
ef.ot = 1; // make the TMC hot like hell
|
ef.ot = 1; // make the TMC hot like hell
|
||||||
FailingIdler(ef, ErrorCode::TMC_OVER_TEMPERATURE_ERROR | ErrorCode::TMC_IDLER_BIT);
|
FailingMovableUnload(ef, ErrorCode::TMC_OVER_TEMPERATURE_ERROR | ErrorCode::TMC_IDLER_BIT, mm::Idler, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("failing_tmc::failing_selector", "[failing_tmc]") {
|
||||||
|
hal::tmc2130::ErrorFlags ef;
|
||||||
|
ef.ot = 1; // make the TMC hot like hell
|
||||||
|
FailingMovableLoad(ef, ErrorCode::TMC_OVER_TEMPERATURE_ERROR | ErrorCode::TMC_SELECTOR_BIT, mm::Selector, 5, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("failing_tmc::failing_pulley", "[failing_tmc]") {
|
||||||
|
hal::tmc2130::ErrorFlags ef;
|
||||||
|
ef.ot = 1; // make the TMC hot like hell
|
||||||
|
FailingMovableUnload(ef, ErrorCode::TMC_OVER_TEMPERATURE_ERROR | ErrorCode::TMC_PULLEY_BIT, mm::Pulley, 2000);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include "../../../../src/modules/leds.h"
|
#include "../../../../src/modules/leds.h"
|
||||||
#include "../../../../src/modules/motion.h"
|
#include "../../../../src/modules/motion.h"
|
||||||
#include "../../../../src/modules/permanent_storage.h"
|
#include "../../../../src/modules/permanent_storage.h"
|
||||||
|
#include "../../../../src/modules/pulley.h"
|
||||||
#include "../../../../src/modules/selector.h"
|
#include "../../../../src/modules/selector.h"
|
||||||
#include "../../../../src/modules/user_input.h"
|
#include "../../../../src/modules/user_input.h"
|
||||||
|
|
||||||
|
|
@ -26,6 +27,7 @@ void main_loop() {
|
||||||
mf::finda.Step();
|
mf::finda.Step();
|
||||||
mfs::fsensor.Step();
|
mfs::fsensor.Step();
|
||||||
mi::idler.Step();
|
mi::idler.Step();
|
||||||
|
mp::pulley.Step();
|
||||||
ms::selector.Step();
|
ms::selector.Step();
|
||||||
mm::motion.Step();
|
mm::motion.Step();
|
||||||
mui::userInput.Step();
|
mui::userInput.Step();
|
||||||
|
|
@ -50,6 +52,7 @@ void ForceReinitAllAutomata() {
|
||||||
new (&mf::finda) mf::FINDA();
|
new (&mf::finda) mf::FINDA();
|
||||||
new (&mfs::fsensor) mfs::FSensor();
|
new (&mfs::fsensor) mfs::FSensor();
|
||||||
new (&mi::idler) mi::Idler();
|
new (&mi::idler) mi::Idler();
|
||||||
|
new (&mp::pulley) mp::Pulley();
|
||||||
new (&ms::selector) ms::Selector();
|
new (&ms::selector) ms::Selector();
|
||||||
new (&mm::motion) mm::Motion();
|
new (&mm::motion) mm::Motion();
|
||||||
|
|
||||||
|
|
@ -137,7 +140,7 @@ void EnsureActiveSlotIndex(uint8_t slot, mg::FilamentLoadState loadState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFINDAStateAndDebounce(bool press) {
|
void SetFINDAStateAndDebounce(bool press) {
|
||||||
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::high);
|
hal::gpio::WritePin(FINDA_PIN, press ? hal::gpio::Level::high : hal::gpio::Level::low);
|
||||||
for (size_t i = 0; i < config::findaDebounceMs + 1; ++i)
|
for (size_t i = 0; i < config::findaDebounceMs + 1; ++i)
|
||||||
main_loop();
|
main_loop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/leds.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/selector.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue