Merge pull request #1869 from DRracer/fix_mintemp_and_fsensor
Fix MINTEMP errors and fsensor runout
This commit is contained in:
commit
9c3b93f900
@ -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();
|
||||
|
@ -3554,6 +3554,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();
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
//! @}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,58 @@ 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 {
|
||||
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;
|
||||
uint8_t repeat = ALERT_AUTOMATON_SPEED_DIV;
|
||||
|
||||
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
|
||||
} else {
|
||||
--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 States::INIT: // initial state - check hysteresis
|
||||
if( current_temp > 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
|
||||
lcd_setalertstatuspgm(m2);
|
||||
substep(States::SHOW_MINTEMP);
|
||||
last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED;
|
||||
break;
|
||||
case States::SHOW_PLEASE_RESTART: // displaying "Please restart"
|
||||
lcd_updatestatuspgm(m1);
|
||||
substep(States::SHOW_MINTEMP);
|
||||
last_alert_sent_to_lcd = LCDALERT_PLEASERESTART;
|
||||
break;
|
||||
case States::SHOW_MINTEMP: // displaying "MINTEMP fixed"
|
||||
lcd_updatestatuspgm(m2);
|
||||
substep(States::SHOW_PLEASE_RESTART);
|
||||
last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static alert_automaton_mintemp alert_automaton_hotend, alert_automaton_bed;
|
||||
|
||||
void check_min_temp_heater0()
|
||||
{
|
||||
@ -2024,7 +2101,17 @@ 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 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.
|
||||
alert_automaton_hotend.step(current_temperature[0], minttemp[0] + TEMP_HYSTERESIS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2035,7 +2122,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
|
||||
alert_automaton_bed.step(current_temperature_bed, BED_MINTEMP + TEMP_HYSTERESIS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user