First pass, improving the error recovery.

This commit is contained in:
VintagePC 2022-06-18 10:17:56 -04:00 committed by D.R.racer
parent 1e391f303c
commit 9a20c85a5d
5 changed files with 72 additions and 45 deletions

View File

@ -91,7 +91,7 @@ MMU2::MMU2()
, resume_hotend_temp(0)
, logicStepLastStatus(StepStatus::Finished)
, state(xState::Stopped)
, mmu_print_saved(false)
, mmu_print_saved(SavedState::None)
, loadFilamentStarted(false)
, loadingToNozzle(false)
{
@ -458,15 +458,14 @@ void MMU2::Home(uint8_t mode){
}
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");
st_synchronize();
mmu_print_saved = true;
resume_hotend_temp = degTargetHotend(active_extruder);
if (move_axes){
mmu_print_saved |= SavedState::ParkExtruder;
// save current pos
for(uint8_t i = 0; i < 3; ++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){
mmu_print_saved |= SavedState::Cooldown;
LogEchoEvent("Heater off");
setAllTargetHotends(0);
}
@ -496,35 +496,37 @@ void MMU2::SaveAndPark(bool move_axes, bool turn_off_nozzle) {
// gcode.reset_stepper_timeout();
}
void MMU2::ResumeAndUnPark(bool move_axes, bool turn_off_nozzle) {
if (mmu_print_saved) {
LogEchoEvent("Resuming print");
void MMU2::ResumeHotendTemp() {
if ((mmu_print_saved & SavedState::Cooldown) && resume_hotend_temp) {
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) {
MMU2_ECHO_MSG("Restoring hotend temperature ");
SERIAL_ECHOLN(resume_hotend_temp);
setTargetHotend(resume_hotend_temp, active_extruder);
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...
}
void MMU2::ResumeUnpark()
{
if (mmu_print_saved & SavedState::ParkExtruder) {
LogEchoEvent("Resuming XYZ");
if (move_axes) {
LogEchoEvent("Resuming XYZ");
current_position[X_AXIS] = resume_position.xyz[X_AXIS];
current_position[Y_AXIS] = resume_position.xyz[Y_AXIS];
plan_buffer_line_curposXYZE(NOZZLE_PARK_XY_FEEDRATE);
st_synchronize();
current_position[Z_AXIS] = resume_position.xyz[Z_AXIS];
plan_buffer_line_curposXYZE(NOZZLE_PARK_Z_FEEDRATE);
st_synchronize();
} else {
LogEchoEvent("NOT resuming XYZ");
}
current_position[X_AXIS] = resume_position.xyz[X_AXIS];
current_position[Y_AXIS] = resume_position.xyz[Y_AXIS];
plan_buffer_line_curposXYZE(NOZZLE_PARK_XY_FEEDRATE);
st_synchronize();
current_position[Z_AXIS] = resume_position.xyz[Z_AXIS];
plan_buffer_line_curposXYZE(NOZZLE_PARK_Z_FEEDRATE);
st_synchronize();
} else {
LogEchoEvent("NOT resuming XYZ");
}
}
@ -534,6 +536,7 @@ void MMU2::CheckUserInput(){
case Left:
case Middle:
case Right:
ResumeHotendTemp(); // Recover the hotend temp before we attempt to do anything else...
Button(btn);
break;
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.
/// That's what's being done here...
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);
@ -577,7 +580,7 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
case Finished:
// command/operation completed, let Marlin continue its work
// 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();
return;
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;
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
ResumeAndUnPark(move_axes, turn_off_nozzle);
ResumeHotendTemp();
ResumeUnpark();
break;
case Processing: // wait for the MMU to respond
default:

View File

@ -58,6 +58,13 @@ public:
ResetPin = 1, ///< trigger the reset pin of the MMU
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
/// @param level physical form of the reset
@ -143,7 +150,7 @@ public:
bool is_mmu_error_monitor_active;
/// 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:
/// Perform software self-reset of the MMU (sends an X0 command)
@ -193,8 +200,11 @@ private:
/// Save print and park the print head
void SaveAndPark(bool move_axes, bool turn_off_nozzle);
/// Resume print (unpark, turn on heating etc.)
void ResumeAndUnPark(bool move_axes, bool turn_off_nozzle);
/// Resume hotend temperature, if it was cooled. Safe to call if we aren't saved.
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
void CheckUserInput();
@ -220,7 +230,7 @@ private:
enum xState state;
bool mmu_print_saved;
uint8_t mmu_print_saved;
bool loadFilamentStarted;
friend struct LoadingToNozzleRAII;

View File

@ -37,7 +37,8 @@ enum class ResponseMsgParamCodes : uint8_t {
Error = 'E',
Finished = 'F',
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.

View File

@ -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.
*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_printf_P(PSTR("%d"), mmu2.FindaDetectsFilament());
@ -78,17 +78,23 @@ static void ReportErrorHookStaticRender(uint8_t ei) {
lcd_update_enable(false);
lcd_clear();
ReportErrorHookSensorLineRender();
// Print title and header
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
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
* @param[in] ei Error code index

View File

@ -28,6 +28,12 @@ void ReportErrorHook(uint16_t ec);
/// Called when the MMU sends operation progress update
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
/// can change at runtime
bool MMUAvailable();