Recover from MMU restart while performing a command
PFW-1427
This commit is contained in:
parent
b8ae9e997b
commit
10a9e0f0a0
|
|
@ -193,8 +193,10 @@ void MMU2::PowerOn(){
|
||||||
bool MMU2::ReadRegister(uint8_t address){
|
bool MMU2::ReadRegister(uint8_t address){
|
||||||
if( ! WaitForMMUReady())
|
if( ! WaitForMMUReady())
|
||||||
return false;
|
return false;
|
||||||
logic.ReadRegister(address); // we may signal the accepted/rejected status of the response as return value of this function
|
do {
|
||||||
manage_response(false, false);
|
logic.ReadRegister(address); // we may signal the accepted/rejected status of the response as return value of this function
|
||||||
|
} while( ! manage_response(false, false) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,8 +209,10 @@ bool MMU2::WriteRegister(uint8_t address, uint16_t data){
|
||||||
logic.PlanExtraLoadDistance(data);
|
logic.PlanExtraLoadDistance(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
logic.WriteRegister(address, data); // we may signal the accepted/rejected status of the response as return value of this function
|
do {
|
||||||
manage_response(false, false);
|
logic.WriteRegister(address, data); // we may signal the accepted/rejected status of the response as return value of this function
|
||||||
|
} while( ! manage_response(false, false) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,8 +337,10 @@ bool MMU2::tool_change(uint8_t index) {
|
||||||
|
|
||||||
tool_change_extruder = index;
|
tool_change_extruder = index;
|
||||||
logic.ToolChange(index); // let the MMU pull the filament out and push a new one in
|
logic.ToolChange(index); // let the MMU pull the filament out and push a new one in
|
||||||
manage_response(true, true);
|
if( ! manage_response(true, true) ){
|
||||||
|
// @@TODO failed to perform the command - retry
|
||||||
|
;
|
||||||
|
}
|
||||||
// reset current position to whatever the planner thinks it is
|
// reset current position to whatever the planner thinks it is
|
||||||
plan_set_e_position(current_position[E_AXIS]);
|
plan_set_e_position(current_position[E_AXIS]);
|
||||||
|
|
||||||
|
|
@ -371,7 +377,10 @@ bool MMU2::tool_change(char code, uint8_t slot) {
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
tool_change_extruder = slot;
|
tool_change_extruder = slot;
|
||||||
logic.ToolChange(slot);
|
logic.ToolChange(slot);
|
||||||
manage_response(false, false);
|
if( ! manage_response(false, false) ){
|
||||||
|
// @@TODO failed to perform the command - retry
|
||||||
|
;
|
||||||
|
}
|
||||||
extruder = slot;
|
extruder = slot;
|
||||||
SpoolJoin::spooljoin.setSlot(slot);
|
SpoolJoin::spooljoin.setSlot(slot);
|
||||||
set_extrude_min_temp(EXTRUDE_MINTEMP);
|
set_extrude_min_temp(EXTRUDE_MINTEMP);
|
||||||
|
|
@ -409,7 +418,10 @@ bool MMU2::set_filament_type(uint8_t index, uint8_t type) {
|
||||||
// cmd_arg = filamentType;
|
// cmd_arg = filamentType;
|
||||||
// command(MMU_CMD_F0 + index);
|
// command(MMU_CMD_F0 + index);
|
||||||
|
|
||||||
manage_response(false, false); // true, true); -- Comment: how is it possible for a filament type set to fail?
|
if( ! manage_response(false, false) ){
|
||||||
|
// @@TODO failed to perform the command - retry
|
||||||
|
;
|
||||||
|
} // true, true); -- Comment: how is it possible for a filament type set to fail?
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -426,7 +438,10 @@ bool MMU2::unload() {
|
||||||
filament_ramming();
|
filament_ramming();
|
||||||
|
|
||||||
logic.UnloadFilament();
|
logic.UnloadFilament();
|
||||||
manage_response(false, true);
|
if( ! manage_response(false, true) ){
|
||||||
|
// @@TODO failed to perform the command - retry
|
||||||
|
;
|
||||||
|
}
|
||||||
Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
|
Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
|
||||||
|
|
||||||
// no active tool
|
// no active tool
|
||||||
|
|
@ -442,7 +457,10 @@ bool MMU2::cut_filament(uint8_t index){
|
||||||
|
|
||||||
ReportingRAII rep(CommandInProgress::CutFilament);
|
ReportingRAII rep(CommandInProgress::CutFilament);
|
||||||
logic.CutFilament(index);
|
logic.CutFilament(index);
|
||||||
manage_response(false, true);
|
if( ! manage_response(false, true) ){
|
||||||
|
// @@TODO failed to perform the command - retry
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -472,7 +490,10 @@ bool MMU2::load_filament(uint8_t index) {
|
||||||
|
|
||||||
ReportingRAII rep(CommandInProgress::LoadFilament);
|
ReportingRAII rep(CommandInProgress::LoadFilament);
|
||||||
logic.LoadFilament(index);
|
logic.LoadFilament(index);
|
||||||
manage_response(false, false);
|
if( ! manage_response(false, false) ){
|
||||||
|
// @@TODO failed to perform the command - retry
|
||||||
|
;
|
||||||
|
}
|
||||||
Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
|
Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
|
||||||
|
|
||||||
lcd_update_enable(true);
|
lcd_update_enable(true);
|
||||||
|
|
@ -510,7 +531,10 @@ bool MMU2::load_filament_to_nozzle(uint8_t index) {
|
||||||
|
|
||||||
tool_change_extruder = index;
|
tool_change_extruder = index;
|
||||||
logic.ToolChange(index);
|
logic.ToolChange(index);
|
||||||
manage_response(true, true);
|
if( ! manage_response(true, true) ){
|
||||||
|
// @@TODO failed to perform the command - retry
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
// The MMU's idler is disengaged at this point
|
// The MMU's idler is disengaged at this point
|
||||||
// That means the MK3/S now has fully control
|
// That means the MK3/S now has fully control
|
||||||
|
|
@ -541,7 +565,10 @@ bool MMU2::eject_filament(uint8_t index, bool recover) {
|
||||||
plan_buffer_line_curposXYZE(2500.F / 60.F);
|
plan_buffer_line_curposXYZE(2500.F / 60.F);
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
logic.EjectFilament(index);
|
logic.EjectFilament(index);
|
||||||
manage_response(false, false);
|
if( ! manage_response(false, false) ){
|
||||||
|
// @@TODO failed to perform the command - retry
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
if (recover) {
|
if (recover) {
|
||||||
// LCD_MESSAGEPGM(MSG_MMU2_EJECT_RECOVER);
|
// LCD_MESSAGEPGM(MSG_MMU2_EJECT_RECOVER);
|
||||||
|
|
@ -559,7 +586,10 @@ bool MMU2::eject_filament(uint8_t index, bool recover) {
|
||||||
|
|
||||||
Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
|
Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
|
||||||
// logic.Command(); //@@TODO command(MMU_CMD_R0);
|
// logic.Command(); //@@TODO command(MMU_CMD_R0);
|
||||||
manage_response(false, false);
|
if( ! manage_response(false, false) ){
|
||||||
|
// @@TODO failed to perform the command - retry
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no active tool
|
// no active tool
|
||||||
|
|
@ -702,7 +732,7 @@ void MMU2::CheckUserInput(){
|
||||||
/// It is closely related to mmu_loop() (which corresponds to our ProtocolLogic::Step()), which does NOT perform any blocking wait for a command to finish.
|
/// It is closely related to mmu_loop() (which corresponds to our ProtocolLogic::Step()), which does NOT perform any blocking wait for a command to finish.
|
||||||
/// But - in case of an error, the command is not yet finished, but we must react accordingly - move the printhead elsewhere, stop heating, eat a cat or so.
|
/// But - in case of an error, the command is not yet finished, but we must react accordingly - move the printhead elsewhere, stop heating, eat a cat or so.
|
||||||
/// That's what's being done here...
|
/// That's what's being done here...
|
||||||
void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
|
bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
|
||||||
mmu_print_saved = SavedState::None;
|
mmu_print_saved = SavedState::None;
|
||||||
|
|
||||||
KEEPALIVE_STATE(IN_PROCESS);
|
KEEPALIVE_STATE(IN_PROCESS);
|
||||||
|
|
@ -741,10 +771,13 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
|
||||||
ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved.
|
ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved.
|
||||||
ResetRetryAttempts(); // Reset the retry counter.
|
ResetRetryAttempts(); // Reset the retry counter.
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
return;
|
return true;
|
||||||
|
case Interrupted:
|
||||||
|
// 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 VersionMismatch: // this basically means the MMU will be disabled until reconnected
|
||||||
CheckUserInput();
|
CheckUserInput();
|
||||||
return;
|
return true;
|
||||||
case CommandError:
|
case CommandError:
|
||||||
// Don't proceed to the park/save if we are doing an autoretry.
|
// Don't proceed to the park/save if we are doing an autoretry.
|
||||||
if (inAutoRetry){
|
if (inAutoRetry){
|
||||||
|
|
@ -784,6 +817,9 @@ StepStatus MMU2::LogicStep(bool reportErrors) {
|
||||||
LogEchoEvent_P(PSTR("MMU Button pushed"));
|
LogEchoEvent_P(PSTR("MMU Button pushed"));
|
||||||
CheckUserInput(); // Process the button immediately
|
CheckUserInput(); // Process the button immediately
|
||||||
break;
|
break;
|
||||||
|
case Interrupted:
|
||||||
|
// can be silently handed over to a higher layer, no processing necessary at this spot
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if(reportErrors) {
|
if(reportErrors) {
|
||||||
switch (ss)
|
switch (ss)
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,8 @@ private:
|
||||||
|
|
||||||
/// Along with the mmu_loop method, this loops until a response from the MMU is received and acts upon.
|
/// Along with the mmu_loop method, this loops until a response from the MMU is received and acts upon.
|
||||||
/// In case of an error, it parks the print head and turns off nozzle heating
|
/// In case of an error, it parks the print head and turns off nozzle heating
|
||||||
void manage_response(const bool move_axes, const bool turn_off_nozzle);
|
/// @returns false if the command could not have been completed (MMU interrupted)
|
||||||
|
[[nodiscard]] bool manage_response(const bool move_axes, const bool turn_off_nozzle);
|
||||||
|
|
||||||
/// The inner private implementation of mmu_loop()
|
/// The inner private implementation of mmu_loop()
|
||||||
/// which is NOT (!!!) recursion-guarded. Use caution - but we do need it during waiting for hotend resume to keep comms alive!
|
/// which is NOT (!!!) recursion-guarded. Use caution - but we do need it during waiting for hotend resume to keep comms alive!
|
||||||
|
|
|
||||||
|
|
@ -295,11 +295,9 @@ StepStatus ProtocolLogic::StartSeqStep() {
|
||||||
return Processing; // Returning Finished is not a good idea in case of a fast error recovery
|
return Processing; // Returning Finished is not a good idea in case of a fast error recovery
|
||||||
// - it tells the printer, that the command which experienced a protocol error and recovered successfully actually terminated.
|
// - it tells the printer, that the command which experienced a protocol error and recovered successfully actually terminated.
|
||||||
// In such a case we must return "Processing" in order to keep the MMU state machine running and prevent the printer from executing next G-codes.
|
// In such a case we must return "Processing" in order to keep the MMU state machine running and prevent the printer from executing next G-codes.
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return VersionMismatch;
|
return VersionMismatch;
|
||||||
}
|
}
|
||||||
return Finished;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StepStatus ProtocolLogic::DelayedRestartWait() {
|
StepStatus ProtocolLogic::DelayedRestartWait() {
|
||||||
|
|
@ -344,9 +342,16 @@ StepStatus ProtocolLogic::ProcessCommandQueryResponse() {
|
||||||
SendAndUpdateFilamentSensor();
|
SendAndUpdateFilamentSensor();
|
||||||
return ButtonPushed;
|
return ButtonPushed;
|
||||||
case ResponseMsgParamCodes::Finished:
|
case ResponseMsgParamCodes::Finished:
|
||||||
progressCode = ProgressCode::OK;
|
// We must check whether the "finished" is actually related to the command issued into the MMU
|
||||||
scopeState = ScopeState::Ready;
|
// It can also be an X0 F which means MMU just successfully restarted.
|
||||||
return Finished;
|
if( ReqMsg().code == rsp.request.code && ReqMsg().value == rsp.request.value ){
|
||||||
|
progressCode = ProgressCode::OK;
|
||||||
|
scopeState = ScopeState::Ready;
|
||||||
|
return Finished;
|
||||||
|
} else {
|
||||||
|
// got response to some other command - the originally issued command was interrupted!
|
||||||
|
return Interrupted;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return ProtocolError;
|
return ProtocolError;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ class ProtocolLogic;
|
||||||
enum StepStatus : uint_fast8_t {
|
enum StepStatus : uint_fast8_t {
|
||||||
Processing = 0,
|
Processing = 0,
|
||||||
MessageReady, ///< a message has been successfully decoded from the received bytes
|
MessageReady, ///< a message has been successfully decoded from the received bytes
|
||||||
Finished,
|
Finished, ///< Scope finished successfully
|
||||||
|
Interrupted, ///< received "Finished" message related to a different command than originally issued (most likely the MMU restarted while doing something)
|
||||||
CommunicationTimeout, ///< the MMU failed to respond to a request within a specified time frame
|
CommunicationTimeout, ///< the MMU failed to respond to a request within a specified time frame
|
||||||
ProtocolError, ///< bytes read from the MMU didn't form a valid response
|
ProtocolError, ///< bytes read from the MMU didn't form a valid response
|
||||||
CommandRejected, ///< the MMU rejected the command due to some other command in progress, may be the user is operating the MMU locally (button commands)
|
CommandRejected, ///< the MMU rejected the command due to some other command in progress, may be the user is operating the MMU locally (button commands)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue