From c8909b16ceaa0a2d5b95eadb8080c33e1b3476d1 Mon Sep 17 00:00:00 2001 From: feldi12 <25982433+feldi12@users.noreply.github.com> Date: Wed, 12 Mar 2025 01:19:20 +0100 Subject: [PATCH 01/10] Fixes and improvements to PID. --- Marlin/Configuration.h | 2 +- Marlin/src/module/temperature.h | 38 +++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 77a9176115a8..d6fa95633798 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -895,7 +895,7 @@ #if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER) //#define PID_OPENLOOP // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX //#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay - #define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature + #define PID_FUNCTIONAL_RANGE 20 // If the temperature difference between the target temperature and the actual temperature // is more than PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. //#define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of flash) diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index ffc86eb4e5ba..7572da2ef0a5 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -173,8 +173,10 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; struct PID_t { protected: bool pid_reset = true; + bool pid_below = false; float temp_iState = 0.0f, temp_dState = 0.0f; float work_p = 0, work_i = 0, work_d = 0; + float max_power_over_i_gain = 255.0f; public: float Kp = 0, Ki = 0, Kd = 0; @@ -189,13 +191,13 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; float cTerm() const { return 0; } float fTerm() const { return 0; } void set_Kp(float p) { Kp = p; } - void set_Ki(float i) { Ki = scalePID_i(i); } + void set_Ki(float i) { Ki = scalePID_i(i); max_power_over_i_gain = float(MAX_POW) / Ki - float(MIN_POW);} void set_Kd(float d) { Kd = scalePID_d(d); } void set_Kc(float) {} void set_Kf(float) {} int low() const { return MIN_POW; } int high() const { return MAX_POW; } - void reset() { pid_reset = true; } + void reset() { pid_reset = true; pid_below = false;} void set(float p, float i, float d, float c=1, float f=0) { set_Kp(p); set_Ki(i); set_Kd(d); set_Kc(c); set_Kf(f); } void set(const raw_pid_t &raw) { set(raw.p, raw.i, raw.d); } void set(const raw_pidcf_t &raw) { set(raw.p, raw.i, raw.d, raw.c, raw.f); } @@ -213,24 +215,32 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; } else if (pid_error > PID_FUNCTIONAL_RANGE) { pid_reset = true; + pid_below = true; + temp_dState = current; output_pow = MAX_POW; } - else { - if (pid_reset) { - pid_reset = false; - temp_iState = 0.0; - work_d = 0.0; + else if (pid_reset) { + pid_reset = false; + work_d = 0; + if(pid_below) + { + temp_iState = max_power_over_i_gain; + pid_below = false; } + else + { + temp_iState = 0; + } + } - const float max_power_over_i_gain = float(MAX_POW) / Ki - float(MIN_POW); - temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain); + temp_iState = constrain(temp_iState + pid_error, temp_iState = -max_power_over_i_gain/4.0f, max_power_over_i_gain); - work_p = Kp * pid_error; - work_i = Ki * temp_iState; - work_d = work_d + PID_K2 * (Kd * (temp_dState - current) - work_d); + work_p = Kp * pid_error; + work_i = Ki * temp_iState; + work_d = work_d + PID_K2 * (Kd * (temp_dState - current) - work_d); - output_pow = constrain(work_p + work_i + work_d + float(MIN_POW), 0, MAX_POW); - } + output_pow = constrain(work_p + work_i + work_d + float(MIN_POW), 0, MAX_POW); + temp_dState = current; From 7f5bd179b238ca755aed7152b6ad0c5e8742d4ab Mon Sep 17 00:00:00 2001 From: feldi12 <25982433+feldi12@users.noreply.github.com> Date: Wed, 12 Mar 2025 02:35:02 +0100 Subject: [PATCH 02/10] Fixed typos. --- Marlin/src/module/temperature.h | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index 7572da2ef0a5..acfe540ad9d7 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -216,31 +216,31 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; else if (pid_error > PID_FUNCTIONAL_RANGE) { pid_reset = true; pid_below = true; - temp_dState = current; output_pow = MAX_POW; } - else if (pid_reset) { - pid_reset = false; - work_d = 0; - if(pid_below) - { - temp_iState = max_power_over_i_gain; - pid_below = false; - } - else - { - temp_iState = 0; + else { + if (pid_reset) { + pid_reset = false; + work_d = 0; + if(pid_below) + { + temp_iState = max_power_over_i_gain; + pid_below = false; + } + else + { + temp_iState = 0; + } } - } - temp_iState = constrain(temp_iState + pid_error, temp_iState = -max_power_over_i_gain/4.0f, max_power_over_i_gain); + temp_iState = constrain(temp_iState + pid_error, -max_power_over_i_gain/4.0f, max_power_over_i_gain); - work_p = Kp * pid_error; - work_i = Ki * temp_iState; - work_d = work_d + PID_K2 * (Kd * (temp_dState - current) - work_d); + work_p = Kp * pid_error; + work_i = Ki * temp_iState; + work_d = work_d + PID_K2 * (Kd * (temp_dState - current) - work_d); - output_pow = constrain(work_p + work_i + work_d + float(MIN_POW), 0, MAX_POW); - + output_pow = constrain(work_p + work_i + work_d + float(MIN_POW), 0, MAX_POW); + } temp_dState = current; From 6359aa53611eed4506d910bdd06fcd79fc88f5cb Mon Sep 17 00:00:00 2001 From: feldi12 <25982433+feldi12@users.noreply.github.com> Date: Wed, 12 Mar 2025 10:39:02 +0100 Subject: [PATCH 03/10] Fixed indentation style. --- Marlin/src/module/temperature.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index acfe540ad9d7..3ccc6f9f555c 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -222,13 +222,11 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; if (pid_reset) { pid_reset = false; work_d = 0; - if(pid_below) - { + if(pid_below) { temp_iState = max_power_over_i_gain; pid_below = false; } - else - { + else { temp_iState = 0; } } From 263a12c80aae731250758e7f0078a3a400365754 Mon Sep 17 00:00:00 2001 From: feldi12 <25982433+feldi12@users.noreply.github.com> Date: Wed, 12 Mar 2025 12:11:13 +0100 Subject: [PATCH 04/10] Even more code style fixes. --- Marlin/src/module/temperature.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index 3ccc6f9f555c..941e02b0ceb6 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -219,10 +219,10 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; output_pow = MAX_POW; } else { - if (pid_reset) { + if (pid_reset) { pid_reset = false; work_d = 0; - if(pid_below) { + if (pid_below) { temp_iState = max_power_over_i_gain; pid_below = false; } @@ -238,7 +238,7 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; work_d = work_d + PID_K2 * (Kd * (temp_dState - current) - work_d); output_pow = constrain(work_p + work_i + work_d + float(MIN_POW), 0, MAX_POW); - } + } temp_dState = current; From 528e189312c91ea7a66432d0610a3429e51e7ac2 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sun, 16 Mar 2025 20:53:18 -0500 Subject: [PATCH 05/10] style and study --- Marlin/src/module/temperature.h | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index 941e02b0ceb6..03a4187d8137 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -174,9 +174,9 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; protected: bool pid_reset = true; bool pid_below = false; - float temp_iState = 0.0f, temp_dState = 0.0f; + float temp_iState = 0, temp_dState = 0; float work_p = 0, work_i = 0, work_d = 0; - float max_power_over_i_gain = 255.0f; + float max_power_over_i_gain = 255; public: float Kp = 0, Ki = 0, Kd = 0; @@ -191,13 +191,13 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; float cTerm() const { return 0; } float fTerm() const { return 0; } void set_Kp(float p) { Kp = p; } - void set_Ki(float i) { Ki = scalePID_i(i); max_power_over_i_gain = float(MAX_POW) / Ki - float(MIN_POW);} + void set_Ki(float i) { Ki = scalePID_i(i); max_power_over_i_gain = float(MAX_POW) / Ki - float(MIN_POW); } void set_Kd(float d) { Kd = scalePID_d(d); } void set_Kc(float) {} void set_Kf(float) {} int low() const { return MIN_POW; } int high() const { return MAX_POW; } - void reset() { pid_reset = true; pid_below = false;} + void reset() { pid_reset = true; pid_below = false; } void set(float p, float i, float d, float c=1, float f=0) { set_Kp(p); set_Ki(i); set_Kd(d); set_Kc(c); set_Kf(f); } void set(const raw_pid_t &raw) { set(raw.p, raw.i, raw.d); } void set(const raw_pidcf_t &raw) { set(raw.p, raw.i, raw.d, raw.c, raw.f); } @@ -220,22 +220,17 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; } else { if (pid_reset) { - pid_reset = false; + temp_iState = pid_below ? max_power_over_i_gain : 0; work_d = 0; - if (pid_below) { - temp_iState = max_power_over_i_gain; - pid_below = false; - } - else { - temp_iState = 0; - } + pid_reset = false; + pid_below = false; } - temp_iState = constrain(temp_iState + pid_error, -max_power_over_i_gain/4.0f, max_power_over_i_gain); + temp_iState = constrain(temp_iState + pid_error, -0.25f * max_power_over_i_gain, max_power_over_i_gain); work_p = Kp * pid_error; work_i = Ki * temp_iState; - work_d = work_d + PID_K2 * (Kd * (temp_dState - current) - work_d); + work_d += (Kd * (temp_dState - current) - work_d) * PID_K2; output_pow = constrain(work_p + work_i + work_d + float(MIN_POW), 0, MAX_POW); } From 5bcfe3ebc7e3bf36ad4f1b4c0319efa8ffcfdf7a Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sun, 16 Mar 2025 21:07:44 -0500 Subject: [PATCH 06/10] Fix max_power_over_i_gain --- Marlin/src/module/temperature.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index 03a4187d8137..da5cacb4e591 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -191,7 +191,7 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; float cTerm() const { return 0; } float fTerm() const { return 0; } void set_Kp(float p) { Kp = p; } - void set_Ki(float i) { Ki = scalePID_i(i); max_power_over_i_gain = float(MAX_POW) / Ki - float(MIN_POW); } + void set_Ki(float i) { Ki = scalePID_i(i); max_power_over_i_gain = float(MAX_POW - MIN_POW) / Ki; } void set_Kd(float d) { Kd = scalePID_d(d); } void set_Kc(float) {} void set_Kf(float) {} From f1f0c9119a375bb8cec820627c6179807faf5fd4 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sun, 16 Mar 2025 21:08:45 -0500 Subject: [PATCH 07/10] controversial negative temp_iState --- Marlin/src/module/temperature.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index da5cacb4e591..814b8ec4bbd2 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -226,7 +226,7 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; pid_below = false; } - temp_iState = constrain(temp_iState + pid_error, -0.25f * max_power_over_i_gain, max_power_over_i_gain); + temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain); work_p = Kp * pid_error; work_i = Ki * temp_iState; From f46d1afd3c717b4d5f749743a86406dc34d56053 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sun, 16 Mar 2025 21:25:50 -0500 Subject: [PATCH 08/10] Fix Sovol RTS setting Ki --- Marlin/src/lcd/sovol_rts/sovol_rts.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Marlin/src/lcd/sovol_rts/sovol_rts.cpp b/Marlin/src/lcd/sovol_rts/sovol_rts.cpp index 1f3322ded786..cf42a55664bb 100644 --- a/Marlin/src/lcd/sovol_rts/sovol_rts.cpp +++ b/Marlin/src/lcd/sovol_rts/sovol_rts.cpp @@ -1313,9 +1313,9 @@ void RTS::handleData() { #endif #if ENABLED(PIDTEMPBED) - case Hot_Bed_P: thermalManager.temp_bed.pid.Kp = float(recdat.data[0]) / 100.0f; break; - case Hot_Bed_I: thermalManager.temp_bed.pid.Ki = float(recdat.data[0]) * 8.0f / 10000.0f; break; - case Hot_Bed_D: thermalManager.temp_bed.pid.Kd = float(recdat.data[0]) / 0.8f; break; + case Hot_Bed_P: thermalManager.temp_bed.pid.set_Kp(float(recdat.data[0]) / 100.0f); break; + case Hot_Bed_I: thermalManager.temp_bed.pid.set_Ki(float(recdat.data[0]) * 8.0f / 10000.0f); break; + case Hot_Bed_D: thermalManager.temp_bed.pid.set_Kd(float(recdat.data[0]) / 0.8f); break; #endif #if HAS_X_AXIS From dbe76e84803b9d8d80f946494dc98ade00069a83 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 1 Apr 2025 03:25:00 -0500 Subject: [PATCH 09/10] Tom's suggestions Co-Authored-By: tombrazier <68918209+tombrazier@users.noreply.github.com> --- Marlin/Configuration.h | 8 ++++---- Marlin/src/module/temperature.h | 16 +++++----------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 83d4489ae51e..71eace10c5b5 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -696,7 +696,7 @@ #define PID_K1 0.95 // Smoothing factor within any PID loop #if ENABLED(PIDTEMP) - //#define MIN_POWER 0 + //#define MIN_POWER 0 // (0 to PID_MAX) For better PID stability, set to the value from M105 times 2 minus 10 to 20. //#define PID_DEBUG // Print PID debug data to the serial port. Use 'M303 D' to toggle activation. //#define PID_PARAMS_PER_HOTEND // Use separate PID parameters for each extruder (useful for mismatched extruders) // Set/get with G-code: M301 E[extruder number, 0-2] @@ -796,8 +796,8 @@ //#define PIDTEMPBED #if ENABLED(PIDTEMPBED) - //#define MIN_BED_POWER 0 - //#define PID_BED_DEBUG // Print Bed PID debug data to the serial port. + //#define MIN_BED_POWER 0 // (0 to MAX_BED_POWER) For better PID stability, set to the value from M105 times 2 minus 10 to 20. + //#define PID_BED_DEBUG // Print Bed PID debug data to the serial port. // 120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+) // from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10) @@ -878,7 +878,7 @@ #define MAX_CHAMBER_POWER 255 // limits duty cycle to chamber heater; 255=full current #if ENABLED(PIDTEMPCHAMBER) - #define MIN_CHAMBER_POWER 0 + #define MIN_CHAMBER_POWER 0 // (0 to MAX_BED_POWER) For better PID stability, set to the value from M105 times 2 minus 10 to 20. //#define PID_CHAMBER_DEBUG // Print Chamber PID debug data to the serial port. // Lasko "MyHeat Personal Heater" (200w) modified with a Fotek SSR-10DA to control only the heating element diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index 8e64c8ff000c..77c16bba0a28 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -173,10 +173,8 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; struct PID_t { protected: bool pid_reset = true; - bool pid_below = false; - float temp_iState = 0, temp_dState = 0; + float temp_dState = 0; float work_p = 0, work_i = 0, work_d = 0; - float max_power_over_i_gain = 255; public: float Kp = 0, Ki = 0, Kd = 0; @@ -191,13 +189,13 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; float cTerm() const { return 0; } float fTerm() const { return 0; } void set_Kp(float p) { Kp = p; } - void set_Ki(float i) { Ki = scalePID_i(i); max_power_over_i_gain = float(MAX_POW - MIN_POW) / Ki; } + void set_Ki(float i) { Ki = scalePID_i(i); } void set_Kd(float d) { Kd = scalePID_d(d); } void set_Kc(float) {} void set_Kf(float) {} int low() const { return MIN_POW; } int high() const { return MAX_POW; } - void reset() { pid_reset = true; pid_below = false; } + void reset() { pid_reset = true; } void set(float p, float i, float d, float c=1, float f=0) { set_Kp(p); set_Ki(i); set_Kd(d); set_Kc(c); set_Kf(f); } void set(const raw_pid_t &raw) { set(raw.p, raw.i, raw.d); } void set(const raw_pidcf_t &raw) { set(raw.p, raw.i, raw.d, raw.c, raw.f); } @@ -215,21 +213,17 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; } else if (pid_error > PID_FUNCTIONAL_RANGE) { pid_reset = true; - pid_below = true; output_pow = MAX_POW; } else { if (pid_reset) { - temp_iState = pid_below ? max_power_over_i_gain : 0; + work_i = 0; work_d = 0; pid_reset = false; - pid_below = false; } - temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain); - work_p = Kp * pid_error; - work_i = Ki * temp_iState; + work_i = constrain(work_i + Ki * pid_error, 0, float(MAX_POW - MIN_POW)); work_d += (Kd * (temp_dState - current) - work_d) * PID_K2; output_pow = constrain(work_p + work_i + work_d + float(MIN_POW), 0, MAX_POW); From 52f0a61c657409e13fbcb85ea8997f04f130d4f6 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 1 Apr 2025 04:01:15 -0500 Subject: [PATCH 10/10] clarify, maybe --- Marlin/Configuration.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 71eace10c5b5..c4973fc1fca8 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -696,7 +696,8 @@ #define PID_K1 0.95 // Smoothing factor within any PID loop #if ENABLED(PIDTEMP) - //#define MIN_POWER 0 // (0 to PID_MAX) For better PID stability, set to the value from M105 times 2 minus 10 to 20. + //#define MIN_POWER 0 // Min power to improve PID stability (0..PID_MAX). + // Get the power from the temperature report ('M105' => @:nnn) and try P*2-20 to P*2-10. //#define PID_DEBUG // Print PID debug data to the serial port. Use 'M303 D' to toggle activation. //#define PID_PARAMS_PER_HOTEND // Use separate PID parameters for each extruder (useful for mismatched extruders) // Set/get with G-code: M301 E[extruder number, 0-2] @@ -796,7 +797,8 @@ //#define PIDTEMPBED #if ENABLED(PIDTEMPBED) - //#define MIN_BED_POWER 0 // (0 to MAX_BED_POWER) For better PID stability, set to the value from M105 times 2 minus 10 to 20. + //#define MIN_BED_POWER 0 // Min power to improve PID stability (0..MAX_BED_POWER). + // Get the power from the temperature report ('M105' => B@:nnn) and try P*2-20 to P*2-10. //#define PID_BED_DEBUG // Print Bed PID debug data to the serial port. // 120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+) @@ -878,7 +880,8 @@ #define MAX_CHAMBER_POWER 255 // limits duty cycle to chamber heater; 255=full current #if ENABLED(PIDTEMPCHAMBER) - #define MIN_CHAMBER_POWER 0 // (0 to MAX_BED_POWER) For better PID stability, set to the value from M105 times 2 minus 10 to 20. + #define MIN_CHAMBER_POWER 0 // Min power to improve PID stability. (0..MAX_CHAMBER_POWER) + // Get the power from the temperature report ('M105' => C@:nnn) and try P*2-20 to P*2-10. //#define PID_CHAMBER_DEBUG // Print Chamber PID debug data to the serial port. // Lasko "MyHeat Personal Heater" (200w) modified with a Fotek SSR-10DA to control only the heating element