Browse Source

More "zero extruders" changes (#15213)

Scott Lahteine 5 years ago
parent
commit
584c86bed1
No account linked to committer's email address

+ 22
- 16
Marlin/src/feature/power_loss_recovery.cpp View File

@@ -175,7 +175,9 @@ void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*=
175 175
       info.active_extruder = active_extruder;
176 176
     #endif
177 177
 
178
-    HOTEND_LOOP() info.target_temperature[e] = thermalManager.temp_hotend[e].target;
178
+    #if EXTRUDERS
179
+      HOTEND_LOOP() info.target_temperature[e] = thermalManager.temp_hotend[e].target;
180
+    #endif
179 181
 
180 182
     #if HAS_HEATED_BED
181 183
       info.target_temperature_bed = thermalManager.temp_bed.target;
@@ -297,17 +299,19 @@ void PrintJobRecovery::resume() {
297 299
   #endif
298 300
 
299 301
   // Restore all hotend temperatures
300
-  HOTEND_LOOP() {
301
-    const int16_t et = info.target_temperature[e];
302
-    if (et) {
303
-      #if HOTENDS > 1
304
-        sprintf_P(cmd, PSTR("T%i"), e);
302
+  #if HOTENDS
303
+    HOTEND_LOOP() {
304
+      const int16_t et = info.target_temperature[e];
305
+      if (et) {
306
+        #if HOTENDS > 1
307
+          sprintf_P(cmd, PSTR("T%i"), e);
308
+          gcode.process_subcommands_now(cmd);
309
+        #endif
310
+        sprintf_P(cmd, PSTR("M109 S%i"), et);
305 311
         gcode.process_subcommands_now(cmd);
306
-      #endif
307
-      sprintf_P(cmd, PSTR("M109 S%i"), et);
308
-      gcode.process_subcommands_now(cmd);
312
+      }
309 313
     }
310
-  }
314
+  #endif
311 315
 
312 316
   // Restore print cooling fan speeds
313 317
   FANS_LOOP(i) {
@@ -452,12 +456,14 @@ void PrintJobRecovery::resume() {
452 456
           DEBUG_ECHOLNPAIR("active_extruder: ", int(info.active_extruder));
453 457
         #endif
454 458
 
455
-        DEBUG_ECHOPGM("target_temperature: ");
456
-        HOTEND_LOOP() {
457
-          DEBUG_ECHO(info.target_temperature[e]);
458
-          if (e < HOTENDS - 1) DEBUG_CHAR(',');
459
-        }
460
-        DEBUG_EOL();
459
+        #if HOTENDS
460
+          DEBUG_ECHOPGM("target_temperature: ");
461
+          HOTEND_LOOP() {
462
+            DEBUG_ECHO(info.target_temperature[e]);
463
+            if (e < HOTENDS - 1) DEBUG_CHAR(',');
464
+          }
465
+          DEBUG_EOL();
466
+        #endif
461 467
 
462 468
         #if HAS_HEATED_BED
463 469
           DEBUG_ECHOLNPAIR("target_temperature_bed: ", info.target_temperature_bed);

+ 3
- 1
Marlin/src/feature/power_loss_recovery.h View File

@@ -59,7 +59,9 @@ typedef struct {
59 59
     uint8_t active_extruder;
60 60
   #endif
61 61
 
62
-  int16_t target_temperature[HOTENDS];
62
+  #if HOTENDS
63
+    int16_t target_temperature[HOTENDS];
64
+  #endif
63 65
 
64 66
   #if HAS_HEATED_BED
65 67
     int16_t target_temperature_bed;

+ 4
- 0
Marlin/src/gcode/config/M221.cpp View File

@@ -23,6 +23,8 @@
23 23
 #include "../gcode.h"
24 24
 #include "../../module/planner.h"
25 25
 
26
+#if EXTRUDERS
27
+
26 28
 /**
27 29
  * M221: Set extrusion percentage (M221 T0 S95)
28 30
  */
@@ -44,3 +46,5 @@ void GcodeSuite::M221() {
44 46
     SERIAL_EOL();
45 47
   }
46 48
 }
49
+
50
+#endif // EXTRUDERS

+ 19
- 12
Marlin/src/gcode/gcode.cpp View File

@@ -400,8 +400,18 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
400 400
         case 100: M100(); break;                                  // M100: Free Memory Report
401 401
       #endif
402 402
 
403
-      case 104: M104(); break;                                    // M104: Set hot end temperature
404
-      case 109: M109(); break;                                    // M109: Wait for hotend temperature to reach target
403
+      #if EXTRUDERS
404
+        case 104: M104(); break;                                  // M104: Set hot end temperature
405
+        case 109: M109(); break;                                  // M109: Wait for hotend temperature to reach target
406
+      #endif
407
+
408
+      case 105: M105(); return;                                   // M105: Report Temperatures (and say "ok")
409
+
410
+      #if FAN_COUNT > 0
411
+        case 106: M106(); break;                                  // M106: Fan On
412
+        case 107: M107(); break;                                  // M107: Fan Off
413
+      #endif
414
+
405 415
       case 110: M110(); break;                                    // M110: Set Current Line Number
406 416
       case 111: M111(); break;                                    // M111: Set debug level
407 417
 
@@ -410,7 +420,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
410 420
         case 112: M112(); break;                                  // M112: Full Shutdown
411 421
         case 410: M410(); break;                                  // M410: Quickstop - Abort all the planned moves.
412 422
         #if ENABLED(HOST_PROMPT_SUPPORT)
413
-          case 876: M876(); break;                                  // M876: Handle Host prompt responses
423
+          case 876: M876(); break;                                // M876: Handle Host prompt responses
414 424
         #endif
415 425
       #else
416 426
         case 108: case 112: case 410:
@@ -434,17 +444,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
434 444
         //case 191: M191(); break;                                // M191: Wait for chamber temperature to reach target
435 445
       #endif
436 446
 
437
-      case 105: M105(); return;                                   // M105: Report Temperatures (and say "ok")
438
-
439 447
       #if ENABLED(AUTO_REPORT_TEMPERATURES) && HAS_TEMP_SENSOR
440 448
         case 155: M155(); break;                                  // M155: Set temperature auto-report interval
441 449
       #endif
442 450
 
443
-      #if FAN_COUNT > 0
444
-        case 106: M106(); break;                                  // M106: Fan On
445
-        case 107: M107(); break;                                  // M107: Fan Off
446
-      #endif
447
-
448 451
       #if ENABLED(PARK_HEAD_ON_PAUSE)
449 452
         case 125: M125(); break;                                  // M125: Store current position and move to filament change position
450 453
       #endif
@@ -481,7 +484,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
481 484
       case 120: M120(); break;                                    // M120: Enable endstops
482 485
       case 121: M121(); break;                                    // M121: Disable endstops
483 486
 
484
-      #if HAS_LCD_MENU
487
+      #if HOTENDS && HAS_LCD_MENU
485 488
         case 145: M145(); break;                                  // M145: Set material heatup parameters
486 489
       #endif
487 490
 
@@ -553,7 +556,11 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
553 556
       #endif
554 557
 
555 558
       case 220: M220(); break;                                    // M220: Set Feedrate Percentage: S<percent> ("FR" on your LCD)
556
-      case 221: M221(); break;                                    // M221: Set Flow Percentage
559
+
560
+      #if EXTRUDERS
561
+        case 221: M221(); break;                                  // M221: Set Flow Percentage
562
+      #endif
563
+
557 564
       case 226: M226(); break;                                    // M226: Wait until a pin reaches a state
558 565
 
559 566
       #if HAS_SERVOS

+ 16
- 7
Marlin/src/gcode/gcode.h View File

@@ -543,10 +543,17 @@ private:
543 543
     static void M100();
544 544
   #endif
545 545
 
546
-  static void M104();
546
+  #if EXTRUDERS
547
+    static void M104();
548
+    static void M109();
549
+  #endif
550
+
547 551
   static void M105();
548
-  static void M106();
549
-  static void M107();
552
+
553
+  #if FAN_COUNT > 0
554
+    static void M106();
555
+    static void M107();
556
+  #endif
550 557
 
551 558
   #if DISABLED(EMERGENCY_PARSER)
552 559
     static void M108();
@@ -557,8 +564,6 @@ private:
557 564
     #endif
558 565
   #endif
559 566
 
560
-  static void M109();
561
-
562 567
   static void M110();
563 568
   static void M111();
564 569
 
@@ -599,7 +604,7 @@ private:
599 604
     //static void M191();
600 605
   #endif
601 606
 
602
-  #if HAS_LCD_MENU
607
+  #if HOTENDS && HAS_LCD_MENU
603 608
     static void M145();
604 609
   #endif
605 610
 
@@ -660,7 +665,11 @@ private:
660 665
   #endif
661 666
 
662 667
   static void M220();
663
-  static void M221();
668
+
669
+  #if EXTRUDERS
670
+    static void M221();
671
+  #endif
672
+
664 673
   static void M226();
665 674
 
666 675
   #if ENABLED(PHOTO_GCODE)

+ 2
- 2
Marlin/src/gcode/lcd/M145.cpp View File

@@ -22,7 +22,7 @@
22 22
 
23 23
 #include "../../inc/MarlinConfig.h"
24 24
 
25
-#if HAS_LCD_MENU
25
+#if HOTENDS && HAS_LCD_MENU
26 26
 
27 27
 #include "../gcode.h"
28 28
 #include "../../lcd/ultralcd.h"
@@ -58,4 +58,4 @@ void GcodeSuite::M145() {
58 58
   }
59 59
 }
60 60
 
61
-#endif // HAS_LCD_MENU
61
+#endif // HOTENDS && HAS_LCD_MENU

+ 6
- 0
Marlin/src/gcode/temperature/M104_M109.cpp View File

@@ -20,6 +20,10 @@
20 20
  *
21 21
  */
22 22
 
23
+#include "../../inc/MarlinConfigPre.h"
24
+
25
+#if EXTRUDERS
26
+
23 27
 #include "../gcode.h"
24 28
 #include "../../module/temperature.h"
25 29
 #include "../../module/motion.h"
@@ -138,3 +142,5 @@ void GcodeSuite::M109() {
138 142
   if (set_temp)
139 143
     (void)thermalManager.wait_for_hotend(target_extruder, no_wait_for_cooling);
140 144
 }
145
+
146
+#endif // EXTRUDERS

+ 28
- 0
Marlin/src/inc/Conditionals_adv.h View File

@@ -26,6 +26,34 @@
26 26
  * Defines that depend on advanced configuration.
27 27
  */
28 28
 
29
+#if EXTRUDERS == 0
30
+  #define NO_VOLUMETRICS
31
+  #undef TEMP_SENSOR_0
32
+  #undef TEMP_SENSOR_1
33
+  #undef TEMP_SENSOR_2
34
+  #undef TEMP_SENSOR_3
35
+  #undef TEMP_SENSOR_4
36
+  #undef TEMP_SENSOR_5
37
+  #undef FWRETRACT
38
+  #undef PIDTEMP
39
+  #undef AUTOTEMP
40
+  #undef PID_EXTRUSION_SCALING
41
+  #undef LIN_ADVANCE
42
+  #undef FILAMENT_RUNOUT_SENSOR
43
+  #undef ADVANCED_PAUSE_FEATURE
44
+  #undef FILAMENT_RUNOUT_DISTANCE_MM
45
+  #undef FILAMENT_LOAD_UNLOAD_GCODES
46
+  #undef DISABLE_INACTIVE_EXTRUDER
47
+  #undef FILAMENT_LOAD_UNLOAD_GCODES
48
+  #undef EXTRUDER_RUNOUT_PREVENT
49
+  #undef PREVENT_COLD_EXTRUSION
50
+  #undef PREVENT_LENGTHY_EXTRUDE
51
+  #undef THERMAL_PROTECTION_HOTENDS
52
+  #undef THERMAL_PROTECTION_PERIOD
53
+  #undef WATCH_TEMP_PERIOD
54
+  #undef SHOW_TEMP_ADC_VALUES
55
+#endif
56
+
29 57
 #define HAS_CUTTER EITHER(SPINDLE_FEATURE, LASER_FEATURE)
30 58
 
31 59
 #if !defined(__AVR__) || !defined(USBCON)

+ 4
- 10
Marlin/src/inc/Conditionals_post.h View File

@@ -43,16 +43,6 @@
43 43
   #define NOT_A_PIN 0 // For PINS_DEBUGGING
44 44
 #endif
45 45
 
46
-#if EXTRUDERS == 0
47
-  #define NO_VOLUMETRICS
48
-  #undef FWRETRACT
49
-  #undef LIN_ADVANCE
50
-  #undef ADVANCED_PAUSE_FEATURE
51
-  #undef DISABLE_INACTIVE_EXTRUDER
52
-  #undef EXTRUDER_RUNOUT_PREVENT
53
-  #undef FILAMENT_LOAD_UNLOAD_GCODES
54
-#endif
55
-
56 46
 #define HAS_CLASSIC_JERK (IS_KINEMATIC || DISABLED(JUNCTION_DEVIATION))
57 47
 
58 48
 /**
@@ -1047,6 +1037,10 @@
1047 1037
 #define BED_OR_CHAMBER (HAS_HEATED_BED || HAS_TEMP_CHAMBER)
1048 1038
 #define HAS_TEMP_SENSOR (HAS_TEMP_HOTEND || BED_OR_CHAMBER)
1049 1039
 
1040
+#if !HAS_TEMP_SENSOR
1041
+  #undef AUTO_REPORT_TEMPERATURES
1042
+#endif
1043
+
1050 1044
 // PID heating
1051 1045
 #if !HAS_HEATED_BED
1052 1046
   #undef PIDTEMPBED

+ 2
- 2
Marlin/src/inc/SanityCheck.h View File

@@ -1476,8 +1476,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
1476 1476
   #error "E0_STEP_PIN or E0_DIR_PIN not defined for this board."
1477 1477
 #elif ( !(defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && (!PIN_EXISTS(E0_STEP, E0_DIR) || !HAS_E0_ENABLE))
1478 1478
   #error "E0_STEP_PIN, E0_DIR_PIN, or E0_ENABLE_PIN not defined for this board."
1479
-#elif TEMP_SENSOR_0 == 0
1480
-  #error "TEMP_SENSOR_0 is required."
1479
+#elif EXTRUDERS && TEMP_SENSOR_0 == 0
1480
+  #error "TEMP_SENSOR_0 is required with any extruders."
1481 1481
 #endif
1482 1482
 
1483 1483
 // Pins are required for heaters

+ 9
- 3
Marlin/src/lcd/HD44780/ultralcd_HD44780.cpp View File

@@ -866,7 +866,11 @@ void MarlinUI::draw_status_screen() {
866 866
           char c;
867 867
           uint16_t per;
868 868
           #if HAS_FAN0
869
-            if (blink || thermalManager.fan_speed_scaler[0] < 128) {
869
+            if (true
870
+              #if EXTRUDERS
871
+                && (blink || thermalManager.fan_speed_scaler[0] < 128)
872
+              #endif
873
+            ) {
870 874
               uint16_t spd = thermalManager.fan_speed[0];
871 875
               if (blink) c = 'F';
872 876
               #if ENABLED(ADAPTIVE_FAN_SLOWING)
@@ -877,8 +881,10 @@ void MarlinUI::draw_status_screen() {
877 881
             else
878 882
           #endif
879 883
             {
880
-              c = 'E';
881
-              per = planner.flow_percentage[0];
884
+              #if EXTRUDERS
885
+                c = 'E';
886
+                per = planner.flow_percentage[0];
887
+              #endif
882 888
             }
883 889
           lcd_put_wchar(c);
884 890
           lcd_put_u8str(i16tostr3(per));

+ 121
- 98
Marlin/src/lcd/dogm/dogm_Statusscreen.h View File

@@ -69,10 +69,28 @@
69 69
     //
70 70
     #if HAS_HEATED_BED && HOTENDS <= 4
71 71
 
72
-      #if HOTENDS == 1
72
+      #if HOTENDS == 0
73
+
74
+        #define STATUS_HEATERS_WIDTH 96
75
+
76
+        const unsigned char status_heaters_bmp[] PROGMEM = {
77
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000,
78
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000,
79
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000,
80
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000,
81
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000,
82
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000,
83
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000,
84
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000,
85
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000,
86
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
87
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000,
88
+          B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000
89
+        };
90
+
91
+      #elif HOTENDS == 1
73 92
 
74 93
         #define STATUS_HEATERS_WIDTH 96
75
-        #define STATUS_BED_TEXT_X   (STATUS_HEATERS_WIDTH - 10)
76 94
 
77 95
         const unsigned char status_heaters_bmp[] PROGMEM = {
78 96
           B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000,
@@ -92,7 +110,6 @@
92 110
       #elif HOTENDS == 2
93 111
 
94 112
         #define STATUS_HEATERS_WIDTH 96
95
-        #define STATUS_BED_TEXT_X   (STATUS_HEATERS_WIDTH - 10)
96 113
 
97 114
         const unsigned char status_heaters_bmp[] PROGMEM = {
98 115
           B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000,
@@ -112,7 +129,6 @@
112 129
       #elif HOTENDS == 3
113 130
 
114 131
         #define STATUS_HEATERS_WIDTH 96
115
-        #define STATUS_BED_TEXT_X   (STATUS_HEATERS_WIDTH - 10)
116 132
 
117 133
         const unsigned char status_heaters_bmp[] PROGMEM = {
118 134
           B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000100,B00010000,B01000000,
@@ -132,7 +148,6 @@
132 148
       #else // HOTENDS > 3
133 149
 
134 150
         #define STATUS_HEATERS_WIDTH 120
135
-        #define STATUS_BED_TEXT_X   (STATUS_HEATERS_WIDTH - 10)
136 151
 
137 152
         const unsigned char status_heaters_bmp[] PROGMEM = {
138 153
           B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000100,B00010000,B01000000,
@@ -151,9 +166,15 @@
151 166
 
152 167
       #endif // HOTENDS
153 168
 
169
+      #define STATUS_BED_TEXT_X (STATUS_HEATERS_WIDTH - 10)
170
+
154 171
     #else // !HAS_HEATED_BED || HOTENDS > 3
155 172
 
156
-      #if HOTENDS == 1
173
+      #if HOTENDS == 0
174
+
175
+        #define STATUS_HEATERS_WIDTH  0
176
+
177
+      #elif HOTENDS == 1
157 178
 
158 179
         #define STATUS_HEATERS_WIDTH  12
159 180
 
@@ -229,7 +250,7 @@
229 250
           B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000
230 251
         };
231 252
 
232
-      #elif HOTENDS > 4
253
+      #else // HOTENDS > 4
233 254
 
234 255
         #define STATUS_HEATERS_WIDTH  108
235 256
 
@@ -304,105 +325,101 @@
304 325
 
305 326
         #endif
306 327
 
307
-      #else
308
-
309
-        #if HOTENDS >= 2
310
-
311
-          #ifdef STATUS_HOTEND_ANIM
328
+      #elif HOTENDS >= 2
312 329
 
313
-            const unsigned char status_hotend1_a_bmp[] PROGMEM = {
314
-              B00011111,B11100000,
315
-              B00111111,B11110000,
316
-              B00111110,B11110000,
317
-              B00111100,B11110000,
318
-              B00011010,B11100000,
319
-              B00011110,B11100000,
320
-              B00111110,B11110000,
321
-              B00111110,B11110000,
322
-              B00111110,B11110000,
323
-              B00001111,B11000000,
324
-              B00000111,B10000000,
325
-              B00000011,B00000000
326
-            };
330
+        #ifdef STATUS_HOTEND_ANIM
327 331
 
328
-            const unsigned char status_hotend1_b_bmp[] PROGMEM = {
329
-              B00011111,B11100000,
330
-              B00100000,B00010000,
331
-              B00100001,B00010000,
332
-              B00100011,B00010000,
333
-              B00010101,B00100000,
334
-              B00010001,B00100000,
335
-              B00100001,B00010000,
336
-              B00100001,B00010000,
337
-              B00110001,B00110000,
338
-              B00001000,B01000000,
339
-              B00000100,B10000000,
340
-              B00000011,B00000000
341
-            };
332
+          const unsigned char status_hotend1_a_bmp[] PROGMEM = {
333
+            B00011111,B11100000,
334
+            B00111111,B11110000,
335
+            B00111110,B11110000,
336
+            B00111100,B11110000,
337
+            B00011010,B11100000,
338
+            B00011110,B11100000,
339
+            B00111110,B11110000,
340
+            B00111110,B11110000,
341
+            B00111110,B11110000,
342
+            B00001111,B11000000,
343
+            B00000111,B10000000,
344
+            B00000011,B00000000
345
+          };
342 346
 
343
-            const unsigned char status_hotend2_a_bmp[] PROGMEM = {
344
-              B00011111,B11100000,
345
-              B00111111,B11110000,
346
-              B00111100,B11110000,
347
-              B00111011,B01110000,
348
-              B00011111,B01100000,
349
-              B00011110,B11100000,
350
-              B00111101,B11110000,
351
-              B00111011,B11110000,
352
-              B00111000,B01110000,
353
-              B00001111,B11000000,
354
-              B00000111,B10000000,
355
-              B00000011,B00000000
356
-            };
347
+          const unsigned char status_hotend1_b_bmp[] PROGMEM = {
348
+            B00011111,B11100000,
349
+            B00100000,B00010000,
350
+            B00100001,B00010000,
351
+            B00100011,B00010000,
352
+            B00010101,B00100000,
353
+            B00010001,B00100000,
354
+            B00100001,B00010000,
355
+            B00100001,B00010000,
356
+            B00110001,B00110000,
357
+            B00001000,B01000000,
358
+            B00000100,B10000000,
359
+            B00000011,B00000000
360
+          };
357 361
 
358
-            const unsigned char status_hotend2_b_bmp[] PROGMEM = {
359
-              B00011111,B11100000,
360
-              B00100000,B00010000,
361
-              B00100011,B00010000,
362
-              B00100100,B10010000,
363
-              B00010000,B10100000,
364
-              B00010001,B00100000,
365
-              B00100010,B00010000,
366
-              B00100100,B00010000,
367
-              B00110111,B10110000,
368
-              B00001000,B01000000,
369
-              B00000100,B10000000,
370
-              B00000011,B00000000
371
-            };
362
+          const unsigned char status_hotend2_a_bmp[] PROGMEM = {
363
+            B00011111,B11100000,
364
+            B00111111,B11110000,
365
+            B00111100,B11110000,
366
+            B00111011,B01110000,
367
+            B00011111,B01100000,
368
+            B00011110,B11100000,
369
+            B00111101,B11110000,
370
+            B00111011,B11110000,
371
+            B00111000,B01110000,
372
+            B00001111,B11000000,
373
+            B00000111,B10000000,
374
+            B00000011,B00000000
375
+          };
372 376
 
373
-          #else
377
+          const unsigned char status_hotend2_b_bmp[] PROGMEM = {
378
+            B00011111,B11100000,
379
+            B00100000,B00010000,
380
+            B00100011,B00010000,
381
+            B00100100,B10010000,
382
+            B00010000,B10100000,
383
+            B00010001,B00100000,
384
+            B00100010,B00010000,
385
+            B00100100,B00010000,
386
+            B00110111,B10110000,
387
+            B00001000,B01000000,
388
+            B00000100,B10000000,
389
+            B00000011,B00000000
390
+          };
374 391
 
375
-            const unsigned char status_hotend1_a_bmp[] PROGMEM = {
376
-              B00011111,B11100000,
377
-              B00111110,B11110000,
378
-              B00111100,B11110000,
379
-              B00111010,B11110000,
380
-              B00011110,B11100000,
381
-              B00011110,B11100000,
382
-              B00111110,B11110000,
383
-              B00111110,B11110000,
384
-              B00111111,B11110000,
385
-              B00001111,B11000000,
386
-              B00000111,B10000000,
387
-              B00000011,B00000000
388
-            };
392
+        #else
389 393
 
390
-            const unsigned char status_hotend2_a_bmp[] PROGMEM = {
391
-              B00011111,B11100000,
392
-              B00111100,B11110000,
393
-              B00111011,B01110000,
394
-              B00111111,B01110000,
395
-              B00011110,B11100000,
396
-              B00011101,B11100000,
397
-              B00111011,B11110000,
398
-              B00111000,B01110000,
399
-              B00111111,B11110000,
400
-              B00001111,B11000000,
401
-              B00000111,B10000000,
402
-              B00000011,B00000000
403
-            };
394
+          const unsigned char status_hotend1_a_bmp[] PROGMEM = {
395
+            B00011111,B11100000,
396
+            B00111110,B11110000,
397
+            B00111100,B11110000,
398
+            B00111010,B11110000,
399
+            B00011110,B11100000,
400
+            B00011110,B11100000,
401
+            B00111110,B11110000,
402
+            B00111110,B11110000,
403
+            B00111111,B11110000,
404
+            B00001111,B11000000,
405
+            B00000111,B10000000,
406
+            B00000011,B00000000
407
+          };
404 408
 
405
-          #endif
409
+          const unsigned char status_hotend2_a_bmp[] PROGMEM = {
410
+            B00011111,B11100000,
411
+            B00111100,B11110000,
412
+            B00111011,B01110000,
413
+            B00111111,B01110000,
414
+            B00011110,B11100000,
415
+            B00011101,B11100000,
416
+            B00111011,B11110000,
417
+            B00111000,B01110000,
418
+            B00111111,B11110000,
419
+            B00001111,B11000000,
420
+            B00000111,B10000000,
421
+            B00000011,B00000000
422
+          };
406 423
 
407 424
         #endif
408 425
 
@@ -573,6 +590,8 @@
573 590
 
574 591
       #endif
575 592
 
593
+    #else
594
+      #define STATUS_HEATERS_HEIGHT 20
576 595
     #endif
577 596
 
578 597
   #endif
@@ -1431,6 +1450,10 @@
1431 1450
     "Status heaters bitmap (status_heaters_bmp) dimensions don't match data."
1432 1451
   );
1433 1452
 
1453
+#else // HOTENDS == 0
1454
+
1455
+  //#error "Incomplete status header"
1456
+
1434 1457
 #endif
1435 1458
 
1436 1459
 //

+ 13
- 3
Marlin/src/lcd/dogm/status_screen_DOGM.cpp View File

@@ -93,7 +93,10 @@
93 93
   #define CHAMBER_ALT() false
94 94
 #endif
95 95
 
96
-#define MAX_HOTEND_DRAW _MIN(HOTENDS, ((LCD_PIXEL_WIDTH - (STATUS_LOGO_BYTEWIDTH + STATUS_FAN_BYTEWIDTH) * 8) / (STATUS_HEATERS_XSPACE)))
96
+#if HOTENDS
97
+  #define MAX_HOTEND_DRAW _MIN(HOTENDS, ((LCD_PIXEL_WIDTH - (STATUS_LOGO_BYTEWIDTH + STATUS_FAN_BYTEWIDTH) * 8) / (STATUS_HEATERS_XSPACE)))
98
+#endif
99
+
97 100
 #define STATUS_HEATERS_BOT (STATUS_HEATERS_Y + STATUS_HEATERS_HEIGHT - 1)
98 101
 
99 102
 #if ENABLED(MARLIN_DEV_MODE)
@@ -127,6 +130,11 @@ FORCE_INLINE void _draw_heater_status(const heater_ind_t heater, const bool blin
127 130
     const bool isHeat = IFBED(BED_ALT(), HOTEND_ALT(heater));
128 131
   #endif
129 132
 
133
+  #ifndef STATUS_HOTEND_TEXT_X
134
+    #define STATUS_HOTEND_TEXT_X(N) 0
135
+    #define STATUS_HEATERS_Y 0
136
+  #endif
137
+
130 138
   const uint8_t tx = IFBED(STATUS_BED_TEXT_X, STATUS_HOTEND_TEXT_X(heater));
131 139
 
132 140
   #if ENABLED(MARLIN_DEV_MODE)
@@ -424,8 +432,10 @@ void MarlinUI::draw_status_screen() {
424 432
   //
425 433
   if (PAGE_UNDER(6 + 1 + 12 + 1 + 6 + 1)) {
426 434
     // Extruders
427
-    for (uint8_t e = 0; e < MAX_HOTEND_DRAW; ++e)
428
-      _draw_heater_status((heater_ind_t)e, blink);
435
+    #if HOTENDS
436
+      for (uint8_t e = 0; e < MAX_HOTEND_DRAW; ++e)
437
+        _draw_heater_status((heater_ind_t)e, blink);
438
+    #endif
429 439
 
430 440
     // Heated bed
431 441
     #if DO_DRAW_BED && DISABLED(STATUS_COMBINE_HEATERS) || (HAS_HEATED_BED && ENABLED(STATUS_COMBINE_HEATERS) && HOTENDS <= 4)

+ 18
- 14
Marlin/src/lcd/extensible_ui/lib/dgus/DGUSDisplay.cpp View File

@@ -497,21 +497,25 @@ void DGUSScreenVariableHandler::HandleTemperatureChanged(DGUS_VP_Variable &var,
497 497
 }
498 498
 
499 499
 void DGUSScreenVariableHandler::HandleFlowRateChanged(DGUS_VP_Variable &var, void *val_ptr) {
500
-  uint16_t newvalue = swap16(*(uint16_t*)val_ptr);
501
-  uint8_t target_extruder;
502
-  switch (var.VP) {
503
-    default: return;
504
-    #if (HOTENDS >= 1)
505
-      case VP_Flowrate_E1: target_extruder = 0; break;
506
-    #endif
507
-    #if (HOTENDS >= 2)
508
-      case VP_Flowrate_E2: target_extruder = 1; break;
509
-    #endif
510
-  }
500
+  #if EXTRUDERS
501
+    uint16_t newvalue = swap16(*(uint16_t*)val_ptr);
502
+    uint8_t target_extruder;
503
+    switch (var.VP) {
504
+      default: return;
505
+      #if (HOTENDS >= 1)
506
+        case VP_Flowrate_E1: target_extruder = 0; break;
507
+      #endif
508
+      #if (HOTENDS >= 2)
509
+        case VP_Flowrate_E2: target_extruder = 1; break;
510
+      #endif
511
+    }
511 512
 
512
-  planner.flow_percentage[target_extruder] = newvalue;
513
-  planner.refresh_e_factor(target_extruder);
514
-  ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
513
+    planner.flow_percentage[target_extruder] = newvalue;
514
+    planner.refresh_e_factor(target_extruder);
515
+    ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
516
+  #else
517
+    UNUSED(var); UNUSED(val_ptr);
518
+  #endif
515 519
 }
516 520
 
517 521
 void DGUSScreenVariableHandler::HandleManualExtrude(DGUS_VP_Variable &var, void *val_ptr) {

+ 26
- 11
Marlin/src/lcd/extensible_ui/ui_api.cpp View File

@@ -168,7 +168,7 @@ namespace ExtUI {
168 168
   }
169 169
 
170 170
   void enableHeater(const extruder_t extruder) {
171
-    #if HEATER_IDLE_HANDLER
171
+    #if HOTENDS && HEATER_IDLE_HANDLER
172 172
       thermalManager.reset_heater_idle_timer(extruder - E0);
173 173
     #endif
174 174
   }
@@ -184,14 +184,18 @@ namespace ExtUI {
184 184
         #if HAS_HEATED_CHAMBER
185 185
           case CHAMBER: return; // Chamber has no idle timer
186 186
         #endif
187
-        default: thermalManager.reset_heater_idle_timer(heater - H0);
187
+        default:
188
+          #if HOTENDS
189
+            thermalManager.reset_heater_idle_timer(heater - H0);
190
+          #endif
191
+          break;
188 192
       }
189 193
     #endif
190 194
   }
191 195
 
192 196
   bool isHeaterIdle(const extruder_t extruder) {
193 197
     return false
194
-      #if HEATER_IDLE_HANDLER
198
+      #if HOTENDS && HEATER_IDLE_HANDLER
195 199
         || thermalManager.hotend_idle[extruder - E0].timed_out
196 200
       #endif
197 201
     ;
@@ -206,7 +210,12 @@ namespace ExtUI {
206 210
         #if HAS_HEATED_CHAMBER
207 211
           case CHAMBER: return false; // Chamber has no idle timer
208 212
         #endif
209
-        default: return thermalManager.hotend_idle[heater - H0].timed_out;
213
+        default:
214
+          #if HOTENDS
215
+            return thermalManager.hotend_idle[heater - H0].timed_out;
216
+          #else
217
+            return false;
218
+          #endif
210 219
       }
211 220
     #else
212 221
       return false;
@@ -841,22 +850,28 @@ namespace ExtUI {
841 850
   }
842 851
 
843 852
   void setTargetTemp_celsius(float value, const heater_t heater) {
844
-    constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP);
845
-    const int16_t e = heater - H0;
846 853
     enableHeater(heater);
847 854
     #if HAS_HEATED_BED
848 855
       if (heater == BED)
849 856
         thermalManager.setTargetBed(clamp(value, 0, BED_MAXTEMP - 10));
850 857
       else
851 858
     #endif
852
-        thermalManager.setTargetHotend(clamp(value, 0, heater_maxtemp[e] - 15), e);
859
+      {
860
+        #if HOTENDS
861
+          static constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP);
862
+          const int16_t e = heater - H0;
863
+          thermalManager.setTargetHotend(clamp(value, 0, heater_maxtemp[e] - 15), e);
864
+        #endif
865
+      }
853 866
   }
854 867
 
855 868
   void setTargetTemp_celsius(float value, const extruder_t extruder) {
856
-    constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP);
857
-    const int16_t e = extruder - E0;
858
-    enableHeater(extruder);
859
-    thermalManager.setTargetHotend(clamp(value, 0, heater_maxtemp[e] - 15), e);
869
+    #if HOTENDS
870
+      constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP);
871
+      const int16_t e = extruder - E0;
872
+      enableHeater(extruder);
873
+      thermalManager.setTargetHotend(clamp(value, 0, heater_maxtemp[e] - 15), e);
874
+    #endif
860 875
   }
861 876
 
862 877
   void setTargetFan_percent(const float value, const fan_t fan) {

+ 3
- 1
Marlin/src/lcd/menu/menu.h View File

@@ -30,7 +30,9 @@
30 30
 extern int8_t encoderLine, encoderTopLine, screen_items;
31 31
 extern bool screen_changed;
32 32
 
33
-constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP);
33
+#if HOTENDS
34
+  constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP);
35
+#endif
34 36
 
35 37
 void scroll_screen(const uint8_t limit, const bool is_menu);
36 38
 bool printer_busy();

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

@@ -43,7 +43,7 @@
43 43
   #include "../../module/temperature.h"
44 44
 #endif
45 45
 
46
-#ifdef FILAMENT_RUNOUT_DISTANCE_MM
46
+#if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM
47 47
   #include "../../feature/runout.h"
48 48
   float lcd_runout_distance_mm;
49 49
 #endif
@@ -178,7 +178,7 @@ void menu_backlash();
178 178
 
179 179
       #if EXTRUDERS == 1
180 180
         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_UNLOAD, &fc_settings[0].unload_length, 0, extrude_maxlength);
181
-      #else // EXTRUDERS > 1
181
+      #elif EXTRUDERS > 1
182 182
         #define EDIT_FIL_UNLOAD(N) MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_UNLOAD MSG_DIAM_E##N, &fc_settings[N-1].unload_length, 0, extrude_maxlength)
183 183
         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_UNLOAD, &fc_settings[active_extruder].unload_length, 0, extrude_maxlength);
184 184
         EDIT_FIL_UNLOAD(1);
@@ -199,7 +199,7 @@ void menu_backlash();
199 199
 
200 200
       #if EXTRUDERS == 1
201 201
         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_LOAD, &fc_settings[0].load_length, 0, extrude_maxlength);
202
-      #else // EXTRUDERS > 1
202
+      #elif EXTRUDERS > 1
203 203
         #define EDIT_FIL_LOAD(N) MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_LOAD MSG_DIAM_E##N, &fc_settings[N-1].load_length, 0, extrude_maxlength)
204 204
         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_LOAD, &fc_settings[active_extruder].load_length, 0, extrude_maxlength);
205 205
         EDIT_FIL_LOAD(1);
@@ -219,7 +219,7 @@ void menu_backlash();
219 219
       #endif // EXTRUDERS > 1
220 220
     #endif
221 221
 
222
-    #ifdef FILAMENT_RUNOUT_DISTANCE_MM
222
+    #if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM
223 223
       MENU_ITEM_EDIT_CALLBACK(float3, MSG_RUNOUT_DISTANCE_MM, &lcd_runout_distance_mm, 1, 30, []{
224 224
         runout.set_runout_distance(lcd_runout_distance_mm);
225 225
       });
@@ -620,7 +620,7 @@ void menu_backlash();
620 620
 #endif // !SLIM_LCD_MENUS
621 621
 
622 622
 void menu_advanced_settings() {
623
-  #ifdef FILAMENT_RUNOUT_DISTANCE_MM
623
+  #if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM
624 624
     lcd_runout_distance_mm = runout.runout_distance();
625 625
   #endif
626 626
   START_MENU();

+ 127
- 115
Marlin/src/lcd/menu/menu_motion.cpp View File

@@ -158,80 +158,85 @@ static void _lcd_move_xyz(PGM_P name, AxisEnum axis) {
158 158
 void lcd_move_x() { _lcd_move_xyz(PSTR(MSG_MOVE_X), X_AXIS); }
159 159
 void lcd_move_y() { _lcd_move_xyz(PSTR(MSG_MOVE_Y), Y_AXIS); }
160 160
 void lcd_move_z() { _lcd_move_xyz(PSTR(MSG_MOVE_Z), Z_AXIS); }
161
-static void _lcd_move_e(
162
-  #if E_MANUAL > 1
163
-    const int8_t eindex=-1
164
-  #endif
165
-) {
166
-  if (ui.use_click()) return ui.goto_previous_screen_no_defer();
167
-  if (ui.encoderPosition) {
168
-    if (!ui.processing_manual_move) {
169
-      const float diff = float(int16_t(ui.encoderPosition)) * move_menu_scale;
170
-      #if IS_KINEMATIC
171
-        manual_move_offset += diff;
161
+
162
+#if E_MANUAL
163
+
164
+  static void _lcd_move_e(
165
+    #if E_MANUAL > 1
166
+      const int8_t eindex=-1
167
+    #endif
168
+  ) {
169
+    if (ui.use_click()) return ui.goto_previous_screen_no_defer();
170
+    if (ui.encoderPosition) {
171
+      if (!ui.processing_manual_move) {
172
+        const float diff = float(int16_t(ui.encoderPosition)) * move_menu_scale;
173
+        #if IS_KINEMATIC
174
+          manual_move_offset += diff;
175
+        #else
176
+          current_position[E_AXIS] += diff;
177
+        #endif
178
+        manual_move_to_current(E_AXIS
179
+          #if E_MANUAL > 1
180
+            , eindex
181
+          #endif
182
+        );
183
+        ui.refresh(LCDVIEW_REDRAW_NOW);
184
+      }
185
+      ui.encoderPosition = 0;
186
+    }
187
+    if (ui.should_draw()) {
188
+      PGM_P pos_label;
189
+      #if E_MANUAL == 1
190
+        pos_label = PSTR(MSG_MOVE_E);
172 191
       #else
173
-        current_position[E_AXIS] += diff;
174
-      #endif
175
-      manual_move_to_current(E_AXIS
176
-        #if E_MANUAL > 1
177
-          , eindex
192
+        switch (eindex) {
193
+          default: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E1); break;
194
+          case 1: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E2); break;
195
+          #if E_MANUAL > 2
196
+            case 2: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E3); break;
197
+            #if E_MANUAL > 3
198
+              case 3: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E4); break;
199
+              #if E_MANUAL > 4
200
+                case 4: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E5); break;
201
+                #if E_MANUAL > 5
202
+                  case 5: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E6); break;
203
+                #endif // E_MANUAL > 5
204
+              #endif // E_MANUAL > 4
205
+            #endif // E_MANUAL > 3
206
+          #endif // E_MANUAL > 2
207
+        }
208
+      #endif // E_MANUAL > 1
209
+
210
+      draw_edit_screen(pos_label, ftostr41sign(current_position[E_AXIS]
211
+        #if IS_KINEMATIC
212
+          + manual_move_offset
213
+        #endif
214
+        #if ENABLED(MANUAL_E_MOVES_RELATIVE)
215
+          - manual_move_e_origin
178 216
         #endif
179
-      );
180
-      ui.refresh(LCDVIEW_REDRAW_NOW);
217
+      ));
181 218
     }
182
-    ui.encoderPosition = 0;
183
-  }
184
-  if (ui.should_draw()) {
185
-    PGM_P pos_label;
186
-    #if E_MANUAL == 1
187
-      pos_label = PSTR(MSG_MOVE_E);
188
-    #else
189
-      switch (eindex) {
190
-        default: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E1); break;
191
-        case 1: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E2); break;
192
-        #if E_MANUAL > 2
193
-          case 2: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E3); break;
194
-          #if E_MANUAL > 3
195
-            case 3: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E4); break;
196
-            #if E_MANUAL > 4
197
-              case 4: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E5); break;
198
-              #if E_MANUAL > 5
199
-                case 5: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E6); break;
200
-              #endif // E_MANUAL > 5
201
-            #endif // E_MANUAL > 4
202
-          #endif // E_MANUAL > 3
203
-        #endif // E_MANUAL > 2
204
-      }
205
-    #endif // E_MANUAL > 1
206
-
207
-    draw_edit_screen(pos_label, ftostr41sign(current_position[E_AXIS]
208
-      #if IS_KINEMATIC
209
-        + manual_move_offset
210
-      #endif
211
-      #if ENABLED(MANUAL_E_MOVES_RELATIVE)
212
-        - manual_move_e_origin
213
-      #endif
214
-    ));
215 219
   }
216
-}
217 220
 
218
-inline void lcd_move_e() { _lcd_move_e(); }
219
-#if E_MANUAL > 1
220
-  inline void lcd_move_e0() { _lcd_move_e(0); }
221
-  inline void lcd_move_e1() { _lcd_move_e(1); }
222
-  #if E_MANUAL > 2
223
-    inline void lcd_move_e2() { _lcd_move_e(2); }
224
-    #if E_MANUAL > 3
225
-      inline void lcd_move_e3() { _lcd_move_e(3); }
226
-      #if E_MANUAL > 4
227
-        inline void lcd_move_e4() { _lcd_move_e(4); }
228
-        #if E_MANUAL > 5
229
-          inline void lcd_move_e5() { _lcd_move_e(5); }
230
-        #endif // E_MANUAL > 5
231
-      #endif // E_MANUAL > 4
232
-    #endif // E_MANUAL > 3
233
-  #endif // E_MANUAL > 2
234
-#endif // E_MANUAL > 1
221
+  inline void lcd_move_e() { _lcd_move_e(); }
222
+  #if E_MANUAL > 1
223
+    inline void lcd_move_e0() { _lcd_move_e(0); }
224
+    inline void lcd_move_e1() { _lcd_move_e(1); }
225
+    #if E_MANUAL > 2
226
+      inline void lcd_move_e2() { _lcd_move_e(2); }
227
+      #if E_MANUAL > 3
228
+        inline void lcd_move_e3() { _lcd_move_e(3); }
229
+        #if E_MANUAL > 4
230
+          inline void lcd_move_e4() { _lcd_move_e(4); }
231
+          #if E_MANUAL > 5
232
+            inline void lcd_move_e5() { _lcd_move_e(5); }
233
+          #endif // E_MANUAL > 5
234
+        #endif // E_MANUAL > 4
235
+      #endif // E_MANUAL > 3
236
+    #endif // E_MANUAL > 2
237
+  #endif // E_MANUAL > 1
238
+
239
+#endif // E_MANUAL
235 240
 
236 241
 //
237 242
 // "Motion" > "Move Xmm" > "Move XYZ" submenu
@@ -295,23 +300,26 @@ void _menu_move_distance(const AxisEnum axis, const screenFunc_t func, const int
295 300
 void lcd_move_get_x_amount() { _menu_move_distance(X_AXIS, lcd_move_x); }
296 301
 void lcd_move_get_y_amount() { _menu_move_distance(Y_AXIS, lcd_move_y); }
297 302
 void lcd_move_get_z_amount() { _menu_move_distance(Z_AXIS, lcd_move_z); }
298
-void lcd_move_get_e_amount() { _menu_move_distance(E_AXIS, lcd_move_e, -1); }
299
-#if E_MANUAL > 1
300
-  void lcd_move_get_e0_amount()     { _menu_move_distance(E_AXIS, lcd_move_e0, 0); }
301
-  void lcd_move_get_e1_amount()     { _menu_move_distance(E_AXIS, lcd_move_e1, 1); }
302
-  #if E_MANUAL > 2
303
-    void lcd_move_get_e2_amount()   { _menu_move_distance(E_AXIS, lcd_move_e2, 2); }
304
-    #if E_MANUAL > 3
305
-      void lcd_move_get_e3_amount() { _menu_move_distance(E_AXIS, lcd_move_e3, 3); }
306
-      #if E_MANUAL > 4
307
-        void lcd_move_get_e4_amount() { _menu_move_distance(E_AXIS, lcd_move_e4, 4); }
308
-        #if E_MANUAL > 5
309
-          void lcd_move_get_e5_amount() { _menu_move_distance(E_AXIS, lcd_move_e5, 5); }
310
-        #endif // E_MANUAL > 5
311
-      #endif // E_MANUAL > 4
312
-    #endif // E_MANUAL > 3
313
-  #endif // E_MANUAL > 2
314
-#endif // E_MANUAL > 1
303
+
304
+#if E_MANUAL
305
+  void lcd_move_get_e_amount() { _menu_move_distance(E_AXIS, lcd_move_e, -1); }
306
+  #if E_MANUAL > 1
307
+    void lcd_move_get_e0_amount()     { _menu_move_distance(E_AXIS, lcd_move_e0, 0); }
308
+    void lcd_move_get_e1_amount()     { _menu_move_distance(E_AXIS, lcd_move_e1, 1); }
309
+    #if E_MANUAL > 2
310
+      void lcd_move_get_e2_amount()   { _menu_move_distance(E_AXIS, lcd_move_e2, 2); }
311
+      #if E_MANUAL > 3
312
+        void lcd_move_get_e3_amount() { _menu_move_distance(E_AXIS, lcd_move_e3, 3); }
313
+        #if E_MANUAL > 4
314
+          void lcd_move_get_e4_amount() { _menu_move_distance(E_AXIS, lcd_move_e4, 4); }
315
+          #if E_MANUAL > 5
316
+            void lcd_move_get_e5_amount() { _menu_move_distance(E_AXIS, lcd_move_e5, 5); }
317
+          #endif // E_MANUAL > 5
318
+        #endif // E_MANUAL > 4
319
+      #endif // E_MANUAL > 3
320
+    #endif // E_MANUAL > 2
321
+  #endif // E_MANUAL > 1
322
+#endif // E_MANUAL
315 323
 
316 324
 #if ENABLED(DELTA)
317 325
   void lcd_lower_z_to_clip_height() {
@@ -396,39 +404,43 @@ void menu_move() {
396 404
 
397 405
   #endif
398 406
 
399
-  #if EITHER(SWITCHING_EXTRUDER, SWITCHING_NOZZLE)
407
+  #if E_MANUAL
400 408
 
401
-    // Only the current...
402
-    MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_get_e_amount);
403
-    // ...and the non-switching
404
-    #if E_MANUAL == 5
405
-      MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E5, lcd_move_get_e4_amount);
406
-    #elif E_MANUAL == 3
407
-      MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E3, lcd_move_get_e2_amount);
408
-    #endif
409
+    #if EITHER(SWITCHING_EXTRUDER, SWITCHING_NOZZLE)
409 410
 
410
-  #else
411
-
412
-    // Independent extruders with one E-stepper per hotend
413
-    MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_get_e_amount);
414
-    #if E_MANUAL > 1
415
-      MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E1, lcd_move_get_e0_amount);
416
-      MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E2, lcd_move_get_e1_amount);
417
-      #if E_MANUAL > 2
411
+      // Only the current...
412
+      MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_get_e_amount);
413
+      // ...and the non-switching
414
+      #if E_MANUAL == 5
415
+        MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E5, lcd_move_get_e4_amount);
416
+      #elif E_MANUAL == 3
418 417
         MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E3, lcd_move_get_e2_amount);
419
-        #if E_MANUAL > 3
420
-          MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E4, lcd_move_get_e3_amount);
421
-          #if E_MANUAL > 4
422
-            MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E5, lcd_move_get_e4_amount);
423
-            #if E_MANUAL > 5
424
-              MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E6, lcd_move_get_e5_amount);
425
-            #endif // E_MANUAL > 5
426
-          #endif // E_MANUAL > 4
427
-        #endif // E_MANUAL > 3
428
-      #endif // E_MANUAL > 2
429
-    #endif // E_MANUAL > 1
418
+      #endif
430 419
 
431
-  #endif
420
+    #else
421
+
422
+      // Independent extruders with one E-stepper per hotend
423
+      MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_get_e_amount);
424
+      #if E_MANUAL > 1
425
+        MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E1, lcd_move_get_e0_amount);
426
+        MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E2, lcd_move_get_e1_amount);
427
+        #if E_MANUAL > 2
428
+          MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E3, lcd_move_get_e2_amount);
429
+          #if E_MANUAL > 3
430
+            MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E4, lcd_move_get_e3_amount);
431
+            #if E_MANUAL > 4
432
+              MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E5, lcd_move_get_e4_amount);
433
+              #if E_MANUAL > 5
434
+                MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E6, lcd_move_get_e5_amount);
435
+              #endif // E_MANUAL > 5
436
+            #endif // E_MANUAL > 4
437
+          #endif // E_MANUAL > 3
438
+        #endif // E_MANUAL > 2
439
+      #endif // E_MANUAL > 1
440
+
441
+    #endif
442
+
443
+  #endif // E_MANUAL
432 444
 
433 445
   END_MENU();
434 446
 }

+ 12
- 6
Marlin/src/lcd/menu/menu_temperature.cpp View File

@@ -48,7 +48,9 @@ uint8_t MarlinUI::preheat_fan_speed[2];
48 48
 //
49 49
 
50 50
 void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb, const uint8_t fan) {
51
-  if (temph > 0) thermalManager.setTargetHotend(_MIN(heater_maxtemp[endnum] - 15, temph), endnum);
51
+  #if HOTENDS
52
+    if (temph > 0) thermalManager.setTargetHotend(_MIN(heater_maxtemp[endnum] - 15, temph), endnum);
53
+  #endif
52 54
   #if HAS_HEATED_BED
53 55
     if (tempb >= 0) thermalManager.setTargetBed(tempb);
54 56
   #else
@@ -165,12 +167,16 @@ void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb
165 167
 
166 168
 #if HAS_TEMP_HOTEND || HAS_HEATED_BED
167 169
 
168
-  void lcd_preheat_m1_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); }
169
-  void lcd_preheat_m2_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); }
170
+  #if HOTENDS
171
+    void lcd_preheat_m1_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); }
172
+    void lcd_preheat_m2_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); }
173
+  #endif
170 174
 
171 175
   #if HAS_HEATED_BED
172
-    void lcd_preheat_m1_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
173
-    void lcd_preheat_m2_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
176
+    #if HOTENDS
177
+      void lcd_preheat_m1_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
178
+      void lcd_preheat_m2_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
179
+    #endif
174 180
     void lcd_preheat_m1_bedonly() { _lcd_preheat(0, 0, ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
175 181
     void lcd_preheat_m2_bedonly() { _lcd_preheat(0, 0, ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
176 182
   #endif
@@ -313,7 +319,7 @@ void menu_temperature() {
313 319
   //
314 320
   #if HOTENDS == 1
315 321
     MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE, &thermalManager.temp_hotend[0].target, 0, HEATER_0_MAXTEMP - 15, thermalManager.start_watching_E0);
316
-  #else // HOTENDS > 1
322
+  #elif HOTENDS > 1
317 323
     #define EDIT_TARGET(N) MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_LCD_N##N, &thermalManager.temp_hotend[N].target, 0, HEATER_##N##_MAXTEMP - 15, thermalManager.start_watching_E##N)
318 324
     EDIT_TARGET(0);
319 325
     EDIT_TARGET(1);

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

@@ -144,7 +144,7 @@ void menu_tune() {
144 144
   //
145 145
   #if HOTENDS == 1
146 146
     MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE, &thermalManager.temp_hotend[0].target, 0, HEATER_0_MAXTEMP - 15, thermalManager.start_watching_E0);
147
-  #else // HOTENDS > 1
147
+  #elif HOTENDS > 1
148 148
     #define EDIT_NOZZLE(N) MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE MSG_LCD_N##N, &thermalManager.temp_hotend[N].target, 0, HEATER_##N##_MAXTEMP - 15, thermalManager.start_watching_E##N)
149 149
     EDIT_NOZZLE(0);
150 150
     EDIT_NOZZLE(1);

+ 12
- 6
Marlin/src/module/configuration_store.cpp View File

@@ -309,7 +309,9 @@ typedef struct SettingsDataStruct {
309 309
   //
310 310
   // ADVANCED_PAUSE_FEATURE
311 311
   //
312
-  fil_change_settings_t fc_settings[EXTRUDERS];         // M603 T U L
312
+  #if EXTRUDERS
313
+    fil_change_settings_t fc_settings[EXTRUDERS];       // M603 T U L
314
+  #endif
313 315
 
314 316
   //
315 317
   // Tool-change settings
@@ -367,7 +369,7 @@ void MarlinSettings::postprocess() {
367 369
 
368 370
   #if DISABLED(NO_VOLUMETRICS)
369 371
     planner.calculate_volumetric_multipliers();
370
-  #else
372
+  #elif EXTRUDERS
371 373
     for (uint8_t i = COUNT(planner.e_factor); i--;)
372 374
       planner.refresh_e_factor(i);
373 375
   #endif
@@ -759,7 +761,7 @@ void MarlinSettings::postprocess() {
759 761
     {
760 762
       _FIELD_TEST(ui_preheat_hotend_temp);
761 763
 
762
-      #if HAS_LCD_MENU
764
+      #if HOTENDS && HAS_LCD_MENU
763 765
         const int16_t (&ui_preheat_hotend_temp)[2]  = ui.preheat_hotend_temp,
764 766
                       (&ui_preheat_bed_temp)[2]     = ui.preheat_bed_temp;
765 767
         const uint8_t (&ui_preheat_fan_speed)[2]    = ui.preheat_fan_speed;
@@ -1164,6 +1166,7 @@ void MarlinSettings::postprocess() {
1164 1166
     //
1165 1167
     // Advanced Pause filament load & unload lengths
1166 1168
     //
1169
+    #if EXTRUDERS
1167 1170
     {
1168 1171
       #if DISABLED(ADVANCED_PAUSE_FEATURE)
1169 1172
         const fil_change_settings_t fc_settings[EXTRUDERS] = { 0, 0 };
@@ -1171,6 +1174,7 @@ void MarlinSettings::postprocess() {
1171 1174
       _FIELD_TEST(fc_settings);
1172 1175
       EEPROM_WRITE(fc_settings);
1173 1176
     }
1177
+    #endif
1174 1178
 
1175 1179
     //
1176 1180
     // Multiple Extruders
@@ -1560,7 +1564,7 @@ void MarlinSettings::postprocess() {
1560 1564
       {
1561 1565
         _FIELD_TEST(ui_preheat_hotend_temp);
1562 1566
 
1563
-        #if HAS_LCD_MENU
1567
+        #if HOTENDS && HAS_LCD_MENU
1564 1568
           int16_t (&ui_preheat_hotend_temp)[2]  = ui.preheat_hotend_temp,
1565 1569
                   (&ui_preheat_bed_temp)[2]     = ui.preheat_bed_temp;
1566 1570
           uint8_t (&ui_preheat_fan_speed)[2]    = ui.preheat_fan_speed;
@@ -1968,6 +1972,7 @@ void MarlinSettings::postprocess() {
1968 1972
       //
1969 1973
       // Advanced Pause filament load & unload lengths
1970 1974
       //
1975
+      #if EXTRUDERS
1971 1976
       {
1972 1977
         #if DISABLED(ADVANCED_PAUSE_FEATURE)
1973 1978
           fil_change_settings_t fc_settings[EXTRUDERS];
@@ -1975,6 +1980,7 @@ void MarlinSettings::postprocess() {
1975 1980
         _FIELD_TEST(fc_settings);
1976 1981
         EEPROM_READ(fc_settings);
1977 1982
       }
1983
+      #endif
1978 1984
 
1979 1985
       //
1980 1986
       // Tool-change settings
@@ -2410,7 +2416,7 @@ void MarlinSettings::reset() {
2410 2416
   // Preheat parameters
2411 2417
   //
2412 2418
 
2413
-  #if HAS_LCD_MENU
2419
+  #if HOTENDS && HAS_LCD_MENU
2414 2420
     ui.preheat_hotend_temp[0] = PREHEAT_1_TEMP_HOTEND;
2415 2421
     ui.preheat_hotend_temp[1] = PREHEAT_2_TEMP_HOTEND;
2416 2422
     ui.preheat_bed_temp[0] = PREHEAT_1_TEMP_BED;
@@ -2956,7 +2962,7 @@ void MarlinSettings::reset() {
2956 2962
 
2957 2963
     #endif // [XYZ]_DUAL_ENDSTOPS
2958 2964
 
2959
-    #if HAS_LCD_MENU
2965
+    #if HOTENDS && HAS_LCD_MENU
2960 2966
 
2961 2967
       CONFIG_ECHO_HEADING("Material heatup parameters:");
2962 2968
       for (uint8_t i = 0; i < COUNT(ui.preheat_hotend_temp); i++) {

+ 3
- 1
Marlin/src/module/motion.h View File

@@ -124,8 +124,10 @@ XYZ_DEFS(signed char, home_dir, HOME_DIR);
124 124
 #if HAS_HOTEND_OFFSET
125 125
   extern float hotend_offset[XYZ][HOTENDS];
126 126
   void reset_hotend_offsets();
127
-#else
127
+#elif HOTENDS > 0
128 128
   constexpr float hotend_offset[XYZ][HOTENDS] = { { 0 }, { 0 }, { 0 } };
129
+#else
130
+  constexpr float hotend_offset[XYZ][1] = { { 0 }, { 0 }, { 0 } };
129 131
 #endif
130 132
 
131 133
 typedef struct { float min, max; } axis_limits_t;

+ 134
- 111
Marlin/src/module/planner.cpp View File

@@ -147,9 +147,10 @@ float Planner::steps_to_mm[XYZE_N];           // (mm) Millimeters per step
147 147
   uint8_t Planner::last_extruder = 0;     // Respond to extruder change
148 148
 #endif
149 149
 
150
-int16_t Planner::flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100); // Extrusion factor for each extruder
151
-
152
-float Planner::e_factor[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0f); // The flow percentage and volumetric multiplier combine to scale E movement
150
+#if EXTRUDERS
151
+  int16_t Planner::flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100); // Extrusion factor for each extruder
152
+  float Planner::e_factor[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0f); // The flow percentage and volumetric multiplier combine to scale E movement
153
+#endif
153 154
 
154 155
 #if DISABLED(NO_VOLUMETRICS)
155 156
   float Planner::filament_size[EXTRUDERS],          // diameter of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder
@@ -1632,7 +1633,11 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
1632 1633
                 db = target[B_AXIS] - position[B_AXIS],
1633 1634
                 dc = target[C_AXIS] - position[C_AXIS];
1634 1635
 
1635
-  int32_t de = target[E_AXIS] - position[E_AXIS];
1636
+  #if EXTRUDERS
1637
+    int32_t de = target[E_AXIS] - position[E_AXIS];
1638
+  #else
1639
+    constexpr int32_t de = 0;
1640
+  #endif
1636 1641
 
1637 1642
   /* <-- add a slash to enable
1638 1643
     SERIAL_ECHOPAIR("  _populate_block FR:", fr_mm_s);
@@ -1642,8 +1647,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
1642 1647
     SERIAL_ECHOPAIR(" (", db);
1643 1648
     SERIAL_ECHOPAIR(" steps) C:", target[C_AXIS]);
1644 1649
     SERIAL_ECHOPAIR(" (", dc);
1645
-    SERIAL_ECHOPAIR(" steps) E:", target[E_AXIS]);
1646
-    SERIAL_ECHOPAIR(" (", de);
1650
+    #if EXTRUDERS
1651
+      SERIAL_ECHOPAIR(" steps) E:", target[E_AXIS]);
1652
+      SERIAL_ECHOPAIR(" (", de);
1653
+    #endif
1647 1654
     SERIAL_ECHOLNPGM(" steps)");
1648 1655
   //*/
1649 1656
 
@@ -1712,8 +1719,12 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
1712 1719
   #endif
1713 1720
   if (de < 0) SBI(dm, E_AXIS);
1714 1721
 
1715
-  const float esteps_float = de * e_factor[extruder];
1716
-  const uint32_t esteps = ABS(esteps_float) + 0.5f;
1722
+  #if EXTRUDERS
1723
+    const float esteps_float = de * e_factor[extruder];
1724
+    const uint32_t esteps = ABS(esteps_float) + 0.5f;
1725
+  #else
1726
+    constexpr uint32_t esteps = 0;
1727
+  #endif
1717 1728
 
1718 1729
   // Clear all flags, including the "busy" bit
1719 1730
   block->flag = 0x00;
@@ -1781,10 +1792,17 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
1781 1792
     delta_mm[B_AXIS] = db * steps_to_mm[B_AXIS];
1782 1793
     delta_mm[C_AXIS] = dc * steps_to_mm[C_AXIS];
1783 1794
   #endif
1784
-  delta_mm[E_AXIS] = esteps_float * steps_to_mm[E_AXIS_N(extruder)];
1795
+
1796
+  #if EXTRUDERS
1797
+    delta_mm[E_AXIS] = esteps_float * steps_to_mm[E_AXIS_N(extruder)];
1798
+  #endif
1785 1799
 
1786 1800
   if (block->steps[A_AXIS] < MIN_STEPS_PER_SEGMENT && block->steps[B_AXIS] < MIN_STEPS_PER_SEGMENT && block->steps[C_AXIS] < MIN_STEPS_PER_SEGMENT) {
1787
-    block->millimeters = ABS(delta_mm[E_AXIS]);
1801
+    block->millimeters = (0
1802
+      #if EXTRUDERS
1803
+        + ABS(delta_mm[E_AXIS])
1804
+      #endif
1805
+    );
1788 1806
   }
1789 1807
   else {
1790 1808
     if (millimeters)
@@ -1816,7 +1834,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
1816 1834
     #endif
1817 1835
   }
1818 1836
 
1819
-  block->steps[E_AXIS] = esteps;
1837
+  #if EXTRUDERS
1838
+    block->steps[E_AXIS] = esteps;
1839
+  #endif
1840
+
1820 1841
   block->step_event_count = _MAX(block->steps[A_AXIS], block->steps[B_AXIS], block->steps[C_AXIS], esteps);
1821 1842
 
1822 1843
   // Bail if this is a zero-length block
@@ -1874,129 +1895,131 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
1874 1895
   #endif
1875 1896
 
1876 1897
   // Enable extruder(s)
1877
-  if (esteps) {
1878
-    #if ENABLED(AUTO_POWER_CONTROL)
1879
-      powerManager.power_on();
1880
-    #endif
1898
+  #if EXTRUDERS
1899
+    if (esteps) {
1900
+      #if ENABLED(AUTO_POWER_CONTROL)
1901
+        powerManager.power_on();
1902
+      #endif
1881 1903
 
1882
-    #if ENABLED(DISABLE_INACTIVE_EXTRUDER) // Enable only the selected extruder
1904
+      #if ENABLED(DISABLE_INACTIVE_EXTRUDER) // Enable only the selected extruder
1883 1905
 
1884
-      #define DISABLE_IDLE_E(N) if (!g_uc_extruder_last_move[N]) disable_E##N();
1906
+        #define DISABLE_IDLE_E(N) if (!g_uc_extruder_last_move[N]) disable_E##N();
1885 1907
 
1886
-      for (uint8_t i = 0; i < EXTRUDERS; i++)
1887
-        if (g_uc_extruder_last_move[i] > 0) g_uc_extruder_last_move[i]--;
1908
+        for (uint8_t i = 0; i < EXTRUDERS; i++)
1909
+          if (g_uc_extruder_last_move[i] > 0) g_uc_extruder_last_move[i]--;
1888 1910
 
1889
-      switch (extruder) {
1890
-        case 0:
1911
+        switch (extruder) {
1912
+          case 0:
1913
+            #if EXTRUDERS > 1
1914
+              DISABLE_IDLE_E(1);
1915
+              #if EXTRUDERS > 2
1916
+                DISABLE_IDLE_E(2);
1917
+                #if EXTRUDERS > 3
1918
+                  DISABLE_IDLE_E(3);
1919
+                  #if EXTRUDERS > 4
1920
+                    DISABLE_IDLE_E(4);
1921
+                    #if EXTRUDERS > 5
1922
+                      DISABLE_IDLE_E(5);
1923
+                    #endif // EXTRUDERS > 5
1924
+                  #endif // EXTRUDERS > 4
1925
+                #endif // EXTRUDERS > 3
1926
+              #endif // EXTRUDERS > 2
1927
+            #endif // EXTRUDERS > 1
1928
+            enable_E0();
1929
+            g_uc_extruder_last_move[0] = (BLOCK_BUFFER_SIZE) * 2;
1930
+            #if HAS_DUPLICATION_MODE
1931
+              if (extruder_duplication_enabled) {
1932
+                enable_E1();
1933
+                g_uc_extruder_last_move[1] = (BLOCK_BUFFER_SIZE) * 2;
1934
+              }
1935
+            #endif
1936
+          break;
1891 1937
           #if EXTRUDERS > 1
1892
-            DISABLE_IDLE_E(1);
1893
-            #if EXTRUDERS > 2
1894
-              DISABLE_IDLE_E(2);
1895
-              #if EXTRUDERS > 3
1896
-                DISABLE_IDLE_E(3);
1897
-                #if EXTRUDERS > 4
1898
-                  DISABLE_IDLE_E(4);
1899
-                  #if EXTRUDERS > 5
1900
-                    DISABLE_IDLE_E(5);
1901
-                  #endif // EXTRUDERS > 5
1902
-                #endif // EXTRUDERS > 4
1903
-              #endif // EXTRUDERS > 3
1904
-            #endif // EXTRUDERS > 2
1905
-          #endif // EXTRUDERS > 1
1906
-          enable_E0();
1907
-          g_uc_extruder_last_move[0] = (BLOCK_BUFFER_SIZE) * 2;
1908
-          #if HAS_DUPLICATION_MODE
1909
-            if (extruder_duplication_enabled) {
1938
+            case 1:
1939
+              DISABLE_IDLE_E(0);
1940
+              #if EXTRUDERS > 2
1941
+                DISABLE_IDLE_E(2);
1942
+                #if EXTRUDERS > 3
1943
+                  DISABLE_IDLE_E(3);
1944
+                  #if EXTRUDERS > 4
1945
+                    DISABLE_IDLE_E(4);
1946
+                    #if EXTRUDERS > 5
1947
+                      DISABLE_IDLE_E(5);
1948
+                    #endif // EXTRUDERS > 5
1949
+                  #endif // EXTRUDERS > 4
1950
+                #endif // EXTRUDERS > 3
1951
+              #endif // EXTRUDERS > 2
1910 1952
               enable_E1();
1911 1953
               g_uc_extruder_last_move[1] = (BLOCK_BUFFER_SIZE) * 2;
1912
-            }
1913
-          #endif
1914
-        break;
1915
-        #if EXTRUDERS > 1
1916
-          case 1:
1917
-            DISABLE_IDLE_E(0);
1918
-            #if EXTRUDERS > 2
1919
-              DISABLE_IDLE_E(2);
1920
-              #if EXTRUDERS > 3
1921
-                DISABLE_IDLE_E(3);
1922
-                #if EXTRUDERS > 4
1923
-                  DISABLE_IDLE_E(4);
1924
-                  #if EXTRUDERS > 5
1925
-                    DISABLE_IDLE_E(5);
1926
-                  #endif // EXTRUDERS > 5
1927
-                #endif // EXTRUDERS > 4
1928
-              #endif // EXTRUDERS > 3
1929
-            #endif // EXTRUDERS > 2
1930
-            enable_E1();
1931
-            g_uc_extruder_last_move[1] = (BLOCK_BUFFER_SIZE) * 2;
1932
-          break;
1933
-          #if EXTRUDERS > 2
1934
-            case 2:
1935
-              DISABLE_IDLE_E(0);
1936
-              DISABLE_IDLE_E(1);
1937
-              #if EXTRUDERS > 3
1938
-                DISABLE_IDLE_E(3);
1939
-                #if EXTRUDERS > 4
1940
-                  DISABLE_IDLE_E(4);
1941
-                  #if EXTRUDERS > 5
1942
-                    DISABLE_IDLE_E(5);
1943
-                  #endif
1944
-                #endif
1945
-              #endif
1946
-              enable_E2();
1947
-              g_uc_extruder_last_move[2] = (BLOCK_BUFFER_SIZE) * 2;
1948 1954
             break;
1949
-            #if EXTRUDERS > 3
1950
-              case 3:
1955
+            #if EXTRUDERS > 2
1956
+              case 2:
1951 1957
                 DISABLE_IDLE_E(0);
1952 1958
                 DISABLE_IDLE_E(1);
1953
-                DISABLE_IDLE_E(2);
1954
-                #if EXTRUDERS > 4
1955
-                  DISABLE_IDLE_E(4);
1956
-                  #if EXTRUDERS > 5
1957
-                    DISABLE_IDLE_E(5);
1959
+                #if EXTRUDERS > 3
1960
+                  DISABLE_IDLE_E(3);
1961
+                  #if EXTRUDERS > 4
1962
+                    DISABLE_IDLE_E(4);
1963
+                    #if EXTRUDERS > 5
1964
+                      DISABLE_IDLE_E(5);
1965
+                    #endif
1958 1966
                   #endif
1959 1967
                 #endif
1960
-                enable_E3();
1961
-                g_uc_extruder_last_move[3] = (BLOCK_BUFFER_SIZE) * 2;
1968
+                enable_E2();
1969
+                g_uc_extruder_last_move[2] = (BLOCK_BUFFER_SIZE) * 2;
1962 1970
               break;
1963
-              #if EXTRUDERS > 4
1964
-                case 4:
1971
+              #if EXTRUDERS > 3
1972
+                case 3:
1965 1973
                   DISABLE_IDLE_E(0);
1966 1974
                   DISABLE_IDLE_E(1);
1967 1975
                   DISABLE_IDLE_E(2);
1968
-                  DISABLE_IDLE_E(3);
1969
-                  #if EXTRUDERS > 5
1970
-                    DISABLE_IDLE_E(5);
1976
+                  #if EXTRUDERS > 4
1977
+                    DISABLE_IDLE_E(4);
1978
+                    #if EXTRUDERS > 5
1979
+                      DISABLE_IDLE_E(5);
1980
+                    #endif
1971 1981
                   #endif
1972
-                  enable_E4();
1973
-                  g_uc_extruder_last_move[4] = (BLOCK_BUFFER_SIZE) * 2;
1982
+                  enable_E3();
1983
+                  g_uc_extruder_last_move[3] = (BLOCK_BUFFER_SIZE) * 2;
1974 1984
                 break;
1975
-                #if EXTRUDERS > 5
1976
-                  case 5:
1985
+                #if EXTRUDERS > 4
1986
+                  case 4:
1977 1987
                     DISABLE_IDLE_E(0);
1978 1988
                     DISABLE_IDLE_E(1);
1979 1989
                     DISABLE_IDLE_E(2);
1980 1990
                     DISABLE_IDLE_E(3);
1981
-                    DISABLE_IDLE_E(4);
1982
-                    enable_E5();
1983
-                    g_uc_extruder_last_move[5] = (BLOCK_BUFFER_SIZE) * 2;
1991
+                    #if EXTRUDERS > 5
1992
+                      DISABLE_IDLE_E(5);
1993
+                    #endif
1994
+                    enable_E4();
1995
+                    g_uc_extruder_last_move[4] = (BLOCK_BUFFER_SIZE) * 2;
1984 1996
                   break;
1985
-                #endif // EXTRUDERS > 5
1986
-              #endif // EXTRUDERS > 4
1987
-            #endif // EXTRUDERS > 3
1988
-          #endif // EXTRUDERS > 2
1989
-        #endif // EXTRUDERS > 1
1990
-      }
1991
-    #else
1992
-      enable_E0();
1993
-      enable_E1();
1994
-      enable_E2();
1995
-      enable_E3();
1996
-      enable_E4();
1997
-      enable_E5();
1998
-    #endif
1999
-  }
1997
+                  #if EXTRUDERS > 5
1998
+                    case 5:
1999
+                      DISABLE_IDLE_E(0);
2000
+                      DISABLE_IDLE_E(1);
2001
+                      DISABLE_IDLE_E(2);
2002
+                      DISABLE_IDLE_E(3);
2003
+                      DISABLE_IDLE_E(4);
2004
+                      enable_E5();
2005
+                      g_uc_extruder_last_move[5] = (BLOCK_BUFFER_SIZE) * 2;
2006
+                    break;
2007
+                  #endif // EXTRUDERS > 5
2008
+                #endif // EXTRUDERS > 4
2009
+              #endif // EXTRUDERS > 3
2010
+            #endif // EXTRUDERS > 2
2011
+          #endif // EXTRUDERS > 1
2012
+        }
2013
+      #else
2014
+        enable_E0();
2015
+        enable_E1();
2016
+        enable_E2();
2017
+        enable_E3();
2018
+        enable_E4();
2019
+        enable_E5();
2020
+      #endif
2021
+    }
2022
+  #endif // EXTRUDERS
2000 2023
 
2001 2024
   if (esteps)
2002 2025
     NOLESS(fr_mm_s, settings.min_feedrate_mm_s);

+ 13
- 10
Marlin/src/module/planner.h View File

@@ -226,9 +226,10 @@ class Planner {
226 226
       static uint8_t last_extruder;                 // Respond to extruder change
227 227
     #endif
228 228
 
229
-    static int16_t flow_percentage[EXTRUDERS];      // Extrusion factor for each extruder
230
-
231
-    static float e_factor[EXTRUDERS];               // The flow percentage and volumetric multiplier combine to scale E movement
229
+    #if EXTRUDERS
230
+      static int16_t flow_percentage[EXTRUDERS];    // Extrusion factor for each extruder
231
+      static float e_factor[EXTRUDERS];             // The flow percentage and volumetric multiplier combine to scale E movement
232
+    #endif
232 233
 
233 234
     #if DISABLED(NO_VOLUMETRICS)
234 235
       static float filament_size[EXTRUDERS],          // diameter of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder
@@ -357,13 +358,15 @@ class Planner {
357 358
     static void reset_acceleration_rates();
358 359
     static void refresh_positioning();
359 360
 
360
-    FORCE_INLINE static void refresh_e_factor(const uint8_t e) {
361
-      e_factor[e] = (flow_percentage[e] * 0.01f
362
-        #if DISABLED(NO_VOLUMETRICS)
363
-          * volumetric_multiplier[e]
364
-        #endif
365
-      );
366
-    }
361
+    #if EXTRUDERS
362
+      FORCE_INLINE static void refresh_e_factor(const uint8_t e) {
363
+        e_factor[e] = (flow_percentage[e] * 0.01f
364
+          #if DISABLED(NO_VOLUMETRICS)
365
+            * volumetric_multiplier[e]
366
+          #endif
367
+        );
368
+      }
369
+    #endif
367 370
 
368 371
     // Manage fans, paste pressure, etc.
369 372
     static void check_axes_activity();

+ 357
- 326
Marlin/src/module/temperature.cpp View File

@@ -112,11 +112,9 @@ Temperature thermalManager;
112 112
   bool Temperature::adaptive_fan_slowing = true;
113 113
 #endif
114 114
 
115
-hotend_info_t Temperature::temp_hotend[HOTENDS
116
-  #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
117
-    + 1
118
-  #endif
119
-]; // = { 0 }
115
+#if HOTENDS
116
+  hotend_info_t Temperature::temp_hotend[HOTEND_TEMPS]; // = { 0 }
117
+#endif
120 118
 
121 119
 #if ENABLED(AUTO_POWER_E_FANS)
122 120
   uint8_t Temperature::autofan_speed[HOTENDS]; // = { 0 }
@@ -283,15 +281,17 @@ volatile bool Temperature::temp_meas_ready = false;
283 281
 
284 282
 #define TEMPDIR(N) ((HEATER_##N##_RAW_LO_TEMP) < (HEATER_##N##_RAW_HI_TEMP) ? 1 : -1)
285 283
 
286
-// Init mintemp and maxtemp with extreme values to prevent false errors during startup
287
-constexpr temp_range_t sensor_heater_0 { HEATER_0_RAW_LO_TEMP, HEATER_0_RAW_HI_TEMP, 0, 16383 },
288
-                       sensor_heater_1 { HEATER_1_RAW_LO_TEMP, HEATER_1_RAW_HI_TEMP, 0, 16383 },
289
-                       sensor_heater_2 { HEATER_2_RAW_LO_TEMP, HEATER_2_RAW_HI_TEMP, 0, 16383 },
290
-                       sensor_heater_3 { HEATER_3_RAW_LO_TEMP, HEATER_3_RAW_HI_TEMP, 0, 16383 },
291
-                       sensor_heater_4 { HEATER_4_RAW_LO_TEMP, HEATER_4_RAW_HI_TEMP, 0, 16383 },
292
-                       sensor_heater_5 { HEATER_5_RAW_LO_TEMP, HEATER_5_RAW_HI_TEMP, 0, 16383 };
284
+#if HOTENDS
285
+  // Init mintemp and maxtemp with extreme values to prevent false errors during startup
286
+  constexpr temp_range_t sensor_heater_0 { HEATER_0_RAW_LO_TEMP, HEATER_0_RAW_HI_TEMP, 0, 16383 },
287
+                         sensor_heater_1 { HEATER_1_RAW_LO_TEMP, HEATER_1_RAW_HI_TEMP, 0, 16383 },
288
+                         sensor_heater_2 { HEATER_2_RAW_LO_TEMP, HEATER_2_RAW_HI_TEMP, 0, 16383 },
289
+                         sensor_heater_3 { HEATER_3_RAW_LO_TEMP, HEATER_3_RAW_HI_TEMP, 0, 16383 },
290
+                         sensor_heater_4 { HEATER_4_RAW_LO_TEMP, HEATER_4_RAW_HI_TEMP, 0, 16383 },
291
+                         sensor_heater_5 { HEATER_5_RAW_LO_TEMP, HEATER_5_RAW_HI_TEMP, 0, 16383 };
293 292
 
294
-temp_range_t Temperature::temp_range[HOTENDS] = ARRAY_BY_HOTENDS(sensor_heater_0, sensor_heater_1, sensor_heater_2, sensor_heater_3, sensor_heater_4, sensor_heater_5);
293
+  temp_range_t Temperature::temp_range[HOTENDS] = ARRAY_BY_HOTENDS(sensor_heater_0, sensor_heater_1, sensor_heater_2, sensor_heater_3, sensor_heater_4, sensor_heater_5);
294
+#endif
295 295
 
296 296
 #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
297 297
   uint8_t Temperature::consecutive_low_temperature_error[HOTENDS] = { 0 };
@@ -627,17 +627,20 @@ temp_range_t Temperature::temp_range[HOTENDS] = ARRAY_BY_HOTENDS(sensor_heater_0
627 627
  * Class and Instance Methods
628 628
  */
629 629
 
630
-Temperature::Temperature() { }
631
-
632 630
 int16_t Temperature::getHeaterPower(const heater_ind_t heater_id) {
633 631
   switch (heater_id) {
634
-    default: return temp_hotend[heater_id].soft_pwm_amount;
635 632
     #if HAS_HEATED_BED
636 633
       case H_BED: return temp_bed.soft_pwm_amount;
637 634
     #endif
638 635
     #if HAS_HEATED_CHAMBER
639 636
       case H_CHAMBER: return temp_chamber.soft_pwm_amount;
640 637
     #endif
638
+    default:
639
+      #if HOTENDS
640
+        return temp_hotend[heater_id].soft_pwm_amount;
641
+      #else
642
+        return 0;
643
+      #endif
641 644
   }
642 645
 }
643 646
 
@@ -816,114 +819,118 @@ void Temperature::min_temp_error(const heater_ind_t heater) {
816 819
   _temp_error(heater, PSTR(MSG_T_MINTEMP), TEMP_ERR_PSTR(MSG_ERR_MINTEMP, heater));
817 820
 }
818 821
 
819
-float Temperature::get_pid_output_hotend(const uint8_t e) {
820
-  #if HOTENDS == 1
821
-    #define _HOTEND_TEST true
822
-  #else
823
-    #define _HOTEND_TEST (e == active_extruder)
824
-  #endif
825
-  E_UNUSED();
826
-  const uint8_t ee = HOTEND_INDEX;
827
-  float pid_output;
828
-  #if ENABLED(PIDTEMP)
829
-    #if DISABLED(PID_OPENLOOP)
830
-      static hotend_pid_t work_pid[HOTENDS];
831
-      static float temp_iState[HOTENDS] = { 0 },
832
-                   temp_dState[HOTENDS] = { 0 };
833
-      static bool pid_reset[HOTENDS] = { false };
834
-      const float pid_error = temp_hotend[ee].target - temp_hotend[ee].celsius;
835
-
836
-      if (temp_hotend[ee].target == 0
837
-        || pid_error < -(PID_FUNCTIONAL_RANGE)
838
-        #if HEATER_IDLE_HANDLER
839
-          || hotend_idle[ee].timed_out
840
-        #endif
841
-      ) {
842
-        pid_output = 0;
843
-        pid_reset[ee] = true;
844
-      }
845
-      else if (pid_error > PID_FUNCTIONAL_RANGE) {
846
-        pid_output = BANG_MAX;
847
-        pid_reset[ee] = true;
848
-      }
849
-      else {
850
-        if (pid_reset[ee]) {
851
-          temp_iState[ee] = 0.0;
852
-          work_pid[ee].Kd = 0.0;
853
-          pid_reset[ee] = false;
822
+#if HOTENDS
823
+
824
+  float Temperature::get_pid_output_hotend(const uint8_t e) {
825
+    #if HOTENDS == 1
826
+      #define _HOTEND_TEST true
827
+    #else
828
+      #define _HOTEND_TEST (e == active_extruder)
829
+    #endif
830
+    E_UNUSED();
831
+    const uint8_t ee = HOTEND_INDEX;
832
+    float pid_output;
833
+    #if ENABLED(PIDTEMP)
834
+      #if DISABLED(PID_OPENLOOP)
835
+        static hotend_pid_t work_pid[HOTENDS];
836
+        static float temp_iState[HOTENDS] = { 0 },
837
+                     temp_dState[HOTENDS] = { 0 };
838
+        static bool pid_reset[HOTENDS] = { false };
839
+        const float pid_error = temp_hotend[ee].target - temp_hotend[ee].celsius;
840
+
841
+        if (temp_hotend[ee].target == 0
842
+          || pid_error < -(PID_FUNCTIONAL_RANGE)
843
+          #if HEATER_IDLE_HANDLER
844
+            || hotend_idle[ee].timed_out
845
+          #endif
846
+        ) {
847
+          pid_output = 0;
848
+          pid_reset[ee] = true;
854 849
         }
850
+        else if (pid_error > PID_FUNCTIONAL_RANGE) {
851
+          pid_output = BANG_MAX;
852
+          pid_reset[ee] = true;
853
+        }
854
+        else {
855
+          if (pid_reset[ee]) {
856
+            temp_iState[ee] = 0.0;
857
+            work_pid[ee].Kd = 0.0;
858
+            pid_reset[ee] = false;
859
+          }
855 860
 
856
-        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);
857
-        const float max_power_over_i_gain = float(PID_MAX) / PID_PARAM(Ki, ee) - float(MIN_POWER);
858
-        temp_iState[ee] = constrain(temp_iState[ee] + pid_error, 0, max_power_over_i_gain);
859
-        work_pid[ee].Kp = PID_PARAM(Kp, ee) * pid_error;
860
-        work_pid[ee].Ki = PID_PARAM(Ki, ee) * temp_iState[ee];
861
-
862
-        pid_output = work_pid[ee].Kp + work_pid[ee].Ki + work_pid[ee].Kd + float(MIN_POWER);
863
-
864
-        #if ENABLED(PID_EXTRUSION_SCALING)
865
-          work_pid[ee].Kc = 0;
866
-          if (_HOTEND_TEST) {
867
-            const long e_position = stepper.position(E_AXIS);
868
-            if (e_position > last_e_position) {
869
-              lpq[lpq_ptr] = e_position - last_e_position;
870
-              last_e_position = e_position;
871
-            }
872
-            else
873
-              lpq[lpq_ptr] = 0;
861
+          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);
862
+          const float max_power_over_i_gain = float(PID_MAX) / PID_PARAM(Ki, ee) - float(MIN_POWER);
863
+          temp_iState[ee] = constrain(temp_iState[ee] + pid_error, 0, max_power_over_i_gain);
864
+          work_pid[ee].Kp = PID_PARAM(Kp, ee) * pid_error;
865
+          work_pid[ee].Ki = PID_PARAM(Ki, ee) * temp_iState[ee];
866
+
867
+          pid_output = work_pid[ee].Kp + work_pid[ee].Ki + work_pid[ee].Kd + float(MIN_POWER);
868
+
869
+          #if ENABLED(PID_EXTRUSION_SCALING)
870
+            work_pid[ee].Kc = 0;
871
+            if (_HOTEND_TEST) {
872
+              const long e_position = stepper.position(E_AXIS);
873
+              if (e_position > last_e_position) {
874
+                lpq[lpq_ptr] = e_position - last_e_position;
875
+                last_e_position = e_position;
876
+              }
877
+              else
878
+                lpq[lpq_ptr] = 0;
874 879
 
875
-            if (++lpq_ptr >= lpq_len) lpq_ptr = 0;
876
-            work_pid[ee].Kc = (lpq[lpq_ptr] * planner.steps_to_mm[E_AXIS]) * PID_PARAM(Kc, ee);
877
-            pid_output += work_pid[ee].Kc;
878
-          }
879
-        #endif // PID_EXTRUSION_SCALING
880
+              if (++lpq_ptr >= lpq_len) lpq_ptr = 0;
881
+              work_pid[ee].Kc = (lpq[lpq_ptr] * planner.steps_to_mm[E_AXIS]) * PID_PARAM(Kc, ee);
882
+              pid_output += work_pid[ee].Kc;
883
+            }
884
+          #endif // PID_EXTRUSION_SCALING
880 885
 
881
-        LIMIT(pid_output, 0, PID_MAX);
882
-      }
883
-      temp_dState[ee] = temp_hotend[ee].celsius;
886
+          LIMIT(pid_output, 0, PID_MAX);
887
+        }
888
+        temp_dState[ee] = temp_hotend[ee].celsius;
884 889
 
885
-    #else // PID_OPENLOOP
890
+      #else // PID_OPENLOOP
886 891
 
887
-      const float pid_output = constrain(temp_hotend[ee].target, 0, PID_MAX);
892
+        const float pid_output = constrain(temp_hotend[ee].target, 0, PID_MAX);
888 893
 
889
-    #endif // PID_OPENLOOP
894
+      #endif // PID_OPENLOOP
890 895
 
891
-    #if ENABLED(PID_DEBUG)
892
-      if (e == active_extruder) {
893
-        SERIAL_ECHO_START();
894
-        SERIAL_ECHOPAIR(
895
-          MSG_PID_DEBUG, ee,
896
-          MSG_PID_DEBUG_INPUT, temp_hotend[ee].celsius,
897
-          MSG_PID_DEBUG_OUTPUT, pid_output
898
-        );
899
-        #if DISABLED(PID_OPENLOOP)
896
+      #if ENABLED(PID_DEBUG)
897
+        if (e == active_extruder) {
898
+          SERIAL_ECHO_START();
900 899
           SERIAL_ECHOPAIR(
901
-            MSG_PID_DEBUG_PTERM, work_pid[ee].Kp,
902
-            MSG_PID_DEBUG_ITERM, work_pid[ee].Ki,
903
-            MSG_PID_DEBUG_DTERM, work_pid[ee].Kd
904
-            #if ENABLED(PID_EXTRUSION_SCALING)
905
-              , MSG_PID_DEBUG_CTERM, work_pid[ee].Kc
906
-            #endif
900
+            MSG_PID_DEBUG, ee,
901
+            MSG_PID_DEBUG_INPUT, temp_hotend[ee].celsius,
902
+            MSG_PID_DEBUG_OUTPUT, pid_output
907 903
           );
908
-        #endif
909
-        SERIAL_EOL();
910
-      }
911
-    #endif // PID_DEBUG
904
+          #if DISABLED(PID_OPENLOOP)
905
+            SERIAL_ECHOPAIR(
906
+              MSG_PID_DEBUG_PTERM, work_pid[ee].Kp,
907
+              MSG_PID_DEBUG_ITERM, work_pid[ee].Ki,
908
+              MSG_PID_DEBUG_DTERM, work_pid[ee].Kd
909
+              #if ENABLED(PID_EXTRUSION_SCALING)
910
+                , MSG_PID_DEBUG_CTERM, work_pid[ee].Kc
911
+              #endif
912
+            );
913
+          #endif
914
+          SERIAL_EOL();
915
+        }
916
+      #endif // PID_DEBUG
912 917
 
913
-  #else // No PID enabled
918
+    #else // No PID enabled
919
+
920
+      #if HEATER_IDLE_HANDLER
921
+        #define _TIMED_OUT_TEST hotend_idle[ee].timed_out
922
+      #else
923
+        #define _TIMED_OUT_TEST false
924
+      #endif
925
+      pid_output = (!_TIMED_OUT_TEST && temp_hotend[ee].celsius < temp_hotend[ee].target) ? BANG_MAX : 0;
926
+      #undef _TIMED_OUT_TEST
914 927
 
915
-    #if HEATER_IDLE_HANDLER
916
-      #define _TIMED_OUT_TEST hotend_idle[ee].timed_out
917
-    #else
918
-      #define _TIMED_OUT_TEST false
919 928
     #endif
920
-    pid_output = (!_TIMED_OUT_TEST && temp_hotend[ee].celsius < temp_hotend[ee].target) ? BANG_MAX : 0;
921
-    #undef _TIMED_OUT_TEST
922 929
 
923
-  #endif
930
+    return pid_output;
931
+  }
924 932
 
925
-  return pid_output;
926
-}
933
+#endif // HOTENDS
927 934
 
928 935
 #if ENABLED(PIDTEMPBED)
929 936
 
@@ -1025,44 +1032,46 @@ void Temperature::manage_heater() {
1025 1032
     if (temp_hotend[1].celsius < _MAX(HEATER_1_MINTEMP, HEATER_1_MAX6675_TMIN + .01)) min_temp_error(H_E1);
1026 1033
   #endif
1027 1034
 
1028
-  #if HAS_THERMAL_PROTECTION || DISABLED(PIDTEMPBED) || HAS_AUTO_FAN || HEATER_IDLE_HANDLER
1029
-    millis_t ms = millis();
1030
-  #endif
1035
+  millis_t ms = millis();
1031 1036
 
1032
-  HOTEND_LOOP() {
1033
-    #if ENABLED(THERMAL_PROTECTION_HOTENDS)
1034
-      if (degHotend(e) > temp_range[e].maxtemp)
1035
-        _temp_error((heater_ind_t)e, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, e));
1036
-    #endif
1037
+  #if HOTENDS
1037 1038
 
1038
-    #if HEATER_IDLE_HANDLER
1039
-      hotend_idle[e].update(ms);
1040
-    #endif
1039
+    HOTEND_LOOP() {
1040
+      #if ENABLED(THERMAL_PROTECTION_HOTENDS)
1041
+        if (degHotend(e) > temp_range[e].maxtemp)
1042
+          _temp_error((heater_ind_t)e, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, e));
1043
+      #endif
1041 1044
 
1042
-    #if ENABLED(THERMAL_PROTECTION_HOTENDS)
1043
-      // Check for thermal runaway
1044
-      thermal_runaway_protection(tr_state_machine[e], temp_hotend[e].celsius, temp_hotend[e].target, (heater_ind_t)e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS);
1045
-    #endif
1045
+      #if HEATER_IDLE_HANDLER
1046
+        hotend_idle[e].update(ms);
1047
+      #endif
1046 1048
 
1047
-    temp_hotend[e].soft_pwm_amount = (temp_hotend[e].celsius > temp_range[e].mintemp || is_preheating(e)) && temp_hotend[e].celsius < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0;
1049
+      #if ENABLED(THERMAL_PROTECTION_HOTENDS)
1050
+        // Check for thermal runaway
1051
+        thermal_runaway_protection(tr_state_machine[e], temp_hotend[e].celsius, temp_hotend[e].target, (heater_ind_t)e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS);
1052
+      #endif
1048 1053
 
1049
-    #if WATCH_HOTENDS
1050
-      // Make sure temperature is increasing
1051
-      if (watch_hotend[e].next_ms && ELAPSED(ms, watch_hotend[e].next_ms)) { // Time to check this extruder?
1052
-        if (degHotend(e) < watch_hotend[e].target)                             // Failed to increase enough?
1053
-          _temp_error((heater_ind_t)e, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, e));
1054
-        else                                                                 // Start again if the target is still far off
1055
-          start_watching_hotend(e);
1056
-      }
1057
-    #endif
1054
+      temp_hotend[e].soft_pwm_amount = (temp_hotend[e].celsius > temp_range[e].mintemp || is_preheating(e)) && temp_hotend[e].celsius < temp_range[e].maxtemp ? (int)get_pid_output_hotend(e) >> 1 : 0;
1058 1055
 
1059
-    #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
1060
-      // Make sure measured temperatures are close together
1061
-      if (ABS(temp_hotend[0].celsius - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF)
1062
-        _temp_error(H_E0, PSTR(MSG_REDUNDANCY), PSTR(MSG_ERR_REDUNDANT_TEMP));
1063
-    #endif
1056
+      #if WATCH_HOTENDS
1057
+        // Make sure temperature is increasing
1058
+        if (watch_hotend[e].next_ms && ELAPSED(ms, watch_hotend[e].next_ms)) { // Time to check this extruder?
1059
+          if (degHotend(e) < watch_hotend[e].target)                             // Failed to increase enough?
1060
+            _temp_error((heater_ind_t)e, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, e));
1061
+          else                                                                 // Start again if the target is still far off
1062
+            start_watching_hotend(e);
1063
+        }
1064
+      #endif
1064 1065
 
1065
-  } // HOTEND_LOOP
1066
+      #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
1067
+        // Make sure measured temperatures are close together
1068
+        if (ABS(temp_hotend[0].celsius - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF)
1069
+          _temp_error(H_E0, PSTR(MSG_REDUNDANCY), PSTR(MSG_ERR_REDUNDANT_TEMP));
1070
+      #endif
1071
+
1072
+    } // HOTEND_LOOP
1073
+
1074
+  #endif // HOTENDS
1066 1075
 
1067 1076
   #if HAS_AUTO_FAN
1068 1077
     if (ELAPSED(ms, next_auto_fan_check_ms)) { // only need to check fan state very infrequently
@@ -1206,6 +1215,8 @@ void Temperature::manage_heater() {
1206 1215
     //temp_bed.soft_pwm_amount = WITHIN(temp_chamber.celsius, CHAMBER_MINTEMP, CHAMBER_MAXTEMP) ? (int)get_pid_output_chamber() >> 1 : 0;
1207 1216
 
1208 1217
   #endif // HAS_HEATED_CHAMBER
1218
+
1219
+  UNUSED(ms);
1209 1220
 }
1210 1221
 
1211 1222
 #define TEMP_AD595(RAW)  ((RAW) * 5.0 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET)
@@ -1358,98 +1369,100 @@ void Temperature::manage_heater() {
1358 1369
   }
1359 1370
 #endif
1360 1371
 
1361
-// Derived from RepRap FiveD extruder::getTemperature()
1362
-// For hot end temperature measurement.
1363
-float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
1364
-  #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
1365
-    if (e > HOTENDS)
1366
-  #else
1367
-    if (e >= HOTENDS)
1368
-  #endif
1369
-    {
1370
-      SERIAL_ERROR_START();
1371
-      SERIAL_ECHO((int)e);
1372
-      SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER_NUM);
1373
-      kill();
1374
-      return 0.0;
1375
-    }
1372
+#if HOTENDS
1373
+  // Derived from RepRap FiveD extruder::getTemperature()
1374
+  // For hot end temperature measurement.
1375
+  float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) {
1376
+    #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
1377
+      if (e > HOTENDS)
1378
+    #else
1379
+      if (e >= HOTENDS)
1380
+    #endif
1381
+      {
1382
+        SERIAL_ERROR_START();
1383
+        SERIAL_ECHO((int)e);
1384
+        SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER_NUM);
1385
+        kill();
1386
+        return 0.0;
1387
+      }
1376 1388
 
1377
-  switch (e) {
1378
-    case 0:
1379
-      #if ENABLED(HEATER_0_USER_THERMISTOR)
1380
-        return user_thermistor_to_deg_c(CTI_HOTEND_0, raw);
1381
-      #elif ENABLED(HEATER_0_USES_MAX6675)
1382
-        return raw * 0.25;
1383
-      #elif ENABLED(HEATER_0_USES_AD595)
1384
-        return TEMP_AD595(raw);
1385
-      #elif ENABLED(HEATER_0_USES_AD8495)
1386
-        return TEMP_AD8495(raw);
1387
-      #else
1388
-        break;
1389
-      #endif
1390
-    case 1:
1391
-      #if ENABLED(HEATER_1_USER_THERMISTOR)
1392
-        return user_thermistor_to_deg_c(CTI_HOTEND_1, raw);
1393
-      #elif ENABLED(HEATER_1_USES_MAX6675)
1394
-        return raw * 0.25;
1395
-      #elif ENABLED(HEATER_1_USES_AD595)
1396
-        return TEMP_AD595(raw);
1397
-      #elif ENABLED(HEATER_1_USES_AD8495)
1398
-        return TEMP_AD8495(raw);
1399
-      #else
1400
-        break;
1401
-      #endif
1402
-    case 2:
1403
-      #if ENABLED(HEATER_2_USER_THERMISTOR)
1404
-        return user_thermistor_to_deg_c(CTI_HOTEND_2, raw);
1405
-      #elif ENABLED(HEATER_2_USES_AD595)
1406
-        return TEMP_AD595(raw);
1407
-      #elif ENABLED(HEATER_2_USES_AD8495)
1408
-        return TEMP_AD8495(raw);
1409
-      #else
1410
-        break;
1411
-      #endif
1412
-    case 3:
1413
-      #if ENABLED(HEATER_3_USER_THERMISTOR)
1414
-        return user_thermistor_to_deg_c(CTI_HOTEND_3, raw);
1415
-      #elif ENABLED(HEATER_3_USES_AD595)
1416
-        return TEMP_AD595(raw);
1417
-      #elif ENABLED(HEATER_3_USES_AD8495)
1418
-        return TEMP_AD8495(raw);
1419
-      #else
1420
-        break;
1421
-      #endif
1422
-    case 4:
1423
-      #if ENABLED(HEATER_4_USER_THERMISTOR)
1424
-        return user_thermistor_to_deg_c(CTI_HOTEND_4, raw);
1425
-      #elif ENABLED(HEATER_4_USES_AD595)
1426
-        return TEMP_AD595(raw);
1427
-      #elif ENABLED(HEATER_4_USES_AD8495)
1428
-        return TEMP_AD8495(raw);
1429
-      #else
1430
-        break;
1431
-      #endif
1432
-    case 5:
1433
-      #if ENABLED(HEATER_5_USER_THERMISTOR)
1434
-        return user_thermistor_to_deg_c(CTI_HOTEND_5, raw);
1435
-      #elif ENABLED(HEATER_5_USES_AD595)
1436
-        return TEMP_AD595(raw);
1437
-      #elif ENABLED(HEATER_5_USES_AD8495)
1438
-        return TEMP_AD8495(raw);
1439
-      #else
1440
-        break;
1441
-      #endif
1442
-    default: break;
1443
-  }
1389
+    switch (e) {
1390
+      case 0:
1391
+        #if ENABLED(HEATER_0_USER_THERMISTOR)
1392
+          return user_thermistor_to_deg_c(CTI_HOTEND_0, raw);
1393
+        #elif ENABLED(HEATER_0_USES_MAX6675)
1394
+          return raw * 0.25;
1395
+        #elif ENABLED(HEATER_0_USES_AD595)
1396
+          return TEMP_AD595(raw);
1397
+        #elif ENABLED(HEATER_0_USES_AD8495)
1398
+          return TEMP_AD8495(raw);
1399
+        #else
1400
+          break;
1401
+        #endif
1402
+      case 1:
1403
+        #if ENABLED(HEATER_1_USER_THERMISTOR)
1404
+          return user_thermistor_to_deg_c(CTI_HOTEND_1, raw);
1405
+        #elif ENABLED(HEATER_1_USES_MAX6675)
1406
+          return raw * 0.25;
1407
+        #elif ENABLED(HEATER_1_USES_AD595)
1408
+          return TEMP_AD595(raw);
1409
+        #elif ENABLED(HEATER_1_USES_AD8495)
1410
+          return TEMP_AD8495(raw);
1411
+        #else
1412
+          break;
1413
+        #endif
1414
+      case 2:
1415
+        #if ENABLED(HEATER_2_USER_THERMISTOR)
1416
+          return user_thermistor_to_deg_c(CTI_HOTEND_2, raw);
1417
+        #elif ENABLED(HEATER_2_USES_AD595)
1418
+          return TEMP_AD595(raw);
1419
+        #elif ENABLED(HEATER_2_USES_AD8495)
1420
+          return TEMP_AD8495(raw);
1421
+        #else
1422
+          break;
1423
+        #endif
1424
+      case 3:
1425
+        #if ENABLED(HEATER_3_USER_THERMISTOR)
1426
+          return user_thermistor_to_deg_c(CTI_HOTEND_3, raw);
1427
+        #elif ENABLED(HEATER_3_USES_AD595)
1428
+          return TEMP_AD595(raw);
1429
+        #elif ENABLED(HEATER_3_USES_AD8495)
1430
+          return TEMP_AD8495(raw);
1431
+        #else
1432
+          break;
1433
+        #endif
1434
+      case 4:
1435
+        #if ENABLED(HEATER_4_USER_THERMISTOR)
1436
+          return user_thermistor_to_deg_c(CTI_HOTEND_4, raw);
1437
+        #elif ENABLED(HEATER_4_USES_AD595)
1438
+          return TEMP_AD595(raw);
1439
+        #elif ENABLED(HEATER_4_USES_AD8495)
1440
+          return TEMP_AD8495(raw);
1441
+        #else
1442
+          break;
1443
+        #endif
1444
+      case 5:
1445
+        #if ENABLED(HEATER_5_USER_THERMISTOR)
1446
+          return user_thermistor_to_deg_c(CTI_HOTEND_5, raw);
1447
+        #elif ENABLED(HEATER_5_USES_AD595)
1448
+          return TEMP_AD595(raw);
1449
+        #elif ENABLED(HEATER_5_USES_AD8495)
1450
+          return TEMP_AD8495(raw);
1451
+        #else
1452
+          break;
1453
+        #endif
1454
+      default: break;
1455
+    }
1444 1456
 
1445
-  #if HOTEND_USES_THERMISTOR
1446
-    // Thermistor with conversion table?
1447
-    const short(*tt)[][2] = (short(*)[][2])(heater_ttbl_map[e]);
1448
-    SCAN_THERMISTOR_TABLE((*tt), heater_ttbllen_map[e]);
1449
-  #endif
1457
+    #if HOTEND_USES_THERMISTOR
1458
+      // Thermistor with conversion table?
1459
+      const short(*tt)[][2] = (short(*)[][2])(heater_ttbl_map[e]);
1460
+      SCAN_THERMISTOR_TABLE((*tt), heater_ttbllen_map[e]);
1461
+    #endif
1450 1462
 
1451
-  return 0;
1452
-}
1463
+    return 0;
1464
+  }
1465
+#endif // HOTENDS
1453 1466
 
1454 1467
 #if HAS_HEATED_BED
1455 1468
   // Derived from RepRap FiveD extruder::getTemperature()
@@ -1500,7 +1513,9 @@ void Temperature::updateTemperaturesFromRawValues() {
1500 1513
   #if ENABLED(HEATER_1_USES_MAX6675)
1501 1514
     temp_hotend[1].raw = READ_MAX6675(1);
1502 1515
   #endif
1503
-  HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e);
1516
+  #if HOTENDS
1517
+    HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e);
1518
+  #endif
1504 1519
   #if HAS_HEATED_BED
1505 1520
     temp_bed.celsius = analog_to_celsius_bed(temp_bed.raw);
1506 1521
   #endif
@@ -1802,7 +1817,7 @@ void Temperature::init() {
1802 1817
       #endif // HOTENDS > 2
1803 1818
     #endif // HOTENDS > 1
1804 1819
 
1805
-  #endif // HOTENDS > 1
1820
+  #endif // HOTENDS
1806 1821
 
1807 1822
   #if HAS_HEATED_BED
1808 1823
     #ifdef BED_MINTEMP
@@ -1976,7 +1991,9 @@ void Temperature::disable_all_heaters() {
1976 1991
     planner.autotemp_enabled = false;
1977 1992
   #endif
1978 1993
 
1979
-  HOTEND_LOOP() setTargetHotend(0, e);
1994
+  #if HOTENDS
1995
+    HOTEND_LOOP() setTargetHotend(0, e);
1996
+  #endif
1980 1997
 
1981 1998
   #if HAS_HEATED_BED
1982 1999
     setTargetBed(0);
@@ -2238,9 +2255,11 @@ void Temperature::readings_ready() {
2238 2255
     current_raw_filwidth = raw_filwidth_value >> 10;  // Divide to get to 0-16384 range since we used 1/128 IIR filter approach
2239 2256
   #endif
2240 2257
 
2241
-  HOTEND_LOOP() temp_hotend[e].reset();
2242
-  #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
2243
-    temp_hotend[1].reset();
2258
+  #if HOTENDS
2259
+    HOTEND_LOOP() temp_hotend[e].reset();
2260
+    #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
2261
+      temp_hotend[1].reset();
2262
+    #endif
2244 2263
   #endif
2245 2264
 
2246 2265
   #if HAS_HEATED_BED
@@ -2261,55 +2280,59 @@ void Temperature::readings_ready() {
2261 2280
     joystick.z.reset();
2262 2281
   #endif
2263 2282
 
2264
-  static constexpr int8_t temp_dir[] = {
2265
-    #if ENABLED(HEATER_0_USES_MAX6675)
2266
-      0
2267
-    #else
2268
-      TEMPDIR(0)
2269
-    #endif
2270
-    #if HOTENDS > 1
2271
-      #if ENABLED(HEATER_1_USES_MAX6675)
2272
-        , 0
2283
+  #if HOTENDS
2284
+
2285
+    static constexpr int8_t temp_dir[] = {
2286
+      #if ENABLED(HEATER_0_USES_MAX6675)
2287
+        0
2273 2288
       #else
2274
-        , TEMPDIR(1)
2289
+        TEMPDIR(0)
2275 2290
       #endif
2276
-      #if HOTENDS > 2
2277
-        , TEMPDIR(2)
2278
-        #if HOTENDS > 3
2279
-          , TEMPDIR(3)
2280
-          #if HOTENDS > 4
2281
-            , TEMPDIR(4)
2282
-            #if HOTENDS > 5
2283
-              , TEMPDIR(5)
2284
-            #endif // HOTENDS > 5
2285
-          #endif // HOTENDS > 4
2286
-        #endif // HOTENDS > 3
2287
-      #endif // HOTENDS > 2
2288
-    #endif // HOTENDS > 1
2289
-  };
2290
-
2291
-  for (uint8_t e = 0; e < COUNT(temp_dir); e++) {
2292
-    const int8_t tdir = temp_dir[e];
2293
-    if (tdir) {
2294
-      const int16_t rawtemp = temp_hotend[e].raw * tdir; // normal direction, +rawtemp, else -rawtemp
2295
-      const bool heater_on = (temp_hotend[e].target > 0
2296
-        #if ENABLED(PIDTEMP)
2297
-          || temp_hotend[e].soft_pwm_amount > 0
2291
+      #if HOTENDS > 1
2292
+        #if ENABLED(HEATER_1_USES_MAX6675)
2293
+          , 0
2294
+        #else
2295
+          , TEMPDIR(1)
2298 2296
         #endif
2299
-      );
2300
-      if (rawtemp > temp_range[e].raw_max * tdir) max_temp_error((heater_ind_t)e);
2301
-      if (heater_on && rawtemp < temp_range[e].raw_min * tdir && !is_preheating(e)) {
2297
+        #if HOTENDS > 2
2298
+          , TEMPDIR(2)
2299
+          #if HOTENDS > 3
2300
+            , TEMPDIR(3)
2301
+            #if HOTENDS > 4
2302
+              , TEMPDIR(4)
2303
+              #if HOTENDS > 5
2304
+                , TEMPDIR(5)
2305
+              #endif // HOTENDS > 5
2306
+            #endif // HOTENDS > 4
2307
+          #endif // HOTENDS > 3
2308
+        #endif // HOTENDS > 2
2309
+      #endif // HOTENDS > 1
2310
+    };
2311
+
2312
+    for (uint8_t e = 0; e < COUNT(temp_dir); e++) {
2313
+      const int8_t tdir = temp_dir[e];
2314
+      if (tdir) {
2315
+        const int16_t rawtemp = temp_hotend[e].raw * tdir; // normal direction, +rawtemp, else -rawtemp
2316
+        const bool heater_on = (temp_hotend[e].target > 0
2317
+          #if ENABLED(PIDTEMP)
2318
+            || temp_hotend[e].soft_pwm_amount > 0
2319
+          #endif
2320
+        );
2321
+        if (rawtemp > temp_range[e].raw_max * tdir) max_temp_error((heater_ind_t)e);
2322
+        if (heater_on && rawtemp < temp_range[e].raw_min * tdir && !is_preheating(e)) {
2323
+          #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
2324
+            if (++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED)
2325
+          #endif
2326
+              min_temp_error((heater_ind_t)e);
2327
+        }
2302 2328
         #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
2303
-          if (++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED)
2329
+          else
2330
+            consecutive_low_temperature_error[e] = 0;
2304 2331
         #endif
2305
-            min_temp_error((heater_ind_t)e);
2306 2332
       }
2307
-      #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
2308
-        else
2309
-          consecutive_low_temperature_error[e] = 0;
2310
-      #endif
2311 2333
     }
2312
-  }
2334
+
2335
+  #endif // HOTENDS
2313 2336
 
2314 2337
   #if HAS_HEATED_BED
2315 2338
     #if TEMPDIR(BED) < 0
@@ -2399,12 +2422,10 @@ void Temperature::isr() {
2399 2422
     static bool ADCKey_pressed = false;
2400 2423
   #endif
2401 2424
 
2402
-  #if ENABLED(SLOW_PWM_HEATERS)
2403
-    static uint8_t slow_pwm_count = 0;
2425
+  #if HOTENDS
2426
+    static SoftPWM soft_pwm_hotend[HOTENDS];
2404 2427
   #endif
2405 2428
 
2406
-  static SoftPWM soft_pwm_hotend[HOTENDS];
2407
-
2408 2429
   #if HAS_HEATED_BED
2409 2430
     static SoftPWM soft_pwm_bed;
2410 2431
   #endif
@@ -2414,40 +2435,46 @@ void Temperature::isr() {
2414 2435
   #endif
2415 2436
 
2416 2437
   #if DISABLED(SLOW_PWM_HEATERS)
2417
-    constexpr uint8_t pwm_mask =
2418
-      #if ENABLED(SOFT_PWM_DITHER)
2419
-        _BV(SOFT_PWM_SCALE) - 1
2420
-      #else
2421
-        0
2422
-      #endif
2423
-    ;
2438
+
2439
+    #if HOTENDS || HAS_HEATED_BED || HAS_HEATED_CHAMBER
2440
+      constexpr uint8_t pwm_mask =
2441
+        #if ENABLED(SOFT_PWM_DITHER)
2442
+          _BV(SOFT_PWM_SCALE) - 1
2443
+        #else
2444
+          0
2445
+        #endif
2446
+      ;
2447
+      #define _PWM_MOD(N,S,T) do{                           \
2448
+        const bool on = S.add(pwm_mask, T.soft_pwm_amount); \
2449
+        WRITE_HEATER_##N(on);                               \
2450
+      }while(0)
2451
+    #endif
2424 2452
 
2425 2453
     /**
2426 2454
      * Standard heater PWM modulation
2427 2455
      */
2428 2456
     if (pwm_count_tmp >= 127) {
2429 2457
       pwm_count_tmp -= 127;
2430
-      #define _PWM_MOD(N,S,T) do{                           \
2431
-        const bool on = S.add(pwm_mask, T.soft_pwm_amount); \
2432
-        WRITE_HEATER_##N(on);                               \
2433
-      }while(0)
2434
-      #define _PWM_MOD_E(N) _PWM_MOD(N,soft_pwm_hotend[N],temp_hotend[N])
2435
-      _PWM_MOD_E(0);
2436
-      #if HOTENDS > 1
2437
-        _PWM_MOD_E(1);
2438
-        #if HOTENDS > 2
2439
-          _PWM_MOD_E(2);
2440
-          #if HOTENDS > 3
2441
-            _PWM_MOD_E(3);
2442
-            #if HOTENDS > 4
2443
-              _PWM_MOD_E(4);
2444
-              #if HOTENDS > 5
2445
-                _PWM_MOD_E(5);
2446
-              #endif // HOTENDS > 5
2447
-            #endif // HOTENDS > 4
2448
-          #endif // HOTENDS > 3
2449
-        #endif // HOTENDS > 2
2450
-      #endif // HOTENDS > 1
2458
+
2459
+      #if HOTENDS
2460
+        #define _PWM_MOD_E(N) _PWM_MOD(N,soft_pwm_hotend[N],temp_hotend[N])
2461
+        _PWM_MOD_E(0);
2462
+        #if HOTENDS > 1
2463
+          _PWM_MOD_E(1);
2464
+          #if HOTENDS > 2
2465
+            _PWM_MOD_E(2);
2466
+            #if HOTENDS > 3
2467
+              _PWM_MOD_E(3);
2468
+              #if HOTENDS > 4
2469
+                _PWM_MOD_E(4);
2470
+                #if HOTENDS > 5
2471
+                  _PWM_MOD_E(5);
2472
+                #endif // HOTENDS > 5
2473
+              #endif // HOTENDS > 4
2474
+            #endif // HOTENDS > 3
2475
+          #endif // HOTENDS > 2
2476
+        #endif // HOTENDS > 1
2477
+      #endif // HOTENDS
2451 2478
 
2452 2479
       #if HAS_HEATED_BED
2453 2480
         _PWM_MOD(BED,soft_pwm_bed,temp_bed);
@@ -2538,6 +2565,8 @@ void Temperature::isr() {
2538 2565
     #define _SLOW_PWM(NR,PWM,SRC) do{ PWM.count = SRC.soft_pwm_amount; _SLOW_SET(NR,PWM,(PWM.count > 0)); }while(0)
2539 2566
     #define _PWM_OFF(NR,PWM) do{ if (PWM.count < slow_pwm_count) _SLOW_SET(NR,PWM,0); }while(0)
2540 2567
 
2568
+    static uint8_t slow_pwm_count = 0;
2569
+
2541 2570
     if (slow_pwm_count == 0) {
2542 2571
 
2543 2572
       #if HOTENDS
@@ -2634,22 +2663,24 @@ void Temperature::isr() {
2634 2663
       slow_pwm_count++;
2635 2664
       slow_pwm_count &= 0x7F;
2636 2665
 
2637
-      soft_pwm_hotend[0].dec();
2638
-      #if HOTENDS > 1
2639
-        soft_pwm_hotend[1].dec();
2640
-        #if HOTENDS > 2
2641
-          soft_pwm_hotend[2].dec();
2642
-          #if HOTENDS > 3
2643
-            soft_pwm_hotend[3].dec();
2644
-            #if HOTENDS > 4
2645
-              soft_pwm_hotend[4].dec();
2646
-              #if HOTENDS > 5
2647
-                soft_pwm_hotend[5].dec();
2648
-              #endif // HOTENDS > 5
2649
-            #endif // HOTENDS > 4
2650
-          #endif // HOTENDS > 3
2651
-        #endif // HOTENDS > 2
2652
-      #endif // HOTENDS > 1
2666
+      #if HOTENDS
2667
+        soft_pwm_hotend[0].dec();
2668
+        #if HOTENDS > 1
2669
+          soft_pwm_hotend[1].dec();
2670
+          #if HOTENDS > 2
2671
+            soft_pwm_hotend[2].dec();
2672
+            #if HOTENDS > 3
2673
+              soft_pwm_hotend[3].dec();
2674
+              #if HOTENDS > 4
2675
+                soft_pwm_hotend[4].dec();
2676
+                #if HOTENDS > 5
2677
+                  soft_pwm_hotend[5].dec();
2678
+                #endif // HOTENDS > 5
2679
+              #endif // HOTENDS > 4
2680
+            #endif // HOTENDS > 3
2681
+          #endif // HOTENDS > 2
2682
+        #endif // HOTENDS > 1
2683
+      #endif // HOTENDS
2653 2684
       #if HAS_HEATED_BED
2654 2685
         soft_pwm_bed.dec();
2655 2686
       #endif
@@ -2940,7 +2971,7 @@ void Temperature::isr() {
2940 2971
 
2941 2972
   #endif // AUTO_REPORT_TEMPERATURES
2942 2973
 
2943
-  #if HAS_DISPLAY
2974
+  #if HOTENDS && HAS_DISPLAY
2944 2975
     void Temperature::set_heating_message(const uint8_t e) {
2945 2976
       const bool heating = isHeatingHotend(e);
2946 2977
       #if HOTENDS > 1

+ 72
- 51
Marlin/src/module/temperature.h View File

@@ -270,11 +270,14 @@ class Temperature {
270 270
 
271 271
     static volatile bool in_temp_isr;
272 272
 
273
-    static hotend_info_t temp_hotend[HOTENDS
273
+    #if HOTENDS
274 274
       #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
275
-        + 1
275
+        #define HOTEND_TEMPS (HOTENDS + 1)
276
+      #else
277
+        #define HOTEND_TEMPS HOTENDS
276 278
       #endif
277
-    ];
279
+      static hotend_info_t temp_hotend[HOTEND_TEMPS];
280
+    #endif
278 281
 
279 282
     #if HAS_HEATED_BED
280 283
       static bed_info_t temp_bed;
@@ -349,7 +352,9 @@ class Temperature {
349 352
       static lpq_ptr_t lpq_ptr;
350 353
     #endif
351 354
 
352
-    static temp_range_t temp_range[HOTENDS];
355
+    #if HOTENDS
356
+      static temp_range_t temp_range[HOTENDS];
357
+    #endif
353 358
 
354 359
     #if HAS_HEATED_BED
355 360
       #if WATCH_BED
@@ -417,8 +422,6 @@ class Temperature {
417 422
      * Instance Methods
418 423
      */
419 424
 
420
-    Temperature();
421
-
422 425
     void init();
423 426
 
424 427
     /**
@@ -456,7 +459,9 @@ class Temperature {
456 459
       }
457 460
     #endif
458 461
 
459
-    static float analog_to_celsius_hotend(const int raw, const uint8_t e);
462
+    #if HOTENDS
463
+      static float analog_to_celsius_hotend(const int raw, const uint8_t e);
464
+    #endif
460 465
 
461 466
     #if HAS_HEATED_BED
462 467
       static float analog_to_celsius_bed(const int raw);
@@ -577,19 +582,31 @@ class Temperature {
577 582
 
578 583
     FORCE_INLINE static float degHotend(const uint8_t e) {
579 584
       E_UNUSED();
580
-      return temp_hotend[HOTEND_INDEX].celsius;
585
+      #if HOTENDS
586
+        return temp_hotend[HOTEND_INDEX].celsius;
587
+      #else
588
+        return 0;
589
+      #endif
581 590
     }
582 591
 
583 592
     #if ENABLED(SHOW_TEMP_ADC_VALUES)
584 593
       FORCE_INLINE static int16_t rawHotendTemp(const uint8_t e) {
585 594
         E_UNUSED();
586
-        return temp_hotend[HOTEND_INDEX].raw;
595
+        #if HOTENDS
596
+          return temp_hotend[HOTEND_INDEX].raw;
597
+        #else
598
+          return 0;
599
+        #endif
587 600
       }
588 601
     #endif
589 602
 
590 603
     FORCE_INLINE static int16_t degTargetHotend(const uint8_t e) {
591 604
       E_UNUSED();
592
-      return temp_hotend[HOTEND_INDEX].target;
605
+      #if HOTENDS
606
+        return temp_hotend[HOTEND_INDEX].target;
607
+      #else
608
+        return 0;
609
+      #endif
593 610
     }
594 611
 
595 612
     #if WATCH_HOTENDS
@@ -598,52 +615,56 @@ class Temperature {
598 615
       static inline void start_watching_hotend(const uint8_t e=0) { UNUSED(e); }
599 616
     #endif
600 617
 
601
-    #if HAS_LCD_MENU
602
-      static inline void start_watching_E0() { start_watching_hotend(0); }
603
-      static inline void start_watching_E1() { start_watching_hotend(1); }
604
-      static inline void start_watching_E2() { start_watching_hotend(2); }
605
-      static inline void start_watching_E3() { start_watching_hotend(3); }
606
-      static inline void start_watching_E4() { start_watching_hotend(4); }
607
-      static inline void start_watching_E5() { start_watching_hotend(5); }
608
-    #endif
618
+    #if HOTENDS
609 619
 
610
-    static void setTargetHotend(const int16_t celsius, const uint8_t e) {
611
-      E_UNUSED();
612
-      const uint8_t ee = HOTEND_INDEX;
613
-      #ifdef MILLISECONDS_PREHEAT_TIME
614
-        if (celsius == 0)
615
-          reset_preheat_time(ee);
616
-        else if (temp_hotend[ee].target == 0)
617
-          start_preheat_time(ee);
618
-      #endif
619
-      #if ENABLED(AUTO_POWER_CONTROL)
620
-        powerManager.power_on();
621
-      #endif
622
-      temp_hotend[ee].target = _MIN(celsius, temp_range[ee].maxtemp - 15);
623
-      start_watching_hotend(ee);
624
-    }
620
+      #if HAS_LCD_MENU
621
+        static inline void start_watching_E0() { start_watching_hotend(0); }
622
+        static inline void start_watching_E1() { start_watching_hotend(1); }
623
+        static inline void start_watching_E2() { start_watching_hotend(2); }
624
+        static inline void start_watching_E3() { start_watching_hotend(3); }
625
+        static inline void start_watching_E4() { start_watching_hotend(4); }
626
+        static inline void start_watching_E5() { start_watching_hotend(5); }
627
+      #endif
625 628
 
626
-    FORCE_INLINE static bool isHeatingHotend(const uint8_t e) {
627
-      E_UNUSED();
628
-      return temp_hotend[HOTEND_INDEX].target > temp_hotend[HOTEND_INDEX].celsius;
629
-    }
629
+      static void setTargetHotend(const int16_t celsius, const uint8_t e) {
630
+        E_UNUSED();
631
+        const uint8_t ee = HOTEND_INDEX;
632
+        #ifdef MILLISECONDS_PREHEAT_TIME
633
+          if (celsius == 0)
634
+            reset_preheat_time(ee);
635
+          else if (temp_hotend[ee].target == 0)
636
+            start_preheat_time(ee);
637
+        #endif
638
+        #if ENABLED(AUTO_POWER_CONTROL)
639
+          powerManager.power_on();
640
+        #endif
641
+        temp_hotend[ee].target = _MIN(celsius, temp_range[ee].maxtemp - 15);
642
+        start_watching_hotend(ee);
643
+      }
630 644
 
631
-    FORCE_INLINE static bool isCoolingHotend(const uint8_t e) {
632
-      E_UNUSED();
633
-      return temp_hotend[HOTEND_INDEX].target < temp_hotend[HOTEND_INDEX].celsius;
634
-    }
645
+      FORCE_INLINE static bool isHeatingHotend(const uint8_t e) {
646
+        E_UNUSED();
647
+        return temp_hotend[HOTEND_INDEX].target > temp_hotend[HOTEND_INDEX].celsius;
648
+      }
635 649
 
636
-    #if HAS_TEMP_HOTEND
637
-      static bool wait_for_hotend(const uint8_t target_extruder, const bool no_wait_for_cooling=true
638
-        #if G26_CLICK_CAN_CANCEL
639
-          , const bool click_to_cancel=false
640
-        #endif
641
-      );
642
-    #endif
650
+      FORCE_INLINE static bool isCoolingHotend(const uint8_t e) {
651
+        E_UNUSED();
652
+        return temp_hotend[HOTEND_INDEX].target < temp_hotend[HOTEND_INDEX].celsius;
653
+      }
643 654
 
644
-    FORCE_INLINE static bool still_heating(const uint8_t e) {
645
-      return degTargetHotend(e) > TEMP_HYSTERESIS && ABS(degHotend(e) - degTargetHotend(e)) > TEMP_HYSTERESIS;
646
-    }
655
+      #if HAS_TEMP_HOTEND
656
+        static bool wait_for_hotend(const uint8_t target_extruder, const bool no_wait_for_cooling=true
657
+          #if G26_CLICK_CAN_CANCEL
658
+            , const bool click_to_cancel=false
659
+          #endif
660
+        );
661
+      #endif
662
+
663
+      FORCE_INLINE static bool still_heating(const uint8_t e) {
664
+        return degTargetHotend(e) > TEMP_HYSTERESIS && ABS(degHotend(e) - degTargetHotend(e)) > TEMP_HYSTERESIS;
665
+      }
666
+
667
+    #endif // HOTENDS
647 668
 
648 669
     #if HAS_HEATED_BED
649 670
 

+ 12
- 5
Marlin/src/module/tool_change.cpp View File

@@ -695,11 +695,13 @@ inline void fast_line_to_current(const AxisEnum fr_axis) {
695 695
 
696 696
 #endif // ELECTROMAGNETIC_SWITCHING_TOOLHEAD
697 697
 
698
-inline void invalid_extruder_error(const uint8_t e) {
699
-  SERIAL_ECHO_START();
700
-  SERIAL_CHAR('T'); SERIAL_ECHO(int(e));
701
-  SERIAL_CHAR(' '); SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER);
702
-}
698
+#if EXTRUDERS
699
+  inline void invalid_extruder_error(const uint8_t e) {
700
+    SERIAL_ECHO_START();
701
+    SERIAL_CHAR('T'); SERIAL_ECHO(int(e));
702
+    SERIAL_CHAR(' '); SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER);
703
+  }
704
+#endif
703 705
 
704 706
 #if ENABLED(DUAL_X_CARRIAGE)
705 707
 
@@ -788,6 +790,11 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
788 790
 
789 791
     mmu2.tool_change(new_tool);
790 792
 
793
+  #elif EXTRUDERS == 0
794
+
795
+    // Nothing to do
796
+    UNUSED(new_tool); UNUSED(no_move);
797
+
791 798
   #elif EXTRUDERS < 2
792 799
 
793 800
     UNUSED(no_move);

Loading…
Cancel
Save