First pass, improving the error recovery.
This commit is contained in:
parent
1e391f303c
commit
9a20c85a5d
|
|
@ -91,7 +91,7 @@ MMU2::MMU2()
|
||||||
, resume_hotend_temp(0)
|
, resume_hotend_temp(0)
|
||||||
, logicStepLastStatus(StepStatus::Finished)
|
, logicStepLastStatus(StepStatus::Finished)
|
||||||
, state(xState::Stopped)
|
, state(xState::Stopped)
|
||||||
, mmu_print_saved(false)
|
, mmu_print_saved(SavedState::None)
|
||||||
, loadFilamentStarted(false)
|
, loadFilamentStarted(false)
|
||||||
, loadingToNozzle(false)
|
, loadingToNozzle(false)
|
||||||
{
|
{
|
||||||
|
|
@ -458,15 +458,14 @@ void MMU2::Home(uint8_t mode){
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU2::SaveAndPark(bool move_axes, bool turn_off_nozzle) {
|
void MMU2::SaveAndPark(bool move_axes, bool turn_off_nozzle) {
|
||||||
if (!mmu_print_saved) { // First occurrence. Save current position, park print head, disable nozzle heater.
|
if (mmu_print_saved == SavedState::None) { // First occurrence. Save current position, park print head, disable nozzle heater.
|
||||||
LogEchoEvent("Saving and parking");
|
LogEchoEvent("Saving and parking");
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
|
|
||||||
mmu_print_saved = true;
|
|
||||||
|
|
||||||
resume_hotend_temp = degTargetHotend(active_extruder);
|
resume_hotend_temp = degTargetHotend(active_extruder);
|
||||||
|
|
||||||
if (move_axes){
|
if (move_axes){
|
||||||
|
mmu_print_saved |= SavedState::ParkExtruder;
|
||||||
// save current pos
|
// save current pos
|
||||||
for(uint8_t i = 0; i < 3; ++i){
|
for(uint8_t i = 0; i < 3; ++i){
|
||||||
resume_position.xyz[i] = current_position[i];
|
resume_position.xyz[i] = current_position[i];
|
||||||
|
|
@ -487,6 +486,7 @@ void MMU2::SaveAndPark(bool move_axes, bool turn_off_nozzle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (turn_off_nozzle){
|
if (turn_off_nozzle){
|
||||||
|
mmu_print_saved |= SavedState::Cooldown;
|
||||||
LogEchoEvent("Heater off");
|
LogEchoEvent("Heater off");
|
||||||
setAllTargetHotends(0);
|
setAllTargetHotends(0);
|
||||||
}
|
}
|
||||||
|
|
@ -496,35 +496,37 @@ void MMU2::SaveAndPark(bool move_axes, bool turn_off_nozzle) {
|
||||||
// gcode.reset_stepper_timeout();
|
// gcode.reset_stepper_timeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU2::ResumeAndUnPark(bool move_axes, bool turn_off_nozzle) {
|
void MMU2::ResumeHotendTemp() {
|
||||||
if (mmu_print_saved) {
|
if ((mmu_print_saved & SavedState::Cooldown) && resume_hotend_temp) {
|
||||||
LogEchoEvent("Resuming print");
|
LogEchoEvent("Resuming Temp");
|
||||||
|
MMU2_ECHO_MSG("Restoring hotend temperature ");
|
||||||
|
SERIAL_ECHOLN(resume_hotend_temp);
|
||||||
|
setTargetHotend(resume_hotend_temp, active_extruder);
|
||||||
|
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature...")); // better report the event and let the GUI do its work somewhere else
|
||||||
|
ReportErrorHookSensorLineRender();
|
||||||
|
waitForHotendTargetTemp(1000, []{
|
||||||
|
ReportErrorHookDynamicRender();
|
||||||
|
});
|
||||||
|
LogEchoEvent("Hotend temperature reached");
|
||||||
|
lcd_update_enable(true); // temporary hack to stop this locking the printer...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (turn_off_nozzle && resume_hotend_temp) {
|
void MMU2::ResumeUnpark()
|
||||||
MMU2_ECHO_MSG("Restoring hotend temperature ");
|
{
|
||||||
SERIAL_ECHOLN(resume_hotend_temp);
|
if (mmu_print_saved & SavedState::ParkExtruder) {
|
||||||
setTargetHotend(resume_hotend_temp, active_extruder);
|
LogEchoEvent("Resuming XYZ");
|
||||||
waitForHotendTargetTemp(3000, []{
|
|
||||||
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature...")); // better report the event and let the GUI do its work somewhere else
|
|
||||||
});
|
|
||||||
LogEchoEvent("Hotend temperature reached");
|
|
||||||
lcd_update_enable(true); // temporary hack to stop this locking the printer...
|
|
||||||
}
|
|
||||||
|
|
||||||
if (move_axes) {
|
current_position[X_AXIS] = resume_position.xyz[X_AXIS];
|
||||||
LogEchoEvent("Resuming XYZ");
|
current_position[Y_AXIS] = resume_position.xyz[Y_AXIS];
|
||||||
|
plan_buffer_line_curposXYZE(NOZZLE_PARK_XY_FEEDRATE);
|
||||||
current_position[X_AXIS] = resume_position.xyz[X_AXIS];
|
st_synchronize();
|
||||||
current_position[Y_AXIS] = resume_position.xyz[Y_AXIS];
|
|
||||||
plan_buffer_line_curposXYZE(NOZZLE_PARK_XY_FEEDRATE);
|
current_position[Z_AXIS] = resume_position.xyz[Z_AXIS];
|
||||||
st_synchronize();
|
plan_buffer_line_curposXYZE(NOZZLE_PARK_Z_FEEDRATE);
|
||||||
|
st_synchronize();
|
||||||
current_position[Z_AXIS] = resume_position.xyz[Z_AXIS];
|
} else {
|
||||||
plan_buffer_line_curposXYZE(NOZZLE_PARK_Z_FEEDRATE);
|
LogEchoEvent("NOT resuming XYZ");
|
||||||
st_synchronize();
|
|
||||||
} else {
|
|
||||||
LogEchoEvent("NOT resuming XYZ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -534,6 +536,7 @@ void MMU2::CheckUserInput(){
|
||||||
case Left:
|
case Left:
|
||||||
case Middle:
|
case Middle:
|
||||||
case Right:
|
case Right:
|
||||||
|
ResumeHotendTemp(); // Recover the hotend temp before we attempt to do anything else...
|
||||||
Button(btn);
|
Button(btn);
|
||||||
break;
|
break;
|
||||||
case RestartMMU:
|
case RestartMMU:
|
||||||
|
|
@ -559,7 +562,7 @@ void MMU2::CheckUserInput(){
|
||||||
/// 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) {
|
void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
|
||||||
mmu_print_saved = false;
|
mmu_print_saved = SavedState::None;
|
||||||
|
|
||||||
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
||||||
|
|
||||||
|
|
@ -577,7 +580,7 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
|
||||||
case Finished:
|
case Finished:
|
||||||
// command/operation completed, let Marlin continue its work
|
// command/operation completed, let Marlin continue its work
|
||||||
// the E may have some more moves to finish - wait for them
|
// the E may have some more moves to finish - wait for them
|
||||||
ResumeAndUnPark(move_axes, turn_off_nozzle); // This is needed here otherwise recovery doesn't work.
|
ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved.
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
return;
|
return;
|
||||||
case VersionMismatch: // this basically means the MMU will be disabled until reconnected
|
case VersionMismatch: // this basically means the MMU will be disabled until reconnected
|
||||||
|
|
@ -591,7 +594,8 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
|
||||||
break;
|
break;
|
||||||
case CommunicationRecovered: // @@TODO communication recovered and may be an error recovered as well
|
case CommunicationRecovered: // @@TODO communication recovered and may be an error recovered as well
|
||||||
// may be the logic layer can detect the change of state a respond with one "Recovered" to be handled here
|
// may be the logic layer can detect the change of state a respond with one "Recovered" to be handled here
|
||||||
ResumeAndUnPark(move_axes, turn_off_nozzle);
|
ResumeHotendTemp();
|
||||||
|
ResumeUnpark();
|
||||||
break;
|
break;
|
||||||
case Processing: // wait for the MMU to respond
|
case Processing: // wait for the MMU to respond
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,13 @@ public:
|
||||||
ResetPin = 1, ///< trigger the reset pin of the MMU
|
ResetPin = 1, ///< trigger the reset pin of the MMU
|
||||||
CutThePower = 2 ///< power off and power on (that includes +5V and +24V power lines)
|
CutThePower = 2 ///< power off and power on (that includes +5V and +24V power lines)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Saved print state on error.
|
||||||
|
enum SavedState: uint8_t {
|
||||||
|
None = 0, // No state saved.
|
||||||
|
ParkExtruder = 1, // The extruder was parked.
|
||||||
|
Cooldown = 2, // The extruder was allowed to cool.
|
||||||
|
};
|
||||||
|
|
||||||
/// Perform a reset of the MMU
|
/// Perform a reset of the MMU
|
||||||
/// @param level physical form of the reset
|
/// @param level physical form of the reset
|
||||||
|
|
@ -143,7 +150,7 @@ public:
|
||||||
bool is_mmu_error_monitor_active;
|
bool is_mmu_error_monitor_active;
|
||||||
|
|
||||||
/// Method to read-only mmu_print_saved
|
/// Method to read-only mmu_print_saved
|
||||||
bool MMU_PRINT_SAVED() const { return mmu_print_saved; }
|
bool MMU_PRINT_SAVED() const { return mmu_print_saved != SavedState::None; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Perform software self-reset of the MMU (sends an X0 command)
|
/// Perform software self-reset of the MMU (sends an X0 command)
|
||||||
|
|
@ -193,8 +200,11 @@ private:
|
||||||
/// Save print and park the print head
|
/// Save print and park the print head
|
||||||
void SaveAndPark(bool move_axes, bool turn_off_nozzle);
|
void SaveAndPark(bool move_axes, bool turn_off_nozzle);
|
||||||
|
|
||||||
/// Resume print (unpark, turn on heating etc.)
|
/// Resume hotend temperature, if it was cooled. Safe to call if we aren't saved.
|
||||||
void ResumeAndUnPark(bool move_axes, bool turn_off_nozzle);
|
void ResumeHotendTemp();
|
||||||
|
|
||||||
|
/// Resume position, if the extruder was parked. Safe to all if state was not saved.
|
||||||
|
void ResumeUnpark();
|
||||||
|
|
||||||
/// Check for any button/user input coming from the printer's UI
|
/// Check for any button/user input coming from the printer's UI
|
||||||
void CheckUserInput();
|
void CheckUserInput();
|
||||||
|
|
@ -220,7 +230,7 @@ private:
|
||||||
|
|
||||||
enum xState state;
|
enum xState state;
|
||||||
|
|
||||||
bool mmu_print_saved;
|
uint8_t mmu_print_saved;
|
||||||
bool loadFilamentStarted;
|
bool loadFilamentStarted;
|
||||||
|
|
||||||
friend struct LoadingToNozzleRAII;
|
friend struct LoadingToNozzleRAII;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ enum class ResponseMsgParamCodes : uint8_t {
|
||||||
Error = 'E',
|
Error = 'E',
|
||||||
Finished = 'F',
|
Finished = 'F',
|
||||||
Accepted = 'A',
|
Accepted = 'A',
|
||||||
Rejected = 'R'
|
Rejected = 'R',
|
||||||
|
Button = 'B' // the MMU registered a button press and is sending it to the printer for processing
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A request message - requests are being sent by the printer into the MMU.
|
/// A request message - requests are being sent by the printer into the MMU.
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ void EndReport(CommandInProgress cip, uint16_t ec) {
|
||||||
* @brief Renders any characters that will be updated live on the MMU error screen.
|
* @brief Renders any characters that will be updated live on the MMU error screen.
|
||||||
*Currently, this is FINDA and Filament Sensor status and Extruder temperature.
|
*Currently, this is FINDA and Filament Sensor status and Extruder temperature.
|
||||||
*/
|
*/
|
||||||
static void ReportErrorHookDynamicRender(void)
|
extern void ReportErrorHookDynamicRender(void)
|
||||||
{
|
{
|
||||||
lcd_set_cursor(3, 2);
|
lcd_set_cursor(3, 2);
|
||||||
lcd_printf_P(PSTR("%d"), mmu2.FindaDetectsFilament());
|
lcd_printf_P(PSTR("%d"), mmu2.FindaDetectsFilament());
|
||||||
|
|
@ -78,17 +78,23 @@ static void ReportErrorHookStaticRender(uint8_t ei) {
|
||||||
lcd_update_enable(false);
|
lcd_update_enable(false);
|
||||||
lcd_clear();
|
lcd_clear();
|
||||||
|
|
||||||
|
ReportErrorHookSensorLineRender();
|
||||||
|
|
||||||
// Print title and header
|
// Print title and header
|
||||||
lcd_printf_P(PSTR("%.20S\nprusa3d.com/ERR04%hu"), _T(PrusaErrorTitle(ei)), PrusaErrorCode(ei) );
|
lcd_printf_P(PSTR("%.20S\nprusa3d.com/ERR04%hu"), _T(PrusaErrorTitle(ei)), PrusaErrorCode(ei) );
|
||||||
|
|
||||||
// Render static characters in third line
|
|
||||||
lcd_set_cursor(0, 2);
|
|
||||||
lcd_printf_P(PSTR("FI: FS: > %c %c"), LCD_STR_THERMOMETER[0], LCD_STR_DEGREE[0]);
|
|
||||||
|
|
||||||
// Render the choices
|
// Render the choices
|
||||||
lcd_show_choices_prompt_P(two_choices ? LCD_LEFT_BUTTON_CHOICE : LCD_MIDDLE_BUTTON_CHOICE, _T(PrusaErrorButtonTitle(button_op_middle)), _T(two_choices ? PrusaErrorButtonMore() : PrusaErrorButtonTitle(button_op_right)), two_choices ? 10 : 7, two_choices ? nullptr : _T(PrusaErrorButtonMore()));
|
lcd_show_choices_prompt_P(two_choices ? LCD_LEFT_BUTTON_CHOICE : LCD_MIDDLE_BUTTON_CHOICE, _T(PrusaErrorButtonTitle(button_op_middle)), _T(two_choices ? PrusaErrorButtonMore() : PrusaErrorButtonTitle(button_op_right)), two_choices ? 10 : 7, two_choices ? nullptr : _T(PrusaErrorButtonMore()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void ReportErrorHookSensorLineRender()
|
||||||
|
{
|
||||||
|
// Render static characters in third line
|
||||||
|
lcd_set_cursor(0, 2);
|
||||||
|
lcd_printf_P(PSTR("FI: FS: > %c %c"), LCD_STR_THERMOMETER[0], LCD_STR_DEGREE[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Monitors the LCD button selection without blocking MMU communication
|
* @brief Monitors the LCD button selection without blocking MMU communication
|
||||||
* @param[in] ei Error code index
|
* @param[in] ei Error code index
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@ void ReportErrorHook(uint16_t ec);
|
||||||
/// Called when the MMU sends operation progress update
|
/// Called when the MMU sends operation progress update
|
||||||
void ReportProgressHook(CommandInProgress cip, uint16_t ec);
|
void ReportProgressHook(CommandInProgress cip, uint16_t ec);
|
||||||
|
|
||||||
|
/// Remders the sensor status line. Also used by the "resume temperature" screen.
|
||||||
|
void ReportErrorHookDynamicRender();
|
||||||
|
|
||||||
|
/// Renders the static part of the sensor state line. Also used by "resuming temperature screen"
|
||||||
|
void ReportErrorHookSensorLineRender();
|
||||||
|
|
||||||
/// @returns true if the MMU is communicating and available
|
/// @returns true if the MMU is communicating and available
|
||||||
/// can change at runtime
|
/// can change at runtime
|
||||||
bool MMUAvailable();
|
bool MMUAvailable();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue