From 9cb0bc7bcf35f3408353a2b67c407293657d5792 Mon Sep 17 00:00:00 2001 From: DRracer Date: Fri, 24 May 2019 08:46:44 +0200 Subject: [PATCH 1/3] Fix MINTEMP errors and fsensor runout --- Firmware/Marlin.h | 7 ++++ Firmware/Marlin_main.cpp | 4 ++ Firmware/fsensor.cpp | 32 ++++++++++----- Firmware/fsensor.h | 3 ++ Firmware/menu.cpp | 2 +- Firmware/menu.h | 21 ++++++++++ Firmware/temperature.cpp | 89 +++++++++++++++++++++++++++++++++++++++- Firmware/ultralcd.cpp | 18 ++++++-- Firmware/ultralcd.h | 9 ++++ 9 files changed, 168 insertions(+), 17 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index b82856f8..2e60597d 100644 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -390,6 +390,13 @@ extern LongTimer safetyTimer; #define PRINT_PERCENT_DONE_INIT 0xff #define PRINTER_ACTIVE (IS_SD_PRINTING || is_usb_printing || isPrintPaused || (custom_message_type == CUSTOM_MSG_TYPE_TEMCAL) || saved_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL) || card.paused || mmu_print_saved) +//! Beware - mcode_in_progress is set as soon as the command gets really processed, +//! which is not the same as posting the M600 command into the command queue +//! There can be a considerable lag between posting M600 and its real processing which might result +//! in posting multiple M600's into the command queue +//! Instead, the fsensor uses another state variable :( , which is set to true, when the M600 command is enqued +//! and is reset to false when the fsensor returns into its filament runout finished handler +//! I'd normally change this macro, but who knows what would happen in the MMU :) #define CHECK_FSENSOR ((IS_SD_PRINTING || is_usb_printing) && (mcode_in_progress != 600) && !saved_printing && e_active()) extern void calculate_extruder_multipliers(); diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index a1740b24..8e216ae0 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3552,6 +3552,10 @@ void process_commands() enquecommand_P(PSTR("M24")); } #ifdef FILAMENT_SENSOR + else if (code_seen("fsensor_recover_IR")) //! PRUSA fsensor_recover_IR + { + fsensor_restore_print_and_continue_IR(); + } else if (code_seen("fsensor_recover")) //! PRUSA fsensor_recover { fsensor_restore_print_and_continue(); diff --git a/Firmware/fsensor.cpp b/Firmware/fsensor.cpp index d520ba53..f9ca8909 100644 --- a/Firmware/fsensor.cpp +++ b/Firmware/fsensor.cpp @@ -57,6 +57,11 @@ bool fsensor_not_responding = false; bool fsensor_printing_saved = false; //! enable/disable quality meassurement bool fsensor_oq_meassure_enabled = false; +//! as explained in the CHECK_FSENSOR macro: this flag is set to true when fsensor posts +//! the M600 into the command queue, which elliminates the hazard of having posted multiple M600's +//! before the first one gets read and started processing. +//! Btw., the IR fsensor could do up to 6 posts before the command queue managed to start processing the first M600 ;) +static bool fsensor_m600_enqueued = false; //! number of errors, updated in ISR uint8_t fsensor_err_cnt = 0; @@ -118,11 +123,17 @@ void fsensor_stop_and_save_print(void) stop_and_save_print_to_ram(0, 0); //XYZE - no change } +void fsensor_restore_print_and_continue_IR(void) +{ + fsensor_watch_runout = true; + fsensor_err_cnt = 0; + fsensor_m600_enqueued = false; +} + void fsensor_restore_print_and_continue(void) { printf_P(PSTR("fsensor_restore_print_and_continue\n")); - fsensor_watch_runout = true; - fsensor_err_cnt = 0; + fsensor_restore_print_and_continue_IR(); restore_print_from_ram_and_continue(0); //XYZ = orig, E - no change } @@ -575,14 +586,15 @@ void fsensor_update(void) fsensor_oq_meassure_enabled = oq_meassure_enabled_tmp; } #else //PAT9125 - if ((digitalRead(IR_SENSOR_PIN) == 1) && CHECK_FSENSOR && fsensor_enabled && ir_sensor_detected) - { - fsensor_stop_and_save_print(); - printf_P(PSTR("fsensor_update - M600\n")); - eeprom_update_byte((uint8_t*)EEPROM_FERROR_COUNT, eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) + 1); - eeprom_update_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) + 1); - enquecommand_front_P(PSTR("PRUSA fsensor_recover")); - enquecommand_front_P((PSTR("M600"))); + if ((digitalRead(IR_SENSOR_PIN) == 1) && CHECK_FSENSOR && fsensor_enabled && ir_sensor_detected && ( ! fsensor_m600_enqueued) ) + { // just plan a simple M600 without any additional position save/restore, + // which caused weird heating issues standing directly over the print + printf_P(PSTR("fsensor_update - M600\n")); + eeprom_update_byte((uint8_t*)EEPROM_FERROR_COUNT, eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) + 1); + eeprom_update_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) + 1); + enquecommand_front_P(PSTR("PRUSA fsensor_recover_IR")); + fsensor_m600_enqueued = true; + enquecommand_front_P((PSTR("M600"))); } #endif //PAT9125 } diff --git a/Firmware/fsensor.h b/Firmware/fsensor.h index 71922fbf..421eee43 100644 --- a/Firmware/fsensor.h +++ b/Firmware/fsensor.h @@ -18,6 +18,9 @@ extern bool fsensor_oq_meassure_enabled; //! @name save restore printing //! @{ extern void fsensor_stop_and_save_print(void); +//! special handling for the IR sensor (no restore position and heating, since this is already correctly handled in the M600 itself) +extern void fsensor_restore_print_and_continue_IR(void); +//! legacy restore print - restore position and heatup to original temperature - for the MMU and the optical fsensor extern void fsensor_restore_print_and_continue(void); //! @} diff --git a/Firmware/menu.cpp b/Firmware/menu.cpp index 847e63c8..e0364056 100755 --- a/Firmware/menu.cpp +++ b/Firmware/menu.cpp @@ -26,7 +26,7 @@ uint8_t menu_data[MENU_DATA_SIZE]; #endif uint8_t menu_depth = 0; - +uint8_t menu_block_entering_on_serious_errors = SERIOUS_ERR_NONE; uint8_t menu_line = 0; uint8_t menu_item = 0; uint8_t menu_row = 0; diff --git a/Firmware/menu.h b/Firmware/menu.h index 9800550b..5f73e18b 100755 --- a/Firmware/menu.h +++ b/Firmware/menu.h @@ -28,6 +28,27 @@ extern uint8_t menu_data[MENU_DATA_SIZE]; extern uint8_t menu_depth; +//! definition of serious errors possibly blocking the main menu +//! Use them as bit mask, so that the code may set various errors at the same time +enum ESeriousErrors { + SERIOUS_ERR_NONE = 0, + SERIOUS_ERR_MINTEMP_HEATER = 0x01, + SERIOUS_ERR_MINTEMP_BED = 0x02 +}; // and possibly others in the future. + +//! this is a flag for disabling entering the main menu. If this is set +//! to anything != 0, the only the main status screen will be shown on the +//! LCD and the user will be prevented from entering the menu. +//! Now used only to block doing anything with the printer when there is +//! the infamous MINTEMP error (SERIOUS_ERR_MINTEMP). +extern uint8_t menu_block_entering_on_serious_errors; + +//! a pair of macros for manipulating the serious errors +//! a c++ class would have been better +#define menu_set_serious_error(x) menu_block_entering_on_serious_errors |= x; +#define menu_unset_serious_error(x) menu_block_entering_on_serious_errors &= ~x; +#define menu_is_serious_error(x) (menu_block_entering_on_serious_errors & x) != 0 + extern uint8_t menu_line; extern uint8_t menu_item; extern uint8_t menu_row; diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 668b857f..5a81c630 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1469,6 +1469,15 @@ void disable_heater() #endif #endif } +//! codes of alert messages for the LCD - it is shorter to compare an uin8_t +//! than raw const char * of the messages themselves. +//! Could be used for MAXTEMP situations too - after reaching MAXTEMP and turning off the heater automagically +//! the heater/bed may cool down and a similar alert message like "MAXTERM fixed..." may be displayed. +enum { LCDALERT_NONE = 0, LCDALERT_HEATERMINTEMP, LCDALERT_BEDMINTEMP, LCDALERT_MINTEMPFIXED, LCDALERT_PLEASERESTART }; + +//! remember the last alert message sent to the LCD +//! to prevent flicker and improve speed +uint8_t last_alert_sent_to_lcd = LCDALERT_NONE; void max_temp_error(uint8_t e) { disable_heater(); @@ -1502,13 +1511,23 @@ void min_temp_error(uint8_t e) { #endif //if (current_temperature_ambient < MINTEMP_MINAMBIENT) return; disable_heater(); + static const char err[] PROGMEM = "Err: MINTEMP"; if(IsStopped() == false) { SERIAL_ERROR_START; SERIAL_ERRORLN((int)e); SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !"); - LCD_ALERTMESSAGEPGM("Err: MINTEMP"); + lcd_setalertstatuspgm(err); + last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; + } else if( last_alert_sent_to_lcd != LCDALERT_HEATERMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) + // we are already stopped due to some error, only update the status message without flickering + lcd_updatestatuspgm(err); + last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE +// if( last_alert_sent_to_lcd != LCDALERT_HEATERMINTEMP ){ +// last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP; +// lcd_print_stop(); +// } Stop(); #endif if (farm_mode) { prusa_statistics(92); } @@ -1538,10 +1557,16 @@ void bed_min_temp_error(void) { #if HEATER_BED_PIN > -1 WRITE(HEATER_BED_PIN, 0); #endif + static const char err[] PROGMEM = "Err: MINTEMP BED"; if(IsStopped() == false) { SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Temperature heated bed switched off. MINTEMP triggered !"); - LCD_ALERTMESSAGEPGM("Err: MINTEMP BED"); + lcd_setalertstatuspgm(err); + last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; + } else if( last_alert_sent_to_lcd != LCDALERT_BEDMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time) + // we are already stopped due to some error, only update the status message without flickering + lcd_updatestatuspgm(err); + last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP; } #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE Stop(); @@ -2015,6 +2040,52 @@ void check_max_temp() #endif } +//! number of repeating the same state with consecutive step() calls +//! used to slow down text switching +struct alert_automaton_mintemp { + enum { ALERT_AUTOMATON_SPEED_DIV = 5 }; + uint8_t state, repeat = ALERT_AUTOMATON_SPEED_DIV; + + void substep(uint8_t next_state){ + if( repeat == 0 ){ + state = next_state; // advance to the next state + repeat = ALERT_AUTOMATON_SPEED_DIV; // and prepare repeating for it too + } else { + --repeat; + } + } + + void step(float current_temp, float mintemp){ + static const char m2[] PROGMEM = "MINTEMP fixed"; + static const char m1[] PROGMEM = "Please restart"; + switch(state){ + case 0: // initial state - check hysteresis + if( current_temp > mintemp ){ + state = 1; + } + // otherwise keep the Err MINTEMP alert message on the display, + // i.e. do not transfer to state 1 + break; + case 1: // the temperature has risen above the hysteresis check + lcd_setalertstatuspgm(m2); + substep(3); + last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED; + break; + case 2: // displaying "Please restart" + lcd_updatestatuspgm(m1); + substep(3); + last_alert_sent_to_lcd = LCDALERT_PLEASERESTART; + break; + case 3: // displaying "MINTEMP fixed" + lcd_updatestatuspgm(m2); + substep(2); + last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED; + break; + } + } +}; + +static alert_automaton_mintemp aam[2]; void check_min_temp_heater0() { @@ -2024,7 +2095,16 @@ void check_min_temp_heater0() #else if (current_temperature_raw[0] <= minttemp_raw[0]) { #endif + menu_set_serious_error(SERIOUS_ERR_MINTEMP_HEATER); min_temp_error(0); + } else if( menu_is_serious_error(SERIOUS_ERR_MINTEMP_HEATER) ) { + // no recovery, just force the user to restart the printer + // which is a safer variant than just continuing printing + // The automaton also checks for hysteresis - the temperature must have reached a few degrees above the MINTEMP, before + // we shall signalize, that MINTEMP has been fixed + // Code notice: normally the aam instance would have been placed here as static alert_automaton_mintemp aam, but + // due to stupid compiler that takes 16 more bytes. + aam[0].step(current_temperature[0], minttemp[0] + TEMP_HYSTERESIS); } } @@ -2035,7 +2115,12 @@ void check_min_temp_bed() #else if (current_temperature_bed_raw <= bed_minttemp_raw) { #endif + menu_set_serious_error(SERIOUS_ERR_MINTEMP_BED); bed_min_temp_error(); + } else if( menu_is_serious_error(SERIOUS_ERR_MINTEMP_BED) ){ + // no recovery, just force the user to restart the printer + // which is a safer variant than just continuing printing + aam[1].step(current_temperature_bed, BED_MINTEMP + TEMP_HYSTERESIS); } } diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 97304adb..23571eed 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -252,6 +252,7 @@ static void lcd_send_status(); static void lcd_connect_printer(); #endif //FARM_CONNECT_MESSAGE +//! Beware: has side effects - forces lcd_draw_update to 2, which means clear the display void lcd_finishstatus(); static void lcd_sdcard_menu(); @@ -1018,7 +1019,10 @@ static void lcd_status_screen() } } - if (current_click && (lcd_commands_type != LCD_COMMAND_STOP_PRINT)) //click is aborted unless stop print finishes + if (current_click + && (lcd_commands_type != LCD_COMMAND_STOP_PRINT) //click is aborted unless stop print finishes + && ( menu_block_entering_on_serious_errors == SERIOUS_ERR_NONE ) // or a serious error blocks entering the menu + ) { menu_depth = 0; //redundant, as already done in lcd_return_to_status(), just to be sure menu_submenu(lcd_main_menu); @@ -8276,13 +8280,19 @@ void lcd_setstatus(const char* message) strncpy(lcd_status_message, message, LCD_WIDTH); lcd_finishstatus(); } +void lcd_updatestatuspgm(const char *message){ + strncpy_P(lcd_status_message, message, LCD_WIDTH); + lcd_status_message[LCD_WIDTH] = 0; + lcd_finishstatus(); + // hack lcd_draw_update to 1, i.e. without clear + lcd_draw_update = 1; +} + void lcd_setstatuspgm(const char* message) { if (lcd_status_message_level > 0) return; - strncpy_P(lcd_status_message, message, LCD_WIDTH); - lcd_status_message[LCD_WIDTH] = 0; - lcd_finishstatus(); + lcd_updatestatuspgm(message); } void lcd_setalertstatuspgm(const char* message) { diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 365f1797..665c1233 100644 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -18,7 +18,16 @@ extern void menu_lcd_lcdupdate_func(void); void ultralcd_init(); void lcd_setstatus(const char* message); void lcd_setstatuspgm(const char* message); +//! return to the main status screen and display the alert message +//! Beware - it has sideeffects: +//! - always returns the display to the main status screen +//! - always makes lcd_reset (which is slow and causes flicker) +//! - does not update the message if there is already one (i.e. lcd_status_message_level > 0) void lcd_setalertstatuspgm(const char* message); +//! only update the alert message on the main status screen +//! has no sideeffects, may be called multiple times +void lcd_updatestatuspgm(const char *message); + void lcd_reset_alert_level(); uint8_t get_message_level(); void lcd_adjust_z(); From 4d020d99f6eefecba90afbc8dec867ce25868c30 Mon Sep 17 00:00:00 2001 From: DRracer Date: Mon, 27 May 2019 14:57:02 +0200 Subject: [PATCH 2/3] Code cleanup --- Firmware/temperature.cpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 5a81c630..20ba8871 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2043,10 +2043,13 @@ void check_max_temp() //! number of repeating the same state with consecutive step() calls //! used to slow down text switching struct alert_automaton_mintemp { +private: enum { ALERT_AUTOMATON_SPEED_DIV = 5 }; - uint8_t state, repeat = ALERT_AUTOMATON_SPEED_DIV; + enum class STATES : uint8_t { INIT = 0, TEMP_ABOVE_MINTEMP, SHOW_PLEASE_RESTART, SHOW_MINTEMP }; + STATES state = STATES::INIT; + uint8_t repeat = ALERT_AUTOMATON_SPEED_DIV; - void substep(uint8_t next_state){ + void substep(STATES next_state){ if( repeat == 0 ){ state = next_state; // advance to the next state repeat = ALERT_AUTOMATON_SPEED_DIV; // and prepare repeating for it too @@ -2054,38 +2057,41 @@ struct alert_automaton_mintemp { --repeat; } } - +public: + //! brief state automaton step routine + //! @param current_temp current hotend/bed temperature (for computing simple hysteresis) + //! @param mintemp minimal temperature including hysteresis to check current_temp against void step(float current_temp, float mintemp){ static const char m2[] PROGMEM = "MINTEMP fixed"; static const char m1[] PROGMEM = "Please restart"; switch(state){ - case 0: // initial state - check hysteresis + case STATES::INIT: // initial state - check hysteresis if( current_temp > mintemp ){ - state = 1; + state = STATES::TEMP_ABOVE_MINTEMP; } // otherwise keep the Err MINTEMP alert message on the display, // i.e. do not transfer to state 1 break; - case 1: // the temperature has risen above the hysteresis check + case STATES::TEMP_ABOVE_MINTEMP: // the temperature has risen above the hysteresis check lcd_setalertstatuspgm(m2); - substep(3); + substep(STATES::SHOW_MINTEMP); last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED; break; - case 2: // displaying "Please restart" + case STATES::SHOW_PLEASE_RESTART: // displaying "Please restart" lcd_updatestatuspgm(m1); - substep(3); + substep(STATES::SHOW_MINTEMP); last_alert_sent_to_lcd = LCDALERT_PLEASERESTART; break; - case 3: // displaying "MINTEMP fixed" + case STATES::SHOW_MINTEMP: // displaying "MINTEMP fixed" lcd_updatestatuspgm(m2); - substep(2); + substep(STATES::SHOW_PLEASE_RESTART); last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED; break; } } }; -static alert_automaton_mintemp aam[2]; +static alert_automaton_mintemp alert_automaton_hotend, alert_automaton_bed; void check_min_temp_heater0() { @@ -2102,9 +2108,10 @@ void check_min_temp_heater0() // which is a safer variant than just continuing printing // The automaton also checks for hysteresis - the temperature must have reached a few degrees above the MINTEMP, before // we shall signalize, that MINTEMP has been fixed - // Code notice: normally the aam instance would have been placed here as static alert_automaton_mintemp aam, but + // Code notice: normally the alert_automaton instance would have been placed here + // as static alert_automaton_mintemp alert_automaton_hotend, but // due to stupid compiler that takes 16 more bytes. - aam[0].step(current_temperature[0], minttemp[0] + TEMP_HYSTERESIS); + alert_automaton_hotend.step(current_temperature[0], minttemp[0] + TEMP_HYSTERESIS); } } @@ -2120,7 +2127,7 @@ void check_min_temp_bed() } else if( menu_is_serious_error(SERIOUS_ERR_MINTEMP_BED) ){ // no recovery, just force the user to restart the printer // which is a safer variant than just continuing printing - aam[1].step(current_temperature_bed, BED_MINTEMP + TEMP_HYSTERESIS); + alert_automaton_bed.step(current_temperature_bed, BED_MINTEMP + TEMP_HYSTERESIS); } } From 253087a4c5a2ebbfe45d2dd7fda8d53ec59be958 Mon Sep 17 00:00:00 2001 From: DRracer Date: Mon, 27 May 2019 16:18:21 +0200 Subject: [PATCH 3/3] Code cleanup --- Firmware/temperature.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 20ba8871..b245b23b 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2045,11 +2045,11 @@ void check_max_temp() struct alert_automaton_mintemp { private: enum { ALERT_AUTOMATON_SPEED_DIV = 5 }; - enum class STATES : uint8_t { INIT = 0, TEMP_ABOVE_MINTEMP, SHOW_PLEASE_RESTART, SHOW_MINTEMP }; - STATES state = STATES::INIT; + enum class States : uint8_t { INIT = 0, TEMP_ABOVE_MINTEMP, SHOW_PLEASE_RESTART, SHOW_MINTEMP }; + States state = States::INIT; uint8_t repeat = ALERT_AUTOMATON_SPEED_DIV; - void substep(STATES next_state){ + void substep(States next_state){ if( repeat == 0 ){ state = next_state; // advance to the next state repeat = ALERT_AUTOMATON_SPEED_DIV; // and prepare repeating for it too @@ -2065,26 +2065,26 @@ public: static const char m2[] PROGMEM = "MINTEMP fixed"; static const char m1[] PROGMEM = "Please restart"; switch(state){ - case STATES::INIT: // initial state - check hysteresis + case States::INIT: // initial state - check hysteresis if( current_temp > mintemp ){ - state = STATES::TEMP_ABOVE_MINTEMP; + state = States::TEMP_ABOVE_MINTEMP; } // otherwise keep the Err MINTEMP alert message on the display, // i.e. do not transfer to state 1 break; - case STATES::TEMP_ABOVE_MINTEMP: // the temperature has risen above the hysteresis check + case States::TEMP_ABOVE_MINTEMP: // the temperature has risen above the hysteresis check lcd_setalertstatuspgm(m2); - substep(STATES::SHOW_MINTEMP); + substep(States::SHOW_MINTEMP); last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED; break; - case STATES::SHOW_PLEASE_RESTART: // displaying "Please restart" + case States::SHOW_PLEASE_RESTART: // displaying "Please restart" lcd_updatestatuspgm(m1); - substep(STATES::SHOW_MINTEMP); + substep(States::SHOW_MINTEMP); last_alert_sent_to_lcd = LCDALERT_PLEASERESTART; break; - case STATES::SHOW_MINTEMP: // displaying "MINTEMP fixed" + case States::SHOW_MINTEMP: // displaying "MINTEMP fixed" lcd_updatestatuspgm(m2); - substep(STATES::SHOW_PLEASE_RESTART); + substep(States::SHOW_PLEASE_RESTART); last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED; break; }