diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index cce5e2f7e9..2a64000449 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -624,6 +624,9 @@ * for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 to autotune the model. */ #if ENABLED(MPCTEMP) + //#define MPC_EDIT_MENU // Add MPC editing to the "Advanced Settings" menu. (~1300 bytes of flash) + //#define MPC_AUTOTUNE_MENU // Add MPC auto-tuning to the "Advanced Settings" menu. (~350 bytes of flash) + #define MPC_MAX BANG_MAX // (0..255) Current to nozzle while MPC is active. #define MPC_HEATER_POWER { 40.0f } // (W) Heat cartridge powers. @@ -652,6 +655,7 @@ #define MPC_STEADYSTATE 0.5f // (K/s) Temperature change rate for steady state logic to be enforced. #define MPC_TUNING_POS { X_CENTER, Y_CENTER, 1.0f } // (mm) M306 Autotuning position, ideally bed center just above the surface. + #define MPC_TUNING_END_Z 10.0f // (mm) M306 Autotuning final Z position. #endif //=========================================================================== diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 0b13161976..78e30fe504 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -232,6 +232,14 @@ #define STR_PID_DEBUG_DTERM " dTerm " #define STR_PID_DEBUG_CTERM " cTerm " #define STR_INVALID_EXTRUDER_NUM " - Invalid extruder number !" +#define STR_MPC_AUTOTUNE "MPC Autotune" +#define STR_MPC_AUTOTUNE_START " start for " STR_E +#define STR_MPC_AUTOTUNE_INTERRUPTED " interrupted!" +#define STR_MPC_AUTOTUNE_FINISHED " finished! Put the constants below into Configuration.h" +#define STR_MPC_COOLING_TO_AMBIENT "Cooling to ambient" +#define STR_MPC_HEATING_PAST_200 "Heating to over 200C" +#define STR_MPC_MEASURING_AMBIENT "Measuring ambient heatloss at " +#define STR_MPC_TEMPERATURE_ERROR "Temperature error" #define STR_HEATER_BED "bed" #define STR_HEATER_CHAMBER "chamber" diff --git a/Marlin/src/gcode/temp/M306.cpp b/Marlin/src/gcode/temp/M306.cpp index 9e1a8dd8ef..0f286e73b2 100644 --- a/Marlin/src/gcode/temp/M306.cpp +++ b/Marlin/src/gcode/temp/M306.cpp @@ -56,17 +56,7 @@ void GcodeSuite::M306() { return; } - HOTEND_LOOP() { - SERIAL_ECHOLNPGM("MPC constants for hotend ", e); - MPC_t& constants = thermalManager.temp_hotend[e].constants; - SERIAL_ECHOLNPGM("Heater power: ", constants.heater_power); - SERIAL_ECHOLNPGM("Heatblock heat capacity: ", constants.block_heat_capacity); - SERIAL_ECHOLNPAIR_F("Sensor responsivness: ", constants.sensor_responsiveness, 4); - SERIAL_ECHOLNPAIR_F("Ambient heat transfer coeff. (no fan): ", constants.ambient_xfer_coeff_fan0, 4); - #if ENABLED(MPC_INCLUDE_FAN) - SERIAL_ECHOLNPAIR_F("Ambient heat transfer coeff. (full fan): ", constants.ambient_xfer_coeff_fan0 + constants.fan255_adjustment, 4); - #endif - } + M306_report(true); } void GcodeSuite::M306_report(const bool forReplay/*=true*/) { @@ -79,7 +69,9 @@ void GcodeSuite::M306_report(const bool forReplay/*=true*/) { SERIAL_ECHOPAIR_F(" C", constants.block_heat_capacity, 2); SERIAL_ECHOPAIR_F(" R", constants.sensor_responsiveness, 4); SERIAL_ECHOPAIR_F(" A", constants.ambient_xfer_coeff_fan0, 4); - SERIAL_ECHOLNPAIR_F(" F", constants.ambient_xfer_coeff_fan0 + constants.fan255_adjustment, 4); + #if ENABLED(MPC_INCLUDE_FAN) + SERIAL_ECHOLNPAIR_F(" F", constants.ambient_xfer_coeff_fan0 + constants.fan255_adjustment, 4); + #endif } } diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 88ba2bb2b6..02e32c83ea 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -2856,6 +2856,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "DWIN_CREALITY_LCD requires SDSUPPORT to be enabled." #elif EITHER(PID_EDIT_MENU, PID_AUTOTUNE_MENU) #error "DWIN_CREALITY_LCD does not support PID_EDIT_MENU or PID_AUTOTUNE_MENU." + #elif EITHER(MPC_EDIT_MENU, MPC_AUTOTUNE_MENU) + #error "DWIN_CREALITY_LCD does not support MPC_EDIT_MENU or MPC_AUTOTUNE_MENU." #elif ENABLED(LEVEL_BED_CORNERS) #error "DWIN_CREALITY_LCD does not support LEVEL_BED_CORNERS." #elif BOTH(LCD_BED_LEVELING, PROBE_MANUALLY) @@ -2866,6 +2868,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "DWIN_LCD_PROUI requires SDSUPPORT to be enabled." #elif EITHER(PID_EDIT_MENU, PID_AUTOTUNE_MENU) #error "DWIN_LCD_PROUI does not support PID_EDIT_MENU or PID_AUTOTUNE_MENU." + #elif EITHER(MPC_EDIT_MENU, MPC_AUTOTUNE_MENU) + #error "DWIN_LCD_PROUI does not support MPC_EDIT_MENU or MPC_AUTOTUNE_MENU." #elif ENABLED(LEVEL_BED_CORNERS) #error "DWIN_LCD_PROUI does not support LEVEL_BED_CORNERS." #elif BOTH(LCD_BED_LEVELING, PROBE_MANUALLY) diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 1358baebc3..2ba729d6d3 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -374,6 +374,14 @@ namespace Language_en { LSTR MSG_PID_BAD_EXTRUDER_NUM = _UxGT("Autotune failed! Bad extruder."); LSTR MSG_PID_TEMP_TOO_HIGH = _UxGT("Autotune failed! Temperature too high."); LSTR MSG_PID_TIMEOUT = _UxGT("Autotune failed! Timeout."); + LSTR MSG_MPC_MEASURING_AMBIENT = _UxGT("Testing heat loss"); + LSTR MSG_MPC_AUTOTUNE = _UxGT("MPC Autotune"); + LSTR MSG_MPC_EDIT = _UxGT("Edit * MPC"); + LSTR MSG_MPC_POWER_E = _UxGT("Power *"); + LSTR MSG_MPC_BLOCK_HEAT_CAPACITY_E = _UxGT("Block C *"); + LSTR MSG_SENSOR_RESPONSIVENESS_E = _UxGT("Sensor res *"); + LSTR MSG_MPC_AMBIENT_XFER_COEFF_E = _UxGT("Ambient h *"); + LSTR MSG_MPC_AMBIENT_XFER_COEFF_FAN255_E= _UxGT("Amb. h fan *"); LSTR MSG_SELECT = _UxGT("Select"); LSTR MSG_SELECT_E = _UxGT("Select *"); LSTR MSG_ACC = _UxGT("Accel"); diff --git a/Marlin/src/lcd/menu/menu_advanced.cpp b/Marlin/src/lcd/menu/menu_advanced.cpp index 21fa01f2aa..bd4ec49889 100644 --- a/Marlin/src/lcd/menu/menu_advanced.cpp +++ b/Marlin/src/lcd/menu/menu_advanced.cpp @@ -245,7 +245,7 @@ void menu_backlash(); } #endif -#if BOTH(AUTOTEMP, HAS_TEMP_HOTEND) || EITHER(PID_AUTOTUNE_MENU, PID_EDIT_MENU) +#if BOTH(AUTOTEMP, HAS_TEMP_HOTEND) || ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU, MPC_AUTOTUNE_MENU, MPC_EDIT_MENU) #define SHOW_MENU_ADVANCED_TEMPERATURE 1 #endif @@ -254,7 +254,17 @@ void menu_backlash(); // #if SHOW_MENU_ADVANCED_TEMPERATURE + #if ENABLED(MPC_EDIT_MENU) + #define MPC_EDIT_DEFS(N) \ + MPC_t &c = thermalManager.temp_hotend[N].constants; \ + TERN_(MPC_INCLUDE_FAN, editable.decimal = c.ambient_xfer_coeff_fan0 + c.fan255_adjustment) + #endif + void menu_advanced_temperature() { + #if ENABLED(MPC_EDIT_MENU) && !HAS_MULTI_HOTEND + MPC_EDIT_DEFS(0); + #endif + START_MENU(); BACK_ITEM(MSG_ADVANCED_SETTINGS); @@ -331,6 +341,46 @@ void menu_backlash(); #endif #endif + #if ENABLED(MPC_EDIT_MENU) + + #define _MPC_EDIT_ITEMS(N) \ + EDIT_ITEM_FAST_N(float31sign, N, MSG_MPC_POWER_E, &c.heater_power, 1, 200); \ + EDIT_ITEM_FAST_N(float31sign, N, MSG_MPC_BLOCK_HEAT_CAPACITY_E, &c.block_heat_capacity, 0, 40); \ + EDIT_ITEM_FAST_N(float43, N, MSG_SENSOR_RESPONSIVENESS_E, &c.sensor_responsiveness, 0, 1); \ + EDIT_ITEM_FAST_N(float43, N, MSG_MPC_AMBIENT_XFER_COEFF_E, &c.ambient_xfer_coeff_fan0, 0, 1) + + #if ENABLED(MPC_INCLUDE_FAN) + #define MPC_EDIT_ITEMS(N) \ + _MPC_EDIT_ITEMS(N); \ + EDIT_ITEM_FAST_N(float43, N, MSG_MPC_AMBIENT_XFER_COEFF_FAN255_E, &editable.decimal, 0, 1, []{ \ + MPC_t &c = thermalManager.temp_hotend[MenuItemBase::itemIndex].constants; \ + c.fan255_adjustment = editable.decimal - c.ambient_xfer_coeff_fan0; \ + }) + #else + #define MPC_EDIT_ITEMS _MPC_EDIT_ITEMS + #endif + + #if HAS_MULTI_HOTEND + static auto mpc_edit_hotend = [](const uint8_t e) { + MPC_EDIT_DEFS(e); + START_MENU(); + BACK_ITEM(MSG_TEMPERATURE); + MPC_EDIT_ITEMS(e); + END_MENU(); + }; + #define MPC_ENTRY(N) SUBMENU_N(N, MSG_MPC_EDIT, []{ mpc_edit_hotend(MenuItemBase::itemIndex); }); + #else + #define MPC_ENTRY MPC_EDIT_ITEMS + #endif + + REPEAT(HOTENDS, MPC_ENTRY); + + #endif // MPC_EDIT_MENU + + #if ENABLED(MPC_AUTOTUNE_MENU) + ACTION_ITEM(MSG_MPC_AUTOTUNE, []{ queue.inject(F("M306 T")); ui.return_to_status(); }); + #endif + #if ENABLED(PIDTEMPBED) #if ENABLED(PID_EDIT_MENU) _PID_EDIT_ITEMS_TMPL(H_BED, thermalManager.temp_bed); diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 6b002e52d9..df1e3f6fc8 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -141,8 +141,12 @@ #endif #endif -#if EITHER(MPCTEMP, PID_EXTRUSION_SCALING) +#if ENABLED(MPCTEMP) #include + #include "probe.h" +#endif + +#if EITHER(MPCTEMP, PID_EXTRUSION_SCALING) #include "stepper.h" #endif @@ -870,33 +874,65 @@ volatile bool Temperature::raw_temps_ready = false; if (ELAPSED(ms, next_report_ms)) { next_report_ms += 1000UL; - SERIAL_ECHOLNPGM("Temperature ", current_temp); + + print_heater_states(active_extruder); + SERIAL_EOL(); } hal.idletask(); + TERN(DWIN_CREALITY_LCD, DWIN_Update(), ui.update()); + + if (!wait_for_heatup) { + SERIAL_ECHOPGM(STR_MPC_AUTOTUNE); + SERIAL_ECHOLNPGM(STR_MPC_AUTOTUNE_INTERRUPTED); + return false; + } + + return true; }; - SERIAL_ECHOLNPGM("Measuring MPC constants for E", active_extruder); - MPCHeaterInfo& hotend = temp_hotend[active_extruder]; - MPC_t& constants = hotend.constants; + struct OnExit { + ~OnExit() { + wait_for_heatup = false; - // move to center of bed, just above bed height and cool with max fan - TERN_(HAS_FAN, zero_fan_speeds()); + ui.reset_status(); + + temp_hotend[active_extruder].target = 0.0f; + temp_hotend[active_extruder].soft_pwm_amount = 0; + #if HAS_FAN + set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0); + planner.sync_fan_speeds(fan_speed); + #endif + + do_z_clearance(MPC_TUNING_END_Z); + } + } on_exit; + + SERIAL_ECHOPGM(STR_MPC_AUTOTUNE); + SERIAL_ECHOLNPGM(STR_MPC_AUTOTUNE_START, active_extruder); + MPCHeaterInfo &hotend = temp_hotend[active_extruder]; + MPC_t &constants = hotend.constants; + + // Move to center of bed, just above bed height and cool with max fan disable_all_heaters(); - TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255)); - TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed)); + #if HAS_FAN + zero_fan_speeds(); + set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255); + planner.sync_fan_speeds(fan_speed); + #endif gcode.home_all_axes(true); const xyz_pos_t tuningpos = MPC_TUNING_POS; do_blocking_move_to(tuningpos); - SERIAL_ECHOLNPGM("Cooling to ambient"); + SERIAL_ECHOLNPGM(STR_MPC_COOLING_TO_AMBIENT); + LCD_MESSAGE(MSG_COOLING); millis_t ms = millis(), next_report_ms = ms, next_test_ms = ms + 10000UL; celsius_float_t current_temp = degHotend(active_extruder), ambient_temp = current_temp; - wait_for_heatup = true; // Can be interrupted with M108 - while (wait_for_heatup) { - housekeeping(ms, current_temp, next_report_ms); + wait_for_heatup = true; + for (;;) { // Can be interrupted with M108 + if (!housekeeping(ms, current_temp, next_report_ms)) return; if (ELAPSED(ms, next_test_ms)) { if (current_temp >= ambient_temp) { @@ -908,12 +944,16 @@ volatile bool Temperature::raw_temps_ready = false; } } - TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0)); - TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed)); + #if HAS_FAN + set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0); + planner.sync_fan_speeds(fan_speed); + #endif hotend.modeled_ambient_temp = ambient_temp; - SERIAL_ECHOLNPGM("Heating to 200C"); + SERIAL_ECHOLNPGM(STR_MPC_HEATING_PAST_200); + LCD_MESSAGE(MSG_HEATING); + hotend.target = 200.0f; // So M105 looks nice hotend.soft_pwm_amount = MPC_MAX >> 1; const millis_t heat_start_time = next_test_ms = ms; celsius_float_t temp_samples[16]; @@ -921,13 +961,13 @@ volatile bool Temperature::raw_temps_ready = false; uint16_t sample_distance = 1; float t1_time = 0; - while (wait_for_heatup) { - housekeeping(ms, current_temp, next_report_ms); + for (;;) { // Can be interrupted with M108 + if (!housekeeping(ms, current_temp, next_report_ms)) return; if (ELAPSED(ms, next_test_ms)) { - // record samples between 100C and 200C + // Record samples between 100C and 200C if (current_temp >= 100.0f) { - // if there are too many samples, space them more widely + // If there are too many samples, space them more widely if (sample_count == COUNT(temp_samples)) { for (uint8_t i = 0; i < COUNT(temp_samples) / 2; i++) temp_samples[i] = temp_samples[i*2]; @@ -950,9 +990,9 @@ volatile bool Temperature::raw_temps_ready = false; sample_count = (sample_count + 1) / 2 * 2 - 1; const float t1 = temp_samples[0], t2 = temp_samples[(sample_count - 1) >> 1], - t3 = temp_samples[sample_count - 1], - asymp_temp = (t2 * t2 - t1 * t3) / (2 * t2 - t1 - t3), - block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1)); + t3 = temp_samples[sample_count - 1]; + float asymp_temp = (t2 * t2 - t1 * t3) / (2 * t2 - t1 - t3), + block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1)); constants.ambient_xfer_coeff_fan0 = constants.heater_power * MPC_MAX / 255 / (asymp_temp - ambient_temp); constants.fan255_adjustment = 0.0f; @@ -963,7 +1003,8 @@ volatile bool Temperature::raw_temps_ready = false; hotend.modeled_sensor_temp = current_temp; // Allow the system to stabilize under MPC, then get a better measure of ambient loss with and without fan - SERIAL_ECHOLNPGM("Measuring ambient heatloss at target ", hotend.modeled_block_temp); + SERIAL_ECHOLNPGM(STR_MPC_MEASURING_AMBIENT, hotend.modeled_block_temp); + LCD_MESSAGE(MSG_MPC_MEASURING_AMBIENT); hotend.target = hotend.modeled_block_temp; next_test_ms = ms + MPC_dT * 1000; constexpr millis_t settle_time = 20000UL, test_duration = 20000UL; @@ -976,18 +1017,16 @@ volatile bool Temperature::raw_temps_ready = false; #endif float last_temp = current_temp; - while (wait_for_heatup) { - housekeeping(ms, current_temp, next_report_ms); + for (;;) { // Can be interrupted with M108 + if (!housekeeping(ms, current_temp, next_report_ms)) return; if (ELAPSED(ms, next_test_ms)) { - // use MPC to control the temperature, let it settle for 30s and then track power output for 10s hotend.soft_pwm_amount = (int)get_pid_output_hotend(active_extruder) >> 1; if (ELAPSED(ms, settle_end_ms) && !ELAPSED(ms, test_end_ms) && TERN1(HAS_FAN, !fan0_done)) total_energy_fan0 += constants.heater_power * hotend.soft_pwm_amount / 127 * MPC_dT + (last_temp - current_temp) * constants.block_heat_capacity; #if HAS_FAN else if (ELAPSED(ms, test_end_ms) && !fan0_done) { - SERIAL_ECHOLNPGM("Measuring ambient heatloss with full fan"); set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255); planner.sync_fan_speeds(fan_speed); settle_end_ms = ms + settle_time; @@ -1003,8 +1042,8 @@ volatile bool Temperature::raw_temps_ready = false; next_test_ms += MPC_dT * 1000; } - if (!WITHIN(current_temp, hotend.target - 15.0f, hotend.target + 15.0f)) { - SERIAL_ECHOLNPGM("Temperature error while measuring ambient loss"); + if (!WITHIN(current_temp, t3 - 15.0f, hotend.target + 15.0f)) { + SERIAL_ECHOLNPGM(STR_MPC_TEMPERATURE_ERROR); break; } } @@ -1018,16 +1057,14 @@ volatile bool Temperature::raw_temps_ready = false; constants.fan255_adjustment = ambient_xfer_coeff_fan255 - constants.ambient_xfer_coeff_fan0; #endif - hotend.target = 0.0f; - hotend.soft_pwm_amount = 0; - TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0)); - TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed)); + // Calculate a new and better asymptotic temperature and re-evaluate the other constants + asymp_temp = ambient_temp + constants.heater_power / constants.ambient_xfer_coeff_fan0; + block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1)); + constants.block_heat_capacity = constants.ambient_xfer_coeff_fan0 / block_responsiveness; + constants.sensor_responsiveness = block_responsiveness / (1.0f - (ambient_temp - asymp_temp) * exp(-block_responsiveness * t1_time) / (t1 - asymp_temp)); - if (!wait_for_heatup) SERIAL_ECHOLNPGM("Test was interrupted"); - - wait_for_heatup = false; - - SERIAL_ECHOLNPGM("Done"); + SERIAL_ECHOPGM(STR_MPC_AUTOTUNE); + SERIAL_ECHOLNPGM(STR_MPC_AUTOTUNE_FINISHED); /* <-- add a slash to enable SERIAL_ECHOLNPGM("t1_time ", t1_time); @@ -1380,7 +1417,7 @@ void Temperature::min_temp_error(const heater_id_t heater_id) { // At startup, initialize modeled temperatures if (isnan(hotend.modeled_block_temp)) { - hotend.modeled_ambient_temp = min(30.0f, hotend.celsius); // cap initial value at reasonable max room temperature of 30C + hotend.modeled_ambient_temp = min(30.0f, hotend.celsius); // Cap initial value at reasonable max room temperature of 30C hotend.modeled_block_temp = hotend.modeled_sensor_temp = hotend.celsius; } @@ -1401,16 +1438,16 @@ void Temperature::min_temp_error(const heater_id_t heater_id) { const int32_t e_position = stepper.position(E_AXIS); const float e_speed = (e_position - mpc_e_position) * planner.mm_per_step[E_AXIS] / MPC_dT; - // the position can appear to make big jumps when, e.g. homing + // The position can appear to make big jumps when, e.g. homing if (fabs(e_speed) > planner.settings.max_feedrate_mm_s[E_AXIS]) mpc_e_position = e_position; - else if (e_speed > 0.0f) { // ignore retract/recover moves + else if (e_speed > 0.0f) { // Ignore retract/recover moves ambient_xfer_coeff += e_speed * FILAMENT_HEAT_CAPACITY_PERMM; mpc_e_position = e_position; } } - // update the modeled temperatures + // Update the modeled temperatures float blocktempdelta = hotend.soft_pwm_amount * constants.heater_power * (MPC_dT / 127) / constants.block_heat_capacity; blocktempdelta += (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff * MPC_dT / constants.block_heat_capacity; hotend.modeled_block_temp += blocktempdelta; @@ -1424,18 +1461,18 @@ void Temperature::min_temp_error(const heater_id_t heater_id) { hotend.modeled_block_temp += delta_to_apply; hotend.modeled_sensor_temp += delta_to_apply; - // only correct ambient when close to steady state (output power is not clipped or asymptotic temperature is reached) + // Only correct ambient when close to steady state (output power is not clipped or asymptotic temperature is reached) if (WITHIN(hotend.soft_pwm_amount, 1, 126) || fabs(blocktempdelta + delta_to_apply) < (MPC_STEADYSTATE * MPC_dT)) hotend.modeled_ambient_temp += delta_to_apply > 0.f ? max(delta_to_apply, MPC_MIN_AMBIENT_CHANGE * MPC_dT) : min(delta_to_apply, -MPC_MIN_AMBIENT_CHANGE * MPC_dT); float power = 0.0; if (hotend.target != 0 && TERN1(HEATER_IDLE_HANDLER, !heater_idle[ee].timed_out)) { - // plan power level to get to target temperature in 2 seconds + // Plan power level to get to target temperature in 2 seconds power = (hotend.target - hotend.modeled_block_temp) * constants.block_heat_capacity / 2.0f; power -= (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff; } - float pid_output = power * 254.0f / constants.heater_power + 1.0f; // ensure correct quantization into a range of 0 to 127 + float pid_output = power * 254.0f / constants.heater_power + 1.0f; // Ensure correct quantization into a range of 0 to 127 pid_output = constrain(pid_output, 0, MPC_MAX); /* <-- add a slash to enable @@ -2081,7 +2118,7 @@ void Temperature::manage_heater() { - (t.beta_recip * t.res_25_log) - (t.sh_c_coeff * cu(t.res_25_log)); } - // maximum adc value .. take into account the over sampling + // Maximum ADC value .. take into account the over sampling constexpr raw_adc_t adc_max = MAX_RAW_THERMISTOR_VALUE; const raw_adc_t adc_raw = constrain(raw, 1, adc_max - 1); // constrain to prevent divide-by-zero @@ -3081,7 +3118,7 @@ void Temperature::disable_all_heaters() { spiInit(MAX_TC_SPEED_BITS); #endif - MAXTC_CS_WRITE(LOW); // enable MAXTC + MAXTC_CS_WRITE(LOW); // Enable MAXTC DELAY_NS(100); // Ensure 100ns delay // Read a big-endian temperature value without using a library @@ -3090,7 +3127,7 @@ void Temperature::disable_all_heaters() { if (i > 0) max_tc_temp <<= 8; // shift left if not the last byte } - MAXTC_CS_WRITE(HIGH); // disable MAXTC + MAXTC_CS_WRITE(HIGH); // Disable MAXTC #else #if HAS_MAX6675_LIBRARY MAX6675 &max6675ref = THERMO_SEL(max6675_0, max6675_1); @@ -3301,7 +3338,7 @@ void Temperature::isr() { static ADCSensorState adc_sensor_state = StartupDelay; static uint8_t pwm_count = _BV(SOFT_PWM_SCALE); - // avoid multiple loads of pwm_count + // Avoid multiple loads of pwm_count uint8_t pwm_count_tmp = pwm_count; #if HAS_ADC_BUTTONS @@ -3579,8 +3616,8 @@ void Temperature::isr() { // 5: / 4 = 244.1406 Hz pwm_count = pwm_count_tmp + _BV(SOFT_PWM_SCALE); - // increment slow_pwm_count only every 64th pwm_count, - // i.e. yielding a PWM frequency of 16/128 Hz (8s). + // Increment slow_pwm_count only every 64th pwm_count, + // i.e., yielding a PWM frequency of 16/128 Hz (8s). if (((pwm_count >> SOFT_PWM_SCALE) & 0x3F) == 0) { slow_pwm_count++; slow_pwm_count &= 0x7F; @@ -4036,7 +4073,7 @@ void Temperature::isr() { // Prevent a wait-forever situation if R is misused i.e. M109 R0 if (wants_to_cool) { - // break after MIN_COOLING_SLOPE_TIME seconds + // Break after MIN_COOLING_SLOPE_TIME seconds // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) { if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG)) break; @@ -4058,7 +4095,7 @@ void Temperature::isr() { wait_for_heatup = false; #if HAS_DWIN_E3V2_BASIC HMI_flag.heat_flag = 0; - duration_t elapsed = print_job_timer.duration(); // print timer + duration_t elapsed = print_job_timer.duration(); // Print timer dwin_heat_time = elapsed.value; #else ui.reset_status(); diff --git a/buildroot/tests/BIGTREE_GTR_V1_0 b/buildroot/tests/BIGTREE_GTR_V1_0 index 919822733b..93342ed4a4 100755 --- a/buildroot/tests/BIGTREE_GTR_V1_0 +++ b/buildroot/tests/BIGTREE_GTR_V1_0 @@ -32,9 +32,15 @@ restore_configs opt_set MOTHERBOARD BOARD_BTT_GTR_V1_0 SERIAL_PORT -1 \ EXTRUDERS 3 TEMP_SENSOR_1 1 TEMP_SENSOR_2 1 \ SERVO_DELAY '{ 300, 300, 300 }' \ - SWITCHING_TOOLHEAD_X_POS '{ 215, 0 ,0 }' -opt_enable SWITCHING_TOOLHEAD TOOL_SENSOR -exec_test $1 $2 "BigTreeTech GTR | Switching Toolhead | Tool Sensors" "$3" + SWITCHING_TOOLHEAD_X_POS '{ 215, 0 ,0 }' \ + MPC_HEATER_POWER '{ 40.0f, 40.0f, 40.0f }' \ + MPC_BLOCK_HEAT_CAPACITY '{ 16.7f, 16.7f, 16.7f }' \ + MPC_SENSOR_RESPONSIVENESS '{ 0.22f, 0.22f, 0.22f }' \ + MPC_AMBIENT_XFER_COEFF '{ 0.068f, 0.068f, 0.068f }' \ + MPC_AMBIENT_XFER_COEFF_FAN255 '{ 0.097f, 0.097f, 0.097f }' +opt_enable SWITCHING_TOOLHEAD TOOL_SENSOR MPCTEMP MPC_EDIT_MENU MPC_AUTOTUNE_MENU +opt_disable PIDTEMP +exec_test $1 $2 "BigTreeTech GTR | MPC | Switching Toolhead | Tool Sensors" "$3" # clean up restore_configs diff --git a/buildroot/tests/STM32F103RC_btt b/buildroot/tests/STM32F103RC_btt index e76060aee8..16419cbfa2 100755 --- a/buildroot/tests/STM32F103RC_btt +++ b/buildroot/tests/STM32F103RC_btt @@ -13,7 +13,6 @@ restore_configs opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_E3_V1_0 SERIAL_PORT 1 SERIAL_PORT_2 -1 \ X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2209 Z_DRIVER_TYPE TMC2209 E0_DRIVER_TYPE TMC2209 opt_enable PINS_DEBUGGING Z_IDLE_HEIGHT - exec_test $1 $2 "BigTreeTech SKR Mini E3 1.0 - Basic Config with TMC2209 HW Serial" "$3" # clean up diff --git a/buildroot/tests/STM32F103RC_btt_maple b/buildroot/tests/STM32F103RC_btt_maple index e74e590213..90e33ab529 100755 --- a/buildroot/tests/STM32F103RC_btt_maple +++ b/buildroot/tests/STM32F103RC_btt_maple @@ -13,7 +13,6 @@ restore_configs opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_E3_V1_0 SERIAL_PORT 1 SERIAL_PORT_2 -1 \ X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2209 Z_DRIVER_TYPE TMC2209 E0_DRIVER_TYPE TMC2209 opt_enable PINS_DEBUGGING Z_IDLE_HEIGHT - exec_test $1 $2 "BigTreeTech SKR Mini E3 1.0 - Basic Config with TMC2209 HW Serial" "$3" # clean up diff --git a/buildroot/tests/mega2560 b/buildroot/tests/mega2560 index 0321e451c4..3677abf60e 100755 --- a/buildroot/tests/mega2560 +++ b/buildroot/tests/mega2560 @@ -181,7 +181,6 @@ opt_set MOTHERBOARD BOARD_RAMPS_14_EFB EXTRUDERS 0 LCD_LANGUAGE en TEMP_SENSOR_C AXIS_RELATIVE_MODES '{ false, false, false }' opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \ LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER MEATPACK_ON_SERIAL_PORT_1 - exec_test $1 $2 "MEGA2560 RAMPS | Laser Feature | Air Evacuation | Air Assist | Cooler | Flowmeter | 12864 LCD | meatpack | SERIAL_PORT_2 " "$3" # @@ -196,7 +195,6 @@ opt_set MOTHERBOARD BOARD_RAMPS_14_EFB EXTRUDERS 0 LCD_LANGUAGE en TEMP_SENSOR_C AXIS_RELATIVE_MODES '{ false, false, false }' opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT PRINTCOUNTER \ LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER I2C_AMMETER - exec_test $1 $2 "MEGA2560 RAMPS | Laser Feature | Air Evacuation | Air Assist | Cooler | Flowmeter | 44780 LCD " "$3" # @@ -207,7 +205,8 @@ opt_set MOTHERBOARD BOARD_RAMPS_14_EFB EXTRUDERS 1 \ TEMP_SENSOR_0 -2 TEMP_SENSOR_REDUNDANT -2 \ TEMP_SENSOR_REDUNDANT_SOURCE E1 TEMP_SENSOR_REDUNDANT_TARGET E0 \ TEMP_0_CS_PIN 11 TEMP_1_CS_PIN 12 - +opt_enable MPCTEMP +opt_disable PIDTEMP exec_test $1 $2 "MEGA2560 RAMPS | Redundant temperature sensor | 2x MAX6675" "$3" #