From 97b1632b4def77dbe7da8017d3aefcacd8367361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Sun, 10 Jul 2022 13:01:52 +0000 Subject: [PATCH 1/6] Limit build number to uint8_t (#49) Currently the MMU only sends one byte so there is no need in storing the version with two bytes --- Firmware/mmu2_protocol_logic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/mmu2_protocol_logic.h b/Firmware/mmu2_protocol_logic.h index a9109d7509..92257615f8 100644 --- a/Firmware/mmu2_protocol_logic.h +++ b/Firmware/mmu2_protocol_logic.h @@ -244,7 +244,7 @@ class ProtocolLogic { return mmuFwVersionMinor; } - inline uint16_t MmuFwVersionBuild() const { + inline uint8_t MmuFwVersionBuild() const { return mmuFwVersionBuild; } #ifndef UNITTEST @@ -320,7 +320,7 @@ class ProtocolLogic { bool findaPressed; uint8_t mmuFwVersionMajor, mmuFwVersionMinor; - uint16_t mmuFwVersionBuild; + uint8_t mmuFwVersionBuild; friend class ProtocolLogicPartBase; friend class Stopped; From fb96778a9d9c61d78fda0b9cd69c2dc87b19dc5f Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Thu, 23 Jun 2022 14:53:32 +0200 Subject: [PATCH 2/6] Perform 3xRetry automatically This is a draft PR showing the potential 3x retry implementation on the printer's side. It is much less code and looks more reliable than the same functionality in the MMU FW. Still, more work needs to be done: - [ ] Button is sent to the MMU even before returning from the parking position - [ ] Then the button is sent again - [ ] Then the printer runs out of retryAttempts We need to find a better spot to check for "automatic" retry and issuing of the buttons --- Firmware/mmu2.cpp | 22 ++++++++++++++++++++++ Firmware/mmu2.h | 12 +++++++++--- Firmware/mmu2_error_converter.cpp | 5 ++++- Firmware/mmu2_error_converter.h | 6 ++++++ Firmware/mmu2_reporting.cpp | 15 +++++++++++++-- 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index 26de0ab011..508de4b8b1 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -113,6 +113,7 @@ MMU2::MMU2() , unloadFilamentStarted(false) , loadingToNozzle(false) { + ResetRetryAttempts(); } void MMU2::Start() { @@ -223,6 +224,25 @@ bool MMU2::WaitForMMUReady(){ } } +bool MMU2::RetryIfPossible(uint16_t ec){ + if( retryAttempts ){ + SERIAL_ECHOPGM("retryAttempts=");SERIAL_ECHOLN((uint16_t)retryAttempts); + SetButtonResponse(ButtonOperations::Retry); + // check, that Retry is actually allowed on that operation + if( ButtonAvailable(ec) != NoButton ){ + SERIAL_ECHOLNPGM("RetryButtonPressed"); + --retryAttempts; // "used" one retry attempt + return true; + } + } + return false; +} + +void MMU2::ResetRetryAttempts(){ + SERIAL_ECHOLNPGM("ResetRetryAttempts"); + retryAttempts = 3; +} + bool MMU2::tool_change(uint8_t index) { if( ! WaitForMMUReady()) return false; @@ -484,6 +504,7 @@ bool MMU2::eject_filament(uint8_t index, bool recover) { } void MMU2::Button(uint8_t index){ + SERIAL_ECHOLNPGM("Button"); logic.Button(index); } @@ -586,6 +607,7 @@ void MMU2::CheckUserInput(){ case Left: case Middle: case Right: + SERIAL_ECHOLNPGM("CheckUserInput-btnLMR"); ResumeHotendTemp(); // Recover the hotend temp before we attempt to do anything else... Button(btn); break; diff --git a/Firmware/mmu2.h b/Firmware/mmu2.h index 0e749b0b31..2d0f271db6 100644 --- a/Firmware/mmu2.h +++ b/Firmware/mmu2.h @@ -159,6 +159,12 @@ class MMU2 { /// Method to read-only mmu_print_saved bool MMU_PRINT_SAVED() const { return mmu_print_saved != SavedState::None; } + /// Automagically "press" a Retry button if we have any retry attempts left + bool RetryIfPossible(uint16_t ec); + + /// Reset the retryAttempts back to the default value + void ResetRetryAttempts(); + private: /// Perform software self-reset of the MMU (sends an X0 command) void ResetX0(); @@ -215,13 +221,13 @@ class MMU2 { /// Check for any button/user input coming from the printer's UI void CheckUserInput(); - + /// Entry check of all external commands. /// It can wait until the MMU becomes ready. /// Optionally, it can also emit/display an error screen and the user can decide what to do next. /// @returns false if the MMU is not ready to perform the command (for whatever reason) bool WaitForMMUReady(); - + ProtocolLogic logic; ///< implementation of the protocol logic layer int extruder; ///< currently active slot in the MMU ... somewhat... not sure where to get it from yet uint8_t previous_extruder; ///< last active slot in the MMU, useful for M600 @@ -247,7 +253,7 @@ class MMU2 { /// unlike the mid-print ToolChange commands, which only load the first ~30mm and then the G-code takes over. bool loadingToNozzle; - + uint8_t retryAttempts; }; /// following Marlin's way of doing stuff - one and only instance of MMU implementation in the code base diff --git a/Firmware/mmu2_error_converter.cpp b/Firmware/mmu2_error_converter.cpp index a450e848c5..b035a628d7 100644 --- a/Firmware/mmu2_error_converter.cpp +++ b/Firmware/mmu2_error_converter.cpp @@ -166,7 +166,10 @@ Buttons ButtonPressed(uint16_t ec) { } ResetOnExit ros; // clear buttonSelectedOperation on exit from this call - + return ButtonAvailable(ec); +} + +Buttons ButtonAvailable(uint16_t ec) { uint8_t ei = PrusaErrorCodeIndex(ec); // The list of responses which occur in mmu error dialogs diff --git a/Firmware/mmu2_error_converter.h b/Firmware/mmu2_error_converter.h index 27dbfbce56..597cc35a5d 100644 --- a/Firmware/mmu2_error_converter.h +++ b/Firmware/mmu2_error_converter.h @@ -37,6 +37,12 @@ const char * const PrusaErrorButtonMore(); void SetButtonResponse(ButtonOperations rsp); /// @returns button index/code based on currently processed error/screen +/// Clears the "pressed" button upon exit Buttons ButtonPressed(uint16_t ec); +/// @returns button index/code based on currently processed error/screen +/// Used as a subfunction of ButtonPressed. +/// Does not clear the "pressed" button upon exit +Buttons ButtonAvailable(uint16_t ec); + } // namespace MMU2 diff --git a/Firmware/mmu2_reporting.cpp b/Firmware/mmu2_reporting.cpp index 4622703b2c..d94b9e7f50 100644 --- a/Firmware/mmu2_reporting.cpp +++ b/Firmware/mmu2_reporting.cpp @@ -204,12 +204,23 @@ enum ReportErrorHookStates ReportErrorHookState = ReportErrorHookStates::RENDER_ * @param[in] ec Error code */ void ReportErrorHook(uint16_t ec) { - if (mmu2.MMUCurrentErrorCode() == ErrorCode::OK) - { + +// SERIAL_ECHOPGM("ReportErrorHookState="); +// SERIAL_ECHOLN((int)ReportErrorHookState); + + if (mmu2.MMUCurrentErrorCode() == ErrorCode::OK) { // If the error code suddenly changes to OK, that means // a button was pushed on the MMU and the LCD should // dismiss the error screen until MMU raises a new error ReportErrorHookState = ReportErrorHookStates::DISMISS_ERROR_SCREEN; + mmu2.ResetRetryAttempts(); + } else { + // attempt an automatic Retry button + if( ReportErrorHookState == ReportErrorHookStates::MONITOR_SELECTION ){ + if( mmu2.RetryIfPossible(ec) ){ + ReportErrorHookState = ReportErrorHookStates::DISMISS_ERROR_SCREEN; + } + } } const uint8_t ei = PrusaErrorCodeIndex(ec); From 781ddb51417ffdd7e6be2977b724bb7df74cacf7 Mon Sep 17 00:00:00 2001 From: VintagePC <53943260+vintagepc@users.noreply.github.com> Date: Sun, 26 Jun 2022 13:58:25 -0400 Subject: [PATCH 3/6] An attempt at fixing the retry. Discussion needed. --- Firmware/mmu2.cpp | 28 ++++++++++++++++++++++++---- Firmware/mmu2.h | 9 +++++++-- Firmware/mmu2_protocol_logic.cpp | 13 +++++++++---- Firmware/mmu2_reporting.cpp | 1 - 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index 508de4b8b1..ccce0e7782 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -112,6 +112,7 @@ MMU2::MMU2() , loadFilamentStarted(false) , unloadFilamentStarted(false) , loadingToNozzle(false) + , inAutoRetry(false) { ResetRetryAttempts(); } @@ -230,11 +231,14 @@ bool MMU2::RetryIfPossible(uint16_t ec){ SetButtonResponse(ButtonOperations::Retry); // check, that Retry is actually allowed on that operation if( ButtonAvailable(ec) != NoButton ){ + inAutoRetry = true; SERIAL_ECHOLNPGM("RetryButtonPressed"); - --retryAttempts; // "used" one retry attempt + // We don't decrement until the button is acknowledged by the MMU. + //--retryAttempts; // "used" one retry attempt return true; } } + inAutoRetry = false; return false; } @@ -243,6 +247,14 @@ void MMU2::ResetRetryAttempts(){ retryAttempts = 3; } +void MMU2::DecrementRetryAttempts(){ + if (inAutoRetry && retryAttempts) + { + SERIAL_ECHOLNPGM("DecrementRetryAttempts"); + retryAttempts--; + } +} + bool MMU2::tool_change(uint8_t index) { if( ! WaitForMMUReady()) return false; @@ -607,7 +619,8 @@ void MMU2::CheckUserInput(){ case Left: case Middle: case Right: - SERIAL_ECHOLNPGM("CheckUserInput-btnLMR"); + SERIAL_ECHOPGM("CheckUserInput-btnLMR "); + SERIAL_ECHOLN(btn); ResumeHotendTemp(); // Recover the hotend temp before we attempt to do anything else... Button(btn); break; @@ -655,7 +668,7 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { if (!nozzleTimeout.running()) { nozzleTimeout.start(); - LogEchoEvent(" Cooling Timeout started"); + LogEchoEvent("Cooling Timeout started"); } else if (nozzleTimeout.expired(DEFAULT_SAFETYTIMER_TIME_MINS*60*1000ul)) // mins->msec. TODO: do we use the global or have our own independent timeout { @@ -676,13 +689,20 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { // command/operation completed, let Marlin continue its work // the E may have some more moves to finish - wait for them ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved. + ResetRetryAttempts(); // Reset the retry counter. st_synchronize(); return; case VersionMismatch: // this basically means the MMU will be disabled until reconnected CheckUserInput(); return; - case CommunicationTimeout: case CommandError: + // Don't proceed to the park/save if we are doing an autoretry. + if (inAutoRetry) + { + continue; + } + /* FALLTHRU */ + case CommunicationTimeout: case ProtocolError: SaveAndPark(move_axes, turn_off_nozzle); // and wait for the user to resolve the problem CheckUserInput(); diff --git a/Firmware/mmu2.h b/Firmware/mmu2.h index 2d0f271db6..509eb7beaf 100644 --- a/Firmware/mmu2.h +++ b/Firmware/mmu2.h @@ -162,10 +162,13 @@ class MMU2 { /// Automagically "press" a Retry button if we have any retry attempts left bool RetryIfPossible(uint16_t ec); - /// Reset the retryAttempts back to the default value - void ResetRetryAttempts(); + /// Decrement the retry attempts, if in a retry. + // Called by the MMU protocol when a sent button is acknowledged. + void DecrementRetryAttempts(); private: + /// Reset the retryAttempts back to the default value + void ResetRetryAttempts(); /// Perform software self-reset of the MMU (sends an X0 command) void ResetX0(); @@ -254,6 +257,8 @@ class MMU2 { bool loadingToNozzle; uint8_t retryAttempts; + + bool inAutoRetry; }; /// following Marlin's way of doing stuff - one and only instance of MMU implementation in the code base diff --git a/Firmware/mmu2_protocol_logic.cpp b/Firmware/mmu2_protocol_logic.cpp index ca5de501e0..b1cc8f4937 100644 --- a/Firmware/mmu2_protocol_logic.cpp +++ b/Firmware/mmu2_protocol_logic.cpp @@ -261,10 +261,15 @@ StepStatus Command::Step() { return ProcessFINDAReqSent(Processing, State::Wait); case State::ButtonSent:{ // button is never confirmed ... may be it should be - // auto expmsg = logic->ExpectingMessage(linkLayerTimeout); - // if (expmsg != MessageReady) - // return expmsg; - SendQuery(); + auto expmsg = logic->ExpectingMessage(linkLayerTimeout); + if (expmsg != MessageReady) + return expmsg; + if (logic->rsp.paramCode == ResponseMsgParamCodes::Accepted) + { + // Button was accepted, decrement the retry. + mmu2.DecrementRetryAttempts(); + } + SendAndUpdateFilamentSensor(); } break; default: return ProtocolError; diff --git a/Firmware/mmu2_reporting.cpp b/Firmware/mmu2_reporting.cpp index d94b9e7f50..f16a295c3e 100644 --- a/Firmware/mmu2_reporting.cpp +++ b/Firmware/mmu2_reporting.cpp @@ -213,7 +213,6 @@ void ReportErrorHook(uint16_t ec) { // a button was pushed on the MMU and the LCD should // dismiss the error screen until MMU raises a new error ReportErrorHookState = ReportErrorHookStates::DISMISS_ERROR_SCREEN; - mmu2.ResetRetryAttempts(); } else { // attempt an automatic Retry button if( ReportErrorHookState == ReportErrorHookStates::MONITOR_SELECTION ){ From 9c698278a1351764e1d8f06e4952b556c69e939e Mon Sep 17 00:00:00 2001 From: VintagePC <53943260+vintagepc@users.noreply.github.com> Date: Tue, 19 Jul 2022 20:08:19 -0400 Subject: [PATCH 4/6] Magic numbers are bad... --- Firmware/mmu2.cpp | 2 +- Firmware/mmu2.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index ccce0e7782..cedacdc4fc 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -244,7 +244,7 @@ bool MMU2::RetryIfPossible(uint16_t ec){ void MMU2::ResetRetryAttempts(){ SERIAL_ECHOLNPGM("ResetRetryAttempts"); - retryAttempts = 3; + retryAttempts = MAX_RETRIES; } void MMU2::DecrementRetryAttempts(){ diff --git a/Firmware/mmu2.h b/Firmware/mmu2.h index 509eb7beaf..a3c614eefa 100644 --- a/Firmware/mmu2.h +++ b/Firmware/mmu2.h @@ -6,6 +6,8 @@ struct E_Step; namespace MMU2 { +static constexpr uint8_t MAX_RETRIES = 3U; + /// @@TODO hmmm, 12 bytes... may be we can reduce that struct xyz_pos_t { float xyz[3]; From 96effd57cd5f7868d5f1de8e019eb883414a730c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Sun, 3 Jul 2022 16:21:48 +0000 Subject: [PATCH 5/6] PFW-1373 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the unload procedure when the user has paused a print then stopped the print after the temperature has reached below 175°C Now the E-motor will move as expected --- Firmware/Marlin.h | 1 + Firmware/Marlin_main.cpp | 18 +++++++++++------- Firmware/ultralcd.cpp | 14 ++++++++++++-- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 2f518cfcbe..60c13db91f 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -438,6 +438,7 @@ extern void print_physical_coordinates(); extern void print_mesh_bed_leveling_table(); extern void stop_and_save_print_to_ram(float z_move, float e_move); +void restore_extruder_temperture_from_ram(); extern void restore_print_from_ram_and_continue(float e_move); extern void cancel_saved_printing(); diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 41b10a4651..5de28744da 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -11307,6 +11307,16 @@ void stop_and_save_print_to_ram(float z_move, float e_move) } } +void restore_extruder_temperture_from_ram() { + if (degTargetHotend(saved_active_extruder) != saved_extruder_temperature) + { + setTargetHotendSafe(saved_extruder_temperature, saved_active_extruder); + heating_status = HeatingStatus::EXTRUDER_HEATING; + wait_for_heater(_millis(), saved_active_extruder); + heating_status = HeatingStatus::EXTRUDER_HEATING_COMPLETE; + } +} + //! @brief Restore print from ram //! //! Restore print saved by stop_and_save_print_to_ram(). Is blocking, restores @@ -11330,13 +11340,7 @@ void restore_print_from_ram_and_continue(float e_move) // current_position[axis] = st_get_position_mm(axis); active_extruder = saved_active_extruder; //restore active_extruder fanSpeed = saved_fanSpeed; - if (degTargetHotend(saved_active_extruder) != saved_extruder_temperature) - { - setTargetHotendSafe(saved_extruder_temperature, saved_active_extruder); - heating_status = HeatingStatus::EXTRUDER_HEATING; - wait_for_heater(_millis(), saved_active_extruder); - heating_status = HeatingStatus::EXTRUDER_HEATING_COMPLETE; - } + restore_extruder_temperture_from_ram(); axis_relative_modes ^= (-saved_extruder_relative_mode ^ axis_relative_modes) & E_AXIS_MASK; float e = saved_pos[E_AXIS] - e_move; plan_set_e_position(e); diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index fa06bf3d5e..7ce2e7c1cb 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -6296,7 +6296,7 @@ void lcd_print_stop() lcd_commands_step = 0; lcd_commands_type = LcdCommands::Idle; - lcd_cooldown(); //turns off heaters and fan; goes to status screen. + lcd_return_to_status(); current_position[Z_AXIS] += 10; //lift Z. plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60); @@ -6309,7 +6309,17 @@ void lcd_print_stop() } st_synchronize(); - if (MMU2::mmu2.Enabled()) MMU2::mmu2.unload(); //M702 C + if (MMU2::mmu2.Enabled()) + { + if (isPrintPaused) + { + // Restore temperature saved in ram after pausing print + restore_extruder_temperture_from_ram(); + } + MMU2::mmu2.unload(); //M702 C + } + + lcd_cooldown(); //turns off heaters and fan; goes to status screen. finishAndDisableSteppers(); //M84 From 7bf003d8d158f722e3c2af3c00a49f61c64dcfd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Mon, 11 Jul 2022 14:21:31 +0000 Subject: [PATCH 6/6] Fix typo --- Firmware/Marlin.h | 2 +- Firmware/Marlin_main.cpp | 4 ++-- Firmware/ultralcd.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 60c13db91f..e3bcc79f4c 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -438,7 +438,7 @@ extern void print_physical_coordinates(); extern void print_mesh_bed_leveling_table(); extern void stop_and_save_print_to_ram(float z_move, float e_move); -void restore_extruder_temperture_from_ram(); +void restore_extruder_temperature_from_ram(); extern void restore_print_from_ram_and_continue(float e_move); extern void cancel_saved_printing(); diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 5de28744da..32315b03e0 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -11307,7 +11307,7 @@ void stop_and_save_print_to_ram(float z_move, float e_move) } } -void restore_extruder_temperture_from_ram() { +void restore_extruder_temperature_from_ram() { if (degTargetHotend(saved_active_extruder) != saved_extruder_temperature) { setTargetHotendSafe(saved_extruder_temperature, saved_active_extruder); @@ -11340,7 +11340,7 @@ void restore_print_from_ram_and_continue(float e_move) // current_position[axis] = st_get_position_mm(axis); active_extruder = saved_active_extruder; //restore active_extruder fanSpeed = saved_fanSpeed; - restore_extruder_temperture_from_ram(); + restore_extruder_temperature_from_ram(); axis_relative_modes ^= (-saved_extruder_relative_mode ^ axis_relative_modes) & E_AXIS_MASK; float e = saved_pos[E_AXIS] - e_move; plan_set_e_position(e); diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 7ce2e7c1cb..d3883cdbf8 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -6314,7 +6314,7 @@ void lcd_print_stop() if (isPrintPaused) { // Restore temperature saved in ram after pausing print - restore_extruder_temperture_from_ram(); + restore_extruder_temperature_from_ram(); } MMU2::mmu2.unload(); //M702 C }