Browse Source

🚸 Improve MPC tuning, add menu items (#23984)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
tombrazier 2 years ago
parent
commit
3da29b4a04
No account linked to committer's email address

+ 4
- 0
Marlin/Configuration.h View File

643
  * for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 to autotune the model.
643
  * for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 to autotune the model.
644
  */
644
  */
645
 #if ENABLED(MPCTEMP)
645
 #if ENABLED(MPCTEMP)
646
+  //#define MPC_EDIT_MENU                             // Add MPC editing to the "Advanced Settings" menu. (~1300 bytes of flash)
647
+  //#define MPC_AUTOTUNE_MENU                         // Add MPC auto-tuning to the "Advanced Settings" menu. (~350 bytes of flash)
648
+
646
   #define MPC_MAX BANG_MAX                            // (0..255) Current to nozzle while MPC is active.
649
   #define MPC_MAX BANG_MAX                            // (0..255) Current to nozzle while MPC is active.
647
   #define MPC_HEATER_POWER { 40.0f }                  // (W) Heat cartridge powers.
650
   #define MPC_HEATER_POWER { 40.0f }                  // (W) Heat cartridge powers.
648
 
651
 
671
   #define MPC_STEADYSTATE 0.5f                        // (K/s) Temperature change rate for steady state logic to be enforced.
674
   #define MPC_STEADYSTATE 0.5f                        // (K/s) Temperature change rate for steady state logic to be enforced.
672
 
675
 
673
   #define MPC_TUNING_POS { X_CENTER, Y_CENTER, 1.0f } // (mm) M306 Autotuning position, ideally bed center just above the surface.
676
   #define MPC_TUNING_POS { X_CENTER, Y_CENTER, 1.0f } // (mm) M306 Autotuning position, ideally bed center just above the surface.
677
+  #define MPC_TUNING_END_Z 10.0f                      // (mm) M306 Autotuning final Z position.
674
 #endif
678
 #endif
675
 
679
 
676
 //===========================================================================
680
 //===========================================================================

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

232
 #define STR_PID_DEBUG_DTERM                 " dTerm "
232
 #define STR_PID_DEBUG_DTERM                 " dTerm "
233
 #define STR_PID_DEBUG_CTERM                 " cTerm "
233
 #define STR_PID_DEBUG_CTERM                 " cTerm "
234
 #define STR_INVALID_EXTRUDER_NUM            " - Invalid extruder number !"
234
 #define STR_INVALID_EXTRUDER_NUM            " - Invalid extruder number !"
235
+#define STR_MPC_AUTOTUNE                    "MPC Autotune"
236
+#define STR_MPC_AUTOTUNE_START              " start for " STR_E
237
+#define STR_MPC_AUTOTUNE_INTERRUPTED        " interrupted!"
238
+#define STR_MPC_AUTOTUNE_FINISHED           " finished! Put the constants below into Configuration.h"
239
+#define STR_MPC_COOLING_TO_AMBIENT          "Cooling to ambient"
240
+#define STR_MPC_HEATING_PAST_200            "Heating to over 200C"
241
+#define STR_MPC_MEASURING_AMBIENT           "Measuring ambient heatloss at "
242
+#define STR_MPC_TEMPERATURE_ERROR           "Temperature error"
235
 
243
 
236
 #define STR_HEATER_BED                      "bed"
244
 #define STR_HEATER_BED                      "bed"
237
 #define STR_HEATER_CHAMBER                  "chamber"
245
 #define STR_HEATER_CHAMBER                  "chamber"

+ 1
- 11
Marlin/src/gcode/temp/M306.cpp View File

56
     return;
56
     return;
57
   }
57
   }
58
 
58
 
59
-  HOTEND_LOOP() {
60
-    SERIAL_ECHOLNPGM("MPC constants for hotend ", e);
61
-    MPC_t& constants = thermalManager.temp_hotend[e].constants;
62
-    SERIAL_ECHOLNPGM("Heater power: ", constants.heater_power);
63
-    SERIAL_ECHOLNPGM("Heatblock heat capacity: ", constants.block_heat_capacity);
64
-    SERIAL_ECHOLNPAIR_F("Sensor responsivness: ", constants.sensor_responsiveness, 4);
65
-    SERIAL_ECHOLNPAIR_F("Ambient heat transfer coeff. (no fan): ", constants.ambient_xfer_coeff_fan0, 4);
66
-    #if ENABLED(MPC_INCLUDE_FAN)
67
-      SERIAL_ECHOLNPAIR_F("Ambient heat transfer coeff. (full fan): ", constants.ambient_xfer_coeff_fan0 + constants.fan255_adjustment, 4);
68
-    #endif
69
-  }
59
+  M306_report(true);
70
 }
60
 }
71
 
61
 
72
 void GcodeSuite::M306_report(const bool forReplay/*=true*/) {
62
 void GcodeSuite::M306_report(const bool forReplay/*=true*/) {

+ 4
- 0
Marlin/src/inc/SanityCheck.h View File

2964
     #error "DWIN_CREALITY_LCD requires SDSUPPORT to be enabled."
2964
     #error "DWIN_CREALITY_LCD requires SDSUPPORT to be enabled."
2965
   #elif EITHER(PID_EDIT_MENU, PID_AUTOTUNE_MENU)
2965
   #elif EITHER(PID_EDIT_MENU, PID_AUTOTUNE_MENU)
2966
     #error "DWIN_CREALITY_LCD does not support PID_EDIT_MENU or PID_AUTOTUNE_MENU."
2966
     #error "DWIN_CREALITY_LCD does not support PID_EDIT_MENU or PID_AUTOTUNE_MENU."
2967
+  #elif EITHER(MPC_EDIT_MENU, MPC_AUTOTUNE_MENU)
2968
+    #error "DWIN_CREALITY_LCD does not support MPC_EDIT_MENU or MPC_AUTOTUNE_MENU."
2967
   #elif ENABLED(LEVEL_BED_CORNERS)
2969
   #elif ENABLED(LEVEL_BED_CORNERS)
2968
     #error "DWIN_CREALITY_LCD does not support LEVEL_BED_CORNERS."
2970
     #error "DWIN_CREALITY_LCD does not support LEVEL_BED_CORNERS."
2969
   #elif BOTH(LCD_BED_LEVELING, PROBE_MANUALLY)
2971
   #elif BOTH(LCD_BED_LEVELING, PROBE_MANUALLY)
2974
     #error "DWIN_LCD_PROUI requires SDSUPPORT to be enabled."
2976
     #error "DWIN_LCD_PROUI requires SDSUPPORT to be enabled."
2975
   #elif EITHER(PID_EDIT_MENU, PID_AUTOTUNE_MENU)
2977
   #elif EITHER(PID_EDIT_MENU, PID_AUTOTUNE_MENU)
2976
     #error "DWIN_LCD_PROUI does not support PID_EDIT_MENU or PID_AUTOTUNE_MENU."
2978
     #error "DWIN_LCD_PROUI does not support PID_EDIT_MENU or PID_AUTOTUNE_MENU."
2979
+  #elif EITHER(MPC_EDIT_MENU, MPC_AUTOTUNE_MENU)
2980
+    #error "DWIN_LCD_PROUI does not support MPC_EDIT_MENU or MPC_AUTOTUNE_MENU."
2977
   #elif ENABLED(LEVEL_BED_CORNERS)
2981
   #elif ENABLED(LEVEL_BED_CORNERS)
2978
     #error "DWIN_LCD_PROUI does not support LEVEL_BED_CORNERS."
2982
     #error "DWIN_LCD_PROUI does not support LEVEL_BED_CORNERS."
2979
   #elif BOTH(LCD_BED_LEVELING, PROBE_MANUALLY)
2983
   #elif BOTH(LCD_BED_LEVELING, PROBE_MANUALLY)

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

350
   LSTR MSG_PID_BAD_EXTRUDER_NUM           = _UxGT("Autotune failed. Bad extruder.");
350
   LSTR MSG_PID_BAD_EXTRUDER_NUM           = _UxGT("Autotune failed. Bad extruder.");
351
   LSTR MSG_PID_TEMP_TOO_HIGH              = _UxGT("Autotune failed. Temperature too high.");
351
   LSTR MSG_PID_TEMP_TOO_HIGH              = _UxGT("Autotune failed. Temperature too high.");
352
   LSTR MSG_PID_TIMEOUT                    = _UxGT("Autotune failed! Timeout.");
352
   LSTR MSG_PID_TIMEOUT                    = _UxGT("Autotune failed! Timeout.");
353
+  LSTR MSG_MPC_MEASURING_AMBIENT          = _UxGT("Testing heat loss");
354
+  LSTR MSG_MPC_AUTOTUNE                   = _UxGT("MPC Autotune");
355
+  LSTR MSG_MPC_EDIT                       = _UxGT("Edit * MPC");
356
+  LSTR MSG_MPC_POWER_E                    = _UxGT("Power *");
357
+  LSTR MSG_MPC_BLOCK_HEAT_CAPACITY_E      = _UxGT("Block C *");
358
+  LSTR MSG_SENSOR_RESPONSIVENESS_E        = _UxGT("Sensor res *");
359
+  LSTR MSG_MPC_AMBIENT_XFER_COEFF_E       = _UxGT("Ambient h *");
360
+  LSTR MSG_MPC_AMBIENT_XFER_COEFF_FAN255_E= _UxGT("Amb. h fan *");
353
   LSTR MSG_SELECT                         = _UxGT("Select");
361
   LSTR MSG_SELECT                         = _UxGT("Select");
354
   LSTR MSG_SELECT_E                       = _UxGT("Select *");
362
   LSTR MSG_SELECT_E                       = _UxGT("Select *");
355
   LSTR MSG_ACC                            = _UxGT("Accel");
363
   LSTR MSG_ACC                            = _UxGT("Accel");

+ 50
- 1
Marlin/src/lcd/menu/menu_advanced.cpp View File

244
   }
244
   }
245
 #endif
245
 #endif
246
 
246
 
247
-#if BOTH(AUTOTEMP, HAS_TEMP_HOTEND) || EITHER(PID_AUTOTUNE_MENU, PID_EDIT_MENU)
247
+#if BOTH(AUTOTEMP, HAS_TEMP_HOTEND) || ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU, MPC_AUTOTUNE_MENU, MPC_EDIT_MENU)
248
   #define SHOW_MENU_ADVANCED_TEMPERATURE 1
248
   #define SHOW_MENU_ADVANCED_TEMPERATURE 1
249
 #endif
249
 #endif
250
 
250
 
253
 //
253
 //
254
 #if SHOW_MENU_ADVANCED_TEMPERATURE
254
 #if SHOW_MENU_ADVANCED_TEMPERATURE
255
 
255
 
256
+  #if ENABLED(MPC_EDIT_MENU)
257
+    #define MPC_EDIT_DEFS(N) \
258
+      MPC_t &c = thermalManager.temp_hotend[N].constants; \
259
+      TERN(MPC_INCLUDE_FAN, editable.decimal = c.ambient_xfer_coeff_fan0 + c.fan255_adjustment)
260
+  #endif
261
+
256
   void menu_advanced_temperature() {
262
   void menu_advanced_temperature() {
263
+    #if ENABLED(MPC_EDIT_MENU) && !HAS_MULTI_HOTEND
264
+      MPC_EDIT_DEFS(0);
265
+    #endif
266
+
257
     START_MENU();
267
     START_MENU();
258
     BACK_ITEM(MSG_ADVANCED_SETTINGS);
268
     BACK_ITEM(MSG_ADVANCED_SETTINGS);
259
 
269
 
330
       #endif
340
       #endif
331
     #endif
341
     #endif
332
 
342
 
343
+    #if ENABLED(MPC_EDIT_MENU)
344
+
345
+      #define _MPC_EDIT_ITEMS(N) \
346
+        EDIT_ITEM_FAST_N(float31sign, N, MSG_MPC_POWER_E, &c.heater_power, 1, 200); \
347
+        EDIT_ITEM_FAST_N(float31sign, N, MSG_MPC_BLOCK_HEAT_CAPACITY_E, &c.block_heat_capacity, 0, 40); \
348
+        EDIT_ITEM_FAST_N(float43, N, MSG_SENSOR_RESPONSIVENESS_E, &c.sensor_responsiveness, 0, 1); \
349
+        EDIT_ITEM_FAST_N(float43, N, MSG_MPC_AMBIENT_XFER_COEFF_E, &c.ambient_xfer_coeff_fan0, 0, 1)
350
+
351
+      #if ENABLED(MPC_INCLUDE_FAN)
352
+        #define MPC_EDIT_ITEMS(N) \
353
+          _MPC_EDIT_ITEMS(N); \
354
+          EDIT_ITEM_FAST_N(float43, N, MSG_MPC_AMBIENT_XFER_COEFF_FAN255_E, &editable.decimal, 0, 1, []{ \
355
+            c.fan255_adjustment = editable.decimal - c.ambient_xfer_coeff_fan0; \
356
+          })
357
+      #else
358
+        #define MPC_EDIT_ITEMS _MPC_EDIT_ITEMS
359
+      #endif
360
+
361
+      #if HAS_MULTI_HOTEND
362
+        auto mpc_edit_hotend = [&](const uint8_t e) {
363
+          MPC_EDIT_DEFS(e);
364
+          START_MENU();
365
+          BACK_ITEM(MSG_TEMPERATURE);
366
+          MPC_EDIT_ITEMS(e);
367
+          END_MENU();
368
+        };
369
+        #define MPC_ENTRY(N) SUBMENU_N(N, MSG_MPC_EDIT, []{ mpc_edit_hotend(MenuItemBase::itemIndex); });
370
+      #else
371
+        #define MPC_ENTRY MPC_EDIT_ITEMS
372
+      #endif
373
+
374
+      REPEAT(HOTENDS, MPC_ENTRY);
375
+
376
+    #endif // MPC_EDIT_MENU
377
+
378
+    #if ENABLED(MPC_AUTOTUNE_MENU)
379
+      ACTION_ITEM(MSG_MPC_AUTOTUNE, []{ queue.inject(F("M306 T")); ui.return_to_status(); });
380
+    #endif
381
+
333
     #if ENABLED(PIDTEMPBED)
382
     #if ENABLED(PIDTEMPBED)
334
       #if ENABLED(PID_EDIT_MENU)
383
       #if ENABLED(PID_EDIT_MENU)
335
         _PID_EDIT_ITEMS_TMPL(H_BED, thermalManager.temp_bed);
384
         _PID_EDIT_ITEMS_TMPL(H_BED, thermalManager.temp_bed);

+ 91
- 54
Marlin/src/module/temperature.cpp View File

141
   #endif
141
   #endif
142
 #endif
142
 #endif
143
 
143
 
144
-#if EITHER(MPCTEMP, PID_EXTRUSION_SCALING)
144
+#if ENABLED(MPCTEMP)
145
   #include <math.h>
145
   #include <math.h>
146
+  #include "probe.h"
147
+#endif
148
+
149
+#if EITHER(MPCTEMP, PID_EXTRUSION_SCALING)
146
   #include "stepper.h"
150
   #include "stepper.h"
147
 #endif
151
 #endif
148
 
152
 
864
 
868
 
865
       if (ELAPSED(ms, next_report_ms)) {
869
       if (ELAPSED(ms, next_report_ms)) {
866
         next_report_ms += 1000UL;
870
         next_report_ms += 1000UL;
867
-        SERIAL_ECHOLNPGM("Temperature ", current_temp);
871
+
872
+        print_heater_states(active_extruder);
873
+        SERIAL_EOL();
868
       }
874
       }
869
 
875
 
870
       hal.idletask();
876
       hal.idletask();
877
+      TERN(DWIN_CREALITY_LCD, DWIN_Update(), ui.update());
878
+
879
+      if (!wait_for_heatup) {
880
+        SERIAL_ECHOPGM(STR_MPC_AUTOTUNE);
881
+        SERIAL_ECHOLNPGM(STR_MPC_AUTOTUNE_INTERRUPTED);
882
+        return false;
883
+      }
884
+
885
+      return true;
871
     };
886
     };
872
 
887
 
873
-    SERIAL_ECHOLNPGM("Measuring MPC constants for E", active_extruder);
874
-    MPCHeaterInfo& hotend = temp_hotend[active_extruder];
875
-    MPC_t& constants = hotend.constants;
888
+    struct OnExit {
889
+      ~OnExit() {
890
+        wait_for_heatup = false;
891
+
892
+        ui.reset_status();
893
+
894
+        temp_hotend[active_extruder].target = 0.0f;
895
+        temp_hotend[active_extruder].soft_pwm_amount = 0;
896
+        #if HAS_FAN
897
+          set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0);
898
+          planner.sync_fan_speeds(fan_speed);
899
+        #endif
876
 
900
 
877
-    // move to center of bed, just above bed height and cool with max fan
878
-    TERN_(HAS_FAN, zero_fan_speeds());
901
+        do_z_clearance(MPC_TUNING_END_Z);
902
+      }
903
+    } on_exit;
904
+
905
+    SERIAL_ECHOPGM(STR_MPC_AUTOTUNE);
906
+    SERIAL_ECHOLNPGM(STR_MPC_AUTOTUNE_START, active_extruder);
907
+    MPCHeaterInfo &hotend = temp_hotend[active_extruder];
908
+    MPC_t &constants = hotend.constants;
909
+
910
+    // Move to center of bed, just above bed height and cool with max fan
879
     disable_all_heaters();
911
     disable_all_heaters();
880
-    TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255));
881
-    TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed));
912
+    #if HAS_FAN
913
+      zero_fan_speeds();
914
+      set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255);
915
+      planner.sync_fan_speeds(fan_speed);
916
+    #endif
882
     gcode.home_all_axes(true);
917
     gcode.home_all_axes(true);
883
     const xyz_pos_t tuningpos = MPC_TUNING_POS;
918
     const xyz_pos_t tuningpos = MPC_TUNING_POS;
884
     do_blocking_move_to(tuningpos);
919
     do_blocking_move_to(tuningpos);
885
 
920
 
886
-    SERIAL_ECHOLNPGM("Cooling to ambient");
921
+    SERIAL_ECHOLNPGM(STR_MPC_COOLING_TO_AMBIENT);
922
+    LCD_MESSAGE(MSG_COOLING);
887
     millis_t ms = millis(), next_report_ms = ms, next_test_ms = ms + 10000UL;
923
     millis_t ms = millis(), next_report_ms = ms, next_test_ms = ms + 10000UL;
888
     celsius_float_t current_temp = degHotend(active_extruder),
924
     celsius_float_t current_temp = degHotend(active_extruder),
889
                     ambient_temp = current_temp;
925
                     ambient_temp = current_temp;
890
 
926
 
891
-    wait_for_heatup = true; // Can be interrupted with M108
892
-    while (wait_for_heatup) {
893
-      housekeeping(ms, current_temp, next_report_ms);
927
+    wait_for_heatup = true;
928
+    for (;;) { // Can be interrupted with M108
929
+      if (!housekeeping(ms, current_temp, next_report_ms)) return;
894
 
930
 
895
       if (ELAPSED(ms, next_test_ms)) {
931
       if (ELAPSED(ms, next_test_ms)) {
896
         if (current_temp >= ambient_temp) {
932
         if (current_temp >= ambient_temp) {
902
       }
938
       }
903
     }
939
     }
904
 
940
 
905
-    TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0));
906
-    TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed));
941
+    #if HAS_FAN
942
+      set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0);
943
+      planner.sync_fan_speeds(fan_speed);
944
+    #endif
907
 
945
 
908
     hotend.modeled_ambient_temp = ambient_temp;
946
     hotend.modeled_ambient_temp = ambient_temp;
909
 
947
 
910
-    SERIAL_ECHOLNPGM("Heating to 200C");
948
+    SERIAL_ECHOLNPGM(STR_MPC_HEATING_PAST_200);
949
+    LCD_MESSAGE(MSG_HEATING);
950
+    hotend.target = 200.0f;   // So M105 looks nice
911
     hotend.soft_pwm_amount = MPC_MAX >> 1;
951
     hotend.soft_pwm_amount = MPC_MAX >> 1;
912
     const millis_t heat_start_time = next_test_ms = ms;
952
     const millis_t heat_start_time = next_test_ms = ms;
913
     celsius_float_t temp_samples[16];
953
     celsius_float_t temp_samples[16];
915
     uint16_t sample_distance = 1;
955
     uint16_t sample_distance = 1;
916
     float t1_time = 0;
956
     float t1_time = 0;
917
 
957
 
918
-    while (wait_for_heatup) {
919
-      housekeeping(ms, current_temp, next_report_ms);
958
+    for (;;) { // Can be interrupted with M108
959
+      if (!housekeeping(ms, current_temp, next_report_ms)) return;
920
 
960
 
921
       if (ELAPSED(ms, next_test_ms)) {
961
       if (ELAPSED(ms, next_test_ms)) {
922
-        // record samples between 100C and 200C
962
+        // Record samples between 100C and 200C
923
         if (current_temp >= 100.0f) {
963
         if (current_temp >= 100.0f) {
924
-          // if there are too many samples, space them more widely
964
+          // If there are too many samples, space them more widely
925
           if (sample_count == COUNT(temp_samples)) {
965
           if (sample_count == COUNT(temp_samples)) {
926
             for (uint8_t i = 0; i < COUNT(temp_samples) / 2; i++)
966
             for (uint8_t i = 0; i < COUNT(temp_samples) / 2; i++)
927
               temp_samples[i] = temp_samples[i*2];
967
               temp_samples[i] = temp_samples[i*2];
944
     sample_count = (sample_count + 1) / 2 * 2 - 1;
984
     sample_count = (sample_count + 1) / 2 * 2 - 1;
945
     const float t1 = temp_samples[0],
985
     const float t1 = temp_samples[0],
946
                 t2 = temp_samples[(sample_count - 1) >> 1],
986
                 t2 = temp_samples[(sample_count - 1) >> 1],
947
-                t3 = temp_samples[sample_count - 1],
948
-                asymp_temp = (t2 * t2 - t1 * t3) / (2 * t2 - t1 - t3),
949
-                block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1));
987
+                t3 = temp_samples[sample_count - 1];
988
+    float asymp_temp = (t2 * t2 - t1 * t3) / (2 * t2 - t1 - t3),
989
+          block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1));
950
 
990
 
951
     constants.ambient_xfer_coeff_fan0 = constants.heater_power * MPC_MAX / 255 / (asymp_temp - ambient_temp);
991
     constants.ambient_xfer_coeff_fan0 = constants.heater_power * MPC_MAX / 255 / (asymp_temp - ambient_temp);
952
     constants.fan255_adjustment = 0.0f;
992
     constants.fan255_adjustment = 0.0f;
957
     hotend.modeled_sensor_temp = current_temp;
997
     hotend.modeled_sensor_temp = current_temp;
958
 
998
 
959
     // Allow the system to stabilize under MPC, then get a better measure of ambient loss with and without fan
999
     // Allow the system to stabilize under MPC, then get a better measure of ambient loss with and without fan
960
-    SERIAL_ECHOLNPGM("Measuring ambient heatloss at target ", hotend.modeled_block_temp);
1000
+    SERIAL_ECHOLNPGM(STR_MPC_MEASURING_AMBIENT, hotend.modeled_block_temp);
1001
+    LCD_MESSAGE(MSG_MPC_MEASURING_AMBIENT);
961
     hotend.target = hotend.modeled_block_temp;
1002
     hotend.target = hotend.modeled_block_temp;
962
     next_test_ms = ms + MPC_dT * 1000;
1003
     next_test_ms = ms + MPC_dT * 1000;
963
     constexpr millis_t settle_time = 20000UL, test_duration = 20000UL;
1004
     constexpr millis_t settle_time = 20000UL, test_duration = 20000UL;
970
     #endif
1011
     #endif
971
     float last_temp = current_temp;
1012
     float last_temp = current_temp;
972
 
1013
 
973
-    while (wait_for_heatup) {
974
-      housekeeping(ms, current_temp, next_report_ms);
1014
+    for (;;) { // Can be interrupted with M108
1015
+      if (!housekeeping(ms, current_temp, next_report_ms)) return;
975
 
1016
 
976
       if (ELAPSED(ms, next_test_ms)) {
1017
       if (ELAPSED(ms, next_test_ms)) {
977
-        // use MPC to control the temperature, let it settle for 30s and then track power output for 10s
978
         hotend.soft_pwm_amount = (int)get_pid_output_hotend(active_extruder) >> 1;
1018
         hotend.soft_pwm_amount = (int)get_pid_output_hotend(active_extruder) >> 1;
979
 
1019
 
980
         if (ELAPSED(ms, settle_end_ms) && !ELAPSED(ms, test_end_ms) && TERN1(HAS_FAN, !fan0_done))
1020
         if (ELAPSED(ms, settle_end_ms) && !ELAPSED(ms, test_end_ms) && TERN1(HAS_FAN, !fan0_done))
981
           total_energy_fan0 += constants.heater_power * hotend.soft_pwm_amount / 127 * MPC_dT + (last_temp - current_temp) * constants.block_heat_capacity;
1021
           total_energy_fan0 += constants.heater_power * hotend.soft_pwm_amount / 127 * MPC_dT + (last_temp - current_temp) * constants.block_heat_capacity;
982
         #if HAS_FAN
1022
         #if HAS_FAN
983
           else if (ELAPSED(ms, test_end_ms) && !fan0_done) {
1023
           else if (ELAPSED(ms, test_end_ms) && !fan0_done) {
984
-            SERIAL_ECHOLNPGM("Measuring ambient heatloss with full fan");
985
             set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255);
1024
             set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255);
986
             planner.sync_fan_speeds(fan_speed);
1025
             planner.sync_fan_speeds(fan_speed);
987
             settle_end_ms = ms + settle_time;
1026
             settle_end_ms = ms + settle_time;
997
         next_test_ms += MPC_dT * 1000;
1036
         next_test_ms += MPC_dT * 1000;
998
       }
1037
       }
999
 
1038
 
1000
-      if (!WITHIN(current_temp, hotend.target - 15.0f, hotend.target + 15.0f)) {
1001
-        SERIAL_ECHOLNPGM("Temperature error while measuring ambient loss");
1039
+      if (!WITHIN(current_temp, t3 - 15.0f, hotend.target + 15.0f)) {
1040
+        SERIAL_ECHOLNPGM(STR_MPC_TEMPERATURE_ERROR);
1002
         break;
1041
         break;
1003
       }
1042
       }
1004
     }
1043
     }
1012
       constants.fan255_adjustment = ambient_xfer_coeff_fan255 - constants.ambient_xfer_coeff_fan0;
1051
       constants.fan255_adjustment = ambient_xfer_coeff_fan255 - constants.ambient_xfer_coeff_fan0;
1013
     #endif
1052
     #endif
1014
 
1053
 
1015
-    hotend.target = 0.0f;
1016
-    hotend.soft_pwm_amount = 0;
1017
-    TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0));
1018
-    TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed));
1019
-
1020
-    if (!wait_for_heatup) SERIAL_ECHOLNPGM("Test was interrupted");
1021
-
1022
-    wait_for_heatup = false;
1054
+    // Calculate a new and better asymptotic temperature and re-evaluate the other constants
1055
+    asymp_temp = ambient_temp + constants.heater_power / constants.ambient_xfer_coeff_fan0;
1056
+    block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1));
1057
+    constants.block_heat_capacity = constants.ambient_xfer_coeff_fan0 / block_responsiveness;
1058
+    constants.sensor_responsiveness = block_responsiveness / (1.0f - (ambient_temp - asymp_temp) * exp(-block_responsiveness * t1_time) / (t1 - asymp_temp));
1023
 
1059
 
1024
-    SERIAL_ECHOLNPGM("Done");
1060
+    SERIAL_ECHOPGM(STR_MPC_AUTOTUNE);
1061
+    SERIAL_ECHOLNPGM(STR_MPC_AUTOTUNE_FINISHED);
1025
 
1062
 
1026
     /* <-- add a slash to enable
1063
     /* <-- add a slash to enable
1027
       SERIAL_ECHOLNPGM("t1_time ", t1_time);
1064
       SERIAL_ECHOLNPGM("t1_time ", t1_time);
1378
 
1415
 
1379
       // At startup, initialize modeled temperatures
1416
       // At startup, initialize modeled temperatures
1380
       if (isnan(hotend.modeled_block_temp)) {
1417
       if (isnan(hotend.modeled_block_temp)) {
1381
-        hotend.modeled_ambient_temp = min(30.0f, hotend.celsius);   // cap initial value at reasonable max room temperature of 30C
1418
+        hotend.modeled_ambient_temp = min(30.0f, hotend.celsius);   // Cap initial value at reasonable max room temperature of 30C
1382
         hotend.modeled_block_temp = hotend.modeled_sensor_temp = hotend.celsius;
1419
         hotend.modeled_block_temp = hotend.modeled_sensor_temp = hotend.celsius;
1383
       }
1420
       }
1384
 
1421
 
1399
         const int32_t e_position = stepper.position(E_AXIS);
1436
         const int32_t e_position = stepper.position(E_AXIS);
1400
         const float e_speed = (e_position - mpc_e_position) * planner.mm_per_step[E_AXIS] / MPC_dT;
1437
         const float e_speed = (e_position - mpc_e_position) * planner.mm_per_step[E_AXIS] / MPC_dT;
1401
 
1438
 
1402
-        // the position can appear to make big jumps when, e.g. homing
1439
+        // The position can appear to make big jumps when, e.g. homing
1403
         if (fabs(e_speed) > planner.settings.max_feedrate_mm_s[E_AXIS])
1440
         if (fabs(e_speed) > planner.settings.max_feedrate_mm_s[E_AXIS])
1404
           mpc_e_position = e_position;
1441
           mpc_e_position = e_position;
1405
-        else if (e_speed > 0.0f) {  // ignore retract/recover moves
1442
+        else if (e_speed > 0.0f) {  // Ignore retract/recover moves
1406
           ambient_xfer_coeff += e_speed * FILAMENT_HEAT_CAPACITY_PERMM;
1443
           ambient_xfer_coeff += e_speed * FILAMENT_HEAT_CAPACITY_PERMM;
1407
           mpc_e_position = e_position;
1444
           mpc_e_position = e_position;
1408
         }
1445
         }
1409
       }
1446
       }
1410
 
1447
 
1411
-      // update the modeled temperatures
1448
+      // Update the modeled temperatures
1412
       float blocktempdelta = hotend.soft_pwm_amount * constants.heater_power * (MPC_dT / 127) / constants.block_heat_capacity;
1449
       float blocktempdelta = hotend.soft_pwm_amount * constants.heater_power * (MPC_dT / 127) / constants.block_heat_capacity;
1413
       blocktempdelta += (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff * MPC_dT / constants.block_heat_capacity;
1450
       blocktempdelta += (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff * MPC_dT / constants.block_heat_capacity;
1414
       hotend.modeled_block_temp += blocktempdelta;
1451
       hotend.modeled_block_temp += blocktempdelta;
1422
       hotend.modeled_block_temp += delta_to_apply;
1459
       hotend.modeled_block_temp += delta_to_apply;
1423
       hotend.modeled_sensor_temp += delta_to_apply;
1460
       hotend.modeled_sensor_temp += delta_to_apply;
1424
 
1461
 
1425
-      // only correct ambient when close to steady state (output power is not clipped or asymptotic temperature is reached)
1462
+      // Only correct ambient when close to steady state (output power is not clipped or asymptotic temperature is reached)
1426
       if (WITHIN(hotend.soft_pwm_amount, 1, 126) || fabs(blocktempdelta + delta_to_apply) < (MPC_STEADYSTATE * MPC_dT))
1463
       if (WITHIN(hotend.soft_pwm_amount, 1, 126) || fabs(blocktempdelta + delta_to_apply) < (MPC_STEADYSTATE * MPC_dT))
1427
         hotend.modeled_ambient_temp += delta_to_apply > 0.f ? max(delta_to_apply, MPC_MIN_AMBIENT_CHANGE * MPC_dT) : min(delta_to_apply, -MPC_MIN_AMBIENT_CHANGE * MPC_dT);
1464
         hotend.modeled_ambient_temp += delta_to_apply > 0.f ? max(delta_to_apply, MPC_MIN_AMBIENT_CHANGE * MPC_dT) : min(delta_to_apply, -MPC_MIN_AMBIENT_CHANGE * MPC_dT);
1428
 
1465
 
1429
       float power = 0.0;
1466
       float power = 0.0;
1430
       if (hotend.target != 0 && TERN1(HEATER_IDLE_HANDLER, !heater_idle[ee].timed_out)) {
1467
       if (hotend.target != 0 && TERN1(HEATER_IDLE_HANDLER, !heater_idle[ee].timed_out)) {
1431
-        // plan power level to get to target temperature in 2 seconds
1468
+        // Plan power level to get to target temperature in 2 seconds
1432
         power = (hotend.target - hotend.modeled_block_temp) * constants.block_heat_capacity / 2.0f;
1469
         power = (hotend.target - hotend.modeled_block_temp) * constants.block_heat_capacity / 2.0f;
1433
         power -= (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff;
1470
         power -= (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff;
1434
       }
1471
       }
1435
 
1472
 
1436
-      float pid_output = power * 254.0f / constants.heater_power + 1.0f;        // ensure correct quantization into a range of 0 to 127
1473
+      float pid_output = power * 254.0f / constants.heater_power + 1.0f;        // Ensure correct quantization into a range of 0 to 127
1437
       pid_output = constrain(pid_output, 0, MPC_MAX);
1474
       pid_output = constrain(pid_output, 0, MPC_MAX);
1438
 
1475
 
1439
       /* <-- add a slash to enable
1476
       /* <-- add a slash to enable
2079
                         - (t.beta_recip * t.res_25_log) - (t.sh_c_coeff * cu(t.res_25_log));
2116
                         - (t.beta_recip * t.res_25_log) - (t.sh_c_coeff * cu(t.res_25_log));
2080
     }
2117
     }
2081
 
2118
 
2082
-    // maximum adc value .. take into account the over sampling
2119
+    // Maximum ADC value .. take into account the over sampling
2083
     constexpr raw_adc_t adc_max = MAX_RAW_THERMISTOR_VALUE;
2120
     constexpr raw_adc_t adc_max = MAX_RAW_THERMISTOR_VALUE;
2084
     const raw_adc_t adc_raw = constrain(raw, 1, adc_max - 1); // constrain to prevent divide-by-zero
2121
     const raw_adc_t adc_raw = constrain(raw, 1, adc_max - 1); // constrain to prevent divide-by-zero
2085
 
2122
 
3077
         spiInit(MAX_TC_SPEED_BITS);
3114
         spiInit(MAX_TC_SPEED_BITS);
3078
       #endif
3115
       #endif
3079
 
3116
 
3080
-      MAXTC_CS_WRITE(LOW);  // enable MAXTC
3117
+      MAXTC_CS_WRITE(LOW);  // Enable MAXTC
3081
       DELAY_NS(100);        // Ensure 100ns delay
3118
       DELAY_NS(100);        // Ensure 100ns delay
3082
 
3119
 
3083
       // Read a big-endian temperature value without using a library
3120
       // Read a big-endian temperature value without using a library
3086
         if (i > 0) max_tc_temp <<= 8; // shift left if not the last byte
3123
         if (i > 0) max_tc_temp <<= 8; // shift left if not the last byte
3087
       }
3124
       }
3088
 
3125
 
3089
-      MAXTC_CS_WRITE(HIGH);  // disable MAXTC
3126
+      MAXTC_CS_WRITE(HIGH);  // Disable MAXTC
3090
     #else
3127
     #else
3091
       #if HAS_MAX6675_LIBRARY
3128
       #if HAS_MAX6675_LIBRARY
3092
         MAX6675 &max6675ref = THERMO_SEL(max6675_0, max6675_1);
3129
         MAX6675 &max6675ref = THERMO_SEL(max6675_0, max6675_1);
3297
   static ADCSensorState adc_sensor_state = StartupDelay;
3334
   static ADCSensorState adc_sensor_state = StartupDelay;
3298
   static uint8_t pwm_count = _BV(SOFT_PWM_SCALE);
3335
   static uint8_t pwm_count = _BV(SOFT_PWM_SCALE);
3299
 
3336
 
3300
-  // avoid multiple loads of pwm_count
3337
+  // Avoid multiple loads of pwm_count
3301
   uint8_t pwm_count_tmp = pwm_count;
3338
   uint8_t pwm_count_tmp = pwm_count;
3302
 
3339
 
3303
   #if HAS_ADC_BUTTONS
3340
   #if HAS_ADC_BUTTONS
3575
     // 5:                /  4 = 244.1406 Hz
3612
     // 5:                /  4 = 244.1406 Hz
3576
     pwm_count = pwm_count_tmp + _BV(SOFT_PWM_SCALE);
3613
     pwm_count = pwm_count_tmp + _BV(SOFT_PWM_SCALE);
3577
 
3614
 
3578
-    // increment slow_pwm_count only every 64th pwm_count,
3579
-    // i.e. yielding a PWM frequency of 16/128 Hz (8s).
3615
+    // Increment slow_pwm_count only every 64th pwm_count,
3616
+    // i.e., yielding a PWM frequency of 16/128 Hz (8s).
3580
     if (((pwm_count >> SOFT_PWM_SCALE) & 0x3F) == 0) {
3617
     if (((pwm_count >> SOFT_PWM_SCALE) & 0x3F) == 0) {
3581
       slow_pwm_count++;
3618
       slow_pwm_count++;
3582
       slow_pwm_count &= 0x7F;
3619
       slow_pwm_count &= 0x7F;
4029
 
4066
 
4030
         // Prevent a wait-forever situation if R is misused i.e. M109 R0
4067
         // Prevent a wait-forever situation if R is misused i.e. M109 R0
4031
         if (wants_to_cool) {
4068
         if (wants_to_cool) {
4032
-          // break after MIN_COOLING_SLOPE_TIME seconds
4069
+          // Break after MIN_COOLING_SLOPE_TIME seconds
4033
           // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG
4070
           // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG
4034
           if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) {
4071
           if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) {
4035
             if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG)) break;
4072
             if (old_temp - temp < float(MIN_COOLING_SLOPE_DEG)) break;
4051
         wait_for_heatup = false;
4088
         wait_for_heatup = false;
4052
         #if HAS_DWIN_E3V2_BASIC
4089
         #if HAS_DWIN_E3V2_BASIC
4053
           HMI_flag.heat_flag = 0;
4090
           HMI_flag.heat_flag = 0;
4054
-          duration_t elapsed = print_job_timer.duration();  // print timer
4091
+          duration_t elapsed = print_job_timer.duration();  // Print timer
4055
           dwin_heat_time = elapsed.value;
4092
           dwin_heat_time = elapsed.value;
4056
         #else
4093
         #else
4057
           ui.reset_status();
4094
           ui.reset_status();

+ 9
- 3
buildroot/tests/BIGTREE_GTR_V1_0 View File

32
 opt_set MOTHERBOARD BOARD_BTT_GTR_V1_0 SERIAL_PORT -1 \
32
 opt_set MOTHERBOARD BOARD_BTT_GTR_V1_0 SERIAL_PORT -1 \
33
         EXTRUDERS 3 TEMP_SENSOR_1 1 TEMP_SENSOR_2 1 \
33
         EXTRUDERS 3 TEMP_SENSOR_1 1 TEMP_SENSOR_2 1 \
34
         SERVO_DELAY '{ 300, 300, 300 }' \
34
         SERVO_DELAY '{ 300, 300, 300 }' \
35
-        SWITCHING_TOOLHEAD_X_POS '{ 215, 0 ,0 }'
36
-opt_enable SWITCHING_TOOLHEAD TOOL_SENSOR
37
-exec_test $1 $2 "BigTreeTech GTR | Switching Toolhead | Tool Sensors" "$3"
35
+        SWITCHING_TOOLHEAD_X_POS '{ 215, 0 ,0 }' \
36
+        MPC_HEATER_POWER '{ 40.0f, 40.0f, 40.0f }' \
37
+        MPC_BLOCK_HEAT_CAPACITY '{ 16.7f, 16.7f, 16.7f }' \
38
+        MPC_SENSOR_RESPONSIVENESS '{ 0.22f, 0.22f, 0.22f }' \
39
+        MPC_AMBIENT_XFER_COEFF '{ 0.068f, 0.068f, 0.068f }' \
40
+        MPC_AMBIENT_XFER_COEFF_FAN255 '{ 0.097f, 0.097f, 0.097f }'
41
+opt_enable SWITCHING_TOOLHEAD TOOL_SENSOR MPCTEMP
42
+opt_disable PIDTEMP
43
+exec_test $1 $2 "BigTreeTech GTR | MPC | Switching Toolhead | Tool Sensors" "$3"
38
 
44
 
39
 # clean up
45
 # clean up
40
 restore_configs
46
 restore_configs

+ 0
- 1
buildroot/tests/STM32F103RC_btt View File

13
 opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_E3_V1_0 SERIAL_PORT 1 SERIAL_PORT_2 -1 \
13
 opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_E3_V1_0 SERIAL_PORT 1 SERIAL_PORT_2 -1 \
14
         X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2209 Z_DRIVER_TYPE TMC2209 E0_DRIVER_TYPE TMC2209
14
         X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2209 Z_DRIVER_TYPE TMC2209 E0_DRIVER_TYPE TMC2209
15
 opt_enable PINS_DEBUGGING Z_IDLE_HEIGHT
15
 opt_enable PINS_DEBUGGING Z_IDLE_HEIGHT
16
-
17
 exec_test $1 $2 "BigTreeTech SKR Mini E3 1.0 - Basic Config with TMC2209 HW Serial" "$3"
16
 exec_test $1 $2 "BigTreeTech SKR Mini E3 1.0 - Basic Config with TMC2209 HW Serial" "$3"
18
 
17
 
19
 # clean up
18
 # clean up

+ 0
- 1
buildroot/tests/STM32F103RC_btt_maple View File

13
 opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_E3_V1_0 SERIAL_PORT 1 SERIAL_PORT_2 -1 \
13
 opt_set MOTHERBOARD BOARD_BTT_SKR_MINI_E3_V1_0 SERIAL_PORT 1 SERIAL_PORT_2 -1 \
14
         X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2209 Z_DRIVER_TYPE TMC2209 E0_DRIVER_TYPE TMC2209
14
         X_DRIVER_TYPE TMC2209 Y_DRIVER_TYPE TMC2209 Z_DRIVER_TYPE TMC2209 E0_DRIVER_TYPE TMC2209
15
 opt_enable PINS_DEBUGGING Z_IDLE_HEIGHT
15
 opt_enable PINS_DEBUGGING Z_IDLE_HEIGHT
16
-
17
 exec_test $1 $2 "BigTreeTech SKR Mini E3 1.0 - Basic Config with TMC2209 HW Serial" "$3"
16
 exec_test $1 $2 "BigTreeTech SKR Mini E3 1.0 - Basic Config with TMC2209 HW Serial" "$3"
18
 
17
 
19
 # clean up
18
 # clean up

+ 2
- 3
buildroot/tests/mega2560 View File

181
         AXIS_RELATIVE_MODES '{ false, false, false }'
181
         AXIS_RELATIVE_MODES '{ false, false, false }'
182
 opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
182
 opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
183
            LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER MEATPACK_ON_SERIAL_PORT_1
183
            LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER MEATPACK_ON_SERIAL_PORT_1
184
-
185
 exec_test $1 $2 "MEGA2560 RAMPS | Laser Feature | Air Evacuation | Air Assist | Cooler | Flowmeter | 12864 LCD | meatpack | SERIAL_PORT_2 " "$3"
184
 exec_test $1 $2 "MEGA2560 RAMPS | Laser Feature | Air Evacuation | Air Assist | Cooler | Flowmeter | 12864 LCD | meatpack | SERIAL_PORT_2 " "$3"
186
 
185
 
187
 #
186
 #
196
         AXIS_RELATIVE_MODES '{ false, false, false }'
195
         AXIS_RELATIVE_MODES '{ false, false, false }'
197
 opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
196
 opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
198
            LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER I2C_AMMETER
197
            LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER I2C_AMMETER
199
-
200
 exec_test $1 $2 "MEGA2560 RAMPS | Laser Feature | Air Evacuation | Air Assist | Cooler | Flowmeter | 44780 LCD " "$3"
198
 exec_test $1 $2 "MEGA2560 RAMPS | Laser Feature | Air Evacuation | Air Assist | Cooler | Flowmeter | 44780 LCD " "$3"
201
 
199
 
202
 #
200
 #
207
         TEMP_SENSOR_0 -2 TEMP_SENSOR_REDUNDANT -2 \
205
         TEMP_SENSOR_0 -2 TEMP_SENSOR_REDUNDANT -2 \
208
         TEMP_SENSOR_REDUNDANT_SOURCE E1 TEMP_SENSOR_REDUNDANT_TARGET E0 \
206
         TEMP_SENSOR_REDUNDANT_SOURCE E1 TEMP_SENSOR_REDUNDANT_TARGET E0 \
209
         TEMP_0_CS_PIN 11 TEMP_1_CS_PIN 12
207
         TEMP_0_CS_PIN 11 TEMP_1_CS_PIN 12
210
-
208
+opt_enable MPCTEMP
209
+opt_disable PIDTEMP
211
 exec_test $1 $2 "MEGA2560 RAMPS | Redundant temperature sensor | 2x MAX6675" "$3"
210
 exec_test $1 $2 "MEGA2560 RAMPS | Redundant temperature sensor | 2x MAX6675" "$3"
212
 
211
 
213
 #
212
 #

Loading…
Cancel
Save