From 79077c5ad0d765df86a09cacb4ff2da3d761114f Mon Sep 17 00:00:00 2001 From: Timofey Titovets Date: Sat, 21 Feb 2026 21:49:03 +0100 Subject: [PATCH] pid_calibrate: analyze pid calibration time ratios For high power heaters current calibration might give too high ID of PID. Detect that by time ratios and suggest to rerun the calibration at different max power. And add a notice about the too-high heating time. Signed-off-by: Timofey Titovets --- klippy/extras/pid_calibrate.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/klippy/extras/pid_calibrate.py b/klippy/extras/pid_calibrate.py index a3618ecf3..c17b732cc 100644 --- a/klippy/extras/pid_calibrate.py +++ b/klippy/extras/pid_calibrate.py @@ -45,6 +45,27 @@ class PIDCalibrate: "PID parameters: pid_Kp=%.3f pid_Ki=%.3f pid_Kd=%.3f\n" "The SAVE_CONFIG command will update the printer config file\n" "with these parameters and restart the printer." % (Kp, Ki, Kd)) + heating = calibrate.final_heating_time + cooling = calibrate.final_cooling_time + ratio = heating/(cooling+heating) + if ratio < 0.49: + gcmd.respond_info( + "Heating takes (%.2f) less than 50%% of the calibration time\n" + "One may consider decreasing calibration power and " + "rerun the calibration\n" + "Suggested MAX_POWER=%.3f" % (ratio * 100, + ratio * 2 * max_power) + ) + if ratio > 0.66: + gcmd.respond_info( + "Heating takes more than twice of cooling time\n" + "One may decrease the TARGET temperature and " + "rerun the calibration" + ) + if ratio > 0.66 and max_power < 1.0: + gcmd.respond_info( + "Or consider increasing the max power" + ) # Store results for SAVE_CONFIG cfgname = heater.get_name() configfile = self.printer.lookup_object('configfile') @@ -66,6 +87,8 @@ class ControlAutoTune: self.peak_time = 0. # Peak recording self.peaks = [] + self.final_heating_time = .0 + self.final_cooling_time = .0 # Sample recording self.last_pwm = 0. self.pwm_samples = [] @@ -130,10 +153,20 @@ class ControlAutoTune: logging.info("Autotune: raw=%f/%f Ku=%f Tu=%f Kp=%f Ki=%f Kd=%f", temp_diff, self.heater_max_power, Ku, Tu, Kp, Ki, Kd) return Kp, Ki, Kd + def track_heating_ratio(self, pos): + # Track heating/cooling ratio to make advices + self.final_heating_time = self.peaks[pos][1] - self.peaks[pos-1][1] + self.final_cooling_time = self.peaks[pos-1][1] - self.peaks[pos-2][1] + # middle is high + if self.peaks[pos][0] < self.peaks[pos-1][0]: + old = self.final_heating_time + self.final_heating_time = self.final_cooling_time + self.final_cooling_time = old def calc_final_pid(self): cycle_times = [(self.peaks[pos][1] - self.peaks[pos-2][1], pos) for pos in range(4, len(self.peaks))] midpoint_pos = sorted(cycle_times)[len(cycle_times)//2][1] + self.track_heating_ratio(midpoint_pos) return self.calc_pid(midpoint_pos) # Offline analysis helper def write_file(self, filename):