Revive MMU stats + LCD screens

This commit is contained in:
D.R.racer 2022-11-19 15:09:06 +01:00 committed by DRracer
parent fe11b7a247
commit 4eaabbf092
8 changed files with 93 additions and 82 deletions

View File

@ -9747,20 +9747,21 @@ bool setTargetedHotend(int code, uint8_t &extruder)
return false; 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 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_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
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_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_FILAMENTUSED, _previous_filament + (_total_filament_used / 1000));
total_filament_used = 0; total_filament_used = 0;
if (MMU2::mmu2.Enabled()) if (MMU2::mmu2.Enabled()) {
{ eeprom_add_dword((uint32_t *)EEPROM_TOTAL_TOOLCHANGE_COUNT, MMU2::mmu2.ToolChangeCounter());
MMU2::mmu2.update_tool_change_counter_eeprom(); // @@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) { float calculate_extruder_multiplier(float diameter) {

View File

@ -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_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_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_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_NO[] PROGMEM_I1 = ISTR("No"); ////MSG_NO c=4
const char MSG_NOZZLE[] PROGMEM_I1 = ISTR("Nozzle"); ////MSG_NOZZLE c=10 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 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

View File

@ -72,6 +72,7 @@ extern const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1[];
extern const char MSG_CALIBRATION[]; extern const char MSG_CALIBRATION[];
extern const char MSG_MMU_FAILS[]; extern const char MSG_MMU_FAILS[];
extern const char MSG_MMU_LOAD_FAILS[]; extern const char MSG_MMU_LOAD_FAILS[];
extern const char MSG_MMU_POWER_FAILS[];
extern const char MSG_NO[]; extern const char MSG_NO[];
extern const char MSG_NOZZLE[]; extern const char MSG_NOZZLE[];
extern const char MSG_PAPER[]; extern const char MSG_PAPER[];

View File

@ -119,6 +119,7 @@ MMU2::MMU2()
, inAutoRetry(false) , inAutoRetry(false)
, retryAttempts(MAX_RETRIES) , retryAttempts(MAX_RETRIES)
, toolchange_counter(0) , 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){ void MMU2::ToolChangeCommon(uint8_t slot){
tool_change_extruder = slot; tool_change_extruder = slot;
do { do {
@ -319,10 +314,13 @@ void MMU2::ToolChangeCommon(uint8_t slot){
if( manage_response(true, true) ) if( manage_response(true, true) )
break; break;
// otherwise: failed to perform the command - unload first and then let it run again // otherwise: failed to perform the command - unload first and then let it run again
IncrementMMUFails();
unload(); unload();
// if we run out of retries, we must do something ... may be raise an error screen and allow the user to do something // 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, // but honestly - if the MMU restarts during every toolchange,
// something else is seriously broken and stopping a print is probably our best option. // 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 // 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]);
@ -336,7 +334,7 @@ void MMU2::ToolChangeCommon(uint8_t slot){
// @@TODO really report onto the serial? May be for the Octoprint? Not important now // @@TODO really report onto the serial? May be for the Octoprint? Not important now
// SERIAL_ECHO_START(); // SERIAL_ECHO_START();
// SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, int(extruder)); // SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, int(extruder));
increment_tool_change_counter(); ++toolchange_counter;
} }
bool MMU2::tool_change(uint8_t slot) { bool MMU2::tool_change(uint8_t slot) {
@ -378,16 +376,8 @@ bool MMU2::tool_change(char code, uint8_t slot) {
case 'x': { case 'x': {
set_extrude_min_temp(0); // Allow cold extrusion since Tx only loads to the gears not nozzle set_extrude_min_temp(0); // Allow cold extrusion since Tx only loads to the gears not nozzle
st_synchronize(); st_synchronize();
tool_change_extruder = slot; ToolChangeCommon(slot); // the only difference was manage_response(false, false), but probably good enough
logic.ToolChange(slot);
if( ! manage_response(false, false) ){
// @@TODO failed to perform the command - retry
;
}
extruder = slot;
SpoolJoin::spooljoin.setSlot(slot);
set_extrude_min_temp(EXTRUDE_MINTEMP); set_extrude_min_temp(EXTRUDE_MINTEMP);
increment_tool_change_counter();
} break; } break;
case 'c': { case 'c': {
@ -442,9 +432,12 @@ bool MMU2::unload() {
// we assume the printer managed to relieve filament tip from the gears, // 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 // so repeating that part in case of an MMU restart is not necessary
do { for(;;) {
logic.UnloadFilament(); logic.UnloadFilament();
} while( ! manage_response(false, true) ); if( manage_response(false, true) )
break;
IncrementMMUFails();
}
Sound_MakeSound(e_SOUND_TYPE_StandardConfirm); Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);
@ -460,12 +453,14 @@ bool MMU2::cut_filament(uint8_t slot){
return false; return false;
ReportingRAII rep(CommandInProgress::CutFilament); ReportingRAII rep(CommandInProgress::CutFilament);
logic.CutFilament(slot);
if( ! manage_response(false, true) ){ for(;;){
// @@TODO failed to perform the command - retry logic.CutFilament(slot);
; if( manage_response(false, true) )
break;
IncrementMMUFails();
} }
return true; return true;
} }
@ -493,9 +488,12 @@ bool MMU2::load_filament(uint8_t slot) {
FullScreenMsg(_T(MSG_LOADING_FILAMENT), slot); FullScreenMsg(_T(MSG_LOADING_FILAMENT), slot);
ReportingRAII rep(CommandInProgress::LoadFilament); ReportingRAII rep(CommandInProgress::LoadFilament);
do { for(;;) {
logic.LoadFilament(slot); logic.LoadFilament(slot);
} while( ! manage_response(false, false) ); if( manage_response(false, false) )
break;
IncrementMMUFails();
}
Sound_MakeSound(e_SOUND_TYPE_StandardConfirm); Sound_MakeSound(e_SOUND_TYPE_StandardConfirm);

View File

@ -195,21 +195,17 @@ public:
// Called by the MMU protocol when a sent button is acknowledged. // Called by the MMU protocol when a sent button is acknowledged.
void DecrementRetryAttempts(); 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 /// @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 /// 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: 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 /// Reset the retryAttempts back to the default value
void ResetRetryAttempts(); void ResetRetryAttempts();
/// Perform software self-reset of the MMU (sends an X0 command) /// Perform software self-reset of the MMU (sends an X0 command)
@ -315,6 +311,7 @@ private:
bool inAutoRetry; bool inAutoRetry;
uint8_t retryAttempts; uint8_t retryAttempts;
uint16_t toolchange_counter; 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 /// following Marlin's way of doing stuff - one and only instance of MMU implementation in the code base

View File

@ -220,8 +220,7 @@ enum class ReportErrorHookStates : uint8_t {
enum ReportErrorHookStates ReportErrorHookState = ReportErrorHookStates::RENDER_ERROR_SCREEN; enum ReportErrorHookStates ReportErrorHookState = ReportErrorHookStates::RENDER_ERROR_SCREEN;
void ReportErrorHook(uint16_t ec) { 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 // If the error code suddenly changes to OK, that means
// a button was pushed on the MMU and the LCD should // a button was pushed on the MMU and the LCD should
// dismiss the error screen until MMU raises a new error // 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); const uint8_t ei = PrusaErrorCodeIndex(ec);
switch ((uint8_t)ReportErrorHookState) switch ((uint8_t)ReportErrorHookState) {
{
case (uint8_t)ReportErrorHookStates::RENDER_ERROR_SCREEN: case (uint8_t)ReportErrorHookStates::RENDER_ERROR_SCREEN:
ReportErrorHookStaticRender(ei); ReportErrorHookStaticRender(ei);
ReportErrorHookState = ReportErrorHookStates::MONITOR_SELECTION; 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: case (uint8_t)ReportErrorHookStates::MONITOR_SELECTION:
mmu2.is_mmu_error_monitor_active = true; mmu2.is_mmu_error_monitor_active = true;
ReportErrorHookDynamicRender(); // Render dynamic characters ReportErrorHookDynamicRender(); // Render dynamic characters
switch (ReportErrorHookMonitor(ei)) switch (ReportErrorHookMonitor(ei)) {
{
case 0: case 0:
// No choice selected, return to loop() // No choice selected, return to loop()
break; break;
@ -276,8 +281,7 @@ void ReportErrorHook(uint16_t ec) {
} }
void ReportProgressHook(CommandInProgress cip, uint16_t ec) { void ReportProgressHook(CommandInProgress cip, uint16_t ec) {
if (cip != CommandInProgress::NoCommand) if (cip != CommandInProgress::NoCommand) {
{
custom_message_type = CustomMsg::MMUProgress; custom_message_type = CustomMsg::MMUProgress;
lcd_setstatuspgm( _T(ProgressCodeToText(ec)) ); lcd_setstatuspgm( _T(ProgressCodeToText(ec)) );
} else { } 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 } // namespace MMU2

View File

@ -46,4 +46,11 @@ bool MMUAvailable();
/// Global Enable/Disable use MMU (to be stored in EEPROM) /// Global Enable/Disable use MMU (to be stored in EEPROM)
bool UseMMU(); 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 } // namespace

View File

@ -1123,11 +1123,14 @@ static void lcd_menu_fails_stats_mmu()
//! | | //! | |
//! ---------------------- //! ----------------------
//! @endcode //! @endcode
static void lcd_menu_fails_stats_mmu_print() static void lcd_menu_fails_stats_mmu_print() {
{ lcd_timeoutToStatus.stop(); //infinite timeout
lcd_timeoutToStatus.stop(); //infinite timeout
lcd_home(); 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_LAST_PRINT_FAILURES),
_T(MSG_MMU_FAILS), clamp999( eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL) ), _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) )); _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 //! | MMU power fails 000| MSG_MMU_POWER_FAILS c=15
//! ---------------------- //! ----------------------
//! @endcode //! @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() {
static void lcd_menu_fails_stats_mmu_total() lcd_timeoutToStatus.stop(); //infinite timeout
{
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;
}
lcd_home(); 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_TOTAL_FAILURES),
_T(MSG_MMU_FAILS), clamp999( MMU2::mmu2.TotalFailStatistics() ));//, _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) ), _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 _i("MMU power fails"), clamp999( MMU2::mmu2.TMCFailures() ));
if (lcd_clicked()) menu_back_if_clicked_fb();
{
lcd_quick_feedback();
menu_back();
}
} }
//! @brief Show Total Failures Statistics MMU //! @brief Show Total Failures Statistics MMU