Browse Source

♻️ Encapsulate PID in class (#24389)

Scott Lahteine 2 years ago
parent
commit
54e7b933cd
No account linked to committer's email address

+ 1
- 1
Marlin/src/MarlinCore.cpp View File

789
   manage_inactivity(no_stepper_sleep);
789
   manage_inactivity(no_stepper_sleep);
790
 
790
 
791
   // Manage Heaters (and Watchdog)
791
   // Manage Heaters (and Watchdog)
792
-  thermalManager.manage_heater();
792
+  thermalManager.task();
793
 
793
 
794
   // Max7219 heartbeat, animation, etc
794
   // Max7219 heartbeat, animation, etc
795
   TERN_(MAX7219_DEBUG, max7219.idle_tasks());
795
   TERN_(MAX7219_DEBUG, max7219.idle_tasks());

+ 0
- 4
Marlin/src/core/language.h View File

227
 #define STR_PID_DEBUG                       " PID_DEBUG "
227
 #define STR_PID_DEBUG                       " PID_DEBUG "
228
 #define STR_PID_DEBUG_INPUT                 ": Input "
228
 #define STR_PID_DEBUG_INPUT                 ": Input "
229
 #define STR_PID_DEBUG_OUTPUT                " Output "
229
 #define STR_PID_DEBUG_OUTPUT                " Output "
230
-#define STR_PID_DEBUG_PTERM                 " pTerm "
231
-#define STR_PID_DEBUG_ITERM                 " iTerm "
232
-#define STR_PID_DEBUG_DTERM                 " dTerm "
233
-#define STR_PID_DEBUG_CTERM                 " cTerm "
234
 #define STR_INVALID_EXTRUDER_NUM            " - Invalid extruder number !"
230
 #define STR_INVALID_EXTRUDER_NUM            " - Invalid extruder number !"
235
 #define STR_MPC_AUTOTUNE                    "MPC Autotune"
231
 #define STR_MPC_AUTOTUNE                    "MPC Autotune"
236
 #define STR_MPC_AUTOTUNE_START              " start for " STR_E
232
 #define STR_MPC_AUTOTUNE_START              " start for " STR_E

+ 2
- 2
Marlin/src/core/utility.cpp View File

29
   while (ms > 50) {
29
   while (ms > 50) {
30
     ms -= 50;
30
     ms -= 50;
31
     delay(50);
31
     delay(50);
32
-    thermalManager.manage_heater();
32
+    thermalManager.task();
33
   }
33
   }
34
   delay(ms);
34
   delay(ms);
35
-  thermalManager.manage_heater(); // This keeps us safe if too many small safe_delay() calls are made
35
+  thermalManager.task(); // This keeps us safe if too many small safe_delay() calls are made
36
 }
36
 }
37
 
37
 
38
 // A delay to provide brittle hosts time to receive bytes
38
 // A delay to provide brittle hosts time to receive bytes

+ 1
- 1
Marlin/src/gcode/motion/G2_G3.cpp View File

290
 
290
 
291
     for (uint16_t i = 1; i < segments; i++) { // Iterate (segments-1) times
291
     for (uint16_t i = 1; i < segments; i++) { // Iterate (segments-1) times
292
 
292
 
293
-      thermalManager.manage_heater();
293
+      thermalManager.task();
294
       const millis_t ms = millis();
294
       const millis_t ms = millis();
295
       if (ELAPSED(ms, next_idle_ms)) {
295
       if (ELAPSED(ms, next_idle_ms)) {
296
         next_idle_ms = ms + 200UL;
296
         next_idle_ms = ms + 200UL;

+ 1
- 1
Marlin/src/gcode/queue.cpp View File

384
   buff[ind] = '\0';                   // Of course, I'm a Terminator.
384
   buff[ind] = '\0';                   // Of course, I'm a Terminator.
385
   const bool is_empty = (ind == 0);   // An empty line?
385
   const bool is_empty = (ind == 0);   // An empty line?
386
   if (is_empty)
386
   if (is_empty)
387
-    thermalManager.manage_heater();   // Keep sensors satisfied
387
+    thermalManager.task();            // Keep sensors satisfied
388
   else
388
   else
389
     ind = 0;                          // Start a new line
389
     ind = 0;                          // Start a new line
390
   return is_empty;                    // Inform the caller
390
   return is_empty;                    // Inform the caller

+ 6
- 6
Marlin/src/lcd/e3v2/jyersui/dwin.cpp View File

1202
                 if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp)
1202
                 if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp)
1203
                   Popup_Handler(ETemp);
1203
                   Popup_Handler(ETemp);
1204
                 else {
1204
                 else {
1205
-                  if (thermalManager.temp_hotend[0].celsius < thermalManager.temp_hotend[0].target - 2) {
1205
+                  if (thermalManager.temp_hotend[0].is_below_target(-2)) {
1206
                     Popup_Handler(Heating);
1206
                     Popup_Handler(Heating);
1207
                     thermalManager.wait_for_hotend(0);
1207
                     thermalManager.wait_for_hotend(0);
1208
                   }
1208
                   }
1345
                 Popup_Handler(ETemp);
1345
                 Popup_Handler(ETemp);
1346
               }
1346
               }
1347
               else {
1347
               else {
1348
-                if (thermalManager.temp_hotend[0].celsius < thermalManager.temp_hotend[0].target - 2) {
1348
+                if (thermalManager.temp_hotend[0].is_below_target(-2)) {
1349
                   Popup_Handler(Heating);
1349
                   Popup_Handler(Heating);
1350
                   thermalManager.wait_for_hotend(0);
1350
                   thermalManager.wait_for_hotend(0);
1351
                   Redraw_Menu();
1351
                   Redraw_Menu();
1732
               if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp)
1732
               if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp)
1733
                 Popup_Handler(ETemp);
1733
                 Popup_Handler(ETemp);
1734
               else {
1734
               else {
1735
-                if (thermalManager.temp_hotend[0].celsius < thermalManager.temp_hotend[0].target - 2) {
1735
+                if (thermalManager.temp_hotend[0].is_below_target(-2)) {
1736
                   Popup_Handler(Heating);
1736
                   Popup_Handler(Heating);
1737
                   thermalManager.wait_for_hotend(0);
1737
                   thermalManager.wait_for_hotend(0);
1738
                 }
1738
                 }
1751
                 Popup_Handler(ETemp);
1751
                 Popup_Handler(ETemp);
1752
               }
1752
               }
1753
               else {
1753
               else {
1754
-                if (thermalManager.temp_hotend[0].celsius < thermalManager.temp_hotend[0].target - 2) {
1754
+                if (thermalManager.temp_hotend[0].is_below_target(-2)) {
1755
                   Popup_Handler(Heating);
1755
                   Popup_Handler(Heating);
1756
                   thermalManager.wait_for_hotend(0);
1756
                   thermalManager.wait_for_hotend(0);
1757
                 }
1757
                 }
1769
               if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp)
1769
               if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp)
1770
                 Popup_Handler(ETemp);
1770
                 Popup_Handler(ETemp);
1771
               else {
1771
               else {
1772
-                if (thermalManager.temp_hotend[0].celsius < thermalManager.temp_hotend[0].target - 2) {
1772
+                if (thermalManager.temp_hotend[0].is_below_target(-2)) {
1773
                   Popup_Handler(Heating);
1773
                   Popup_Handler(Heating);
1774
                   thermalManager.wait_for_hotend(0);
1774
                   thermalManager.wait_for_hotend(0);
1775
                 }
1775
                 }
4404
             if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp)
4404
             if (thermalManager.temp_hotend[0].target < thermalManager.extrude_min_temp)
4405
               Popup_Handler(ETemp);
4405
               Popup_Handler(ETemp);
4406
             else {
4406
             else {
4407
-              if (thermalManager.temp_hotend[0].celsius < thermalManager.temp_hotend[0].target - 2) {
4407
+              if (thermalManager.temp_hotend[0].is_below_target(-2)) {
4408
                 Popup_Handler(Heating);
4408
                 Popup_Handler(Heating);
4409
                 thermalManager.wait_for_hotend(0);
4409
                 thermalManager.wait_for_hotend(0);
4410
               }
4410
               }

+ 1
- 1
Marlin/src/lcd/extui/ui_api.cpp View File

169
   }
169
   }
170
 
170
 
171
   void yield() {
171
   void yield() {
172
-    if (!flags.printer_killed) thermalManager.manage_heater();
172
+    if (!flags.printer_killed) thermalManager.task();
173
   }
173
   }
174
 
174
 
175
   void enableHeater(const extruder_t extruder) {
175
   void enableHeater(const extruder_t extruder) {

+ 1
- 1
Marlin/src/libs/buzzer.cpp View File

48
   if (!ui.sound_on) return;
48
   if (!ui.sound_on) return;
49
   while (buffer.isFull()) {
49
   while (buffer.isFull()) {
50
     tick();
50
     tick();
51
-    thermalManager.manage_heater();
51
+    thermalManager.task();
52
   }
52
   }
53
   tone_t tone = { duration, frequency };
53
   tone_t tone = { duration, frequency };
54
   buffer.enqueue(tone);
54
   buffer.enqueue(tone);

+ 1
- 1
Marlin/src/module/motion.cpp View File

966
     next_idle_ms = ms + 200UL;
966
     next_idle_ms = ms + 200UL;
967
     return idle();
967
     return idle();
968
   }
968
   }
969
-  thermalManager.manage_heater();  // Returns immediately on most calls
969
+  thermalManager.task();  // Returns immediately on most calls
970
 }
970
 }
971
 
971
 
972
 #if IS_KINEMATIC
972
 #if IS_KINEMATIC

+ 1
- 1
Marlin/src/module/planner_bezier.cpp View File

123
 
123
 
124
   for (float t = 0; t < 1;) {
124
   for (float t = 0; t < 1;) {
125
 
125
 
126
-    thermalManager.manage_heater();
126
+    thermalManager.task();
127
     millis_t now = millis();
127
     millis_t now = millis();
128
     if (ELAPSED(now, next_idle_ms)) {
128
     if (ELAPSED(now, next_idle_ms)) {
129
       next_idle_ms = now + 200UL;
129
       next_idle_ms = now + 200UL;

+ 189
- 273
Marlin/src/module/temperature.cpp View File

1318
 }
1318
 }
1319
 
1319
 
1320
 #if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
1320
 #if ANY(PID_DEBUG, PID_BED_DEBUG, PID_CHAMBER_DEBUG)
1321
-  bool Temperature::pid_debug_flag; // = 0
1321
+  #define HAS_PID_DEBUG 1
1322
+  bool Temperature::pid_debug_flag; // = false
1322
 #endif
1323
 #endif
1323
 
1324
 
1324
-#if HAS_HOTEND
1325
+#if HAS_PID_HEATING
1325
 
1326
 
1326
-  float Temperature::get_pid_output_hotend(const uint8_t E_NAME) {
1327
-    const uint8_t ee = HOTEND_INDEX;
1328
-    #if ENABLED(PIDTEMP)
1329
-      #if DISABLED(PID_OPENLOOP)
1330
-        static hotend_pid_t work_pid[HOTENDS];
1331
-        static float temp_iState[HOTENDS] = { 0 },
1332
-                     temp_dState[HOTENDS] = { 0 };
1333
-        static Flags<HOTENDS> pid_reset;
1334
-        const float pid_error = temp_hotend[ee].target - temp_hotend[ee].celsius;
1335
-
1336
-        float pid_output;
1337
-
1338
-        if (temp_hotend[ee].target == 0
1339
-          || pid_error < -(PID_FUNCTIONAL_RANGE)
1340
-          || TERN0(HEATER_IDLE_HANDLER, heater_idle[ee].timed_out)
1341
-        ) {
1342
-          pid_output = 0;
1343
-          pid_reset.set(ee);
1327
+  template<typename TT, int MIN_POW, int MAX_POW>
1328
+  class PIDRunner {
1329
+  public:
1330
+    TT &tempinfo;
1331
+    __typeof__(TT::pid) work_pid{0};
1332
+    float temp_iState = 0, temp_dState = 0;
1333
+    bool pid_reset = true;
1334
+
1335
+    PIDRunner(TT &t) : tempinfo(t) { }
1336
+
1337
+    float get_pid_output() {
1338
+
1339
+      #if ENABLED(PID_OPENLOOP)
1340
+
1341
+        return constrain(tempinfo.target, 0, MAX_POW);
1342
+
1343
+      #else // !PID_OPENLOOP
1344
+
1345
+        const float pid_error = tempinfo.target - tempinfo.celsius;
1346
+        if (!tempinfo.target || pid_error < -(PID_FUNCTIONAL_RANGE)) {
1347
+          pid_reset = true;
1348
+          return 0;
1344
         }
1349
         }
1345
         else if (pid_error > PID_FUNCTIONAL_RANGE) {
1350
         else if (pid_error > PID_FUNCTIONAL_RANGE) {
1346
-          pid_output = PID_MAX;
1347
-          pid_reset.set(ee);
1351
+          pid_reset = true;
1352
+          return MAX_POW;
1348
         }
1353
         }
1349
-        else {
1350
-          if (pid_reset[ee]) {
1351
-            temp_iState[ee] = 0.0;
1352
-            work_pid[ee].Kd = 0.0;
1353
-            pid_reset.clear(ee);
1354
-          }
1355
 
1354
 
1356
-          work_pid[ee].Kd = work_pid[ee].Kd + PID_K2 * (PID_PARAM(Kd, ee) * (temp_dState[ee] - temp_hotend[ee].celsius) - work_pid[ee].Kd);
1357
-          const float max_power_over_i_gain = float(PID_MAX) / PID_PARAM(Ki, ee) - float(MIN_POWER);
1358
-          temp_iState[ee] = constrain(temp_iState[ee] + pid_error, 0, max_power_over_i_gain);
1359
-          work_pid[ee].Kp = PID_PARAM(Kp, ee) * pid_error;
1360
-          work_pid[ee].Ki = PID_PARAM(Ki, ee) * temp_iState[ee];
1355
+        if (pid_reset) {
1356
+          pid_reset = false;
1357
+          temp_iState = 0.0;
1358
+          work_pid.Kd = 0.0;
1359
+        }
1361
 
1360
 
1362
-          pid_output = work_pid[ee].Kp + work_pid[ee].Ki + work_pid[ee].Kd + float(MIN_POWER);
1361
+        const float max_power_over_i_gain = float(MAX_POW) / tempinfo.pid.Ki - float(MIN_POW);
1362
+        temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain);
1363
 
1363
 
1364
-          #if ENABLED(PID_EXTRUSION_SCALING)
1365
-            #if HOTENDS == 1
1366
-              constexpr bool this_hotend = true;
1367
-            #else
1368
-              const bool this_hotend = (ee == active_extruder);
1369
-            #endif
1370
-            work_pid[ee].Kc = 0;
1371
-            if (this_hotend) {
1372
-              const long e_position = stepper.position(E_AXIS);
1373
-              if (e_position > pes_e_position) {
1374
-                lpq[lpq_ptr] = e_position - pes_e_position;
1375
-                pes_e_position = e_position;
1376
-              }
1377
-              else
1378
-                lpq[lpq_ptr] = 0;
1364
+        work_pid.Kp = tempinfo.pid.Kp * pid_error;
1365
+        work_pid.Ki = tempinfo.pid.Ki * temp_iState;
1366
+        work_pid.Kd = work_pid.Kd + PID_K2 * (tempinfo.pid.Kd * (temp_dState - tempinfo.celsius) - work_pid.Kd);
1379
 
1367
 
1380
-              if (++lpq_ptr >= lpq_len) lpq_ptr = 0;
1381
-              work_pid[ee].Kc = (lpq[lpq_ptr] * planner.mm_per_step[E_AXIS]) * PID_PARAM(Kc, ee);
1382
-              pid_output += work_pid[ee].Kc;
1383
-            }
1384
-          #endif // PID_EXTRUSION_SCALING
1385
-          #if ENABLED(PID_FAN_SCALING)
1386
-            if (fan_speed[active_extruder] > PID_FAN_SCALING_MIN_SPEED) {
1387
-              work_pid[ee].Kf = PID_PARAM(Kf, ee) + (PID_FAN_SCALING_LIN_FACTOR) * fan_speed[active_extruder];
1388
-              pid_output += work_pid[ee].Kf;
1389
-            }
1390
-            //pid_output -= work_pid[ee].Ki;
1391
-            //pid_output += work_pid[ee].Ki * work_pid[ee].Kf
1392
-          #endif // PID_FAN_SCALING
1393
-          LIMIT(pid_output, 0, PID_MAX);
1394
-        }
1395
-        temp_dState[ee] = temp_hotend[ee].celsius;
1368
+        temp_dState = tempinfo.celsius;
1396
 
1369
 
1397
-      #else // PID_OPENLOOP
1370
+        return constrain(work_pid.Kp + work_pid.Ki + work_pid.Kd + float(MIN_POW), 0, MAX_POW);
1398
 
1371
 
1399
-        const float pid_output = constrain(temp_hotend[ee].target, 0, PID_MAX);
1372
+      #endif // !PID_OPENLOOP
1373
+    }
1400
 
1374
 
1401
-      #endif // PID_OPENLOOP
1375
+    FORCE_INLINE void debug(const_celsius_float_t c, const_float_t pid_out, FSTR_P const name=nullptr, const int8_t index=-1) {
1376
+      if (TERN0(HAS_PID_DEBUG, thermalManager.pid_debug_flag)) {
1377
+        SERIAL_ECHO_START();
1378
+        if (name) SERIAL_ECHOLNF(name);
1379
+        if (index >= 0) SERIAL_ECHO(index);
1380
+        SERIAL_ECHOLNPGM(
1381
+          STR_PID_DEBUG_INPUT, c,
1382
+          STR_PID_DEBUG_OUTPUT, pid_out
1383
+          #if DISABLED(PID_OPENLOOP)
1384
+            , "pTerm", work_pid.Kp, "iTerm", work_pid.Ki, "dTerm", work_pid.Kd
1385
+          #endif
1386
+        );
1387
+      }
1388
+    }
1389
+  };
1390
+
1391
+#endif // HAS_PID_HEATING
1392
+
1393
+#if HAS_HOTEND
1394
+
1395
+  float Temperature::get_pid_output_hotend(const uint8_t E_NAME) {
1396
+    const uint8_t ee = HOTEND_INDEX;
1397
+
1398
+    #if ENABLED(PIDTEMP)
1399
+
1400
+      typedef PIDRunner<hotend_info_t, 0, PID_MAX> PIDRunnerHotend;
1401
+
1402
+      static PIDRunnerHotend hotend_pid[HOTENDS] = {
1403
+        #define _HOTENDPID(E) temp_hotend[E],
1404
+        REPEAT(HOTENDS, _HOTENDPID)
1405
+      };
1406
+
1407
+      const float pid_output = hotend_pid[ee].get_pid_output();
1402
 
1408
 
1403
       #if ENABLED(PID_DEBUG)
1409
       #if ENABLED(PID_DEBUG)
1404
-        if (ee == active_extruder && pid_debug_flag) {
1405
-          SERIAL_ECHO_MSG(STR_PID_DEBUG, ee, STR_PID_DEBUG_INPUT, temp_hotend[ee].celsius, STR_PID_DEBUG_OUTPUT, pid_output
1406
-            #if DISABLED(PID_OPENLOOP)
1407
-              , STR_PID_DEBUG_PTERM, work_pid[ee].Kp
1408
-              , STR_PID_DEBUG_ITERM, work_pid[ee].Ki
1409
-              , STR_PID_DEBUG_DTERM, work_pid[ee].Kd
1410
-              #if ENABLED(PID_EXTRUSION_SCALING)
1411
-                , STR_PID_DEBUG_CTERM, work_pid[ee].Kc
1412
-              #endif
1413
-            #endif
1414
-          );
1415
-        }
1410
+        if (ee == active_extruder)
1411
+          hotend_pid[ee].debug(temp_hotend[ee].celsius, pid_output, F("E"), ee);
1416
       #endif
1412
       #endif
1417
 
1413
 
1418
     #elif ENABLED(MPCTEMP)
1414
     #elif ENABLED(MPCTEMP)
1415
+
1419
       MPCHeaterInfo &hotend = temp_hotend[ee];
1416
       MPCHeaterInfo &hotend = temp_hotend[ee];
1420
       MPC_t &constants = hotend.constants;
1417
       MPC_t &constants = hotend.constants;
1421
 
1418
 
1497
     #else // No PID or MPC enabled
1494
     #else // No PID or MPC enabled
1498
 
1495
 
1499
       const bool is_idling = TERN0(HEATER_IDLE_HANDLER, heater_idle[ee].timed_out);
1496
       const bool is_idling = TERN0(HEATER_IDLE_HANDLER, heater_idle[ee].timed_out);
1500
-      const float pid_output = (!is_idling && temp_hotend[ee].celsius < temp_hotend[ee].target) ? BANG_MAX : 0;
1497
+      const float pid_output = (!is_idling && temp_hotend[ee].is_below_target()) ? BANG_MAX : 0;
1501
 
1498
 
1502
     #endif
1499
     #endif
1503
 
1500
 
1509
 #if ENABLED(PIDTEMPBED)
1506
 #if ENABLED(PIDTEMPBED)
1510
 
1507
 
1511
   float Temperature::get_pid_output_bed() {
1508
   float Temperature::get_pid_output_bed() {
1512
-
1513
-    #if DISABLED(PID_OPENLOOP)
1514
-
1515
-      static PID_t work_pid{0};
1516
-      static float temp_iState = 0, temp_dState = 0;
1517
-      static bool pid_reset = true;
1518
-      float pid_output = 0;
1519
-      const float max_power_over_i_gain = float(MAX_BED_POWER) / temp_bed.pid.Ki - float(MIN_BED_POWER),
1520
-                  pid_error = temp_bed.target - temp_bed.celsius;
1521
-
1522
-      if (!temp_bed.target || pid_error < -(PID_FUNCTIONAL_RANGE)) {
1523
-        pid_output = 0;
1524
-        pid_reset = true;
1525
-      }
1526
-      else if (pid_error > PID_FUNCTIONAL_RANGE) {
1527
-        pid_output = MAX_BED_POWER;
1528
-        pid_reset = true;
1529
-      }
1530
-      else {
1531
-        if (pid_reset) {
1532
-          temp_iState = 0.0;
1533
-          work_pid.Kd = 0.0;
1534
-          pid_reset = false;
1535
-        }
1536
-
1537
-        temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain);
1538
-
1539
-        work_pid.Kp = temp_bed.pid.Kp * pid_error;
1540
-        work_pid.Ki = temp_bed.pid.Ki * temp_iState;
1541
-        work_pid.Kd = work_pid.Kd + PID_K2 * (temp_bed.pid.Kd * (temp_dState - temp_bed.celsius) - work_pid.Kd);
1542
-
1543
-        temp_dState = temp_bed.celsius;
1544
-
1545
-        pid_output = constrain(work_pid.Kp + work_pid.Ki + work_pid.Kd + float(MIN_BED_POWER), 0, MAX_BED_POWER);
1546
-      }
1547
-
1548
-    #else // PID_OPENLOOP
1549
-
1550
-      const float pid_output = constrain(temp_bed.target, 0, MAX_BED_POWER);
1551
-
1552
-    #endif // PID_OPENLOOP
1553
-
1554
-    #if ENABLED(PID_BED_DEBUG)
1555
-      if (pid_debug_flag) {
1556
-        SERIAL_ECHO_MSG(
1557
-          " PID_BED_DEBUG : Input ", temp_bed.celsius, " Output ", pid_output
1558
-          #if DISABLED(PID_OPENLOOP)
1559
-            , STR_PID_DEBUG_PTERM, work_pid.Kp
1560
-            , STR_PID_DEBUG_ITERM, work_pid.Ki
1561
-            , STR_PID_DEBUG_DTERM, work_pid.Kd
1562
-          #endif
1563
-        );
1564
-      }
1565
-    #endif
1566
-
1509
+    static PIDRunner<bed_info_t, MIN_BED_POWER, MAX_BED_POWER> bed_pid(temp_bed);
1510
+    const float pid_output = bed_pid.get_pid_output();
1511
+    TERN_(PID_BED_DEBUG, bed_pid.debug(temp_bed.celsius, pid_output, F("(Bed)")));
1567
     return pid_output;
1512
     return pid_output;
1568
   }
1513
   }
1569
 
1514
 
1572
 #if ENABLED(PIDTEMPCHAMBER)
1517
 #if ENABLED(PIDTEMPCHAMBER)
1573
 
1518
 
1574
   float Temperature::get_pid_output_chamber() {
1519
   float Temperature::get_pid_output_chamber() {
1575
-
1576
-    #if DISABLED(PID_OPENLOOP)
1577
-
1578
-      static PID_t work_pid{0};
1579
-      static float temp_iState = 0, temp_dState = 0;
1580
-      static bool pid_reset = true;
1581
-      float pid_output = 0;
1582
-      const float max_power_over_i_gain = float(MAX_CHAMBER_POWER) / temp_chamber.pid.Ki - float(MIN_CHAMBER_POWER),
1583
-                  pid_error = temp_chamber.target - temp_chamber.celsius;
1584
-
1585
-      if (!temp_chamber.target || pid_error < -(PID_FUNCTIONAL_RANGE)) {
1586
-        pid_output = 0;
1587
-        pid_reset = true;
1588
-      }
1589
-      else if (pid_error > PID_FUNCTIONAL_RANGE) {
1590
-        pid_output = MAX_CHAMBER_POWER;
1591
-        pid_reset = true;
1592
-      }
1593
-      else {
1594
-        if (pid_reset) {
1595
-          temp_iState = 0.0;
1596
-          work_pid.Kd = 0.0;
1597
-          pid_reset = false;
1598
-        }
1599
-
1600
-        temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain);
1601
-
1602
-        work_pid.Kp = temp_chamber.pid.Kp * pid_error;
1603
-        work_pid.Ki = temp_chamber.pid.Ki * temp_iState;
1604
-        work_pid.Kd = work_pid.Kd + PID_K2 * (temp_chamber.pid.Kd * (temp_dState - temp_chamber.celsius) - work_pid.Kd);
1605
-
1606
-        temp_dState = temp_chamber.celsius;
1607
-
1608
-        pid_output = constrain(work_pid.Kp + work_pid.Ki + work_pid.Kd + float(MIN_CHAMBER_POWER), 0, MAX_CHAMBER_POWER);
1609
-      }
1610
-
1611
-    #else // PID_OPENLOOP
1612
-
1613
-      const float pid_output = constrain(temp_chamber.target, 0, MAX_CHAMBER_POWER);
1614
-
1615
-    #endif // PID_OPENLOOP
1616
-
1617
-    #if ENABLED(PID_CHAMBER_DEBUG)
1618
-    {
1619
-      SERIAL_ECHO_MSG(
1620
-        " PID_CHAMBER_DEBUG : Input ", temp_chamber.celsius, " Output ", pid_output
1621
-        #if DISABLED(PID_OPENLOOP)
1622
-          , STR_PID_DEBUG_PTERM, work_pid.Kp
1623
-          , STR_PID_DEBUG_ITERM, work_pid.Ki
1624
-          , STR_PID_DEBUG_DTERM, work_pid.Kd
1625
-        #endif
1626
-      );
1627
-    }
1628
-    #endif
1629
-
1520
+    static PIDRunner<chamber_info_t, MIN_CHAMBER_POWER, MAX_CHAMBER_POWER> chamber_pid(temp_chamber);
1521
+    const float pid_output = chamber_pid.get_pid_output();
1522
+    TERN_(PID_CHAMBER_DEBUG, chamber_pid.debug(temp_chamber.celsius, pid_output, F("(Chamber)")));
1630
     return pid_output;
1523
     return pid_output;
1631
   }
1524
   }
1632
 
1525
 
1633
 #endif // PIDTEMPCHAMBER
1526
 #endif // PIDTEMPCHAMBER
1634
 
1527
 
1635
-/**
1636
- * Manage heating activities for extruder hot-ends and a heated bed
1637
- *  - Acquire updated temperature readings
1638
- *    - Also resets the watchdog timer
1639
- *  - Invoke thermal runaway protection
1640
- *  - Manage extruder auto-fan
1641
- *  - Apply filament width to the extrusion rate (may move)
1642
- *  - Update the heated bed PID output value
1643
- */
1644
-void Temperature::manage_heater() {
1645
-  if (marlin_state == MF_INITIALIZING) return hal.watchdog_refresh(); // If Marlin isn't started, at least reset the watchdog!
1646
-
1647
-  static bool no_reentry = false;  // Prevent recursion
1648
-  if (no_reentry) return;
1649
-  REMEMBER(mh, no_reentry, true);
1650
-
1651
-  #if ENABLED(EMERGENCY_PARSER)
1652
-    if (emergency_parser.killed_by_M112) kill(FPSTR(M112_KILL_STR), nullptr, true);
1653
-
1654
-    if (emergency_parser.quickstop_by_M410) {
1655
-      emergency_parser.quickstop_by_M410 = false; // quickstop_stepper may call idle so clear this now!
1656
-      quickstop_stepper();
1657
-    }
1658
-  #endif
1659
-
1660
-  if (!updateTemperaturesIfReady()) return; // Will also reset the watchdog if temperatures are ready
1661
-
1662
-  #if DISABLED(IGNORE_THERMOCOUPLE_ERRORS)
1663
-    #if TEMP_SENSOR_0_IS_MAX_TC
1664
-      if (degHotend(0) > _MIN(HEATER_0_MAXTEMP, TEMP_SENSOR_0_MAX_TC_TMAX - 1.0)) max_temp_error(H_E0);
1665
-      if (degHotend(0) < _MAX(HEATER_0_MINTEMP, TEMP_SENSOR_0_MAX_TC_TMIN + .01)) min_temp_error(H_E0);
1666
-    #endif
1667
-    #if TEMP_SENSOR_1_IS_MAX_TC
1668
-      if (degHotend(1) > _MIN(HEATER_1_MAXTEMP, TEMP_SENSOR_1_MAX_TC_TMAX - 1.0)) max_temp_error(H_E1);
1669
-      if (degHotend(1) < _MAX(HEATER_1_MINTEMP, TEMP_SENSOR_1_MAX_TC_TMIN + .01)) min_temp_error(H_E1);
1670
-    #endif
1671
-    #if TEMP_SENSOR_REDUNDANT_IS_MAX_TC
1672
-      if (degRedundant() > TEMP_SENSOR_REDUNDANT_MAX_TC_TMAX - 1.0) max_temp_error(H_REDUNDANT);
1673
-      if (degRedundant() < TEMP_SENSOR_REDUNDANT_MAX_TC_TMIN + .01) min_temp_error(H_REDUNDANT);
1674
-    #endif
1675
-  #else
1676
-    #warning "Safety Alert! Disable IGNORE_THERMOCOUPLE_ERRORS for the final build!"
1677
-  #endif
1678
-
1679
-  millis_t ms = millis();
1680
-
1681
-  #if HAS_HOTEND
1528
+#if HAS_HOTEND
1682
 
1529
 
1530
+  void Temperature::manage_hotends(const millis_t &ms) {
1683
     HOTEND_LOOP() {
1531
     HOTEND_LOOP() {
1684
       #if ENABLED(THERMAL_PROTECTION_HOTENDS)
1532
       #if ENABLED(THERMAL_PROTECTION_HOTENDS)
1685
         if (degHotend(e) > temp_range[e].maxtemp) max_temp_error((heater_id_t)e);
1533
         if (degHotend(e) > temp_range[e].maxtemp) max_temp_error((heater_id_t)e);
1707
       #endif
1555
       #endif
1708
 
1556
 
1709
     } // HOTEND_LOOP
1557
     } // HOTEND_LOOP
1558
+  }
1710
 
1559
 
1711
-  #endif // HAS_HOTEND
1712
-
1713
-  #if HAS_TEMP_REDUNDANT
1714
-    // Make sure measured temperatures are close together
1715
-    if (ABS(degRedundantTarget() - degRedundant()) > TEMP_SENSOR_REDUNDANT_MAX_DIFF)
1716
-      _temp_error((heater_id_t)HEATER_ID(TEMP_SENSOR_REDUNDANT_TARGET), F(STR_REDUNDANCY), GET_TEXT_F(MSG_ERR_REDUNDANT_TEMP));
1717
-  #endif
1718
-
1719
-  // Manage extruder auto fans and/or read fan tachometers
1720
-  TERN_(HAS_FAN_LOGIC, manage_extruder_fans(ms));
1560
+#endif // HAS_HOTEND
1721
 
1561
 
1722
-  /**
1723
-   * Dynamically set the volumetric multiplier based
1724
-   * on the delayed Filament Width measurement.
1725
-   */
1726
-  TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_volumetric());
1562
+#if HAS_HEATED_BED
1727
 
1563
 
1728
-  #if HAS_HEATED_BED
1564
+  void Temperature::manage_heated_bed(const millis_t &ms) {
1729
 
1565
 
1730
     #if ENABLED(THERMAL_PROTECTION_BED)
1566
     #if ENABLED(THERMAL_PROTECTION_BED)
1731
       if (degBed() > BED_MAXTEMP) max_temp_error(H_BED);
1567
       if (degBed() > BED_MAXTEMP) max_temp_error(H_BED);
1770
       #if HEATER_IDLE_HANDLER
1606
       #if HEATER_IDLE_HANDLER
1771
         if (heater_idle[IDLE_INDEX_BED].timed_out) {
1607
         if (heater_idle[IDLE_INDEX_BED].timed_out) {
1772
           temp_bed.soft_pwm_amount = 0;
1608
           temp_bed.soft_pwm_amount = 0;
1773
-          #if DISABLED(PIDTEMPBED)
1774
-            WRITE_HEATER_BED(LOW);
1775
-          #endif
1609
+          if (DISABLED(PIDTEMPBED)) WRITE_HEATER_BED(LOW);
1776
         }
1610
         }
1777
         else
1611
         else
1778
       #endif
1612
       #endif
1785
             #if ENABLED(BED_LIMIT_SWITCHING)
1619
             #if ENABLED(BED_LIMIT_SWITCHING)
1786
               if (temp_bed.celsius >= temp_bed.target + BED_HYSTERESIS)
1620
               if (temp_bed.celsius >= temp_bed.target + BED_HYSTERESIS)
1787
                 temp_bed.soft_pwm_amount = 0;
1621
                 temp_bed.soft_pwm_amount = 0;
1788
-              else if (temp_bed.celsius <= temp_bed.target - (BED_HYSTERESIS))
1622
+              else if (temp_bed.is_below_target(-(BED_HYSTERESIS) + 1))
1789
                 temp_bed.soft_pwm_amount = MAX_BED_POWER >> 1;
1623
                 temp_bed.soft_pwm_amount = MAX_BED_POWER >> 1;
1790
             #else // !PIDTEMPBED && !BED_LIMIT_SWITCHING
1624
             #else // !PIDTEMPBED && !BED_LIMIT_SWITCHING
1791
-              temp_bed.soft_pwm_amount = temp_bed.celsius < temp_bed.target ? MAX_BED_POWER >> 1 : 0;
1625
+              temp_bed.soft_pwm_amount = temp_bed.is_below_target() ? MAX_BED_POWER >> 1 : 0;
1792
             #endif
1626
             #endif
1793
           }
1627
           }
1794
           else {
1628
           else {
1799
       }
1633
       }
1800
 
1634
 
1801
     } while (false);
1635
     } while (false);
1636
+  }
1802
 
1637
 
1803
-  #endif // HAS_HEATED_BED
1638
+#endif // HAS_HEATED_BED
1804
 
1639
 
1805
-  #if HAS_HEATED_CHAMBER
1640
+#if HAS_HEATED_CHAMBER
1641
+
1642
+  void Temperature::manage_heated_chamber(const millis_t &ms) {
1806
 
1643
 
1807
     #ifndef CHAMBER_CHECK_INTERVAL
1644
     #ifndef CHAMBER_CHECK_INTERVAL
1808
       #define CHAMBER_CHECK_INTERVAL 1000UL
1645
       #define CHAMBER_CHECK_INTERVAL 1000UL
1897
           if (flag_chamber_excess_heat) {
1734
           if (flag_chamber_excess_heat) {
1898
             temp_chamber.soft_pwm_amount = 0;
1735
             temp_chamber.soft_pwm_amount = 0;
1899
             #if ENABLED(CHAMBER_VENT)
1736
             #if ENABLED(CHAMBER_VENT)
1900
-              if (!flag_chamber_off) servo[CHAMBER_VENT_SERVO_NR].move(temp_chamber.celsius <= temp_chamber.target ? 0 : 90);
1737
+              if (!flag_chamber_off) servo[CHAMBER_VENT_SERVO_NR].move(temp_chamber.is_below_target() ? 0 : 90);
1901
             #endif
1738
             #endif
1902
           }
1739
           }
1903
           else {
1740
           else {
1904
             #if ENABLED(CHAMBER_LIMIT_SWITCHING)
1741
             #if ENABLED(CHAMBER_LIMIT_SWITCHING)
1905
               if (temp_chamber.celsius >= temp_chamber.target + TEMP_CHAMBER_HYSTERESIS)
1742
               if (temp_chamber.celsius >= temp_chamber.target + TEMP_CHAMBER_HYSTERESIS)
1906
                 temp_chamber.soft_pwm_amount = 0;
1743
                 temp_chamber.soft_pwm_amount = 0;
1907
-              else if (temp_chamber.celsius <= temp_chamber.target - (TEMP_CHAMBER_HYSTERESIS))
1744
+              else if (temp_chamber.is_below_target(-(TEMP_CHAMBER_HYSTERESIS) + 1))
1908
                 temp_chamber.soft_pwm_amount = (MAX_CHAMBER_POWER) >> 1;
1745
                 temp_chamber.soft_pwm_amount = (MAX_CHAMBER_POWER) >> 1;
1909
             #else
1746
             #else
1910
-              temp_chamber.soft_pwm_amount = temp_chamber.celsius < temp_chamber.target ? (MAX_CHAMBER_POWER) >> 1 : 0;
1747
+              temp_chamber.soft_pwm_amount = temp_chamber.is_below_target() ? (MAX_CHAMBER_POWER) >> 1 : 0;
1911
             #endif
1748
             #endif
1912
             #if ENABLED(CHAMBER_VENT)
1749
             #if ENABLED(CHAMBER_VENT)
1913
               if (!flag_chamber_off) servo[CHAMBER_VENT_SERVO_NR].move(0);
1750
               if (!flag_chamber_off) servo[CHAMBER_VENT_SERVO_NR].move(0);
1923
        tr_state_machine[RUNAWAY_IND_CHAMBER].run(temp_chamber.celsius, temp_chamber.target, H_CHAMBER, THERMAL_PROTECTION_CHAMBER_PERIOD, THERMAL_PROTECTION_CHAMBER_HYSTERESIS);
1760
        tr_state_machine[RUNAWAY_IND_CHAMBER].run(temp_chamber.celsius, temp_chamber.target, H_CHAMBER, THERMAL_PROTECTION_CHAMBER_PERIOD, THERMAL_PROTECTION_CHAMBER_HYSTERESIS);
1924
      #endif
1761
      #endif
1925
    #endif
1762
    #endif
1763
+  }
1926
 
1764
 
1927
-  #endif // HAS_HEATED_CHAMBER
1765
+#endif // HAS_HEATED_CHAMBER
1928
 
1766
 
1929
-  #if HAS_COOLER
1767
+#if HAS_COOLER
1768
+
1769
+  void Temperature::manage_cooler(const millis_t &ms) {
1930
 
1770
 
1931
     #ifndef COOLER_CHECK_INTERVAL
1771
     #ifndef COOLER_CHECK_INTERVAL
1932
       #define COOLER_CHECK_INTERVAL 2000UL
1772
       #define COOLER_CHECK_INTERVAL 2000UL
1984
     #if ENABLED(THERMAL_PROTECTION_COOLER)
1824
     #if ENABLED(THERMAL_PROTECTION_COOLER)
1985
       tr_state_machine[RUNAWAY_IND_COOLER].run(temp_cooler.celsius, temp_cooler.target, H_COOLER, THERMAL_PROTECTION_COOLER_PERIOD, THERMAL_PROTECTION_COOLER_HYSTERESIS);
1825
       tr_state_machine[RUNAWAY_IND_COOLER].run(temp_cooler.celsius, temp_cooler.target, H_COOLER, THERMAL_PROTECTION_COOLER_PERIOD, THERMAL_PROTECTION_COOLER_HYSTERESIS);
1986
     #endif
1826
     #endif
1827
+  }
1987
 
1828
 
1988
-  #endif // HAS_COOLER
1829
+#endif // HAS_COOLER
1830
+
1831
+/**
1832
+ * Manage heating activities for extruder hot-ends and a heated bed
1833
+ *  - Acquire updated temperature readings
1834
+ *    - Also resets the watchdog timer
1835
+ *  - Invoke thermal runaway protection
1836
+ *  - Manage extruder auto-fan
1837
+ *  - Apply filament width to the extrusion rate (may move)
1838
+ *  - Update the heated bed PID output value
1839
+ */
1840
+void Temperature::task() {
1841
+  if (marlin_state == MF_INITIALIZING) return hal.watchdog_refresh(); // If Marlin isn't started, at least reset the watchdog!
1842
+
1843
+  static bool no_reentry = false;  // Prevent recursion
1844
+  if (no_reentry) return;
1845
+  REMEMBER(mh, no_reentry, true);
1846
+
1847
+  #if ENABLED(EMERGENCY_PARSER)
1848
+    if (emergency_parser.killed_by_M112) kill(FPSTR(M112_KILL_STR), nullptr, true);
1849
+
1850
+    if (emergency_parser.quickstop_by_M410) {
1851
+      emergency_parser.quickstop_by_M410 = false; // quickstop_stepper may call idle so clear this now!
1852
+      quickstop_stepper();
1853
+    }
1854
+  #endif
1855
+
1856
+  if (!updateTemperaturesIfReady()) return; // Will also reset the watchdog if temperatures are ready
1857
+
1858
+  #if DISABLED(IGNORE_THERMOCOUPLE_ERRORS)
1859
+    #if TEMP_SENSOR_0_IS_MAX_TC
1860
+      if (degHotend(0) > _MIN(HEATER_0_MAXTEMP, TEMP_SENSOR_0_MAX_TC_TMAX - 1.0)) max_temp_error(H_E0);
1861
+      if (degHotend(0) < _MAX(HEATER_0_MINTEMP, TEMP_SENSOR_0_MAX_TC_TMIN + .01)) min_temp_error(H_E0);
1862
+    #endif
1863
+    #if TEMP_SENSOR_1_IS_MAX_TC
1864
+      if (degHotend(1) > _MIN(HEATER_1_MAXTEMP, TEMP_SENSOR_1_MAX_TC_TMAX - 1.0)) max_temp_error(H_E1);
1865
+      if (degHotend(1) < _MAX(HEATER_1_MINTEMP, TEMP_SENSOR_1_MAX_TC_TMIN + .01)) min_temp_error(H_E1);
1866
+    #endif
1867
+    #if TEMP_SENSOR_REDUNDANT_IS_MAX_TC
1868
+      if (degRedundant() > TEMP_SENSOR_REDUNDANT_MAX_TC_TMAX - 1.0) max_temp_error(H_REDUNDANT);
1869
+      if (degRedundant() < TEMP_SENSOR_REDUNDANT_MAX_TC_TMIN + .01) min_temp_error(H_REDUNDANT);
1870
+    #endif
1871
+  #else
1872
+    #warning "Safety Alert! Disable IGNORE_THERMOCOUPLE_ERRORS for the final build!"
1873
+  #endif
1874
+
1875
+  const millis_t ms = millis();
1876
+
1877
+  // Handle Hotend Temp Errors, Heating Watch, etc.
1878
+  TERN_(HAS_HOTEND, manage_hotends(ms));
1879
+
1880
+  #if HAS_TEMP_REDUNDANT
1881
+    // Make sure measured temperatures are close together
1882
+    if (ABS(degRedundantTarget() - degRedundant()) > TEMP_SENSOR_REDUNDANT_MAX_DIFF)
1883
+      _temp_error((heater_id_t)HEATER_ID(TEMP_SENSOR_REDUNDANT_TARGET), F(STR_REDUNDANCY), GET_TEXT_F(MSG_ERR_REDUNDANT_TEMP));
1884
+  #endif
1885
+
1886
+  // Manage extruder auto fans and/or read fan tachometers
1887
+  TERN_(HAS_FAN_LOGIC, manage_extruder_fans(ms));
1888
+
1889
+  /**
1890
+   * Dynamically set the volumetric multiplier based
1891
+   * on the delayed Filament Width measurement.
1892
+   */
1893
+  TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_volumetric());
1894
+
1895
+  // Handle Bed Temp Errors, Heating Watch, etc.
1896
+  TERN_(HAS_HEATED_BED, manage_heated_bed(ms));
1897
+
1898
+  // Handle Heated Chamber Temp Errors, Heating Watch, etc.
1899
+  TERN_(HAS_HEATED_CHAMBER, manage_heated_chamber(ms));
1900
+
1901
+  // Handle Cooler Temp Errors, Cooling Watch, etc.
1902
+  TERN_(HAS_COOLER, manage_cooler(ms));
1989
 
1903
 
1990
   #if ENABLED(LASER_COOLANT_FLOW_METER)
1904
   #if ENABLED(LASER_COOLANT_FLOW_METER)
1991
     cooler.flowmeter_task(ms);
1905
     cooler.flowmeter_task(ms);
2479
 /**
2393
 /**
2480
  * Initialize the temperature manager
2394
  * Initialize the temperature manager
2481
  *
2395
  *
2482
- * The manager is implemented by periodic calls to manage_heater()
2396
+ * The manager is implemented by periodic calls to task()
2483
  *
2397
  *
2484
  *  - Init (and disable) SPI thermocouples like MAX6675 and MAX31865
2398
  *  - Init (and disable) SPI thermocouples like MAX6675 and MAX31865
2485
  *  - Disable RUMBA JTAG to accommodate a thermocouple extension
2399
  *  - Disable RUMBA JTAG to accommodate a thermocouple extension
3111
     static millis_t next_max_tc_ms[MAX_TC_COUNT] = { 0 };
3025
     static millis_t next_max_tc_ms[MAX_TC_COUNT] = { 0 };
3112
 
3026
 
3113
     // Return last-read value between readings
3027
     // Return last-read value between readings
3114
-    millis_t ms = millis();
3028
+    const millis_t ms = millis();
3115
     if (PENDING(ms, next_max_tc_ms[hindex]))
3029
     if (PENDING(ms, next_max_tc_ms[hindex]))
3116
       return THERMO_TEMP(hindex);
3030
       return THERMO_TEMP(hindex);
3117
 
3031
 
3419
         _PWM_MOD(COOLER, soft_pwm_cooler, temp_cooler);
3333
         _PWM_MOD(COOLER, soft_pwm_cooler, temp_cooler);
3420
       #endif
3334
       #endif
3421
 
3335
 
3422
-      #if BOTH(USE_CONTROLLER_FAN, FAN_SOFT_PWM)
3423
-        WRITE(CONTROLLER_FAN_PIN, soft_pwm_controller.add(pwm_mask, soft_pwm_controller_speed));
3424
-      #endif
3425
-
3426
       #if ENABLED(FAN_SOFT_PWM)
3336
       #if ENABLED(FAN_SOFT_PWM)
3337
+
3338
+        #if ENABLED(USE_CONTROLLER_FAN)
3339
+          WRITE(CONTROLLER_FAN_PIN, soft_pwm_controller.add(pwm_mask, soft_pwm_controller_speed));
3340
+        #endif
3341
+
3427
         #define _FAN_PWM(N) do{                                     \
3342
         #define _FAN_PWM(N) do{                                     \
3428
           uint8_t &spcf = soft_pwm_count_fan[N];                    \
3343
           uint8_t &spcf = soft_pwm_count_fan[N];                    \
3429
           spcf = (spcf & pwm_mask) + (soft_pwm_amount_fan[N] >> 1); \
3344
           spcf = (spcf & pwm_mask) + (soft_pwm_amount_fan[N] >> 1); \
3430
           WRITE_FAN(N, spcf > pwm_mask ? HIGH : LOW);               \
3345
           WRITE_FAN(N, spcf > pwm_mask ? HIGH : LOW);               \
3431
         }while(0)
3346
         }while(0)
3347
+
3432
         #if HAS_FAN0
3348
         #if HAS_FAN0
3433
           _FAN_PWM(0);
3349
           _FAN_PWM(0);
3434
         #endif
3350
         #endif

+ 11
- 5
Marlin/src/module/temperature.h View File

232
 typedef struct HeaterInfo : public TempInfo {
232
 typedef struct HeaterInfo : public TempInfo {
233
   celsius_t target;
233
   celsius_t target;
234
   uint8_t soft_pwm_amount;
234
   uint8_t soft_pwm_amount;
235
+  bool is_below_target(const celsius_t offs=0) const { return (celsius < (target + offs)); }
235
 } heater_info_t;
236
 } heater_info_t;
236
 
237
 
237
 // A heater with PID stabilization
238
 // A heater with PID stabilization
715
     static void readings_ready();
716
     static void readings_ready();
716
 
717
 
717
     /**
718
     /**
718
-     * Call periodically to manage heaters
719
+     * Call periodically to manage heaters and keep the watchdog fed
719
      */
720
      */
720
-    static void manage_heater() __O2; // __O2 added to work around a compiler error
721
+    static void task();
721
 
722
 
722
     /**
723
     /**
723
      * Preheating hotends
724
      * Preheating hotends
807
         #endif
808
         #endif
808
       }
809
       }
809
 
810
 
811
+      static void manage_hotends(const millis_t &ms);
812
+
810
     #endif // HAS_HOTEND
813
     #endif // HAS_HOTEND
811
 
814
 
812
     #if HAS_HEATED_BED
815
     #if HAS_HEATED_BED
819
       static celsius_t degTargetBed()  { return temp_bed.target; }
822
       static celsius_t degTargetBed()  { return temp_bed.target; }
820
       static bool isHeatingBed()       { return temp_bed.target > temp_bed.celsius; }
823
       static bool isHeatingBed()       { return temp_bed.target > temp_bed.celsius; }
821
       static bool isCoolingBed()       { return temp_bed.target < temp_bed.celsius; }
824
       static bool isCoolingBed()       { return temp_bed.target < temp_bed.celsius; }
825
+      static bool degBedNear(const celsius_t temp) {
826
+        return ABS(wholeDegBed() - temp) < (TEMP_BED_HYSTERESIS);
827
+      }
822
 
828
 
823
       // Start watching the Bed to make sure it's really heating up
829
       // Start watching the Bed to make sure it's really heating up
824
       static void start_watching_bed() { TERN_(WATCH_BED, watch_bed.restart(degBed(), degTargetBed())); }
830
       static void start_watching_bed() { TERN_(WATCH_BED, watch_bed.restart(degBed(), degTargetBed())); }
835
 
841
 
836
       static void wait_for_bed_heating();
842
       static void wait_for_bed_heating();
837
 
843
 
838
-      static bool degBedNear(const celsius_t temp) {
839
-        return ABS(wholeDegBed() - temp) < (TEMP_BED_HYSTERESIS);
840
-      }
844
+      static void manage_heated_bed(const millis_t &ms);
841
 
845
 
842
     #endif // HAS_HEATED_BED
846
     #endif // HAS_HEATED_BED
843
 
847
 
863
         static bool isHeatingChamber()       { return temp_chamber.target > temp_chamber.celsius; }
867
         static bool isHeatingChamber()       { return temp_chamber.target > temp_chamber.celsius; }
864
         static bool isCoolingChamber()       { return temp_chamber.target < temp_chamber.celsius; }
868
         static bool isCoolingChamber()       { return temp_chamber.target < temp_chamber.celsius; }
865
         static bool wait_for_chamber(const bool no_wait_for_cooling=true);
869
         static bool wait_for_chamber(const bool no_wait_for_cooling=true);
870
+        static void manage_heated_chamber(const millis_t &ms);
866
       #endif
871
       #endif
867
     #endif
872
     #endif
868
 
873
 
886
         static bool isLaserHeating()       { return temp_cooler.target > temp_cooler.celsius; }
891
         static bool isLaserHeating()       { return temp_cooler.target > temp_cooler.celsius; }
887
         static bool isLaserCooling()       { return temp_cooler.target < temp_cooler.celsius; }
892
         static bool isLaserCooling()       { return temp_cooler.target < temp_cooler.celsius; }
888
         static bool wait_for_cooler(const bool no_wait_for_cooling=true);
893
         static bool wait_for_cooler(const bool no_wait_for_cooling=true);
894
+        static void manage_cooler(const millis_t &ms);
889
       #endif
895
       #endif
890
     #endif
896
     #endif
891
 
897
 

+ 1
- 1
Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.cpp View File

62
   #define USB_HOST_MANUAL_POLL // Optimization to shut off IRQ automatically
62
   #define USB_HOST_MANUAL_POLL // Optimization to shut off IRQ automatically
63
 
63
 
64
   // Workarounds to keep Marlin's watchdog timer from barking...
64
   // Workarounds to keep Marlin's watchdog timer from barking...
65
-  void marlin_yield() { thermalManager.manage_heater(); }
65
+  void marlin_yield() { thermalManager.task(); }
66
   #define SYSTEM_OR_SPECIAL_YIELD(...) marlin_yield();
66
   #define SYSTEM_OR_SPECIAL_YIELD(...) marlin_yield();
67
   #define delay(x) safe_delay(x)
67
   #define delay(x) safe_delay(x)
68
 
68
 

Loading…
Cancel
Save