diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index c311f221..41921919 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -273,7 +273,6 @@ void CardReader::startFileprint() if(cardOK) { sdprinting = true; - Stopped = false; #ifdef SDCARD_SORT_ALPHA //flush_presort(); #endif diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 5357b55d..f5035d2d 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -92,6 +92,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | 0x0FF7 4087 | uint8 | EEPROM_CALIBRATION_STATUS | ffh 255 | ffh 255 | Assembled _default_ | ??? | D3 Ax0ff7 C1 | ^ | ^ | ^ | 01h 1 | ^ | Calibrated | ^ | ^ | ^ | ^ | ^ | e6h 230 | ^ | needs Live Z adjustment | ^ | ^ +| ^ | ^ | ^ | ebh 235 | ^ | needs Temp Model calibration | ^ | ^ | ^ | ^ | ^ | f0h 240 | ^ __P__ | needs Z calibration | ^ | ^ | ^ | ^ | ^ | fah 250 | ^ | needs XYZ calibration | ^ | ^ | ^ | ^ | ^ | 00h 0 | ^ | Unknown | ^ | ^ diff --git a/Firmware/temp_model.h b/Firmware/temp_model.h index 8d925007..492781fd 100644 --- a/Firmware/temp_model.h +++ b/Firmware/temp_model.h @@ -15,6 +15,7 @@ constexpr uint8_t TEMP_MODEL_LAG_SIZE = (TEMP_MODEL_LAG / TEMP_MGR_INTV + 0.5); // resistance values for all fan levels constexpr uint8_t TEMP_MODEL_R_SIZE = (1 << FAN_SOFT_PWM_BITS); +static const float TEMP_MODEL_R_DEFAULT[TEMP_MODEL_R_SIZE] PROGMEM = TEMP_MODEL_Rv; namespace temp_model { @@ -59,7 +60,6 @@ struct model_data }; static bool enabled; // model check enabled -static bool valid = false; // model is valid static bool warn_beep = true; // beep on warning threshold static model_data data; // default heater data diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 42d5aa71..1f832aa9 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -2506,10 +2506,14 @@ static void temp_model_reset_enabled(bool enabled) { TempMgrGuard temp_mgr_guard; temp_model::enabled = enabled; - temp_model::valid = enabled; temp_model::data.flag_bits.uninitialized = true; } +bool temp_model_enabled() +{ + return temp_model::enabled; +} + void temp_model_set_enabled(bool enabled) { // set the enabled flag @@ -2517,19 +2521,11 @@ void temp_model_set_enabled(bool enabled) TempMgrGuard temp_mgr_guard; temp_model::enabled = enabled; temp_model::setup(); - temp_model::valid = true; } // verify that the model has been enabled - if(enabled && !temp_model::enabled) { + if(enabled && !temp_model::enabled) SERIAL_ECHOLNPGM("TM: invalid parameters, cannot enable"); - temp_model::valid = false; - } -} - -bool temp_model_valid() -{ - return temp_model::valid; } void temp_model_set_warn_beep(bool enabled) @@ -2583,15 +2579,14 @@ void temp_model_reset_settings() temp_model::data.P = TEMP_MODEL_P; temp_model::data.C = TEMP_MODEL_C; - temp_model::data.R[0] = TEMP_MODEL_R; - for(uint8_t i = 1; i != TEMP_MODEL_R_SIZE; ++i) - temp_model::data.R[i] = NAN; + for(uint8_t i = 0; i != TEMP_MODEL_R_SIZE; ++i) + temp_model::data.R[i] = pgm_read_float(TEMP_MODEL_R_DEFAULT + i); temp_model::data.Ta_corr = TEMP_MODEL_Ta_corr; temp_model::data.warn = TEMP_MODEL_W; temp_model::data.err = TEMP_MODEL_E; temp_model::warn_beep = true; - temp_model::enabled = false; - temp_model::valid = false; + temp_model::enabled = true; + temp_model::data.flag_bits.uninitialized = true; } void temp_model_load_settings() @@ -2794,7 +2789,8 @@ static bool autotune(int16_t cal_temp) { uint16_t samples; float e; - char tm_message[20]; + char tm_message[LCD_WIDTH+1]; + // bootstrap C/R values without fan set_fan_speed(0); @@ -2802,16 +2798,12 @@ static bool autotune(int16_t cal_temp) const char* PROGMEM verb = (i == 0? PSTR("initial"): PSTR("refine")); target_temperature[0] = 0; if(current_temperature[0] >= TEMP_MODEL_CAL_Tl) { -//!01234567890123456789| -//!TM: cool down <50C | sprintf_P(tm_message, PSTR("TM: cool down <%dC"), TEMP_MODEL_CAL_Tl); lcd_setstatus_serial(tm_message); cooldown(TEMP_MODEL_CAL_Tl); wait(10000); } -//!01234567890123456789| -//!TM: initial R est. | -//!TM: refine R est. | + sprintf_P(tm_message, PSTR("TM: %S C est."), verb); lcd_setstatus_serial(tm_message); target_temperature[0] = cal_temp; @@ -2832,9 +2824,7 @@ static bool autotune(int16_t cal_temp) wait_temp(); if(i) break; // we don't need to refine R wait(30000); // settle PID regulation -//!01234567890123456789| -//!TM: initial R 230C | -//!TM: refine R 230C | + sprintf_P(tm_message, PSTR("TM: %S R %dC"), verb, cal_temp); lcd_setstatus_serial(tm_message); samples = record(); @@ -2856,11 +2846,14 @@ static bool autotune(int16_t cal_temp) wait(30000); for(int8_t i = TEMP_MODEL_R_SIZE - 1; i > 0; i -= TEMP_MODEL_CAL_R_STEP) { + // always disable the checker while estimating fan resistance as the difference + // (esp with 3rd-party blowers) can be massive + temp_model::data.R[i] = NAN; + uint8_t speed = 256 / TEMP_MODEL_R_SIZE * (i + 1) - 1; set_fan_speed(speed); wait(10000); -//!01234567890123456789| -//!TM: R[15] estimat. | + sprintf_P(tm_message, PSTR("TM: R[%u] estimat."), (unsigned)i); lcd_setstatus_serial(tm_message); samples = record(); @@ -2896,12 +2889,19 @@ static bool autotune(int16_t cal_temp) } // namespace temp_model_cal +static bool temp_model_autotune_err = true; + void temp_model_autotune(int16_t temp, bool selftest) { - char tm_message[20]; + float orig_C, orig_R[TEMP_MODEL_R_SIZE]; + bool orig_enabled; + static_assert(sizeof(orig_R) == sizeof(temp_model::data.R)); + + // fail-safe error state + temp_model_autotune_err = true; + + char tm_message[LCD_WIDTH+1]; if(moves_planned() || printer_active()) { -//!01234567890123456789| -//!TM: Cal. NOT ILDE | sprintf_P(tm_message, PSTR("TM: Cal. NOT IDLE")); lcd_setstatus_serial(tm_message); return; @@ -2912,26 +2912,36 @@ void temp_model_autotune(int16_t temp, bool selftest) menu_set_block(MENU_BLOCK_TEMP_MODEL_AUTOTUNE); lcd_return_to_status(); - // set the model checking state during self-calibration - bool was_enabled = temp_model::enabled; + // save the original model data and set the model checking state during self-calibration + orig_C = temp_model::data.C; + memcpy(orig_R, temp_model::data.R, sizeof(temp_model::data.R)); + orig_enabled = temp_model::enabled; temp_model_reset_enabled(selftest); + + // autotune SERIAL_ECHOLNPGM("TM: calibration start"); - bool err = temp_model_cal::autotune(temp > 0 ? temp : TEMP_MODEL_CAL_Th); + temp_model_autotune_err = temp_model_cal::autotune(temp > 0 ? temp : TEMP_MODEL_CAL_Th); // always reset temperature disable_heater(); - if(err) { -//!01234567890123456789| -//!TM: calibr. failed! | + if(temp_model_autotune_err) { sprintf_P(tm_message, PSTR("TM: calibr. failed!")); lcd_setstatus_serial(tm_message); if(temp_error_state.v) temp_model_cal::set_fan_speed(255); + + // show calibrated values before overwriting them + temp_model_report_settings(); + + // restore original state + temp_model::data.C = orig_C; + memcpy(temp_model::data.R, orig_R, sizeof(temp_model::data.R)); + temp_model_set_enabled(orig_enabled); } else { lcd_setstatuspgm(MSG_WELCOME); temp_model_cal::set_fan_speed(0); - temp_model_set_enabled(was_enabled); + temp_model_set_enabled(orig_enabled); temp_model_report_settings(); } @@ -2939,6 +2949,11 @@ void temp_model_autotune(int16_t temp, bool selftest) menu_unset_block(MENU_BLOCK_TEMP_MODEL_AUTOTUNE); } +bool temp_model_autotune_result() +{ + return !temp_model_autotune_err; +} + #ifdef TEMP_MODEL_DEBUG void temp_model_log_enable(bool enable) { diff --git a/Firmware/temperature.h b/Firmware/temperature.h index 2b66397d..03629db1 100755 --- a/Firmware/temperature.h +++ b/Firmware/temperature.h @@ -217,8 +217,8 @@ FORCE_INLINE void autotempShutdown(){ void PID_autotune(float temp, int extruder, int ncycles); #ifdef TEMP_MODEL +bool temp_model_enabled(); // return temperature model state void temp_model_set_enabled(bool enabled); -bool temp_model_valid(); void temp_model_set_warn_beep(bool enabled); void temp_model_set_params(float C = NAN, float P = NAN, float Ta_corr = NAN, float warn = NAN, float err = NAN); void temp_model_set_resistance(uint8_t index, float R); @@ -229,6 +229,7 @@ void temp_model_load_settings(); void temp_model_save_settings(); void temp_model_autotune(int16_t temp = 0, bool selftest = false); +bool temp_model_autotune_result(); // return true if the last autotune was complete and successful #ifdef TEMP_MODEL_DEBUG void temp_model_log_enable(bool enable); diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 6300bc8d..2d23d030 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1041,27 +1041,42 @@ void lcd_commands() lcd_commands_type = LcdCommands::Idle; } } + #ifdef TEMP_MODEL - if (lcd_commands_type == LcdCommands::TempModel) { - if (lcd_commands_step == 0) { + if (lcd_commands_type == LcdCommands::TempModel && cmd_buffer_empty()) + { + switch (lcd_commands_step) + { + case 0: lcd_commands_step = 3; - } - if (lcd_commands_step == 3) { - enquecommand_P(PSTR("M310 A F0")); + [[fallthrough]]; + + case 3: + enquecommand_P(PSTR("M310 A F1")); lcd_commands_step = 2; - } - if (lcd_commands_step ==2 && temp_model_valid()) { - enquecommand_P(PSTR("M310 S1")); + break; + + case 2: + if (temp_model_autotune_result()) + enquecommand_P(PSTR("M500")); lcd_commands_step = 1; - } - //if (lcd_commands_step == 1 && calibrated()) { - if (lcd_commands_step == 1 && temp_model_valid()) { + break; + + case 1: lcd_commands_step = 0; lcd_commands_type = LcdCommands::Idle; - enquecommand_P(PSTR("M500")); - if (eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE) == 1) { - lcd_wizard(WizState::IsFil); + + if (temp_model_autotune_result()) { + if (calibration_status() == CALIBRATION_STATUS_TEMP_MODEL_CALIBRATION) { + // move to the next calibration step if not fully calibrated + calibration_status_store(CALIBRATION_STATUS_LIVE_ADJUST); + } + if ((eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE) == 1)) { + // successful: resume the wizard + lcd_wizard(WizState::IsFil); + } } + break; } } #endif //TEMP_MODEL @@ -1070,6 +1085,9 @@ void lcd_commands() { if (!blocks_queued() && cmd_buffer_empty() && !saved_printing) { +#ifdef TEMP_MODEL + static bool was_enabled; +#endif //TEMP_MODEL switch(lcd_commands_step) { case 0: @@ -1084,7 +1102,7 @@ void lcd_commands() enquecommand_P(PSTR("G1 X125 Y10 Z150 F1000")); enquecommand_P(PSTR("M109 S280")); #ifdef TEMP_MODEL - //enquecommand_P(PSTR("M310 S0")); + was_enabled = temp_model_enabled(); temp_model_set_enabled(false); #endif //TEMP_MODEL lcd_commands_step = 2; @@ -1098,13 +1116,11 @@ void lcd_commands() enquecommand_P(PSTR("M84 XY")); lcd_update_enabled = false; //hack to avoid lcd_update recursion. if (lcd_show_fullscreen_message_yes_no_and_wait_P(_T(MSG_NOZZLE_CNG_CHANGED), false, true)) { + setAllTargetHotends(0); #ifdef TEMP_MODEL - //enquecommand_P(PSTR("M310 S1")); - temp_model_set_enabled(true); + temp_model_set_enabled(was_enabled); #endif //TEMP_MODEL - //enquecommand_P(PSTR("M104 S0")); - setTargetHotendSafe(0,0); - lcd_commands_step = 1; + lcd_commands_step = 1; } lcd_update_enabled = true; break; @@ -4271,10 +4287,6 @@ void lcd_wizard(WizState state) case S::Z: //z cal. msg = _T(MSG_WIZARD_CALIBRATION_FAILED); break; -#ifdef TEMP_MODEL - case S::TempModel: //Temp model calibration - break; -#endif //TEMP_MODEL case S::Finish: //we are finished msg = _T(MSG_WIZARD_DONE); lcd_reset_alert_level(); @@ -4284,6 +4296,9 @@ void lcd_wizard(WizState state) case S::Preheat: case S::Lay1CalCold: case S::Lay1CalHot: +#ifdef TEMP_MODEL + case S::TempModel: // exiting for calibration +#endif //TEMP_MODEL break; default: msg = _T(MSG_WIZARD_QUIT); @@ -6996,11 +7011,7 @@ static bool lcd_selfcheck_endstops() static bool lcd_selfcheck_check_heater(bool _isbed) { - uint8_t _counter = 0; uint8_t _progress = 0; - bool _stepresult = false; - bool _docycle = true; - int _checked_snapshot = (_isbed) ? degBed() : degHotend(0); int _opposite_snapshot = (_isbed) ? degHotend(0) : degBed(); uint8_t _cycles = (_isbed) ? 180 : 60; //~ 90s / 30s @@ -7010,13 +7021,13 @@ static bool lcd_selfcheck_check_heater(bool _isbed) manage_heater(); manage_inactivity(true); - do { - _counter++; - _docycle = (_counter < _cycles) ? true : false; - + for(uint8_t _counter = 0; _counter < _cycles && !Stopped; ++_counter) + { manage_heater(); manage_inactivity(true); - _progress = (_isbed) ? lcd_selftest_screen(TestScreen::Bed, _progress, 2, false, 400) : lcd_selftest_screen(TestScreen::Hotend, _progress, 2, false, 400); + _progress = (_isbed? + lcd_selftest_screen(TestScreen::Bed, _progress, 2, false, 400) : + lcd_selftest_screen(TestScreen::Hotend, _progress, 2, false, 400)); /*if (_isbed) { MYSERIAL.print("Bed temp:"); MYSERIAL.println(degBed()); @@ -7026,8 +7037,7 @@ static bool lcd_selfcheck_check_heater(bool _isbed) MYSERIAL.println(degHotend(0)); }*/ if(_counter%5 == 0) serialecho_temperatures(); //show temperatures once in two seconds - - } while (_docycle); + } target_temperature[0] = 0; target_temperature_bed = 0; @@ -7043,21 +7053,26 @@ static bool lcd_selfcheck_check_heater(bool _isbed) MYSERIAL.println(_opposite_result); */ - if (_opposite_result < ((_isbed) ? 30 : 9)) - { - if (_checked_result >= ((_isbed) ? 9 : 30)) - { - _stepresult = true; - } - else - { - lcd_selftest_error(TestError::Heater, "", ""); - } - } - else - { - lcd_selftest_error(TestError::Bed, "", ""); - } + bool _stepresult = false; + if (Stopped) + { + // thermal error occurred while heating the nozzle + lcd_selftest_error(TestError::Heater, "", ""); + } + else + { + if (_opposite_result < ((_isbed) ? 30 : 9)) + { + if (_checked_result >= ((_isbed) ? 9 : 30)) + _stepresult = true; + else + lcd_selftest_error(TestError::Heater, "", ""); + } + else + { + lcd_selftest_error(TestError::Bed, "", ""); + } + } manage_heater(); manage_inactivity(true); diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index ecab4565..df08de9e 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -437,6 +437,9 @@ #define TEMP_MODEL_CAL_Th 230 // Default calibration working temperature (C) #define TEMP_MODEL_CAL_Tl 50 // Default calibration cooling temperature (C) +// fall-back resistance vector (R0-15) +#define TEMP_MODEL_Rv {TEMP_MODEL_R, 18.4, 16.7, 15.2, 14.1, 13.3, 12.7, 12.1, 11.7, 11.3, 11., 10.8, 10.6, 10.4, 10.2, 10.1} + /*------------------------------------ MOTOR CURRENT SETTINGS diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index c1767ae1..af6ffa3b 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -441,6 +441,9 @@ #define TEMP_MODEL_CAL_Th 230 // Default calibration working temperature (C) #define TEMP_MODEL_CAL_Tl 50 // Default calibration cooling temperature (C) +// fall-back resistance vector (R0-15) +#define TEMP_MODEL_Rv {TEMP_MODEL_R, 18.4, 16.7, 15.2, 14.1, 13.3, 12.7, 12.1, 11.7, 11.3, 11., 10.8, 10.6, 10.4, 10.2, 10.1} + /*------------------------------------ MOTOR CURRENT SETTINGS