Browse Source

✨ Temperature variance monitor (#23373)

John Lagonikas 2 years ago
parent
commit
63f71d85f2
No account linked to committer's email address

+ 4
- 0
Marlin/Configuration_adv.h View File

@@ -349,6 +349,10 @@
349 349
   #define WATCH_COOLER_TEMP_INCREASE            3 // Degrees Celsius
350 350
 #endif
351 351
 
352
+#if ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_BED, THERMAL_PROTECTION_CHAMBER, THERMAL_PROTECTION_COOLER)
353
+  #define THERMAL_PROTECTION_VARIANCE_MONITOR     // Detect a sensor malfunction preventing temperature updates
354
+#endif
355
+
352 356
 #if ENABLED(PIDTEMP)
353 357
   // Add an experimental additional term to the heater power, proportional to the extrusion speed.
354 358
   // A well-chosen Kc value should add just enough power to melt the increased material volume.

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

@@ -240,6 +240,7 @@
240 240
 #define STR_REDUNDANCY                      "Heater switched off. Temperature difference between temp sensors is too high !"
241 241
 #define STR_T_HEATING_FAILED                "Heating failed"
242 242
 #define STR_T_THERMAL_RUNAWAY               "Thermal Runaway"
243
+#define STR_T_MALFUNCTION                   "Thermal Malfunction"
243 244
 #define STR_T_MAXTEMP                       "MAXTEMP triggered"
244 245
 #define STR_T_MINTEMP                       "MINTEMP triggered"
245 246
 #define STR_ERR_PROBING_FAILED              "Probing Failed"

+ 3
- 0
Marlin/src/inc/Conditionals_post.h View File

@@ -2564,6 +2564,9 @@
2564 2564
 #if BOTH(HAS_COOLER, THERMAL_PROTECTION_COOLER) && WATCH_COOLER_TEMP_PERIOD > 0
2565 2565
   #define WATCH_COOLER 1
2566 2566
 #endif
2567
+#if NONE(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_CHAMBER, THERMAL_PROTECTION_BED, THERMAL_PROTECTION_COOLER)
2568
+  #undef THERMAL_PROTECTION_VARIANCE_MONITOR
2569
+#endif
2567 2570
 #if  (ENABLED(THERMAL_PROTECTION_HOTENDS) || !EXTRUDERS) \
2568 2571
   && (ENABLED(THERMAL_PROTECTION_BED)     || !HAS_HEATED_BED) \
2569 2572
   && (ENABLED(THERMAL_PROTECTION_CHAMBER) || !HAS_HEATED_CHAMBER) \

+ 1
- 0
Marlin/src/lcd/language/language_el.h View File

@@ -202,6 +202,7 @@ namespace Language_el {
202 202
   LSTR MSG_HEATING_FAILED_LCD             = _UxGT("Αποτυχία θέρμανσης");
203 203
   LSTR MSG_ERR_REDUNDANT_TEMP             = _UxGT("ΠΛΕΟΝΑΖΟΥΣΑ ΘΕΡΜΟΤΗΤΑ");
204 204
   LSTR MSG_THERMAL_RUNAWAY                = _UxGT("ΘΕΡΜΙΚΗ ΔΙΑΦΥΓΗ");
205
+  LSTR MSG_TEMP_MALFUNCTION               = _UxGT("ΘΕΡΜΙΚΗ ΔΥΣΛΕΙΤΟΥΡΓΙΑ");
205 206
   LSTR MSG_ERR_MAXTEMP                    = _UxGT("ΠΕΡΙΤΤΗ ΘΕΡΜΟΚΡΑΣΙΑ");
206 207
   LSTR MSG_ERR_MINTEMP                    = _UxGT("ΑΝΕΠΑΡΚΗΣ ΘΕΡΜΟΚΡΑΣΙΑ");
207 208
   LSTR MSG_HALTED                         = _UxGT("Εκτυπωτής διεκόπη");

+ 1
- 0
Marlin/src/lcd/language/language_en.h View File

@@ -533,6 +533,7 @@ namespace Language_en {
533 533
   LSTR MSG_HEATING_FAILED_LCD             = _UxGT("Heating Failed");
534 534
   LSTR MSG_ERR_REDUNDANT_TEMP             = _UxGT("Err: REDUNDANT TEMP");
535 535
   LSTR MSG_THERMAL_RUNAWAY                = _UxGT("THERMAL RUNAWAY");
536
+  LSTR MSG_TEMP_MALFUNCTION               = _UxGT("TEMP MALFUNCTION");
536 537
   LSTR MSG_THERMAL_RUNAWAY_BED            = _UxGT("BED THERMAL RUNAWAY");
537 538
   LSTR MSG_THERMAL_RUNAWAY_CHAMBER        = _UxGT("CHAMBER T. RUNAWAY");
538 539
   LSTR MSG_THERMAL_RUNAWAY_COOLER         = _UxGT("Cooler Runaway");

+ 47
- 8
Marlin/src/module/temperature.cpp View File

@@ -196,6 +196,7 @@
196 196
 Temperature thermalManager;
197 197
 
198 198
 PGMSTR(str_t_thermal_runaway, STR_T_THERMAL_RUNAWAY);
199
+PGMSTR(str_t_temp_malfunction, STR_T_MALFUNCTION);
199 200
 PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED);
200 201
 
201 202
 /**
@@ -2570,14 +2571,30 @@ void Temperature::init() {
2570 2571
       );
2571 2572
     */
2572 2573
 
2573
-    // If the heater idle timeout expires, restart
2574
-    if (TERN0(HEATER_IDLE_HANDLER, heater_idle[idle_index].timed_out)) {
2575
-      state = TRInactive;
2576
-      running_temp = 0;
2577
-    }
2578
-    else if (running_temp != target) { // If the target temperature changes, restart
2579
-      running_temp = target;
2580
-      state = target > 0 ? TRFirstHeating : TRInactive;
2574
+    #if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
2575
+      if (state == TRMalfunction) { // temperature invariance may continue, regardless of heater state
2576
+        variance += ABS(current - last_temp); // no need for detection window now, a single change in variance is enough
2577
+        last_temp = current;
2578
+        if (!NEAR_ZERO(variance)) {
2579
+          variance_timer = millis() + SEC_TO_MS(period_seconds);
2580
+          variance = 0.0;
2581
+          state = TRStable; // resume from where we detected the problem
2582
+        }
2583
+      }
2584
+    #endif
2585
+
2586
+    if (TERN1(THERMAL_PROTECTION_VARIANCE_MONITOR, state != TRMalfunction)) {
2587
+      // If the heater idle timeout expires, restart
2588
+      if (TERN0(HEATER_IDLE_HANDLER, heater_idle[idle_index].timed_out)) {
2589
+        state = TRInactive;
2590
+        running_temp = 0;
2591
+        TERN_(THERMAL_PROTECTION_VARIANCE_MONITOR, variance_timer = 0);
2592
+      }
2593
+      else if (running_temp != target) { // If the target temperature changes, restart
2594
+        running_temp = target;
2595
+        state = target > 0 ? TRFirstHeating : TRInactive;
2596
+        TERN_(THERMAL_PROTECTION_VARIANCE_MONITOR, variance_timer = 0);
2597
+      }
2581 2598
     }
2582 2599
 
2583 2600
     switch (state) {
@@ -2610,6 +2627,22 @@ void Temperature::init() {
2610 2627
 
2611 2628
         const millis_t now = millis();
2612 2629
 
2630
+        #if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
2631
+          if (PENDING(now, variance_timer)) {
2632
+            variance += ABS(current - last_temp);
2633
+            last_temp = current;
2634
+          }
2635
+          else {
2636
+            if (NEAR_ZERO(variance) && variance_timer) { // valid variance monitoring window
2637
+              state = TRMalfunction;
2638
+              break;
2639
+            }
2640
+            variance_timer = now + SEC_TO_MS(period_seconds);
2641
+            variance = 0.0;
2642
+            last_temp = current;
2643
+          }
2644
+        #endif
2645
+
2613 2646
         if (current >= running_temp - hysteresis_degc) {
2614 2647
           timer = now + SEC_TO_MS(period_seconds);
2615 2648
           break;
@@ -2622,6 +2655,12 @@ void Temperature::init() {
2622 2655
       case TRRunaway:
2623 2656
         TERN_(HAS_DWIN_E3V2_BASIC, DWIN_Popup_Temperature(0));
2624 2657
         _temp_error(heater_id, FPSTR(str_t_thermal_runaway), GET_TEXT_F(MSG_THERMAL_RUNAWAY));
2658
+
2659
+      #if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
2660
+        case TRMalfunction:
2661
+          TERN_(HAS_DWIN_E3V2_BASIC, DWIN_Popup_Temperature(0));
2662
+          _temp_error(heater_id, FPSTR(str_t_temp_malfunction), GET_TEXT_F(MSG_TEMP_MALFUNCTION));
2663
+      #endif
2625 2664
     }
2626 2665
   }
2627 2666
 

+ 7
- 1
Marlin/src/module/temperature.h View File

@@ -1035,12 +1035,18 @@ class Temperature {
1035 1035
         return (RunawayIndex)_MAX(heater_id, 0);
1036 1036
       }
1037 1037
 
1038
-      enum TRState : char { TRInactive, TRFirstHeating, TRStable, TRRunaway };
1038
+      enum TRState : char { TRInactive, TRFirstHeating, TRStable, TRRunaway
1039
+        OPTARG(THERMAL_PROTECTION_VARIANCE_MONITOR, TRMalfunction)
1040
+      };
1039 1041
 
1040 1042
       typedef struct {
1041 1043
         millis_t timer = 0;
1042 1044
         TRState state = TRInactive;
1043 1045
         float running_temp;
1046
+        #if ENABLED(THERMAL_PROTECTION_VARIANCE_MONITOR)
1047
+          millis_t variance_timer = 0;
1048
+          celsius_float_t last_temp = 0.0, variance = 0.0;
1049
+        #endif
1044 1050
         void run(const_celsius_float_t current, const_celsius_float_t target, const heater_id_t heater_id, const uint16_t period_seconds, const celsius_t hysteresis_degc);
1045 1051
       } tr_state_machine_t;
1046 1052
 

Loading…
Cancel
Save