Просмотр исходного кода

PID loop improvements (#14746)

* Fix macro evaluation in `temperature.cpp`
* Improve bed PID, PID debug output
* Add min PID power define
mikeshub 5 лет назад
Родитель
Сommit
1579091c20

+ 2 - 1
Marlin/Configuration.h

@@ -461,6 +461,7 @@
 #define PID_MAX BANG_MAX // Limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
 #define PID_K1 0.95      // Smoothing factor within any PID loop
 #if ENABLED(PIDTEMP)
+  //#define MIN_POWER 0
   //#define PID_EDIT_MENU         // Add PID editing to the "Advanced Settings" menu. (~700 bytes of PROGMEM)
   //#define PID_AUTOTUNE_MENU     // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of PROGMEM)
   //#define PID_DEBUG             // Sends debug data to the serial port.
@@ -520,7 +521,7 @@
 #define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
 
 #if ENABLED(PIDTEMPBED)
-
+  //#define MIN_BED_POWER 0
   //#define PID_BED_DEBUG // Sends debug data to the serial port.
 
   //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)

+ 7 - 0
Marlin/src/inc/Conditionals_post.h

@@ -1153,10 +1153,17 @@
   #define WRITE_HEATER_0(v) WRITE_HEATER_0P(v)
 #endif
 
+#ifndef MIN_POWER
+  #define MIN_POWER 0
+#endif
+
 /**
  * Heated bed requires settings
  */
 #if HAS_HEATED_BED
+  #ifndef MIN_BED_POWER
+    #define MIN_BED_POWER 0
+  #endif
   #ifndef MAX_BED_POWER
     #define MAX_BED_POWER 255
   #endif

+ 60 - 30
Marlin/src/module/temperature.cpp

@@ -469,12 +469,23 @@ temp_range_t Temperature::temp_range[HOTENDS] = ARRAY_BY_HOTENDS(sensor_heater_0
                             Tu = float(t_low + t_high) * 0.001f,
                             pf = isbed ? 0.2f : 0.6f,
                             df = isbed ? 1.0f / 3.0f : 1.0f / 8.0f;
-                tune_pid.Kp = Ku * pf;
-                tune_pid.Kd = tune_pid.Kp * Tu * df;
-                tune_pid.Ki = 2 * tune_pid.Kp / Tu;
+
                 SERIAL_ECHOPAIR(MSG_KU, Ku, MSG_TU, Tu);
-                SERIAL_ECHOLNPGM("\n" MSG_CLASSIC_PID);
-                SERIAL_ECHOLNPAIR(MSG_KP, tune_pid.Kp, MSG_KI, tune_pid.Ki, MSG_KD, tune_pid.Kd);
+                if (isbed) { // Do not remove this otherwise PID autotune won't work right for the bed!
+                  tune_pid.Kp = Ku * 0.2f;
+                  tune_pid.Ki = 2 * tune_pid.Kp / Tu;
+                  tune_pid.Kd = tune_pid.Kp * Tu / 3;
+                  SERIAL_ECHOLNPGM("\n" " No overshoot"); // Works far better for the bed. Classic and some have bad ringing.
+                  SERIAL_ECHOLNPAIR(MSG_KP, tune_pid.Kp, MSG_KI, tune_pid.Ki, MSG_KD, tune_pid.Kd);
+                }
+                else {
+                  tune_pid.Kp = Ku * pf;
+                  tune_pid.Kd = tune_pid.Kp * Tu * df;
+                  tune_pid.Ki = 2 * tune_pid.Kp / Tu;
+                  SERIAL_ECHOLNPGM("\n" MSG_CLASSIC_PID);
+                  SERIAL_ECHOLNPAIR(MSG_KP, tune_pid.Kp, MSG_KI, tune_pid.Ki, MSG_KD, tune_pid.Kd);
+                }
+
                 /**
                 tune_pid.Kp = 0.33 * Ku;
                 tune_pid.Ki = tune_pid.Kp / Tu;
@@ -850,12 +861,12 @@ float Temperature::get_pid_output_hotend(const uint8_t e) {
         }
 
         work_pid[ee].Kd = work_pid[ee].Kd + PID_K2 * (PID_PARAM(Kd, ee) * (temp_dState[ee] - temp_hotend[ee].current) - work_pid[ee].Kd);
-        const float max_power_over_i_gain = (float)PID_MAX / PID_PARAM(Ki, ee);
+        const float max_power_over_i_gain = float(PID_MAX) / PID_PARAM(Ki, ee) - float(MIN_POWER);
         temp_iState[ee] = constrain(temp_iState[ee] + pid_error, 0, max_power_over_i_gain);
         work_pid[ee].Kp = PID_PARAM(Kp, ee) * pid_error;
         work_pid[ee].Ki = PID_PARAM(Ki, ee) * temp_iState[ee];
 
-        pid_output = work_pid[ee].Kp + work_pid[ee].Ki + work_pid[ee].Kd;
+        pid_output = work_pid[ee].Kp + work_pid[ee].Ki + work_pid[ee].Kd + float(MIN_POWER);
 
         #if ENABLED(PID_EXTRUSION_SCALING)
           work_pid[ee].Kc = 0;
@@ -885,23 +896,25 @@ float Temperature::get_pid_output_hotend(const uint8_t e) {
     #endif // PID_OPENLOOP
 
     #if ENABLED(PID_DEBUG)
-      SERIAL_ECHO_START();
-      SERIAL_ECHOPAIR(
-        MSG_PID_DEBUG, ee,
-        MSG_PID_DEBUG_INPUT, temp_hotend[ee].current,
-        MSG_PID_DEBUG_OUTPUT, pid_output
-      );
-      #if DISABLED(PID_OPENLOOP)
+      if (e == active_extruder) {
+        SERIAL_ECHO_START();
         SERIAL_ECHOPAIR(
-          MSG_PID_DEBUG_PTERM, work_pid[ee].Kp,
-          MSG_PID_DEBUG_ITERM, work_pid[ee].Ki,
-          MSG_PID_DEBUG_DTERM, work_pid[ee].Kd
-          #if ENABLED(PID_EXTRUSION_SCALING)
-            , MSG_PID_DEBUG_CTERM, work_pid[ee].Kc
-          #endif
+          MSG_PID_DEBUG, ee,
+          MSG_PID_DEBUG_INPUT, temp_hotend[ee].current,
+          MSG_PID_DEBUG_OUTPUT, pid_output
         );
-      #endif
-      SERIAL_EOL();
+        #if DISABLED(PID_OPENLOOP)
+          SERIAL_ECHOPAIR(
+            MSG_PID_DEBUG_PTERM, work_pid[ee].Kp,
+            MSG_PID_DEBUG_ITERM, work_pid[ee].Ki,
+            MSG_PID_DEBUG_DTERM, work_pid[ee].Kd
+            #if ENABLED(PID_EXTRUSION_SCALING)
+              , MSG_PID_DEBUG_CTERM, work_pid[ee].Kc
+            #endif
+          );
+        #endif
+        SERIAL_EOL();
+      }
     #endif // PID_DEBUG
 
   #else // No PID enabled
@@ -927,19 +940,36 @@ float Temperature::get_pid_output_hotend(const uint8_t e) {
 
       static PID_t work_pid = { 0 };
       static float temp_iState = 0, temp_dState = 0;
-
-      const float max_power_over_i_gain = (float)MAX_BED_POWER / temp_bed.pid.Ki,
+      static bool pid_reset = true;
+      float pid_output = 0;
+      const float max_power_over_i_gain = float(MAX_BED_POWER) / temp_bed.pid.Ki - float(MIN_BED_POWER),
                   pid_error = temp_bed.target - temp_bed.current;
 
-      temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain);
+      if (!temp_bed.target || pid_error < -(PID_FUNCTIONAL_RANGE)) {
+        pid_output = 0;
+        pid_reset = true;
+      }
+      else if (pid_error > PID_FUNCTIONAL_RANGE) {
+        pid_output = BANG_MAX;
+        pid_reset = true;
+      }
+      else {
+        if (pid_reset) {
+          temp_iState = 0.0;
+          work_pid.Kd = 0.0;
+          pid_reset = false;
+        }
 
-      work_pid.Kp = temp_bed.pid.Kp * pid_error;
-      work_pid.Ki = temp_bed.pid.Ki * temp_iState;
-      work_pid.Kd = work_pid.Kd + PID_K2 * (temp_bed.pid.Kd * (temp_dState - temp_bed.current) - work_pid.Kd);
+        temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain);
 
-      temp_dState = temp_bed.current;
+        work_pid.Kp = temp_bed.pid.Kp * pid_error;
+        work_pid.Ki = temp_bed.pid.Ki * temp_iState;
+        work_pid.Kd = work_pid.Kd + PID_K2 * (temp_bed.pid.Kd * (temp_dState - temp_bed.current) - work_pid.Kd);
 
-      const float pid_output = constrain(work_pid.Kp + work_pid.Ki + work_pid.Kd, 0, MAX_BED_POWER);
+        temp_dState = temp_bed.current;
+
+        pid_output = constrain(work_pid.Kp + work_pid.Ki + work_pid.Kd + float(MIN_BED_POWER), 0, MAX_BED_POWER);
+      }
 
     #else // PID_OPENLOOP
 

+ 1 - 1
config/default/Configuration.h

@@ -520,7 +520,7 @@
 #define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
 
 #if ENABLED(PIDTEMPBED)
-
+  //#define MIN_BED_POWER 0
   //#define PID_BED_DEBUG // Sends debug data to the serial port.
 
   //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)

+ 1 - 1
config/examples/3DFabXYZ/Migbot/Configuration.h

@@ -525,7 +525,7 @@
 #define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
 
 #if ENABLED(PIDTEMPBED)
-
+  //#define MIN_BED_POWER 0
   //#define PID_BED_DEBUG // Sends debug data to the serial port.
 
   //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)

+ 1 - 1
config/examples/AlephObjects/TAZ4/Configuration.h

@@ -529,7 +529,7 @@
 #define MAX_BED_POWER 206 // limits duty cycle to bed; 255=full current
 
 #if ENABLED(PIDTEMPBED)
-
+  //#define MIN_BED_POWER 0
   //#define PID_BED_DEBUG // Sends debug data to the serial port.
 
   //24V 360W silicone heater from NPH on 3mm borosilicate (TAZ 2.2+)

+ 1 - 1
config/examples/Alfawise/U20/Configuration.h

@@ -575,7 +575,7 @@
 #define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
 
 #if ENABLED(PIDTEMPBED)
-
+  //#define MIN_BED_POWER 0
   //#define PID_BED_DEBUG // Sends debug data to the serial port.
 
   //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)

+ 1 - 1
config/examples/AliExpress/CL-260/Configuration.h

@@ -520,7 +520,7 @@
 #define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
 
 #if ENABLED(PIDTEMPBED)
-
+  //#define MIN_BED_POWER 0
   //#define PID_BED_DEBUG // Sends debug data to the serial port.
 
   //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)

+ 1 - 1
config/examples/AliExpress/UM2pExt/Configuration.h

@@ -531,7 +531,7 @@
 #define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
 
 #if ENABLED(PIDTEMPBED)
-
+  //#define MIN_BED_POWER 0
   //#define PID_BED_DEBUG // Sends debug data to the serial port.
 
   //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)

+ 1 - 1
config/examples/Anet/A2/Configuration.h

@@ -520,7 +520,7 @@
 #define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
 
 #if ENABLED(PIDTEMPBED)
-
+  //#define MIN_BED_POWER 0
   //#define PID_BED_DEBUG // Sends debug data to the serial port.
 
   //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)

Некоторые файлы не были показаны из-за большого количества измененных файлов