Fixes from tests

- introduce Cut Filament
- limit retries try-unload
- fix waiting in "Load to extruder failed" error screen
- add LOAD_TO_EXTRUDER_FAILED error definition
This commit is contained in:
D.R.racer 2022-12-27 12:18:11 +01:00 committed by DRracer
parent a30ea1c5ab
commit d4f0f363cd
6 changed files with 81 additions and 48 deletions

View File

@ -273,52 +273,52 @@ bool MMU2::VerifyFilamentEnteredPTFE()
}
}
void MMU2::ToolChangeCommon(uint8_t slot){
for(;;) { // while not successfully fed into extruder's PTFE tube
uint8_t retries = 3;
for(/*nothing*/; retries; --retries){
for(;;) {
tool_change_extruder = slot;
logic.ToolChange(slot); // let the MMU pull the filament out and push a new one in
if( manage_response(true, true) )
break;
// otherwise: failed to perform the command - unload first and then let it run again
IncrementMMUFails();
// just in case we stood in an error screen for too long and the hotend got cold
ResumeHotendTemp();
// if the extruder has been parked, it will get unparked once the ToolChange command finishes OK
// - so no ResumeUnpark() at this spot
unload();
// if we run out of retries, we must do something ... may be raise an error screen and allow the user to do something
// but honestly - if the MMU restarts during every toolchange,
// something else is seriously broken and stopping a print is probably our best option.
}
// reset current position to whatever the planner thinks it is
plan_set_e_position(current_position[E_AXIS]);
if (VerifyFilamentEnteredPTFE()){
bool MMU2::ToolChangeCommonOnce(uint8_t slot){
static_assert(MAX_RETRIES > 1); // need >1 retries to do the cut in the last attempt
for(uint8_t retries = MAX_RETRIES; retries; --retries){
for(;;) {
tool_change_extruder = slot;
logic.ToolChange(slot); // let the MMU pull the filament out and push a new one in
if( manage_response(true, true) )
break;
} else { // Prepare a retry attempt
unload(); // @@TODO cut filament
// cut_filament(slot);
// otherwise: failed to perform the command - unload first and then let it run again
IncrementMMUFails();
// just in case we stood in an error screen for too long and the hotend got cold
ResumeHotendTemp();
// if the extruder has been parked, it will get unparked once the ToolChange command finishes OK
// - so no ResumeUnpark() at this spot
unload();
// if we run out of retries, we must do something ... may be raise an error screen and allow the user to do something
// but honestly - if the MMU restarts during every toolchange,
// something else is seriously broken and stopping a print is probably our best option.
}
// reset current position to whatever the planner thinks it is
plan_set_e_position(current_position[E_AXIS]);
if (VerifyFilamentEnteredPTFE()){
return true; // success
} else { // Prepare a retry attempt
unload();
if( retries == 1 && eeprom_read_byte((uint8_t*)EEPROM_MMU_CUTTER_ENABLED) == EEPROM_MMU_CUTTER_ENABLED_enabled){
cut_filament(slot); // try cutting filament tip at the last attempt
}
}
if( retries ){
// we were successful in pushing the filament into the nozzle
break;
} else {
// failed autoretry, report an error by forcing a "printer" error into the MMU infrastructure - it is a hack to leverage existing code
logic.SetPrinterError(ErrorCode::LOAD_TO_EXTRUDER_FAILED);
SaveAndPark(true);
SaveHotendTemp(true);
// We only have to wait for the user to fix the issue and press "Retry".
// @@TODO Do we need to process the return value of manage_response?
manage_response(true, true);
logic.ClearPrinterError();
ResumeHotendTemp();
ResumeUnpark();
}
}
return false; // couldn't accomplish the task
}
void MMU2::ToolChangeCommon(uint8_t slot){
while( ! ToolChangeCommonOnce(slot) ){ // while not successfully fed into extruder's PTFE tube
// failed autoretry, report an error by forcing a "printer" error into the MMU infrastructure - it is a hack to leverage existing code
logic.SetPrinterError(ErrorCode::LOAD_TO_EXTRUDER_FAILED);
SaveAndPark(true);
SaveHotendTemp(true);
// We only have to wait for the user to fix the issue and press "Retry".
// Please see CheckUserInput() for details how we "leave" manage_response.
// If manage_response returns false at this spot (MMU operation interrupted aka MMU reset)
// we can safely continue because the MMU is not doing an operation now.
manage_response(true, true);
}
extruder = slot; //filament change is finished
@ -686,6 +686,11 @@ void MMU2::CheckUserInput(){
SERIAL_ECHOPGM("CheckUserInput-btnLMR ");
SERIAL_ECHOLN(btn);
ResumeHotendTemp(); // Recover the hotend temp before we attempt to do anything else...
// In case of LOAD_TO_EXTRUDER_FAILED sending a button into the MMU has an interesting side effect
// - it triggers the standalone LoadFilament function on the current active slot.
// Considering the fact, that we are recovering from a failed load to extruder, this side effect is actually quite beneficial
// - it checks if the filament is correctly loaded in the MMU (we assume the user was playing with the filament to recover from the failed load)
Button(btn);
// A quick hack: for specific error codes move the E-motor every time.
@ -696,6 +701,13 @@ void MMU2::CheckUserInput(){
case ErrorCode::FSENSOR_TOO_EARLY:
HelpUnloadToFinda();
break;
case ErrorCode::LOAD_TO_EXTRUDER_FAILED:
// A horrible hack - clear the explicit printer error allowing manage_response to recover on MMU's Finished state
// Moreover - if the MMU is currently doing something (like the LoadFilament - see comment above)
// we'll actually wait for it automagically in manage_response and after it finishes correctly,
// we'll issue another command (like toolchange)
logic.ClearPrinterError();
break;
default:
break;
}
@ -767,9 +779,13 @@ bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
// now what :D ... big bad ... ramming, unload, retry the whole command originally issued
return false;
case VersionMismatch: // this basically means the MMU will be disabled until reconnected
case PrinterError:
CheckUserInput();
return true;
case PrinterError:
CheckUserInput();
// if button pressed "Done", return true, otherwise stay within manage_response
// Please see CheckUserInput() for details how we "leave" manage_response
break;
case CommandError:
case CommunicationTimeout:
case ProtocolError:

View File

@ -294,6 +294,7 @@ private:
/// Common processing of pushing filament into the extruder - shared by tool_change, load_to_nozzle and probably others
void ToolChangeCommon(uint8_t slot);
bool ToolChangeCommonOnce(uint8_t slot);
void HelpUnloadToFinda();

View File

@ -54,9 +54,8 @@ enum class ErrorCode : uint_fast16_t {
MOVE_IDLER_FAILED = MOVE_FAILED | TMC_IDLER_BIT, ///< E33033 the Idler was unable to move - unused at the time of creation, but added for completeness
MOVE_PULLEY_FAILED = MOVE_FAILED | TMC_PULLEY_BIT, ///< E32841 the Pulley was unable to move - unused at the time of creation, but added for completeness
LOAD_TO_EXTRUDER_FAILED = 0x802a, ///< E32811 internal error of the printer - try-load-unload sequence detected missing filament -> failed load into the nozzle
QUEUE_FULL = 0x802b, ///< E32811 internal logic error - attempt to move with a full queue
LOAD_TO_EXTRUDER_FAILED = 0x802b, ///< E32811 internal error of the printer - try-load-unload sequence detected missing filament -> failed load into the nozzle
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
MMU_NOT_RESPONDING = 0x802e, ///< E32814 internal error of the printer - communication with the MMU is not working

View File

@ -23,6 +23,7 @@ typedef enum : uint16_t {
ERR_MECHANICAL_PULLEY_CANNOT_MOVE = 105,
ERR_MECHANICAL_FSENSOR_TOO_EARLY = 106,
ERR_MECHANICAL_INSPECT_FINDA = 107,
ERR_MECHANICAL_LOAD_TO_EXTRUDER_FAILED = 108,
ERR_MECHANICAL_SELECTOR_CANNOT_HOME = 115,
ERR_MECHANICAL_SELECTOR_CANNOT_MOVE = 116,
ERR_MECHANICAL_IDLER_CANNOT_HOME = 125,
@ -87,6 +88,7 @@ static const constexpr uint16_t errorCodes[] PROGMEM = {
ERR_MECHANICAL_PULLEY_CANNOT_MOVE,
ERR_MECHANICAL_FSENSOR_TOO_EARLY,
ERR_MECHANICAL_INSPECT_FINDA,
ERR_MECHANICAL_LOAD_TO_EXTRUDER_FAILED,
ERR_MECHANICAL_SELECTOR_CANNOT_HOME,
ERR_MECHANICAL_SELECTOR_CANNOT_MOVE,
ERR_MECHANICAL_IDLER_CANNOT_HOME,
@ -130,6 +132,7 @@ static const char MSG_TITLE_FSENSOR_DIDNT_GO_OFF[] PROGMEM_I1 = ISTR("FSENSOR
static const char MSG_TITLE_PULLEY_CANNOT_MOVE[] PROGMEM_I1 = ISTR("PULLEY CANNOT MOVE"); ////MSG_TITLE_PULLEY_CANNOT_MOVE c=20
static const char MSG_TITLE_FSENSOR_TOO_EARLY[] PROGMEM_I1 = ISTR("FSENSOR TOO EARLY"); ////MSG_TITLE_FSENSOR_TOO_EARLY c=20
static const char MSG_TITLE_INSPECT_FINDA[] PROGMEM_I1 = ISTR("INSPECT FINDA"); ////MSG_TITLE_INSPECT_FINDA c=20
static const char MSG_TITLE_LOAD_TO_EXTRUDER_FAILED[] PROGMEM_I1 = ISTR("LOAD TO EXTR. FAILED"); ////MSG_TITLE_LOAD_TO_EXTRUDER_FAILED c=20
static const char MSG_TITLE_SELECTOR_CANNOT_MOVE[] PROGMEM_I1 = ISTR("SELECTOR CANNOT MOVE"); ////MSG_TITLE_SELECTOR_CANNOT_MOVE c=20
static const char MSG_TITLE_SELECTOR_CANNOT_HOME[] PROGMEM_I1 = ISTR("SELECTOR CANNOT HOME"); ////MSG_TITLE_SELECTOR_CANNOT_HOME c=20
static const char MSG_TITLE_IDLER_CANNOT_MOVE[] PROGMEM_I1 = ISTR("IDLER CANNOT MOVE"); ////MSG_TITLE_IDLER_CANNOT_MOVE c=20
@ -170,6 +173,7 @@ static const char * const errorTitles [] PROGMEM = {
_R(MSG_TITLE_PULLEY_CANNOT_MOVE),
_R(MSG_TITLE_FSENSOR_TOO_EARLY),
_R(MSG_TITLE_INSPECT_FINDA),
_R(MSG_TITLE_LOAD_TO_EXTRUDER_FAILED),
_R(MSG_TITLE_SELECTOR_CANNOT_HOME),
_R(MSG_TITLE_SELECTOR_CANNOT_MOVE),
_R(MSG_TITLE_IDLER_CANNOT_HOME),
@ -214,6 +218,7 @@ static const char MSG_DESC_FSENSOR_DIDNT_GO_OFF[] PROGMEM_I1 = ISTR("Filament se
static const char MSG_DESC_PULLEY_STALLED[] PROGMEM_I1 = ISTR("Pulley motor stalled. Ensure the pulley can move and check the wiring."); ////MSG_DESC_PULLEY_STALLED c=20 r=8
static const char MSG_DESC_FSENSOR_TOO_EARLY[] PROGMEM_I1 = ISTR("Filament sensor triggered too early while loading to extruder. Check there isn't anything stuck in PTFE tube. Check that sensor reads properly."); ////MSG_DESC_FSENSOR_TOO_EARLY c=20 r=8
static const char MSG_DESC_INSPECT_FINDA[] PROGMEM_I1 = ISTR("Selector can't move due to FINDA detecting a filament. Make sure no filament is in selector and FINDA works properly."); ////MSG_DESC_INSPECT_FINDA c=20 r=8
static const char MSG_DESC_LOAD_TO_EXTRUDER_FAILED[] PROGMEM_I1 = ISTR("@@TODO - load to extruder failed."); ////MSG_DESC_LOAD_TO_EXTRUDER_FAILED c=20 r=8
static const char MSG_DESC_SELECTOR_CANNOT_HOME[] PROGMEM_I1 = ISTR("The Selector cannot home properly. Check for anything blocking its movement."); ////MSG_DESC_SELECTOR_CANNOT_HOME c=20 r=8
static const char MSG_DESC_CANNOT_MOVE[] PROGMEM_I1 = ISTR("Can't move Selector or Idler."); /////MSG_DESC_CANNOT_MOVE c=20 r=4
//static const char MSG_DESC_SELECTOR_CANNOT_MOVE[] PROGMEM_I1 = ISTR("The Selector cannot move. Check for anything blocking its movement. Check the wiring is correct.");
@ -255,6 +260,7 @@ static const char * const errorDescs[] PROGMEM = {
_R(MSG_DESC_PULLEY_STALLED),
_R(MSG_DESC_FSENSOR_TOO_EARLY),
_R(MSG_DESC_INSPECT_FINDA),
_R(MSG_DESC_LOAD_TO_EXTRUDER_FAILED),
_R(MSG_DESC_SELECTOR_CANNOT_HOME),
_R(MSG_DESC_CANNOT_MOVE),
_R(MSG_DESC_IDLER_CANNOT_HOME),
@ -332,6 +338,7 @@ static const uint8_t errorButtons[] PROGMEM = {
Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//PULLEY_STALLED
Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//FSENSOR_TOO_EARLY
Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//INSPECT_FINDA
Btns(ButtonOperations::Continue, ButtonOperations::NoOperation),//LOAD_TO_EXTRUDER_FAILED
Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//SELECTOR_CANNOT_HOME
Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//SELECTOR_CANNOT_MOVE
Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//IDLER_CANNOT_HOME

View File

@ -49,6 +49,8 @@ uint8_t PrusaErrorCodeIndex(uint16_t ec) {
return FindErrorIndex(ERR_MECHANICAL_FSENSOR_TOO_EARLY);
case (uint16_t)ErrorCode::FINDA_FLICKERS:
return FindErrorIndex(ERR_MECHANICAL_INSPECT_FINDA);
case (uint16_t)ErrorCode::LOAD_TO_EXTRUDER_FAILED:
return FindErrorIndex(ERR_MECHANICAL_LOAD_TO_EXTRUDER_FAILED);
case (uint16_t)ErrorCode::STALLED_PULLEY:
case (uint16_t)ErrorCode::MOVE_PULLEY_FAILED:
@ -222,7 +224,14 @@ Buttons ButtonAvailable(uint16_t ec) {
break;
}
break;
case ERR_MECHANICAL_LOAD_TO_EXTRUDER_FAILED:
switch (buttonSelectedOperation) {
case ButtonOperations::Continue: // User solved the serious mechanical problem by hand - there is no other way around
return Middle;
default:
break;
}
break;
case ERR_TEMPERATURE_PULLEY_WARNING_TMC_TOO_HOT:
case ERR_TEMPERATURE_SELECTOR_WARNING_TMC_TOO_HOT:
case ERR_TEMPERATURE_IDLER_WARNING_TMC_TOO_HOT:

View File

@ -496,7 +496,8 @@ StepStatus ProtocolLogic::IdleStep() {
}
ProtocolLogic::ProtocolLogic(MMU2Serial *uart, uint8_t extraLoadDistance)
: currentScope(Scope::Stopped)
: explicitPrinterError(ErrorCode::OK)
, currentScope(Scope::Stopped)
, scopeState(ScopeState::Ready)
, plannedRq(RequestMsgCodes::unknown, 0)
, lastUARTActivityMs(0)