Add bit masks for error codes for the TMC drivers
+ add common error handling for idler and selector + improve error handling in command_base + rename ERR1xxxx errors to ERRxxxx (remove the '1')pull/78/head
parent
df2c1ba7fe
commit
751ee46450
|
|
@ -1,25 +1,25 @@
|
||||||
#include "command_base.h"
|
#include "command_base.h"
|
||||||
#include "../modules/idler.h"
|
#include "../modules/idler.h"
|
||||||
|
#include "../modules/selector.h"
|
||||||
|
|
||||||
namespace mi = modules::idler;
|
namespace mi = modules::idler;
|
||||||
|
namespace ms = modules::selector;
|
||||||
|
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
||||||
bool CommandBase::Step() {
|
bool CommandBase::Step() {
|
||||||
// check the global HW errors - may be we should avoid the modules layer and check for the HAL layer errors directly
|
// check the global HW errors - may be we should avoid the modules layer and check for the HAL layer errors directly
|
||||||
// @@TODO discuss...
|
if (mi::idler.State() == mi::Idler::Failed) {
|
||||||
bool any_error = mi::idler.State() == mi::Idler::Failed;
|
state = ProgressCode::ERRTMCFailed;
|
||||||
|
error = ErrorCode::TMC_IOIN_MISMATCH;
|
||||||
// @@TODO check all other HW issues here to be able to respond with the appropriate error code into the printer
|
return true; // the HW error prevents us from continuing with the with the state machine - the MMU must be restarted/fixed before continuing
|
||||||
|
} else if (ms::selector.State() == ms::Selector::Failed) {
|
||||||
if (any_error) {
|
state = ProgressCode::ERRTMCFailed;
|
||||||
state = ProgressCode::ERR1TMCInitFailed;
|
error = ErrorCode::TMC_IOIN_MISMATCH;
|
||||||
error = ErrorCode::TMC_INIT_ERROR;
|
return true; // the HW error prevents us from continuing with the with the state machine - the MMU must be restarted/fixed before continuing
|
||||||
return true; // the HW error prevents us from continuing with the with the state machine
|
|
||||||
// the MMU must be restarted/fixed before continuing
|
|
||||||
} else {
|
|
||||||
return StepInner();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return StepInner();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace logic
|
} // namespace logic
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,54 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/// A complete set of error codes which may be a result of a high-level command/operation
|
/// A complete set of error codes which may be a result of a high-level command/operation.
|
||||||
/// This header file shall be included in the printer's firmware as well as a reference,
|
/// This header file shall be included in the printer's firmware as well as a reference,
|
||||||
/// therefore the error codes have been extracted to one place
|
/// therefore the error codes have been extracted to one place.
|
||||||
enum class ErrorCode : int_fast8_t {
|
///
|
||||||
RUNNING = 0, ///< the operation is still running
|
/// Please note the errors are intentionally coded as "negative" values (highest bit set),
|
||||||
OK, ///< the operation finished OK
|
/// becase they are a complement to reporting the state of the high-level state machines -
|
||||||
|
/// positive values are considered as normal progress, negative values are errors.
|
||||||
|
///
|
||||||
|
/// Please note, that multiple TMC errors can occur at once, thus they are defined as a bitmask of the higher byte.
|
||||||
|
/// Also, as there are 3 TMC drivers on the board, each error is added a bit for the corresponding TMC -
|
||||||
|
/// TMC_PULLEY_BIT, TMC_SELECTOR_BIT, TMC_IDLER_BIT,
|
||||||
|
/// The resulting error is a bitwise OR over 3 TMC drivers and their status, which should cover most of the situations correctly.
|
||||||
|
enum class ErrorCode : uint_fast16_t {
|
||||||
|
RUNNING = 0x0000, ///< the operation is still running
|
||||||
|
OK = 0x0001, ///< the operation finished OK
|
||||||
|
|
||||||
/// Unload Filament related error codes
|
/// Unload Filament related error codes
|
||||||
FINDA_DIDNT_SWITCH_ON = -1, ///< FINDA didn't switch on while loading filament - either there is something blocking the metal ball or a cable is broken/disconnected
|
FINDA_DIDNT_SWITCH_ON = 0x8001, ///< FINDA didn't switch on while loading filament - either there is something blocking the metal ball or a cable is broken/disconnected
|
||||||
FINDA_DIDNT_SWITCH_OFF = -2, ///< FINDA didn't switch off while unloading filament
|
FINDA_DIDNT_SWITCH_OFF = 0x8002, ///< FINDA didn't switch off while unloading filament
|
||||||
|
|
||||||
FSENSOR_DIDNT_SWITCH_ON = -3, ///< Filament sensor didn't switch on while performing LoadFilament
|
FSENSOR_DIDNT_SWITCH_ON = 0x8003, ///< Filament sensor didn't switch on while performing LoadFilament
|
||||||
FSENSOR_DIDNT_SWITCH_OFF = -4, ///< Filament sensor didn't switch off while performing UnloadFilament
|
FSENSOR_DIDNT_SWITCH_OFF = 0x8004, ///< Filament sensor didn't switch off while performing UnloadFilament
|
||||||
|
|
||||||
FILAMENT_ALREADY_LOADED = -5, ///< cannot perform operation LoadFilament or move the selector as the filament is already loaded
|
FILAMENT_ALREADY_LOADED = 0x8005, ///< cannot perform operation LoadFilament or move the selector as the filament is already loaded
|
||||||
|
|
||||||
TMC_INIT_ERROR = -6, ///< TMC driver init error - the MMU cannot move one motor due to a HW problem
|
MMU_NOT_RESPONDING = 0x807e, ///< internal error of the printer - communication with the MMU is not working
|
||||||
|
|
||||||
MMU_NOT_RESPONDING = -126, ///< internal error of the printer - communication with the MMU is not working
|
INTERNAL = 0x807f, ///< internal runtime error (software)
|
||||||
|
|
||||||
INTERNAL = -127, ///< internal runtime error (software)
|
// TMC bit masks
|
||||||
|
|
||||||
|
TMC_PULLEY_BIT = 0x0080, ///< TMC Pulley bit
|
||||||
|
TMC_SELECTOR_BIT = 0x00A0, ///< TMC Pulley bit
|
||||||
|
TMC_IDLER_BIT = 0x00C0, ///< TMC Pulley bit
|
||||||
|
|
||||||
|
TMC_IOIN_MISMATCH = 0x8100, ///< TMC driver init error - TMC dead or bad communication
|
||||||
|
|
||||||
|
/// TMC driver reset - recoverable, we just need to rehome the axis
|
||||||
|
/// Idler: can be rehomed any time
|
||||||
|
/// Selector: if there is a filament, remove it and rehome, if there is no filament, just rehome
|
||||||
|
/// Pulley: do nothing - for the loading sequence - just restart and move slowly, for the unload sequence just restart
|
||||||
|
TMC_RESET = 0x8200,
|
||||||
|
|
||||||
|
TMC_UNDERVOLTAGE_ON_CHARGE_PUMP = 0x8400, ///< not enough current for the TMC, NOT RECOVERABLE
|
||||||
|
|
||||||
|
TMC_SERIOUS_ERROR = 0x8800, ///< TMC driver serious error coil A or coil B - dangerous to recover
|
||||||
|
TMC_ERROR_A = 0x9000, ///< TMC driver error coil A or coil B - can be recovered
|
||||||
|
|
||||||
|
TMC_OVER_TEMPERATURE_WARN = 0xA000, ///< TMC driver over temperature warning - can be recovered by restarting the driver
|
||||||
|
TMC_OVER_TEMPERATURE_ERROR = 0xC000, ///< TMC driver over temperature error - the TMC probably fried
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ bool LoadFilament::StepInner() {
|
||||||
if (feed.Step()) {
|
if (feed.Step()) {
|
||||||
if (feed.State() == FeedToFinda::Failed) {
|
if (feed.State() == FeedToFinda::Failed) {
|
||||||
// @@TODO - try to repeat 6x - push/pull sequence - probably something to put into feed_to_finda as an option
|
// @@TODO - try to repeat 6x - push/pull sequence - probably something to put into feed_to_finda as an option
|
||||||
state = ProgressCode::ERR1DisengagingIdler;
|
state = ProgressCode::ERRDisengagingIdler;
|
||||||
error = ErrorCode::FINDA_DIDNT_SWITCH_ON;
|
error = ErrorCode::FINDA_DIDNT_SWITCH_ON;
|
||||||
mi::idler.Disengage();
|
mi::idler.Disengage();
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::Mode::off);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::Mode::off);
|
||||||
|
|
@ -74,18 +74,18 @@ bool LoadFilament::StepInner() {
|
||||||
break;
|
break;
|
||||||
case ProgressCode::OK:
|
case ProgressCode::OK:
|
||||||
return true;
|
return true;
|
||||||
case ProgressCode::ERR1DisengagingIdler: // couldn't unload to FINDA
|
case ProgressCode::ERRDisengagingIdler: // couldn't unload to FINDA
|
||||||
if (!mi::idler.Engaged()) {
|
if (!mi::idler.Engaged()) {
|
||||||
state = ProgressCode::ERR1WaitingForUser;
|
state = ProgressCode::ERRWaitingForUser;
|
||||||
mu::userInput.Clear(); // remove all buffered events if any just before we wait for some input
|
mu::userInput.Clear(); // remove all buffered events if any just before we wait for some input
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case ProgressCode::ERR1WaitingForUser: {
|
case ProgressCode::ERRWaitingForUser: {
|
||||||
// waiting for user buttons and/or a command from the printer
|
// waiting for user buttons and/or a command from the printer
|
||||||
mu::Event ev = mu::userInput.ConsumeEvent();
|
mu::Event ev = mu::userInput.ConsumeEvent();
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
case mu::Event::Left: // try to manually load just a tiny bit - help the filament with the pulley
|
case mu::Event::Left: // try to manually load just a tiny bit - help the filament with the pulley
|
||||||
state = ProgressCode::ERR1EngagingIdler;
|
state = ProgressCode::ERREngagingIdler;
|
||||||
mi::idler.Engage(mg::globals.ActiveSlot());
|
mi::idler.Engage(mg::globals.ActiveSlot());
|
||||||
break;
|
break;
|
||||||
case mu::Event::Middle: // try again the whole sequence
|
case mu::Event::Middle: // try again the whole sequence
|
||||||
|
|
@ -102,20 +102,20 @@ bool LoadFilament::StepInner() {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case ProgressCode::ERR1EngagingIdler:
|
case ProgressCode::ERREngagingIdler:
|
||||||
if (mi::idler.Engaged()) {
|
if (mi::idler.Engaged()) {
|
||||||
state = ProgressCode::ERR1HelpingFilament;
|
state = ProgressCode::ERRHelpingFilament;
|
||||||
mm::motion.PlanMove(mm::Pulley, 450, 5000); //@@TODO constants
|
mm::motion.PlanMove(mm::Pulley, 450, 5000); //@@TODO constants
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case ProgressCode::ERR1HelpingFilament:
|
case ProgressCode::ERRHelpingFilament:
|
||||||
if (mf::finda.Pressed()) {
|
if (mf::finda.Pressed()) {
|
||||||
// the help was enough to press the FINDA, we are ok, continue normally
|
// the help was enough to press the FINDA, we are ok, continue normally
|
||||||
state = ProgressCode::FeedingToBondtech;
|
state = ProgressCode::FeedingToBondtech;
|
||||||
error = ErrorCode::OK;
|
error = ErrorCode::OK;
|
||||||
} else if (mm::motion.QueueEmpty()) {
|
} else if (mm::motion.QueueEmpty()) {
|
||||||
// helped a bit, but FINDA didn't trigger, return to the main error state
|
// helped a bit, but FINDA didn't trigger, return to the main error state
|
||||||
state = ProgressCode::ERR1DisengagingIdler;
|
state = ProgressCode::ERRDisengagingIdler;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
default: // we got into an unhandled state, better report it
|
default: // we got into an unhandled state, better report it
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ enum class ProgressCode : uint_fast8_t {
|
||||||
AvoidingGrind,
|
AvoidingGrind,
|
||||||
FinishingMoves,
|
FinishingMoves,
|
||||||
|
|
||||||
ERR1DisengagingIdler,
|
ERRDisengagingIdler,
|
||||||
ERR1EngagingIdler,
|
ERREngagingIdler,
|
||||||
ERR1WaitingForUser,
|
ERRWaitingForUser,
|
||||||
ERRInternal,
|
ERRInternal,
|
||||||
ERR1HelpingFilament,
|
ERRHelpingFilament,
|
||||||
ERR1TMCInitFailed,
|
ERRTMCFailed,
|
||||||
|
|
||||||
UnloadingFilament,
|
UnloadingFilament,
|
||||||
LoadingFilament,
|
LoadingFilament,
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ bool UnloadFilament::StepInner() {
|
||||||
if (unl.Step()) {
|
if (unl.Step()) {
|
||||||
if (unl.State() == UnloadToFinda::Failed) {
|
if (unl.State() == UnloadToFinda::Failed) {
|
||||||
// couldn't unload to FINDA, report error and wait for user to resolve it
|
// couldn't unload to FINDA, report error and wait for user to resolve it
|
||||||
state = ProgressCode::ERR1DisengagingIdler;
|
state = ProgressCode::ERRDisengagingIdler;
|
||||||
error = ErrorCode::FINDA_DIDNT_SWITCH_OFF;
|
error = ErrorCode::FINDA_DIDNT_SWITCH_OFF;
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::blink0);
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::off);
|
||||||
|
|
@ -68,18 +68,18 @@ bool UnloadFilament::StepInner() {
|
||||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::on);
|
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::on);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case ProgressCode::ERR1DisengagingIdler: // couldn't unload to FINDA
|
case ProgressCode::ERRDisengagingIdler: // couldn't unload to FINDA
|
||||||
if (!mi::idler.Engaged()) {
|
if (!mi::idler.Engaged()) {
|
||||||
state = ProgressCode::ERR1WaitingForUser;
|
state = ProgressCode::ERRWaitingForUser;
|
||||||
mu::userInput.Clear(); // remove all buffered events if any just before we wait for some input
|
mu::userInput.Clear(); // remove all buffered events if any just before we wait for some input
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case ProgressCode::ERR1WaitingForUser: {
|
case ProgressCode::ERRWaitingForUser: {
|
||||||
// waiting for user buttons and/or a command from the printer
|
// waiting for user buttons and/or a command from the printer
|
||||||
mu::Event ev = mu::userInput.ConsumeEvent();
|
mu::Event ev = mu::userInput.ConsumeEvent();
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
case mu::Event::Left: // try to manually unload just a tiny bit - help the filament with the pulley
|
case mu::Event::Left: // try to manually unload just a tiny bit - help the filament with the pulley
|
||||||
state = ProgressCode::ERR1EngagingIdler;
|
state = ProgressCode::ERREngagingIdler;
|
||||||
mi::idler.Engage(mg::globals.ActiveSlot());
|
mi::idler.Engage(mg::globals.ActiveSlot());
|
||||||
break;
|
break;
|
||||||
case mu::Event::Middle: // try again the whole sequence
|
case mu::Event::Middle: // try again the whole sequence
|
||||||
|
|
@ -96,20 +96,20 @@ bool UnloadFilament::StepInner() {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case ProgressCode::ERR1EngagingIdler:
|
case ProgressCode::ERREngagingIdler:
|
||||||
if (mi::idler.Engaged()) {
|
if (mi::idler.Engaged()) {
|
||||||
state = ProgressCode::ERR1HelpingFilament;
|
state = ProgressCode::ERRHelpingFilament;
|
||||||
mm::motion.PlanMove(mm::Pulley, 450, 5000);
|
mm::motion.PlanMove(mm::Pulley, 450, 5000);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case ProgressCode::ERR1HelpingFilament:
|
case ProgressCode::ERRHelpingFilament:
|
||||||
if (!mf::finda.Pressed()) {
|
if (!mf::finda.Pressed()) {
|
||||||
// the help was enough to depress the FINDA, we are ok, continue normally
|
// the help was enough to depress the FINDA, we are ok, continue normally
|
||||||
state = ProgressCode::DisengagingIdler;
|
state = ProgressCode::DisengagingIdler;
|
||||||
error = ErrorCode::OK;
|
error = ErrorCode::OK;
|
||||||
} else if (mm::motion.QueueEmpty()) {
|
} else if (mm::motion.QueueEmpty()) {
|
||||||
// helped a bit, but FINDA didn't trigger, return to the main error state
|
// helped a bit, but FINDA didn't trigger, return to the main error state
|
||||||
state = ProgressCode::ERR1DisengagingIdler;
|
state = ProgressCode::ERRDisengagingIdler;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case ProgressCode::OK:
|
case ProgressCode::OK:
|
||||||
|
|
|
||||||
|
|
@ -207,18 +207,18 @@ void ReportVersion(const mp::RequestMsg &rq) {
|
||||||
|
|
||||||
void ReportRunningCommand() {
|
void ReportRunningCommand() {
|
||||||
mp::ResponseMsgParamCodes commandStatus;
|
mp::ResponseMsgParamCodes commandStatus;
|
||||||
uint8_t value = 0;
|
uint16_t value = 0;
|
||||||
switch (currentCommand->Error()) {
|
switch (currentCommand->Error()) {
|
||||||
case ErrorCode::RUNNING:
|
case ErrorCode::RUNNING:
|
||||||
commandStatus = mp::ResponseMsgParamCodes::Processing;
|
commandStatus = mp::ResponseMsgParamCodes::Processing;
|
||||||
value = (uint8_t)currentCommand->State();
|
value = (uint16_t)currentCommand->State();
|
||||||
break;
|
break;
|
||||||
case ErrorCode::OK:
|
case ErrorCode::OK:
|
||||||
commandStatus = mp::ResponseMsgParamCodes::Finished;
|
commandStatus = mp::ResponseMsgParamCodes::Finished;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
commandStatus = mp::ResponseMsgParamCodes::Error;
|
commandStatus = mp::ResponseMsgParamCodes::Error;
|
||||||
value = (uint8_t)currentCommand->Error();
|
value = (uint16_t)currentCommand->Error();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ target_sources(
|
||||||
idler.cpp
|
idler.cpp
|
||||||
leds.cpp
|
leds.cpp
|
||||||
motion.cpp
|
motion.cpp
|
||||||
|
movable_base.cpp
|
||||||
permanent_storage.cpp
|
permanent_storage.cpp
|
||||||
selector.cpp
|
selector.cpp
|
||||||
timebase.cpp
|
timebase.cpp
|
||||||
|
|
|
||||||
|
|
@ -11,57 +11,34 @@ Idler idler;
|
||||||
|
|
||||||
namespace mm = modules::motion;
|
namespace mm = modules::motion;
|
||||||
|
|
||||||
Idler::EngageDisengage Idler::Disengage() {
|
void Idler::PrepareMoveToPlannedSlot() {
|
||||||
if (state == Moving)
|
mm::motion.PlanMoveTo<mm::Idler>(SlotPosition(plannedSlot), 1000._I_deg_s); // @@TODO
|
||||||
return EngageDisengage::Refused;
|
}
|
||||||
|
|
||||||
|
Idler::OperationResult Idler::Disengage() {
|
||||||
|
if (state == Moving)
|
||||||
|
return OperationResult::Refused;
|
||||||
|
|
||||||
|
plannedSlot = IdleSlotIndex();
|
||||||
plannedEngage = false;
|
plannedEngage = false;
|
||||||
|
|
||||||
if (!Engaged())
|
if (!Engaged())
|
||||||
return true;
|
return OperationResult::Accepted;
|
||||||
|
|
||||||
mm::motion.InitAxis(mm::Idler);
|
return InitMovement(mm::Idler);
|
||||||
// plan move to idle position
|
|
||||||
mm::motion.PlanMoveTo<mm::Idler>(SlotPosition(IdleSlotIndex()), 1000._I_deg_s); // @@TODO
|
|
||||||
state = Moving;
|
|
||||||
return true;
|
|
||||||
// return EngageDisengage::Accepted;
|
|
||||||
//
|
|
||||||
// if (!mm::motion.InitAxis(mm::Idler)) {
|
|
||||||
// state = Failed;
|
|
||||||
// return EngageDisengage::Failed;
|
|
||||||
// } else {
|
|
||||||
// // plan move to idle position
|
|
||||||
// mm::motion.PlanMove(mm::Idler, config::idlerSlotPositions[IdleSlotIndex()] - mm::motion.Position(mm::Idler), 1000); // @@TODO
|
|
||||||
// state = Moving;
|
|
||||||
// return EngageDisengage::Accepted;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Idler::EngageDisengage Idler::Engage(uint8_t slot) {
|
Idler::OperationResult Idler::Engage(uint8_t slot) {
|
||||||
if (state == Moving)
|
if (state == Moving)
|
||||||
return EngageDisengage::Refused;
|
return OperationResult::Refused;
|
||||||
|
|
||||||
plannedSlot = slot;
|
plannedSlot = slot;
|
||||||
plannedEngage = true;
|
plannedEngage = true;
|
||||||
|
|
||||||
if (Engaged())
|
if (Engaged())
|
||||||
return true;
|
return OperationResult::Accepted;
|
||||||
|
|
||||||
mm::motion.InitAxis(mm::Idler);
|
return InitMovement(mm::Idler);
|
||||||
mm::motion.PlanMoveTo<mm::Idler>(SlotPosition(slot), 1000._I_deg_s); // @@TODO
|
|
||||||
state = Moving;
|
|
||||||
return true;
|
|
||||||
// return EngageDisengage::Accepted;
|
|
||||||
//
|
|
||||||
// if (!mm::motion.InitAxis(mm::Idler)) {
|
|
||||||
// state = Failed;
|
|
||||||
// return EngageDisengage::Failed;
|
|
||||||
// } else {
|
|
||||||
// mm::motion.PlanMove(mm::Idler, config::idlerSlotPositions[slot] - mm::motion.Position(mm::Idler), 1000); // @@TODO
|
|
||||||
// state = Moving;
|
|
||||||
// return EngageDisengage::Accepted;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Idler::Home() {
|
bool Idler::Home() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../config/config.h"
|
#include "../config/config.h"
|
||||||
#include "../modules/axisunit.h"
|
#include "axisunit.h"
|
||||||
|
#include "movable_base.h"
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
|
@ -10,37 +11,21 @@ namespace idler {
|
||||||
namespace mm = modules::motion;
|
namespace mm = modules::motion;
|
||||||
|
|
||||||
/// The Idler model handles asynchronnous Engaging / Disengaging operations and keeps track of idler's current state.
|
/// The Idler model handles asynchronnous Engaging / Disengaging operations and keeps track of idler's current state.
|
||||||
class Idler {
|
class Idler : public motion::MovableBase {
|
||||||
public:
|
public:
|
||||||
/// Internal states of idler's state machine
|
|
||||||
enum {
|
|
||||||
Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code
|
|
||||||
Moving,
|
|
||||||
Failed
|
|
||||||
};
|
|
||||||
|
|
||||||
inline constexpr Idler()
|
inline constexpr Idler()
|
||||||
: state(Ready)
|
: MovableBase()
|
||||||
, plannedEngage(false)
|
, plannedEngage(false)
|
||||||
, plannedSlot(0)
|
|
||||||
, currentSlot(0)
|
|
||||||
, currentlyEngaged(false) {}
|
, currentlyEngaged(false) {}
|
||||||
|
|
||||||
/// Engage/Disengage return values
|
|
||||||
enum class EngageDisengage : uint8_t {
|
|
||||||
Accepted, ///< the operation has been successfully started
|
|
||||||
Refused, ///< another operation is currently underway, cannot start a new one
|
|
||||||
Failed ///< the operation could not been started due to HW issues
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Plan engaging of the idler to a specific filament slot
|
/// Plan engaging of the idler to a specific filament slot
|
||||||
/// @param slot index to be activated
|
/// @param slot index to be activated
|
||||||
/// @returns #EngageDisengage
|
/// @returns #EngageDisengage
|
||||||
EngageDisengage Engage(uint8_t slot);
|
OperationResult Engage(uint8_t slot);
|
||||||
|
|
||||||
/// Plan disengaging of the idler, i.e. parking the idler
|
/// Plan disengaging of the idler, i.e. parking the idler
|
||||||
/// @returns #EngageDisengage
|
/// @returns #EngageDisengage
|
||||||
EngageDisengage Disengage();
|
OperationResult Disengage();
|
||||||
|
|
||||||
/// Plan homing of the idler axis
|
/// Plan homing of the idler axis
|
||||||
/// @returns false in case an operation is already underway
|
/// @returns false in case an operation is already underway
|
||||||
|
|
@ -55,9 +40,6 @@ public:
|
||||||
/// state machines to use this call as a waiting condition for the desired state of the idler
|
/// state machines to use this call as a waiting condition for the desired state of the idler
|
||||||
inline bool Engaged() const { return currentlyEngaged; }
|
inline bool Engaged() const { return currentlyEngaged; }
|
||||||
|
|
||||||
/// @returns currently active slot
|
|
||||||
inline uint8_t Slot() const { return currentSlot; }
|
|
||||||
|
|
||||||
/// @returns predefined positions of individual slots
|
/// @returns predefined positions of individual slots
|
||||||
static constexpr mm::I_pos_t SlotPosition(uint8_t slot) {
|
static constexpr mm::I_pos_t SlotPosition(uint8_t slot) {
|
||||||
return mm::unitToAxisUnit<mm::I_pos_t>(config::idlerSlotPositions[slot]);
|
return mm::unitToAxisUnit<mm::I_pos_t>(config::idlerSlotPositions[slot]);
|
||||||
|
|
@ -66,19 +48,14 @@ public:
|
||||||
/// @returns the index of idle position of the idler, usually 5 in case of 0-4 valid indices of filament slots
|
/// @returns the index of idle position of the idler, usually 5 in case of 0-4 valid indices of filament slots
|
||||||
inline static constexpr uint8_t IdleSlotIndex() { return config::toolCount; }
|
inline static constexpr uint8_t IdleSlotIndex() { return config::toolCount; }
|
||||||
|
|
||||||
/// @returns internal state of the Idler
|
protected:
|
||||||
inline uint8_t State() const { return state; }
|
virtual void PrepareMoveToPlannedSlot() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// internal state of the automaton
|
|
||||||
uint8_t state;
|
|
||||||
|
|
||||||
/// direction of travel - engage/disengage
|
/// direction of travel - engage/disengage
|
||||||
bool plannedEngage;
|
bool plannedEngage;
|
||||||
uint8_t plannedSlot;
|
|
||||||
|
|
||||||
/// current state
|
/// current state
|
||||||
uint8_t currentSlot;
|
|
||||||
bool currentlyEngaged;
|
bool currentlyEngaged;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include "movable_base.h"
|
||||||
|
#include "motion.h"
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
namespace motion {
|
||||||
|
|
||||||
|
MovableBase::OperationResult MovableBase::InitMovement(config::Axis axis) {
|
||||||
|
if (motion.InitAxis(axis)) {
|
||||||
|
PrepareMoveToPlannedSlot();
|
||||||
|
state = Moving;
|
||||||
|
return OperationResult::Accepted;
|
||||||
|
} else {
|
||||||
|
state = Failed;
|
||||||
|
return OperationResult::Failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace motion
|
||||||
|
} // namespace modules
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../config/axis.h"
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
namespace motion {
|
||||||
|
|
||||||
|
/// Base class for movable modules - #Idler and #Selector contains the common code
|
||||||
|
class MovableBase {
|
||||||
|
public:
|
||||||
|
/// Internal states of the state machine
|
||||||
|
enum {
|
||||||
|
Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code
|
||||||
|
Moving,
|
||||||
|
Failed
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Operation (Engage/Disengage/MoveToSlot) return values
|
||||||
|
enum class OperationResult : uint8_t {
|
||||||
|
Accepted, ///< the operation has been successfully started
|
||||||
|
Refused, ///< another operation is currently underway, cannot start a new one
|
||||||
|
Failed ///< the operation could not been started due to HW issues
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr MovableBase()
|
||||||
|
: state(Ready)
|
||||||
|
, plannedSlot(0)
|
||||||
|
, currentSlot(0) {}
|
||||||
|
|
||||||
|
/// virtual ~MovableBase(); intentionally disabled, see description in logic::CommandBase
|
||||||
|
|
||||||
|
/// @returns currently active slot
|
||||||
|
/// this state is updated only when a planned move is successfully finished, so it is safe for higher-level
|
||||||
|
/// state machines to use this call as a waiting condition for the desired state of the derive class (idler/selector)
|
||||||
|
inline uint8_t Slot() const { return currentSlot; }
|
||||||
|
|
||||||
|
/// @returns internal state of the state machine
|
||||||
|
inline uint8_t State() const { return state; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// internal state of the automaton
|
||||||
|
uint8_t state;
|
||||||
|
|
||||||
|
/// planned slot - where to move to
|
||||||
|
uint8_t plannedSlot;
|
||||||
|
|
||||||
|
/// current slot
|
||||||
|
uint8_t currentSlot;
|
||||||
|
|
||||||
|
virtual void PrepareMoveToPlannedSlot() = 0;
|
||||||
|
|
||||||
|
OperationResult InitMovement(config::Axis axis);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace motion
|
||||||
|
} // namespace modules
|
||||||
|
|
@ -197,7 +197,7 @@ uint8_t Protocol::EncodeResponseVersion(const RequestMsg &msg, uint8_t value, ui
|
||||||
return dst - txbuff + 1;
|
return dst - txbuff + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff) {
|
uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint16_t value, uint8_t *txbuff) {
|
||||||
txbuff[0] = (uint8_t)msg.code;
|
txbuff[0] = (uint8_t)msg.code;
|
||||||
txbuff[1] = msg.value + '0';
|
txbuff[1] = msg.value + '0';
|
||||||
txbuff[2] = ' ';
|
txbuff[2] = ' ';
|
||||||
|
|
@ -209,10 +209,21 @@ uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMs
|
||||||
} else if (value < 100) {
|
} else if (value < 100) {
|
||||||
*dst++ = value / 10 + '0';
|
*dst++ = value / 10 + '0';
|
||||||
*dst++ = value % 10 + '0';
|
*dst++ = value % 10 + '0';
|
||||||
} else {
|
} else if (value < 1000) {
|
||||||
*dst++ = value / 100 + '0';
|
*dst++ = value / 100 + '0';
|
||||||
*dst++ = (value / 10) % 10 + '0';
|
*dst++ = (value / 10) % 10 + '0';
|
||||||
*dst++ = value % 10 + '0';
|
*dst++ = value % 10 + '0';
|
||||||
|
} else if (value < 10000) {
|
||||||
|
*dst++ = value / 1000 + '0';
|
||||||
|
*dst++ = (value / 100) % 100 + '0';
|
||||||
|
*dst++ = (value / 10) % 10 + '0';
|
||||||
|
*dst++ = value % 10 + '0';
|
||||||
|
} else {
|
||||||
|
*dst++ = value / 10000 + '0';
|
||||||
|
*dst++ = (value / 1000) % 1000 + '0';
|
||||||
|
*dst++ = (value / 100) % 100 + '0';
|
||||||
|
*dst++ = (value / 10) % 10 + '0';
|
||||||
|
*dst++ = value % 10 + '0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*dst = '\n';
|
*dst = '\n';
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,12 @@ struct RequestMsg {
|
||||||
struct ResponseMsg {
|
struct ResponseMsg {
|
||||||
RequestMsg request; ///< response is always preceeded by the request message
|
RequestMsg request; ///< response is always preceeded by the request message
|
||||||
ResponseMsgParamCodes paramCode; ///< code of the parameter
|
ResponseMsgParamCodes paramCode; ///< code of the parameter
|
||||||
uint8_t paramValue; ///< value of the parameter
|
uint16_t paramValue; ///< value of the parameter
|
||||||
|
|
||||||
/// @param request the source request message this response is a reply to
|
/// @param request the source request message this response is a reply to
|
||||||
/// @param paramCode code of the parameter
|
/// @param paramCode code of the parameter
|
||||||
/// @param paramValue value of the parameter
|
/// @param paramValue value of the parameter
|
||||||
inline ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint8_t paramValue)
|
inline ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint16_t paramValue)
|
||||||
: request(request)
|
: request(request)
|
||||||
, paramCode(paramCode)
|
, paramCode(paramCode)
|
||||||
, paramValue(paramValue) {}
|
, paramValue(paramValue) {}
|
||||||
|
|
@ -123,7 +123,7 @@ public:
|
||||||
/// @param value related to status of operation(e.g. error code or progress)
|
/// @param value related to status of operation(e.g. error code or progress)
|
||||||
/// @param txbuff where to format the message
|
/// @param txbuff where to format the message
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff);
|
static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint16_t value, uint8_t *txbuff);
|
||||||
|
|
||||||
/// @returns the most recently lexed request message
|
/// @returns the most recently lexed request message
|
||||||
inline const RequestMsg GetRequestMsg() const { return requestMsg; }
|
inline const RequestMsg GetRequestMsg() const { return requestMsg; }
|
||||||
|
|
|
||||||
|
|
@ -11,19 +11,20 @@ Selector selector;
|
||||||
|
|
||||||
namespace mm = modules::motion;
|
namespace mm = modules::motion;
|
||||||
|
|
||||||
bool Selector::MoveToSlot(uint8_t slot) {
|
void Selector::PrepareMoveToPlannedSlot() {
|
||||||
|
mm::motion.PlanMoveTo<mm::Selector>(SlotPosition(plannedSlot), 1000.0_S_mm_s); // @@TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
Selector::OperationResult Selector::MoveToSlot(uint8_t slot) {
|
||||||
if (state == Moving)
|
if (state == Moving)
|
||||||
return false;
|
return OperationResult::Refused;
|
||||||
|
|
||||||
plannedSlot = slot;
|
plannedSlot = slot;
|
||||||
|
|
||||||
if (currentSlot == slot)
|
if (currentSlot == slot)
|
||||||
return true;
|
return OperationResult::Accepted;
|
||||||
|
|
||||||
mm::motion.InitAxis(mm::Selector);
|
return InitMovement(mm::Selector);
|
||||||
mm::motion.PlanMoveTo<mm::Selector>(SlotPosition(slot), 1000.0_S_mm_s); // @@TODO
|
|
||||||
state = Moving;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Selector::Home() {
|
bool Selector::Home() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../config/config.h"
|
#include "../config/config.h"
|
||||||
#include "../modules/axisunit.h"
|
#include "axisunit.h"
|
||||||
|
#include "movable_base.h"
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
|
@ -10,24 +11,15 @@ namespace selector {
|
||||||
namespace mm = modules::motion;
|
namespace mm = modules::motion;
|
||||||
|
|
||||||
/// The selector model - handles asynchronnous move operations between filament individual slots and keeps track of selector's current state.
|
/// The selector model - handles asynchronnous move operations between filament individual slots and keeps track of selector's current state.
|
||||||
class Selector {
|
class Selector : public mm::MovableBase {
|
||||||
public:
|
public:
|
||||||
/// Internal states of selector's state machine
|
|
||||||
enum {
|
|
||||||
Ready = 0,
|
|
||||||
Moving,
|
|
||||||
Failed
|
|
||||||
};
|
|
||||||
|
|
||||||
inline constexpr Selector()
|
inline constexpr Selector()
|
||||||
: state(Ready)
|
: MovableBase() {}
|
||||||
, plannedSlot(0)
|
|
||||||
, currentSlot(0) {}
|
|
||||||
|
|
||||||
/// 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
|
||||||
/// @returns false in case an operation is already underway
|
/// @returns false in case an operation is already underway
|
||||||
bool MoveToSlot(uint8_t slot);
|
OperationResult MoveToSlot(uint8_t slot);
|
||||||
|
|
||||||
/// Plan homing of the selector's axis
|
/// Plan homing of the selector's axis
|
||||||
/// @returns false in case an operation is already underway
|
/// @returns false in case an operation is already underway
|
||||||
|
|
@ -37,11 +29,6 @@ public:
|
||||||
/// @returns true if the selector is ready to accept new commands (i.e. it has finished the last operation)
|
/// @returns true if the selector is ready to accept new commands (i.e. it has finished the last operation)
|
||||||
bool Step();
|
bool Step();
|
||||||
|
|
||||||
/// @returns the current slot of selector
|
|
||||||
/// this state is updated only when a planned move is successfully finished, so it is safe for higher-level
|
|
||||||
/// state machines to use this call as a waiting condition for the desired state of the selector
|
|
||||||
inline uint8_t Slot() const { return currentSlot; }
|
|
||||||
|
|
||||||
/// @returns predefined positions of individual slots
|
/// @returns predefined positions of individual slots
|
||||||
static constexpr mm::S_pos_t SlotPosition(uint8_t slot) {
|
static constexpr mm::S_pos_t SlotPosition(uint8_t slot) {
|
||||||
return mm::unitToAxisUnit<mm::S_pos_t>(config::selectorSlotPositions[slot]);
|
return mm::unitToAxisUnit<mm::S_pos_t>(config::selectorSlotPositions[slot]);
|
||||||
|
|
@ -50,13 +37,10 @@ public:
|
||||||
/// @returns the index of idle position of the selector, usually 5 in case of 0-4 valid indices of filament slots
|
/// @returns the index of idle position of the selector, usually 5 in case of 0-4 valid indices of filament slots
|
||||||
inline static constexpr uint8_t IdleSlotIndex() { return config::toolCount; }
|
inline static constexpr uint8_t IdleSlotIndex() { return config::toolCount; }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
/// internal state of the automaton
|
virtual void PrepareMoveToPlannedSlot() override;
|
||||||
uint8_t state;
|
|
||||||
uint8_t plannedSlot;
|
|
||||||
|
|
||||||
/// current state
|
private:
|
||||||
uint8_t currentSlot;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The one and only instance of Selector in the FW
|
/// The one and only instance of Selector in the FW
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
||||||
${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/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.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
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
||||||
${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/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.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
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
||||||
${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/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.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
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
||||||
${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/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.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
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
||||||
${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/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.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
|
||||||
|
|
|
||||||
|
|
@ -96,11 +96,11 @@ void FailedLoadToFinda(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
// Stage 2 - feeding to finda
|
// Stage 2 - feeding to finda
|
||||||
// we'll assume the finda is defective here and does not trigger
|
// we'll assume the finda is defective here and does not trigger
|
||||||
REQUIRE(WhileTopState(lf, ProgressCode::FeedingToFinda, 5000));
|
REQUIRE(WhileTopState(lf, ProgressCode::FeedingToFinda, 5000));
|
||||||
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1DisengagingIdler));
|
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERRDisengagingIdler));
|
||||||
|
|
||||||
// Stage 3 - disengaging idler in error mode
|
// Stage 3 - disengaging idler in error mode
|
||||||
REQUIRE(WhileTopState(lf, ProgressCode::ERR1DisengagingIdler, 5000));
|
REQUIRE(WhileTopState(lf, ProgressCode::ERRDisengagingIdler, 5000));
|
||||||
REQUIRE(VerifyState(lf, false, mi::Idler::IdleSlotIndex(), slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1WaitingForUser));
|
REQUIRE(VerifyState(lf, false, mi::Idler::IdleSlotIndex(), slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERRWaitingForUser));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FailedLoadToFindaResolveHelp(uint8_t slot, logic::LoadFilament &lf) {
|
void FailedLoadToFindaResolveHelp(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
|
@ -119,12 +119,12 @@ void FailedLoadToFindaResolveHelp(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
lf.Step();
|
lf.Step();
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE(VerifyState(lf, false, mi::Idler::IdleSlotIndex(), slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1EngagingIdler));
|
REQUIRE(VerifyState(lf, false, mi::Idler::IdleSlotIndex(), slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERREngagingIdler));
|
||||||
|
|
||||||
// Stage 4 - engage the idler
|
// Stage 4 - engage the idler
|
||||||
REQUIRE(WhileTopState(lf, ProgressCode::ERR1EngagingIdler, 5000));
|
REQUIRE(WhileTopState(lf, ProgressCode::ERREngagingIdler, 5000));
|
||||||
|
|
||||||
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1HelpingFilament));
|
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERRHelpingFilament));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FailedLoadToFindaResolveHelpFindaTriggered(uint8_t slot, logic::LoadFilament &lf) {
|
void FailedLoadToFindaResolveHelpFindaTriggered(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
|
@ -135,7 +135,7 @@ void FailedLoadToFindaResolveHelpFindaTriggered(uint8_t slot, logic::LoadFilamen
|
||||||
if(step == 100){ // on 100th step make FINDA trigger
|
if(step == 100){ // on 100th step make FINDA trigger
|
||||||
hal::adc::SetADC(config::findaADCIndex, 1023);
|
hal::adc::SetADC(config::findaADCIndex, 1023);
|
||||||
}
|
}
|
||||||
return lf.TopLevelState() == ProgressCode::ERR1HelpingFilament; },
|
return lf.TopLevelState() == ProgressCode::ERRHelpingFilament; },
|
||||||
5000));
|
5000));
|
||||||
|
|
||||||
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::off, ml::blink0, ErrorCode::OK, ProgressCode::FeedingToBondtech));
|
REQUIRE(VerifyState(lf, false, slot, slot, true, ml::off, ml::blink0, ErrorCode::OK, ProgressCode::FeedingToBondtech));
|
||||||
|
|
@ -143,9 +143,9 @@ void FailedLoadToFindaResolveHelpFindaTriggered(uint8_t slot, logic::LoadFilamen
|
||||||
|
|
||||||
void FailedLoadToFindaResolveHelpFindaDidntTrigger(uint8_t slot, logic::LoadFilament &lf) {
|
void FailedLoadToFindaResolveHelpFindaDidntTrigger(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
// Stage 5 - move the pulley a bit - no FINDA change
|
// Stage 5 - move the pulley a bit - no FINDA change
|
||||||
REQUIRE(WhileTopState(lf, ProgressCode::ERR1HelpingFilament, 5000));
|
REQUIRE(WhileTopState(lf, ProgressCode::ERRHelpingFilament, 5000));
|
||||||
|
|
||||||
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERR1DisengagingIdler));
|
REQUIRE(VerifyState(lf, false, slot, slot, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERRDisengagingIdler));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_ok", "[load_filament]") {
|
TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_ok", "[load_filament]") {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
||||||
${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/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.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
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
||||||
${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/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.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
|
||||||
|
|
|
||||||
|
|
@ -158,10 +158,10 @@ void FindaDidntTriggerCommonSetup(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
// no change in selector's position
|
// no change in selector's position
|
||||||
// FINDA still on
|
// FINDA still on
|
||||||
// red LED should blink, green LED should be off
|
// red LED should blink, green LED should be off
|
||||||
REQUIRE(VerifyState(uf, true, slot, slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERR1DisengagingIdler));
|
REQUIRE(VerifyState(uf, true, slot, slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERRDisengagingIdler));
|
||||||
|
|
||||||
// Stage 2 - idler should get disengaged
|
// Stage 2 - idler should get disengaged
|
||||||
REQUIRE(WhileTopState(uf, ProgressCode::ERR1DisengagingIdler, 5000));
|
REQUIRE(WhileTopState(uf, ProgressCode::ERRDisengagingIdler, 5000));
|
||||||
|
|
||||||
// we still think we have filament loaded at this stage
|
// we still think we have filament loaded at this stage
|
||||||
// idler should have been disengaged
|
// idler should have been disengaged
|
||||||
|
|
@ -169,7 +169,7 @@ void FindaDidntTriggerCommonSetup(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
// FINDA still on
|
// FINDA still on
|
||||||
// red LED should blink
|
// red LED should blink
|
||||||
// green LED should be off
|
// green LED should be off
|
||||||
REQUIRE(VerifyState(uf, true, mi::Idler::IdleSlotIndex(), slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERR1WaitingForUser));
|
REQUIRE(VerifyState(uf, true, mi::Idler::IdleSlotIndex(), slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERRWaitingForUser));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindaDidntTriggerResolveHelp(uint8_t slot, logic::UnloadFilament &uf) {
|
void FindaDidntTriggerResolveHelp(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
|
|
@ -194,17 +194,17 @@ void FindaDidntTriggerResolveHelp(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
// no change in selector's position
|
// no change in selector's position
|
||||||
// FINDA still on
|
// FINDA still on
|
||||||
// red LED should blink, green LED should be off
|
// red LED should blink, green LED should be off
|
||||||
REQUIRE(VerifyState(uf, true, mi::Idler::IdleSlotIndex(), slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERR1EngagingIdler));
|
REQUIRE(VerifyState(uf, true, mi::Idler::IdleSlotIndex(), slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERREngagingIdler));
|
||||||
|
|
||||||
// Stage 4 - engage the idler
|
// Stage 4 - engage the idler
|
||||||
REQUIRE(WhileTopState(uf, ProgressCode::ERR1EngagingIdler, 5000));
|
REQUIRE(WhileTopState(uf, ProgressCode::ERREngagingIdler, 5000));
|
||||||
|
|
||||||
// we still think we have filament loaded at this stage
|
// we still think we have filament loaded at this stage
|
||||||
// idler should be engaged
|
// idler should be engaged
|
||||||
// no change in selector's position
|
// no change in selector's position
|
||||||
// FINDA still on
|
// FINDA still on
|
||||||
// red LED should blink, green LED should be off
|
// red LED should blink, green LED should be off
|
||||||
REQUIRE(VerifyState(uf, true, slot, slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERR1HelpingFilament));
|
REQUIRE(VerifyState(uf, true, slot, slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERRHelpingFilament));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindaDidntTriggerResolveHelpFindaTriggered(uint8_t slot, logic::UnloadFilament &uf) {
|
void FindaDidntTriggerResolveHelpFindaTriggered(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
|
|
@ -215,7 +215,7 @@ void FindaDidntTriggerResolveHelpFindaTriggered(uint8_t slot, logic::UnloadFilam
|
||||||
if(step == 100){ // on 100th step make FINDA trigger
|
if(step == 100){ // on 100th step make FINDA trigger
|
||||||
hal::adc::SetADC(config::findaADCIndex, 0);
|
hal::adc::SetADC(config::findaADCIndex, 0);
|
||||||
}
|
}
|
||||||
return uf.TopLevelState() == ProgressCode::ERR1HelpingFilament; },
|
return uf.TopLevelState() == ProgressCode::ERRHelpingFilament; },
|
||||||
5000));
|
5000));
|
||||||
|
|
||||||
// we still think we have filament loaded at this stage
|
// we still think we have filament loaded at this stage
|
||||||
|
|
@ -228,14 +228,14 @@ void FindaDidntTriggerResolveHelpFindaTriggered(uint8_t slot, logic::UnloadFilam
|
||||||
|
|
||||||
void FindaDidntTriggerResolveHelpFindaDidntTrigger(uint8_t slot, logic::UnloadFilament &uf) {
|
void FindaDidntTriggerResolveHelpFindaDidntTrigger(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
// Stage 5 - move the pulley a bit - no FINDA change
|
// Stage 5 - move the pulley a bit - no FINDA change
|
||||||
REQUIRE(WhileTopState(uf, ProgressCode::ERR1HelpingFilament, 5000));
|
REQUIRE(WhileTopState(uf, ProgressCode::ERRHelpingFilament, 5000));
|
||||||
|
|
||||||
// we still think we have filament loaded at this stage
|
// we still think we have filament loaded at this stage
|
||||||
// idler should be engaged
|
// idler should be engaged
|
||||||
// no change in selector's position
|
// no change in selector's position
|
||||||
// FINDA still pressed
|
// FINDA still pressed
|
||||||
// red LED should blink, green LED should be off
|
// red LED should blink, green LED should be off
|
||||||
REQUIRE(VerifyState(uf, true, slot, slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERR1DisengagingIdler));
|
REQUIRE(VerifyState(uf, true, slot, slot, true, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERRDisengagingIdler));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("unload_filament::finda_didnt_trigger_resolve_help_second_ok", "[unload_filament]") {
|
TEST_CASE("unload_filament::finda_didnt_trigger_resolve_help_second_ok", "[unload_filament]") {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ add_executable(
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/globals.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/idler.cpp
|
||||||
${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/permanent_storage.cpp
|
${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue