From 4eaabbf092e2f8a85b85de3a034daa69bab1c834 Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Sat, 19 Nov 2022 15:09:06 +0100 Subject: [PATCH] Revive MMU stats + LCD screens --- Firmware/Marlin_main.cpp | 23 +++++++++--------- Firmware/messages.cpp | 1 + Firmware/messages.h | 1 + Firmware/mmu2.cpp | 48 ++++++++++++++++++------------------- Firmware/mmu2.h | 17 ++++++------- Firmware/mmu2_reporting.cpp | 32 ++++++++++++++++++------- Firmware/mmu2_reporting.h | 7 ++++++ Firmware/ultralcd.cpp | 46 +++++++++++++++-------------------- 8 files changed, 93 insertions(+), 82 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 2129cee2d..b1922e2a8 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -9747,20 +9747,21 @@ bool setTargetedHotend(int code, uint8_t &extruder) return false; } -void save_statistics(unsigned long _total_filament_used, unsigned long _total_print_time) //_total_filament_used unit: mm/100; print time in s -{ - uint32_t _previous_filament = eeprom_init_default_dword((uint32_t *)EEPROM_FILAMENTUSED, 0); //_previous_filament unit: cm - uint32_t _previous_time = eeprom_init_default_dword((uint32_t *)EEPROM_TOTALTIME, 0); //_previous_time unit: min +void save_statistics(unsigned long _total_filament_used, unsigned long _total_print_time) { //_total_filament_used unit: mm/100; print time in s + uint32_t _previous_filament = eeprom_init_default_dword((uint32_t *)EEPROM_FILAMENTUSED, 0); //_previous_filament unit: cm + uint32_t _previous_time = eeprom_init_default_dword((uint32_t *)EEPROM_TOTALTIME, 0); //_previous_time unit: min - eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, _previous_time + (_total_print_time/60)); //EEPROM_TOTALTIME unit: min - eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, _previous_filament + (_total_filament_used / 1000)); + eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, _previous_time + (_total_print_time / 60)); // EEPROM_TOTALTIME unit: min + eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, _previous_filament + (_total_filament_used / 1000)); - total_filament_used = 0; + total_filament_used = 0; - if (MMU2::mmu2.Enabled()) - { - MMU2::mmu2.update_tool_change_counter_eeprom(); - } + if (MMU2::mmu2.Enabled()) { + eeprom_add_dword((uint32_t *)EEPROM_TOTAL_TOOLCHANGE_COUNT, MMU2::mmu2.ToolChangeCounter()); + // @@TODO why were EEPROM_MMU_FAIL_TOT and EEPROM_MMU_LOAD_FAIL_TOT behaving differently - i.e. updated with every change? + MMU2::mmu2.ClearToolChangeCounter(); + MMU2::mmu2.ClearTMCFailures(); // not stored into EEPROM + } } float calculate_extruder_multiplier(float diameter) { diff --git a/Firmware/messages.cpp b/Firmware/messages.cpp index 4a85aa4a5..11f0f0a8e 100644 --- a/Firmware/messages.cpp +++ b/Firmware/messages.cpp @@ -67,6 +67,7 @@ const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1[] PROGMEM_I1 = ISTR("Measuring const char MSG_CALIBRATION[] PROGMEM_I1 = ISTR("Calibration"); ////MSG_CALIBRATION c=18 const char MSG_MMU_FAILS[] PROGMEM_I1 = ISTR("MMU fails"); ////MSG_MMU_FAILS c=15 const char MSG_MMU_LOAD_FAILS[] PROGMEM_I1 = ISTR("MMU load fails"); ////MSG_MMU_LOAD_FAILS c=15 +const char MSG_MMU_POWER_FAILS[] PROGMEM_I1 = ISTR("MMU power fails"); ////MSG_MMU_POWER_FAILS c=15 const char MSG_NO[] PROGMEM_I1 = ISTR("No"); ////MSG_NO c=4 const char MSG_NOZZLE[] PROGMEM_I1 = ISTR("Nozzle"); ////MSG_NOZZLE c=10 const char MSG_PAPER[] PROGMEM_I1 = ISTR("Place a sheet of paper under the nozzle during the calibration of first 4 points. If the nozzle catches the paper, power off the printer immediately."); ////MSG_PAPER c=20 r=10 diff --git a/Firmware/messages.h b/Firmware/messages.h index 2e75d0643..d966d0299 100644 --- a/Firmware/messages.h +++ b/Firmware/messages.h @@ -72,6 +72,7 @@ extern const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1[]; extern const char MSG_CALIBRATION[]; extern const char MSG_MMU_FAILS[]; extern const char MSG_MMU_LOAD_FAILS[]; +extern const char MSG_MMU_POWER_FAILS[]; extern const char MSG_NO[]; extern const char MSG_NOZZLE[]; extern const char MSG_PAPER[]; diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index a991dc8df..baa43ede1 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -119,6 +119,7 @@ MMU2::MMU2() , inAutoRetry(false) , retryAttempts(MAX_RETRIES) , toolchange_counter(0) + , tmcFailures(0) { } @@ -305,12 +306,6 @@ void MMU2::DecrementRetryAttempts() { } } -void MMU2::update_tool_change_counter_eeprom() { - uint32_t toolchanges = eeprom_read_dword((uint32_t *)EEPROM_TOTAL_TOOLCHANGE_COUNT); - eeprom_update_dword((uint32_t *)EEPROM_TOTAL_TOOLCHANGE_COUNT, toolchanges + (uint32_t)read_toolchange_counter()); - reset_toolchange_counter(); -} - void MMU2::ToolChangeCommon(uint8_t slot){ tool_change_extruder = slot; do { @@ -319,10 +314,13 @@ void MMU2::ToolChangeCommon(uint8_t slot){ if( manage_response(true, true) ) break; // otherwise: failed to perform the command - unload first and then let it run again + IncrementMMUFails(); 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. + + // IncrementLoadFails(); // this should be contained in the while condition } // reset current position to whatever the planner thinks it is plan_set_e_position(current_position[E_AXIS]); @@ -336,7 +334,7 @@ void MMU2::ToolChangeCommon(uint8_t slot){ // @@TODO really report onto the serial? May be for the Octoprint? Not important now // SERIAL_ECHO_START(); // SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, int(extruder)); - increment_tool_change_counter(); + ++toolchange_counter; } bool MMU2::tool_change(uint8_t slot) { @@ -378,16 +376,8 @@ bool MMU2::tool_change(char code, uint8_t slot) { case 'x': { set_extrude_min_temp(0); // Allow cold extrusion since Tx only loads to the gears not nozzle st_synchronize(); - tool_change_extruder = slot; - logic.ToolChange(slot); - if( ! manage_response(false, false) ){ - // @@TODO failed to perform the command - retry - ; - } - extruder = slot; - SpoolJoin::spooljoin.setSlot(slot); + ToolChangeCommon(slot); // the only difference was manage_response(false, false), but probably good enough set_extrude_min_temp(EXTRUDE_MINTEMP); - increment_tool_change_counter(); } break; case 'c': { @@ -442,9 +432,12 @@ bool MMU2::unload() { // we assume the printer managed to relieve filament tip from the gears, // so repeating that part in case of an MMU restart is not necessary - do { + for(;;) { logic.UnloadFilament(); - } while( ! manage_response(false, true) ); + if( manage_response(false, true) ) + break; + IncrementMMUFails(); + } Sound_MakeSound(e_SOUND_TYPE_StandardConfirm); @@ -460,12 +453,14 @@ bool MMU2::cut_filament(uint8_t slot){ return false; ReportingRAII rep(CommandInProgress::CutFilament); - logic.CutFilament(slot); - if( ! manage_response(false, true) ){ - // @@TODO failed to perform the command - retry - ; + + for(;;){ + logic.CutFilament(slot); + if( manage_response(false, true) ) + break; + IncrementMMUFails(); } - + return true; } @@ -493,9 +488,12 @@ bool MMU2::load_filament(uint8_t slot) { FullScreenMsg(_T(MSG_LOADING_FILAMENT), slot); ReportingRAII rep(CommandInProgress::LoadFilament); - do { + for(;;) { logic.LoadFilament(slot); - } while( ! manage_response(false, false) ); + if( manage_response(false, false) ) + break; + IncrementMMUFails(); + } Sound_MakeSound(e_SOUND_TYPE_StandardConfirm); diff --git a/Firmware/mmu2.h b/Firmware/mmu2.h index 0dc328c91..323b869f3 100644 --- a/Firmware/mmu2.h +++ b/Firmware/mmu2.h @@ -195,21 +195,17 @@ public: // Called by the MMU protocol when a sent button is acknowledged. void DecrementRetryAttempts(); - /// Updates toolchange counter in EEPROM - /// ATmega2560 EEPROM has only 100'000 write/erase cycles - /// so we can't call this function on every tool change. - void update_tool_change_counter_eeprom(); - /// @return count for toolchange in current print - inline uint16_t read_toolchange_counter() const { return toolchange_counter; }; + inline uint16_t ToolChangeCounter() const { return toolchange_counter; }; /// Set toolchange counter to zero - inline void reset_toolchange_counter() { toolchange_counter = 0; }; + inline void ClearToolChangeCounter() { toolchange_counter = 0; }; + + inline uint16_t TMCFailures()const { return tmcFailures; } + inline void IncrementTMCFailures() { ++tmcFailures; } + inline void ClearTMCFailures() { tmcFailures = 0; } private: - // Increment the toolchange counter via SRAM to reserve EEPROM write cycles - inline void increment_tool_change_counter() { ++toolchange_counter; }; - /// Reset the retryAttempts back to the default value void ResetRetryAttempts(); /// Perform software self-reset of the MMU (sends an X0 command) @@ -315,6 +311,7 @@ private: bool inAutoRetry; uint8_t retryAttempts; uint16_t toolchange_counter; + uint16_t tmcFailures; }; /// following Marlin's way of doing stuff - one and only instance of MMU implementation in the code base diff --git a/Firmware/mmu2_reporting.cpp b/Firmware/mmu2_reporting.cpp index 198e67e88..eae3ef8ab 100644 --- a/Firmware/mmu2_reporting.cpp +++ b/Firmware/mmu2_reporting.cpp @@ -220,8 +220,7 @@ enum class ReportErrorHookStates : uint8_t { enum ReportErrorHookStates ReportErrorHookState = ReportErrorHookStates::RENDER_ERROR_SCREEN; void ReportErrorHook(uint16_t ec) { - if (mmu2.MMUCurrentErrorCode() == ErrorCode::OK && mmu2.MMULastErrorSource() == MMU2::ErrorSourceMMU) - { + if (mmu2.MMUCurrentErrorCode() == ErrorCode::OK && mmu2.MMULastErrorSource() == MMU2::ErrorSourceMMU) { // 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 @@ -230,17 +229,23 @@ void ReportErrorHook(uint16_t ec) { const uint8_t ei = PrusaErrorCodeIndex(ec); - switch ((uint8_t)ReportErrorHookState) - { + switch ((uint8_t)ReportErrorHookState) { case (uint8_t)ReportErrorHookStates::RENDER_ERROR_SCREEN: ReportErrorHookStaticRender(ei); ReportErrorHookState = ReportErrorHookStates::MONITOR_SELECTION; - // Fall through + IncrementMMUFails(); + + // check if it is a "power" failure - we consider TMC-related errors as power failures + if( (uint16_t)ec & 0x7e00 ){ // @@TODO can be optimized to uint8_t operation + // TMC-related errors are from 0x8200 higher + // we can increment a power error at this spot + mmu2.IncrementTMCFailures(); + } + [[fallthrough]]; case (uint8_t)ReportErrorHookStates::MONITOR_SELECTION: mmu2.is_mmu_error_monitor_active = true; ReportErrorHookDynamicRender(); // Render dynamic characters - switch (ReportErrorHookMonitor(ei)) - { + switch (ReportErrorHookMonitor(ei)) { case 0: // No choice selected, return to loop() break; @@ -276,8 +281,7 @@ void ReportErrorHook(uint16_t ec) { } void ReportProgressHook(CommandInProgress cip, uint16_t ec) { - if (cip != CommandInProgress::NoCommand) - { + if (cip != CommandInProgress::NoCommand) { custom_message_type = CustomMsg::MMUProgress; lcd_setstatuspgm( _T(ProgressCodeToText(ec)) ); } else { @@ -288,4 +292,14 @@ void ReportProgressHook(CommandInProgress cip, uint16_t ec) { } } +void IncrementLoadFails(){ + eeprom_increment_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL); + eeprom_increment_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT); +} + +void IncrementMMUFails(){ + eeprom_increment_byte((uint8_t *)EEPROM_MMU_FAIL); + eeprom_increment_word((uint16_t *)EEPROM_MMU_FAIL_TOT); +} + } // namespace MMU2 diff --git a/Firmware/mmu2_reporting.h b/Firmware/mmu2_reporting.h index e361bd3f2..1b76b920f 100644 --- a/Firmware/mmu2_reporting.h +++ b/Firmware/mmu2_reporting.h @@ -46,4 +46,11 @@ bool MMUAvailable(); /// Global Enable/Disable use MMU (to be stored in EEPROM) bool UseMMU(); +/// Increments EEPROM cell - number of failed loads into the nozzle +/// Note: technically, this is not an MMU error but an error of the printer. +void IncrementLoadFails(); + +/// Increments EEPROM cell - number of MMU errors +void IncrementMMUFails(); + } // namespace diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 120c5444b..a7ca7db99 100644 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1123,11 +1123,14 @@ static void lcd_menu_fails_stats_mmu() //! | | //! ---------------------- //! @endcode -static void lcd_menu_fails_stats_mmu_print() -{ - lcd_timeoutToStatus.stop(); //infinite timeout +static void lcd_menu_fails_stats_mmu_print() { + lcd_timeoutToStatus.stop(); //infinite timeout lcd_home(); - lcd_printf_P(PSTR("%S\n" " %-16.16S%-3d\n" " %-16.16S%-3d"), + lcd_printf_P( + PSTR("%S\n" + " %-16.16S%-3d\n" + " %-16.16S%-3d" + ), _T(MSG_LAST_PRINT_FAILURES), _T(MSG_MMU_FAILS), clamp999( eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL) ), _T(MSG_MMU_LOAD_FAILS), clamp999( eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL) )); @@ -1144,31 +1147,20 @@ static void lcd_menu_fails_stats_mmu_print() //! | MMU power fails 000| MSG_MMU_POWER_FAILS c=15 //! ---------------------- //! @endcode -//! @todo Positioning of the messages and values on LCD aren't fixed to their exact place. This causes issues with translations. -static void lcd_menu_fails_stats_mmu_total() -{ - typedef struct - { - bool initialized; // 1byte - } _menu_data_t; - static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data"); - _menu_data_t* _md = (_menu_data_t*)&(menu_data[0]); - if(_md->initialized) { - MMU2::mmu2.get_statistics(); - lcd_timeoutToStatus.stop(); //infinite timeout - _md->initialized = false; - } +static void lcd_menu_fails_stats_mmu_total() { + lcd_timeoutToStatus.stop(); //infinite timeout lcd_home(); - lcd_printf_P(PSTR("%S\n" " %-16.16S%-3d\n"/* " %-16.16S%-3d\n" " %-16.16S%-3d"*/), + lcd_printf_P( + PSTR("%S\n" + " %-16.16S%-3d\n" + " %-16.16S%-3d\n" + " %-16.16S%-3d" + ), _T(MSG_TOTAL_FAILURES), - _T(MSG_MMU_FAILS), clamp999( MMU2::mmu2.TotalFailStatistics() ));//, - //_T(MSG_MMU_LOAD_FAILS), clamp999( eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) ), - //_i("MMU power fails"), clamp999( mmu_power_failures )); ////MSG_MMU_POWER_FAILS c=15 - if (lcd_clicked()) - { - lcd_quick_feedback(); - menu_back(); - } + _T(MSG_MMU_FAILS), clamp999( eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT) ), + _T(MSG_MMU_LOAD_FAILS), clamp999( eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) ), + _i("MMU power fails"), clamp999( MMU2::mmu2.TMCFailures() )); + menu_back_if_clicked_fb(); } //! @brief Show Total Failures Statistics MMU