More "zero extruders" changes (#15213)
This commit is contained in:
		| @@ -175,7 +175,9 @@ void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*= | ||||
|       info.active_extruder = active_extruder; | ||||
|     #endif | ||||
|  | ||||
|     HOTEND_LOOP() info.target_temperature[e] = thermalManager.temp_hotend[e].target; | ||||
|     #if EXTRUDERS | ||||
|       HOTEND_LOOP() info.target_temperature[e] = thermalManager.temp_hotend[e].target; | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_HEATED_BED | ||||
|       info.target_temperature_bed = thermalManager.temp_bed.target; | ||||
| @@ -297,17 +299,19 @@ void PrintJobRecovery::resume() { | ||||
|   #endif | ||||
|  | ||||
|   // Restore all hotend temperatures | ||||
|   HOTEND_LOOP() { | ||||
|     const int16_t et = info.target_temperature[e]; | ||||
|     if (et) { | ||||
|       #if HOTENDS > 1 | ||||
|         sprintf_P(cmd, PSTR("T%i"), e); | ||||
|   #if HOTENDS | ||||
|     HOTEND_LOOP() { | ||||
|       const int16_t et = info.target_temperature[e]; | ||||
|       if (et) { | ||||
|         #if HOTENDS > 1 | ||||
|           sprintf_P(cmd, PSTR("T%i"), e); | ||||
|           gcode.process_subcommands_now(cmd); | ||||
|         #endif | ||||
|         sprintf_P(cmd, PSTR("M109 S%i"), et); | ||||
|         gcode.process_subcommands_now(cmd); | ||||
|       #endif | ||||
|       sprintf_P(cmd, PSTR("M109 S%i"), et); | ||||
|       gcode.process_subcommands_now(cmd); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   #endif | ||||
|  | ||||
|   // Restore print cooling fan speeds | ||||
|   FANS_LOOP(i) { | ||||
| @@ -452,12 +456,14 @@ void PrintJobRecovery::resume() { | ||||
|           DEBUG_ECHOLNPAIR("active_extruder: ", int(info.active_extruder)); | ||||
|         #endif | ||||
|  | ||||
|         DEBUG_ECHOPGM("target_temperature: "); | ||||
|         HOTEND_LOOP() { | ||||
|           DEBUG_ECHO(info.target_temperature[e]); | ||||
|           if (e < HOTENDS - 1) DEBUG_CHAR(','); | ||||
|         } | ||||
|         DEBUG_EOL(); | ||||
|         #if HOTENDS | ||||
|           DEBUG_ECHOPGM("target_temperature: "); | ||||
|           HOTEND_LOOP() { | ||||
|             DEBUG_ECHO(info.target_temperature[e]); | ||||
|             if (e < HOTENDS - 1) DEBUG_CHAR(','); | ||||
|           } | ||||
|           DEBUG_EOL(); | ||||
|         #endif | ||||
|  | ||||
|         #if HAS_HEATED_BED | ||||
|           DEBUG_ECHOLNPAIR("target_temperature_bed: ", info.target_temperature_bed); | ||||
|   | ||||
| @@ -59,7 +59,9 @@ typedef struct { | ||||
|     uint8_t active_extruder; | ||||
|   #endif | ||||
|  | ||||
|   int16_t target_temperature[HOTENDS]; | ||||
|   #if HOTENDS | ||||
|     int16_t target_temperature[HOTENDS]; | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_HEATED_BED | ||||
|     int16_t target_temperature_bed; | ||||
|   | ||||
| @@ -23,6 +23,8 @@ | ||||
| #include "../gcode.h" | ||||
| #include "../../module/planner.h" | ||||
|  | ||||
| #if EXTRUDERS | ||||
|  | ||||
| /** | ||||
|  * M221: Set extrusion percentage (M221 T0 S95) | ||||
|  */ | ||||
| @@ -44,3 +46,5 @@ void GcodeSuite::M221() { | ||||
|     SERIAL_EOL(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| #endif // EXTRUDERS | ||||
|   | ||||
| @@ -400,8 +400,18 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|         case 100: M100(); break;                                  // M100: Free Memory Report | ||||
|       #endif | ||||
|  | ||||
|       case 104: M104(); break;                                    // M104: Set hot end temperature | ||||
|       case 109: M109(); break;                                    // M109: Wait for hotend temperature to reach target | ||||
|       #if EXTRUDERS | ||||
|         case 104: M104(); break;                                  // M104: Set hot end temperature | ||||
|         case 109: M109(); break;                                  // M109: Wait for hotend temperature to reach target | ||||
|       #endif | ||||
|  | ||||
|       case 105: M105(); return;                                   // M105: Report Temperatures (and say "ok") | ||||
|  | ||||
|       #if FAN_COUNT > 0 | ||||
|         case 106: M106(); break;                                  // M106: Fan On | ||||
|         case 107: M107(); break;                                  // M107: Fan Off | ||||
|       #endif | ||||
|  | ||||
|       case 110: M110(); break;                                    // M110: Set Current Line Number | ||||
|       case 111: M111(); break;                                    // M111: Set debug level | ||||
|  | ||||
| @@ -410,7 +420,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|         case 112: M112(); break;                                  // M112: Full Shutdown | ||||
|         case 410: M410(); break;                                  // M410: Quickstop - Abort all the planned moves. | ||||
|         #if ENABLED(HOST_PROMPT_SUPPORT) | ||||
|           case 876: M876(); break;                                  // M876: Handle Host prompt responses | ||||
|           case 876: M876(); break;                                // M876: Handle Host prompt responses | ||||
|         #endif | ||||
|       #else | ||||
|         case 108: case 112: case 410: | ||||
| @@ -434,17 +444,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|         //case 191: M191(); break;                                // M191: Wait for chamber temperature to reach target | ||||
|       #endif | ||||
|  | ||||
|       case 105: M105(); return;                                   // M105: Report Temperatures (and say "ok") | ||||
|  | ||||
|       #if ENABLED(AUTO_REPORT_TEMPERATURES) && HAS_TEMP_SENSOR | ||||
|         case 155: M155(); break;                                  // M155: Set temperature auto-report interval | ||||
|       #endif | ||||
|  | ||||
|       #if FAN_COUNT > 0 | ||||
|         case 106: M106(); break;                                  // M106: Fan On | ||||
|         case 107: M107(); break;                                  // M107: Fan Off | ||||
|       #endif | ||||
|  | ||||
|       #if ENABLED(PARK_HEAD_ON_PAUSE) | ||||
|         case 125: M125(); break;                                  // M125: Store current position and move to filament change position | ||||
|       #endif | ||||
| @@ -481,7 +484,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|       case 120: M120(); break;                                    // M120: Enable endstops | ||||
|       case 121: M121(); break;                                    // M121: Disable endstops | ||||
|  | ||||
|       #if HAS_LCD_MENU | ||||
|       #if HOTENDS && HAS_LCD_MENU | ||||
|         case 145: M145(); break;                                  // M145: Set material heatup parameters | ||||
|       #endif | ||||
|  | ||||
| @@ -553,7 +556,11 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|       #endif | ||||
|  | ||||
|       case 220: M220(); break;                                    // M220: Set Feedrate Percentage: S<percent> ("FR" on your LCD) | ||||
|       case 221: M221(); break;                                    // M221: Set Flow Percentage | ||||
|  | ||||
|       #if EXTRUDERS | ||||
|         case 221: M221(); break;                                  // M221: Set Flow Percentage | ||||
|       #endif | ||||
|  | ||||
|       case 226: M226(); break;                                    // M226: Wait until a pin reaches a state | ||||
|  | ||||
|       #if HAS_SERVOS | ||||
|   | ||||
| @@ -543,10 +543,17 @@ private: | ||||
|     static void M100(); | ||||
|   #endif | ||||
|  | ||||
|   static void M104(); | ||||
|   #if EXTRUDERS | ||||
|     static void M104(); | ||||
|     static void M109(); | ||||
|   #endif | ||||
|  | ||||
|   static void M105(); | ||||
|   static void M106(); | ||||
|   static void M107(); | ||||
|  | ||||
|   #if FAN_COUNT > 0 | ||||
|     static void M106(); | ||||
|     static void M107(); | ||||
|   #endif | ||||
|  | ||||
|   #if DISABLED(EMERGENCY_PARSER) | ||||
|     static void M108(); | ||||
| @@ -557,8 +564,6 @@ private: | ||||
|     #endif | ||||
|   #endif | ||||
|  | ||||
|   static void M109(); | ||||
|  | ||||
|   static void M110(); | ||||
|   static void M111(); | ||||
|  | ||||
| @@ -599,7 +604,7 @@ private: | ||||
|     //static void M191(); | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_LCD_MENU | ||||
|   #if HOTENDS && HAS_LCD_MENU | ||||
|     static void M145(); | ||||
|   #endif | ||||
|  | ||||
| @@ -660,7 +665,11 @@ private: | ||||
|   #endif | ||||
|  | ||||
|   static void M220(); | ||||
|   static void M221(); | ||||
|  | ||||
|   #if EXTRUDERS | ||||
|     static void M221(); | ||||
|   #endif | ||||
|  | ||||
|   static void M226(); | ||||
|  | ||||
|   #if ENABLED(PHOTO_GCODE) | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
|  | ||||
| #include "../../inc/MarlinConfig.h" | ||||
|  | ||||
| #if HAS_LCD_MENU | ||||
| #if HOTENDS && HAS_LCD_MENU | ||||
|  | ||||
| #include "../gcode.h" | ||||
| #include "../../lcd/ultralcd.h" | ||||
| @@ -58,4 +58,4 @@ void GcodeSuite::M145() { | ||||
|   } | ||||
| } | ||||
|  | ||||
| #endif // HAS_LCD_MENU | ||||
| #endif // HOTENDS && HAS_LCD_MENU | ||||
|   | ||||
| @@ -20,6 +20,10 @@ | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
|  | ||||
| #if EXTRUDERS | ||||
|  | ||||
| #include "../gcode.h" | ||||
| #include "../../module/temperature.h" | ||||
| #include "../../module/motion.h" | ||||
| @@ -138,3 +142,5 @@ void GcodeSuite::M109() { | ||||
|   if (set_temp) | ||||
|     (void)thermalManager.wait_for_hotend(target_extruder, no_wait_for_cooling); | ||||
| } | ||||
|  | ||||
| #endif // EXTRUDERS | ||||
|   | ||||
| @@ -26,6 +26,34 @@ | ||||
|  * Defines that depend on advanced configuration. | ||||
|  */ | ||||
|  | ||||
| #if EXTRUDERS == 0 | ||||
|   #define NO_VOLUMETRICS | ||||
|   #undef TEMP_SENSOR_0 | ||||
|   #undef TEMP_SENSOR_1 | ||||
|   #undef TEMP_SENSOR_2 | ||||
|   #undef TEMP_SENSOR_3 | ||||
|   #undef TEMP_SENSOR_4 | ||||
|   #undef TEMP_SENSOR_5 | ||||
|   #undef FWRETRACT | ||||
|   #undef PIDTEMP | ||||
|   #undef AUTOTEMP | ||||
|   #undef PID_EXTRUSION_SCALING | ||||
|   #undef LIN_ADVANCE | ||||
|   #undef FILAMENT_RUNOUT_SENSOR | ||||
|   #undef ADVANCED_PAUSE_FEATURE | ||||
|   #undef FILAMENT_RUNOUT_DISTANCE_MM | ||||
|   #undef FILAMENT_LOAD_UNLOAD_GCODES | ||||
|   #undef DISABLE_INACTIVE_EXTRUDER | ||||
|   #undef FILAMENT_LOAD_UNLOAD_GCODES | ||||
|   #undef EXTRUDER_RUNOUT_PREVENT | ||||
|   #undef PREVENT_COLD_EXTRUSION | ||||
|   #undef PREVENT_LENGTHY_EXTRUDE | ||||
|   #undef THERMAL_PROTECTION_HOTENDS | ||||
|   #undef THERMAL_PROTECTION_PERIOD | ||||
|   #undef WATCH_TEMP_PERIOD | ||||
|   #undef SHOW_TEMP_ADC_VALUES | ||||
| #endif | ||||
|  | ||||
| #define HAS_CUTTER EITHER(SPINDLE_FEATURE, LASER_FEATURE) | ||||
|  | ||||
| #if !defined(__AVR__) || !defined(USBCON) | ||||
|   | ||||
| @@ -43,16 +43,6 @@ | ||||
|   #define NOT_A_PIN 0 // For PINS_DEBUGGING | ||||
| #endif | ||||
|  | ||||
| #if EXTRUDERS == 0 | ||||
|   #define NO_VOLUMETRICS | ||||
|   #undef FWRETRACT | ||||
|   #undef LIN_ADVANCE | ||||
|   #undef ADVANCED_PAUSE_FEATURE | ||||
|   #undef DISABLE_INACTIVE_EXTRUDER | ||||
|   #undef EXTRUDER_RUNOUT_PREVENT | ||||
|   #undef FILAMENT_LOAD_UNLOAD_GCODES | ||||
| #endif | ||||
|  | ||||
| #define HAS_CLASSIC_JERK (IS_KINEMATIC || DISABLED(JUNCTION_DEVIATION)) | ||||
|  | ||||
| /** | ||||
| @@ -1047,6 +1037,10 @@ | ||||
| #define BED_OR_CHAMBER (HAS_HEATED_BED || HAS_TEMP_CHAMBER) | ||||
| #define HAS_TEMP_SENSOR (HAS_TEMP_HOTEND || BED_OR_CHAMBER) | ||||
|  | ||||
| #if !HAS_TEMP_SENSOR | ||||
|   #undef AUTO_REPORT_TEMPERATURES | ||||
| #endif | ||||
|  | ||||
| // PID heating | ||||
| #if !HAS_HEATED_BED | ||||
|   #undef PIDTEMPBED | ||||
|   | ||||
| @@ -1476,8 +1476,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS | ||||
|   #error "E0_STEP_PIN or E0_DIR_PIN not defined for this board." | ||||
| #elif ( !(defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && (!PIN_EXISTS(E0_STEP, E0_DIR) || !HAS_E0_ENABLE)) | ||||
|   #error "E0_STEP_PIN, E0_DIR_PIN, or E0_ENABLE_PIN not defined for this board." | ||||
| #elif TEMP_SENSOR_0 == 0 | ||||
|   #error "TEMP_SENSOR_0 is required." | ||||
| #elif EXTRUDERS && TEMP_SENSOR_0 == 0 | ||||
|   #error "TEMP_SENSOR_0 is required with any extruders." | ||||
| #endif | ||||
|  | ||||
| // Pins are required for heaters | ||||
|   | ||||
| @@ -866,7 +866,11 @@ void MarlinUI::draw_status_screen() { | ||||
|           char c; | ||||
|           uint16_t per; | ||||
|           #if HAS_FAN0 | ||||
|             if (blink || thermalManager.fan_speed_scaler[0] < 128) { | ||||
|             if (true | ||||
|               #if EXTRUDERS | ||||
|                 && (blink || thermalManager.fan_speed_scaler[0] < 128) | ||||
|               #endif | ||||
|             ) { | ||||
|               uint16_t spd = thermalManager.fan_speed[0]; | ||||
|               if (blink) c = 'F'; | ||||
|               #if ENABLED(ADAPTIVE_FAN_SLOWING) | ||||
| @@ -877,8 +881,10 @@ void MarlinUI::draw_status_screen() { | ||||
|             else | ||||
|           #endif | ||||
|             { | ||||
|               c = 'E'; | ||||
|               per = planner.flow_percentage[0]; | ||||
|               #if EXTRUDERS | ||||
|                 c = 'E'; | ||||
|                 per = planner.flow_percentage[0]; | ||||
|               #endif | ||||
|             } | ||||
|           lcd_put_wchar(c); | ||||
|           lcd_put_u8str(i16tostr3(per)); | ||||
|   | ||||
| @@ -69,10 +69,28 @@ | ||||
|     // | ||||
|     #if HAS_HEATED_BED && HOTENDS <= 4 | ||||
|  | ||||
|       #if HOTENDS == 1 | ||||
|       #if HOTENDS == 0 | ||||
|  | ||||
|         #define STATUS_HEATERS_WIDTH 96 | ||||
|  | ||||
|         const unsigned char status_heaters_bmp[] PROGMEM = { | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000010,B00001000,B00100000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00010000,B01000001,B00000000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,B00100000,B10000000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000, | ||||
|           B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B11111000 | ||||
|         }; | ||||
|  | ||||
|       #elif HOTENDS == 1 | ||||
|  | ||||
|         #define STATUS_HEATERS_WIDTH 96 | ||||
|         #define STATUS_BED_TEXT_X   (STATUS_HEATERS_WIDTH - 10) | ||||
|  | ||||
|         const unsigned char status_heaters_bmp[] PROGMEM = { | ||||
|           B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, | ||||
| @@ -92,7 +110,6 @@ | ||||
|       #elif HOTENDS == 2 | ||||
|  | ||||
|         #define STATUS_HEATERS_WIDTH 96 | ||||
|         #define STATUS_BED_TEXT_X   (STATUS_HEATERS_WIDTH - 10) | ||||
|  | ||||
|         const unsigned char status_heaters_bmp[] PROGMEM = { | ||||
|           B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, | ||||
| @@ -112,7 +129,6 @@ | ||||
|       #elif HOTENDS == 3 | ||||
|  | ||||
|         #define STATUS_HEATERS_WIDTH 96 | ||||
|         #define STATUS_BED_TEXT_X   (STATUS_HEATERS_WIDTH - 10) | ||||
|  | ||||
|         const unsigned char status_heaters_bmp[] PROGMEM = { | ||||
|           B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000100,B00010000,B01000000, | ||||
| @@ -132,7 +148,6 @@ | ||||
|       #else // HOTENDS > 3 | ||||
|  | ||||
|         #define STATUS_HEATERS_WIDTH 120 | ||||
|         #define STATUS_BED_TEXT_X   (STATUS_HEATERS_WIDTH - 10) | ||||
|  | ||||
|         const unsigned char status_heaters_bmp[] PROGMEM = { | ||||
|           B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000100,B00010000,B01000000, | ||||
| @@ -151,9 +166,15 @@ | ||||
|  | ||||
|       #endif // HOTENDS | ||||
|  | ||||
|       #define STATUS_BED_TEXT_X (STATUS_HEATERS_WIDTH - 10) | ||||
|  | ||||
|     #else // !HAS_HEATED_BED || HOTENDS > 3 | ||||
|  | ||||
|       #if HOTENDS == 1 | ||||
|       #if HOTENDS == 0 | ||||
|  | ||||
|         #define STATUS_HEATERS_WIDTH  0 | ||||
|  | ||||
|       #elif HOTENDS == 1 | ||||
|  | ||||
|         #define STATUS_HEATERS_WIDTH  12 | ||||
|  | ||||
| @@ -229,7 +250,7 @@ | ||||
|           B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000,B00000000,B00000011,B00000000 | ||||
|         }; | ||||
|  | ||||
|       #elif HOTENDS > 4 | ||||
|       #else // HOTENDS > 4 | ||||
|  | ||||
|         #define STATUS_HEATERS_WIDTH  108 | ||||
|  | ||||
| @@ -304,105 +325,101 @@ | ||||
|  | ||||
|         #endif | ||||
|  | ||||
|       #else | ||||
|       #elif HOTENDS >= 2 | ||||
|  | ||||
|         #if HOTENDS >= 2 | ||||
|         #ifdef STATUS_HOTEND_ANIM | ||||
|  | ||||
|           #ifdef STATUS_HOTEND_ANIM | ||||
|           const unsigned char status_hotend1_a_bmp[] PROGMEM = { | ||||
|             B00011111,B11100000, | ||||
|             B00111111,B11110000, | ||||
|             B00111110,B11110000, | ||||
|             B00111100,B11110000, | ||||
|             B00011010,B11100000, | ||||
|             B00011110,B11100000, | ||||
|             B00111110,B11110000, | ||||
|             B00111110,B11110000, | ||||
|             B00111110,B11110000, | ||||
|             B00001111,B11000000, | ||||
|             B00000111,B10000000, | ||||
|             B00000011,B00000000 | ||||
|           }; | ||||
|  | ||||
|             const unsigned char status_hotend1_a_bmp[] PROGMEM = { | ||||
|               B00011111,B11100000, | ||||
|               B00111111,B11110000, | ||||
|               B00111110,B11110000, | ||||
|               B00111100,B11110000, | ||||
|               B00011010,B11100000, | ||||
|               B00011110,B11100000, | ||||
|               B00111110,B11110000, | ||||
|               B00111110,B11110000, | ||||
|               B00111110,B11110000, | ||||
|               B00001111,B11000000, | ||||
|               B00000111,B10000000, | ||||
|               B00000011,B00000000 | ||||
|             }; | ||||
|           const unsigned char status_hotend1_b_bmp[] PROGMEM = { | ||||
|             B00011111,B11100000, | ||||
|             B00100000,B00010000, | ||||
|             B00100001,B00010000, | ||||
|             B00100011,B00010000, | ||||
|             B00010101,B00100000, | ||||
|             B00010001,B00100000, | ||||
|             B00100001,B00010000, | ||||
|             B00100001,B00010000, | ||||
|             B00110001,B00110000, | ||||
|             B00001000,B01000000, | ||||
|             B00000100,B10000000, | ||||
|             B00000011,B00000000 | ||||
|           }; | ||||
|  | ||||
|             const unsigned char status_hotend1_b_bmp[] PROGMEM = { | ||||
|               B00011111,B11100000, | ||||
|               B00100000,B00010000, | ||||
|               B00100001,B00010000, | ||||
|               B00100011,B00010000, | ||||
|               B00010101,B00100000, | ||||
|               B00010001,B00100000, | ||||
|               B00100001,B00010000, | ||||
|               B00100001,B00010000, | ||||
|               B00110001,B00110000, | ||||
|               B00001000,B01000000, | ||||
|               B00000100,B10000000, | ||||
|               B00000011,B00000000 | ||||
|             }; | ||||
|           const unsigned char status_hotend2_a_bmp[] PROGMEM = { | ||||
|             B00011111,B11100000, | ||||
|             B00111111,B11110000, | ||||
|             B00111100,B11110000, | ||||
|             B00111011,B01110000, | ||||
|             B00011111,B01100000, | ||||
|             B00011110,B11100000, | ||||
|             B00111101,B11110000, | ||||
|             B00111011,B11110000, | ||||
|             B00111000,B01110000, | ||||
|             B00001111,B11000000, | ||||
|             B00000111,B10000000, | ||||
|             B00000011,B00000000 | ||||
|           }; | ||||
|  | ||||
|             const unsigned char status_hotend2_a_bmp[] PROGMEM = { | ||||
|               B00011111,B11100000, | ||||
|               B00111111,B11110000, | ||||
|               B00111100,B11110000, | ||||
|               B00111011,B01110000, | ||||
|               B00011111,B01100000, | ||||
|               B00011110,B11100000, | ||||
|               B00111101,B11110000, | ||||
|               B00111011,B11110000, | ||||
|               B00111000,B01110000, | ||||
|               B00001111,B11000000, | ||||
|               B00000111,B10000000, | ||||
|               B00000011,B00000000 | ||||
|             }; | ||||
|           const unsigned char status_hotend2_b_bmp[] PROGMEM = { | ||||
|             B00011111,B11100000, | ||||
|             B00100000,B00010000, | ||||
|             B00100011,B00010000, | ||||
|             B00100100,B10010000, | ||||
|             B00010000,B10100000, | ||||
|             B00010001,B00100000, | ||||
|             B00100010,B00010000, | ||||
|             B00100100,B00010000, | ||||
|             B00110111,B10110000, | ||||
|             B00001000,B01000000, | ||||
|             B00000100,B10000000, | ||||
|             B00000011,B00000000 | ||||
|           }; | ||||
|  | ||||
|             const unsigned char status_hotend2_b_bmp[] PROGMEM = { | ||||
|               B00011111,B11100000, | ||||
|               B00100000,B00010000, | ||||
|               B00100011,B00010000, | ||||
|               B00100100,B10010000, | ||||
|               B00010000,B10100000, | ||||
|               B00010001,B00100000, | ||||
|               B00100010,B00010000, | ||||
|               B00100100,B00010000, | ||||
|               B00110111,B10110000, | ||||
|               B00001000,B01000000, | ||||
|               B00000100,B10000000, | ||||
|               B00000011,B00000000 | ||||
|             }; | ||||
|         #else | ||||
|  | ||||
|           #else | ||||
|           const unsigned char status_hotend1_a_bmp[] PROGMEM = { | ||||
|             B00011111,B11100000, | ||||
|             B00111110,B11110000, | ||||
|             B00111100,B11110000, | ||||
|             B00111010,B11110000, | ||||
|             B00011110,B11100000, | ||||
|             B00011110,B11100000, | ||||
|             B00111110,B11110000, | ||||
|             B00111110,B11110000, | ||||
|             B00111111,B11110000, | ||||
|             B00001111,B11000000, | ||||
|             B00000111,B10000000, | ||||
|             B00000011,B00000000 | ||||
|           }; | ||||
|  | ||||
|             const unsigned char status_hotend1_a_bmp[] PROGMEM = { | ||||
|               B00011111,B11100000, | ||||
|               B00111110,B11110000, | ||||
|               B00111100,B11110000, | ||||
|               B00111010,B11110000, | ||||
|               B00011110,B11100000, | ||||
|               B00011110,B11100000, | ||||
|               B00111110,B11110000, | ||||
|               B00111110,B11110000, | ||||
|               B00111111,B11110000, | ||||
|               B00001111,B11000000, | ||||
|               B00000111,B10000000, | ||||
|               B00000011,B00000000 | ||||
|             }; | ||||
|  | ||||
|             const unsigned char status_hotend2_a_bmp[] PROGMEM = { | ||||
|               B00011111,B11100000, | ||||
|               B00111100,B11110000, | ||||
|               B00111011,B01110000, | ||||
|               B00111111,B01110000, | ||||
|               B00011110,B11100000, | ||||
|               B00011101,B11100000, | ||||
|               B00111011,B11110000, | ||||
|               B00111000,B01110000, | ||||
|               B00111111,B11110000, | ||||
|               B00001111,B11000000, | ||||
|               B00000111,B10000000, | ||||
|               B00000011,B00000000 | ||||
|             }; | ||||
|  | ||||
|           #endif | ||||
|           const unsigned char status_hotend2_a_bmp[] PROGMEM = { | ||||
|             B00011111,B11100000, | ||||
|             B00111100,B11110000, | ||||
|             B00111011,B01110000, | ||||
|             B00111111,B01110000, | ||||
|             B00011110,B11100000, | ||||
|             B00011101,B11100000, | ||||
|             B00111011,B11110000, | ||||
|             B00111000,B01110000, | ||||
|             B00111111,B11110000, | ||||
|             B00001111,B11000000, | ||||
|             B00000111,B10000000, | ||||
|             B00000011,B00000000 | ||||
|           }; | ||||
|  | ||||
|         #endif | ||||
|  | ||||
| @@ -573,6 +590,8 @@ | ||||
|  | ||||
|       #endif | ||||
|  | ||||
|     #else | ||||
|       #define STATUS_HEATERS_HEIGHT 20 | ||||
|     #endif | ||||
|  | ||||
|   #endif | ||||
| @@ -1431,6 +1450,10 @@ | ||||
|     "Status heaters bitmap (status_heaters_bmp) dimensions don't match data." | ||||
|   ); | ||||
|  | ||||
| #else // HOTENDS == 0 | ||||
|  | ||||
|   //#error "Incomplete status header" | ||||
|  | ||||
| #endif | ||||
|  | ||||
| // | ||||
|   | ||||
| @@ -93,7 +93,10 @@ | ||||
|   #define CHAMBER_ALT() false | ||||
| #endif | ||||
|  | ||||
| #define MAX_HOTEND_DRAW _MIN(HOTENDS, ((LCD_PIXEL_WIDTH - (STATUS_LOGO_BYTEWIDTH + STATUS_FAN_BYTEWIDTH) * 8) / (STATUS_HEATERS_XSPACE))) | ||||
| #if HOTENDS | ||||
|   #define MAX_HOTEND_DRAW _MIN(HOTENDS, ((LCD_PIXEL_WIDTH - (STATUS_LOGO_BYTEWIDTH + STATUS_FAN_BYTEWIDTH) * 8) / (STATUS_HEATERS_XSPACE))) | ||||
| #endif | ||||
|  | ||||
| #define STATUS_HEATERS_BOT (STATUS_HEATERS_Y + STATUS_HEATERS_HEIGHT - 1) | ||||
|  | ||||
| #if ENABLED(MARLIN_DEV_MODE) | ||||
| @@ -127,6 +130,11 @@ FORCE_INLINE void _draw_heater_status(const heater_ind_t heater, const bool blin | ||||
|     const bool isHeat = IFBED(BED_ALT(), HOTEND_ALT(heater)); | ||||
|   #endif | ||||
|  | ||||
|   #ifndef STATUS_HOTEND_TEXT_X | ||||
|     #define STATUS_HOTEND_TEXT_X(N) 0 | ||||
|     #define STATUS_HEATERS_Y 0 | ||||
|   #endif | ||||
|  | ||||
|   const uint8_t tx = IFBED(STATUS_BED_TEXT_X, STATUS_HOTEND_TEXT_X(heater)); | ||||
|  | ||||
|   #if ENABLED(MARLIN_DEV_MODE) | ||||
| @@ -424,8 +432,10 @@ void MarlinUI::draw_status_screen() { | ||||
|   // | ||||
|   if (PAGE_UNDER(6 + 1 + 12 + 1 + 6 + 1)) { | ||||
|     // Extruders | ||||
|     for (uint8_t e = 0; e < MAX_HOTEND_DRAW; ++e) | ||||
|       _draw_heater_status((heater_ind_t)e, blink); | ||||
|     #if HOTENDS | ||||
|       for (uint8_t e = 0; e < MAX_HOTEND_DRAW; ++e) | ||||
|         _draw_heater_status((heater_ind_t)e, blink); | ||||
|     #endif | ||||
|  | ||||
|     // Heated bed | ||||
|     #if DO_DRAW_BED && DISABLED(STATUS_COMBINE_HEATERS) || (HAS_HEATED_BED && ENABLED(STATUS_COMBINE_HEATERS) && HOTENDS <= 4) | ||||
|   | ||||
| @@ -497,21 +497,25 @@ void DGUSScreenVariableHandler::HandleTemperatureChanged(DGUS_VP_Variable &var, | ||||
| } | ||||
|  | ||||
| void DGUSScreenVariableHandler::HandleFlowRateChanged(DGUS_VP_Variable &var, void *val_ptr) { | ||||
|   uint16_t newvalue = swap16(*(uint16_t*)val_ptr); | ||||
|   uint8_t target_extruder; | ||||
|   switch (var.VP) { | ||||
|     default: return; | ||||
|     #if (HOTENDS >= 1) | ||||
|       case VP_Flowrate_E1: target_extruder = 0; break; | ||||
|     #endif | ||||
|     #if (HOTENDS >= 2) | ||||
|       case VP_Flowrate_E2: target_extruder = 1; break; | ||||
|     #endif | ||||
|   } | ||||
|   #if EXTRUDERS | ||||
|     uint16_t newvalue = swap16(*(uint16_t*)val_ptr); | ||||
|     uint8_t target_extruder; | ||||
|     switch (var.VP) { | ||||
|       default: return; | ||||
|       #if (HOTENDS >= 1) | ||||
|         case VP_Flowrate_E1: target_extruder = 0; break; | ||||
|       #endif | ||||
|       #if (HOTENDS >= 2) | ||||
|         case VP_Flowrate_E2: target_extruder = 1; break; | ||||
|       #endif | ||||
|     } | ||||
|  | ||||
|   planner.flow_percentage[target_extruder] = newvalue; | ||||
|   planner.refresh_e_factor(target_extruder); | ||||
|   ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel | ||||
|     planner.flow_percentage[target_extruder] = newvalue; | ||||
|     planner.refresh_e_factor(target_extruder); | ||||
|     ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel | ||||
|   #else | ||||
|     UNUSED(var); UNUSED(val_ptr); | ||||
|   #endif | ||||
| } | ||||
|  | ||||
| void DGUSScreenVariableHandler::HandleManualExtrude(DGUS_VP_Variable &var, void *val_ptr) { | ||||
|   | ||||
| @@ -168,7 +168,7 @@ namespace ExtUI { | ||||
|   } | ||||
|  | ||||
|   void enableHeater(const extruder_t extruder) { | ||||
|     #if HEATER_IDLE_HANDLER | ||||
|     #if HOTENDS && HEATER_IDLE_HANDLER | ||||
|       thermalManager.reset_heater_idle_timer(extruder - E0); | ||||
|     #endif | ||||
|   } | ||||
| @@ -184,14 +184,18 @@ namespace ExtUI { | ||||
|         #if HAS_HEATED_CHAMBER | ||||
|           case CHAMBER: return; // Chamber has no idle timer | ||||
|         #endif | ||||
|         default: thermalManager.reset_heater_idle_timer(heater - H0); | ||||
|         default: | ||||
|           #if HOTENDS | ||||
|             thermalManager.reset_heater_idle_timer(heater - H0); | ||||
|           #endif | ||||
|           break; | ||||
|       } | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   bool isHeaterIdle(const extruder_t extruder) { | ||||
|     return false | ||||
|       #if HEATER_IDLE_HANDLER | ||||
|       #if HOTENDS && HEATER_IDLE_HANDLER | ||||
|         || thermalManager.hotend_idle[extruder - E0].timed_out | ||||
|       #endif | ||||
|     ; | ||||
| @@ -206,7 +210,12 @@ namespace ExtUI { | ||||
|         #if HAS_HEATED_CHAMBER | ||||
|           case CHAMBER: return false; // Chamber has no idle timer | ||||
|         #endif | ||||
|         default: return thermalManager.hotend_idle[heater - H0].timed_out; | ||||
|         default: | ||||
|           #if HOTENDS | ||||
|             return thermalManager.hotend_idle[heater - H0].timed_out; | ||||
|           #else | ||||
|             return false; | ||||
|           #endif | ||||
|       } | ||||
|     #else | ||||
|       return false; | ||||
| @@ -841,22 +850,28 @@ namespace ExtUI { | ||||
|   } | ||||
|  | ||||
|   void setTargetTemp_celsius(float value, const heater_t heater) { | ||||
|     constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP); | ||||
|     const int16_t e = heater - H0; | ||||
|     enableHeater(heater); | ||||
|     #if HAS_HEATED_BED | ||||
|       if (heater == BED) | ||||
|         thermalManager.setTargetBed(clamp(value, 0, BED_MAXTEMP - 10)); | ||||
|       else | ||||
|     #endif | ||||
|         thermalManager.setTargetHotend(clamp(value, 0, heater_maxtemp[e] - 15), e); | ||||
|       { | ||||
|         #if HOTENDS | ||||
|           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); | ||||
|           const int16_t e = heater - H0; | ||||
|           thermalManager.setTargetHotend(clamp(value, 0, heater_maxtemp[e] - 15), e); | ||||
|         #endif | ||||
|       } | ||||
|   } | ||||
|  | ||||
|   void setTargetTemp_celsius(float value, const extruder_t extruder) { | ||||
|     constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP); | ||||
|     const int16_t e = extruder - E0; | ||||
|     enableHeater(extruder); | ||||
|     thermalManager.setTargetHotend(clamp(value, 0, heater_maxtemp[e] - 15), e); | ||||
|     #if HOTENDS | ||||
|       constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP); | ||||
|       const int16_t e = extruder - E0; | ||||
|       enableHeater(extruder); | ||||
|       thermalManager.setTargetHotend(clamp(value, 0, heater_maxtemp[e] - 15), e); | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   void setTargetFan_percent(const float value, const fan_t fan) { | ||||
|   | ||||
| @@ -30,7 +30,9 @@ | ||||
| extern int8_t encoderLine, encoderTopLine, screen_items; | ||||
| extern bool screen_changed; | ||||
|  | ||||
| constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP); | ||||
| #if HOTENDS | ||||
|   constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP, HEATER_3_MAXTEMP, HEATER_4_MAXTEMP); | ||||
| #endif | ||||
|  | ||||
| void scroll_screen(const uint8_t limit, const bool is_menu); | ||||
| bool printer_busy(); | ||||
|   | ||||
| @@ -43,7 +43,7 @@ | ||||
|   #include "../../module/temperature.h" | ||||
| #endif | ||||
|  | ||||
| #ifdef FILAMENT_RUNOUT_DISTANCE_MM | ||||
| #if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM | ||||
|   #include "../../feature/runout.h" | ||||
|   float lcd_runout_distance_mm; | ||||
| #endif | ||||
| @@ -178,7 +178,7 @@ void menu_backlash(); | ||||
|  | ||||
|       #if EXTRUDERS == 1 | ||||
|         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_UNLOAD, &fc_settings[0].unload_length, 0, extrude_maxlength); | ||||
|       #else // EXTRUDERS > 1 | ||||
|       #elif EXTRUDERS > 1 | ||||
|         #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) | ||||
|         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_UNLOAD, &fc_settings[active_extruder].unload_length, 0, extrude_maxlength); | ||||
|         EDIT_FIL_UNLOAD(1); | ||||
| @@ -199,7 +199,7 @@ void menu_backlash(); | ||||
|  | ||||
|       #if EXTRUDERS == 1 | ||||
|         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_LOAD, &fc_settings[0].load_length, 0, extrude_maxlength); | ||||
|       #else // EXTRUDERS > 1 | ||||
|       #elif EXTRUDERS > 1 | ||||
|         #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) | ||||
|         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_FILAMENT_LOAD, &fc_settings[active_extruder].load_length, 0, extrude_maxlength); | ||||
|         EDIT_FIL_LOAD(1); | ||||
| @@ -219,7 +219,7 @@ void menu_backlash(); | ||||
|       #endif // EXTRUDERS > 1 | ||||
|     #endif | ||||
|  | ||||
|     #ifdef FILAMENT_RUNOUT_DISTANCE_MM | ||||
|     #if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM | ||||
|       MENU_ITEM_EDIT_CALLBACK(float3, MSG_RUNOUT_DISTANCE_MM, &lcd_runout_distance_mm, 1, 30, []{ | ||||
|         runout.set_runout_distance(lcd_runout_distance_mm); | ||||
|       }); | ||||
| @@ -620,7 +620,7 @@ void menu_backlash(); | ||||
| #endif // !SLIM_LCD_MENUS | ||||
|  | ||||
| void menu_advanced_settings() { | ||||
|   #ifdef FILAMENT_RUNOUT_DISTANCE_MM | ||||
|   #if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM | ||||
|     lcd_runout_distance_mm = runout.runout_distance(); | ||||
|   #endif | ||||
|   START_MENU(); | ||||
|   | ||||
| @@ -158,80 +158,85 @@ static void _lcd_move_xyz(PGM_P name, AxisEnum axis) { | ||||
| void lcd_move_x() { _lcd_move_xyz(PSTR(MSG_MOVE_X), X_AXIS); } | ||||
| void lcd_move_y() { _lcd_move_xyz(PSTR(MSG_MOVE_Y), Y_AXIS); } | ||||
| void lcd_move_z() { _lcd_move_xyz(PSTR(MSG_MOVE_Z), Z_AXIS); } | ||||
| static void _lcd_move_e( | ||||
|   #if E_MANUAL > 1 | ||||
|     const int8_t eindex=-1 | ||||
|   #endif | ||||
| ) { | ||||
|   if (ui.use_click()) return ui.goto_previous_screen_no_defer(); | ||||
|   if (ui.encoderPosition) { | ||||
|     if (!ui.processing_manual_move) { | ||||
|       const float diff = float(int16_t(ui.encoderPosition)) * move_menu_scale; | ||||
|       #if IS_KINEMATIC | ||||
|         manual_move_offset += diff; | ||||
|       #else | ||||
|         current_position[E_AXIS] += diff; | ||||
|       #endif | ||||
|       manual_move_to_current(E_AXIS | ||||
|         #if E_MANUAL > 1 | ||||
|           , eindex | ||||
|  | ||||
| #if E_MANUAL | ||||
|  | ||||
|   static void _lcd_move_e( | ||||
|     #if E_MANUAL > 1 | ||||
|       const int8_t eindex=-1 | ||||
|     #endif | ||||
|   ) { | ||||
|     if (ui.use_click()) return ui.goto_previous_screen_no_defer(); | ||||
|     if (ui.encoderPosition) { | ||||
|       if (!ui.processing_manual_move) { | ||||
|         const float diff = float(int16_t(ui.encoderPosition)) * move_menu_scale; | ||||
|         #if IS_KINEMATIC | ||||
|           manual_move_offset += diff; | ||||
|         #else | ||||
|           current_position[E_AXIS] += diff; | ||||
|         #endif | ||||
|       ); | ||||
|       ui.refresh(LCDVIEW_REDRAW_NOW); | ||||
|     } | ||||
|     ui.encoderPosition = 0; | ||||
|   } | ||||
|   if (ui.should_draw()) { | ||||
|     PGM_P pos_label; | ||||
|     #if E_MANUAL == 1 | ||||
|       pos_label = PSTR(MSG_MOVE_E); | ||||
|     #else | ||||
|       switch (eindex) { | ||||
|         default: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E1); break; | ||||
|         case 1: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E2); break; | ||||
|         #if E_MANUAL > 2 | ||||
|           case 2: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E3); break; | ||||
|           #if E_MANUAL > 3 | ||||
|             case 3: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E4); break; | ||||
|             #if E_MANUAL > 4 | ||||
|               case 4: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E5); break; | ||||
|               #if E_MANUAL > 5 | ||||
|                 case 5: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E6); break; | ||||
|               #endif // E_MANUAL > 5 | ||||
|             #endif // E_MANUAL > 4 | ||||
|           #endif // E_MANUAL > 3 | ||||
|         #endif // E_MANUAL > 2 | ||||
|         manual_move_to_current(E_AXIS | ||||
|           #if E_MANUAL > 1 | ||||
|             , eindex | ||||
|           #endif | ||||
|         ); | ||||
|         ui.refresh(LCDVIEW_REDRAW_NOW); | ||||
|       } | ||||
|     #endif // E_MANUAL > 1 | ||||
|       ui.encoderPosition = 0; | ||||
|     } | ||||
|     if (ui.should_draw()) { | ||||
|       PGM_P pos_label; | ||||
|       #if E_MANUAL == 1 | ||||
|         pos_label = PSTR(MSG_MOVE_E); | ||||
|       #else | ||||
|         switch (eindex) { | ||||
|           default: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E1); break; | ||||
|           case 1: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E2); break; | ||||
|           #if E_MANUAL > 2 | ||||
|             case 2: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E3); break; | ||||
|             #if E_MANUAL > 3 | ||||
|               case 3: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E4); break; | ||||
|               #if E_MANUAL > 4 | ||||
|                 case 4: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E5); break; | ||||
|                 #if E_MANUAL > 5 | ||||
|                   case 5: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E6); break; | ||||
|                 #endif // E_MANUAL > 5 | ||||
|               #endif // E_MANUAL > 4 | ||||
|             #endif // E_MANUAL > 3 | ||||
|           #endif // E_MANUAL > 2 | ||||
|         } | ||||
|       #endif // E_MANUAL > 1 | ||||
|  | ||||
|     draw_edit_screen(pos_label, ftostr41sign(current_position[E_AXIS] | ||||
|       #if IS_KINEMATIC | ||||
|         + manual_move_offset | ||||
|       #endif | ||||
|       #if ENABLED(MANUAL_E_MOVES_RELATIVE) | ||||
|         - manual_move_e_origin | ||||
|       #endif | ||||
|     )); | ||||
|       draw_edit_screen(pos_label, ftostr41sign(current_position[E_AXIS] | ||||
|         #if IS_KINEMATIC | ||||
|           + manual_move_offset | ||||
|         #endif | ||||
|         #if ENABLED(MANUAL_E_MOVES_RELATIVE) | ||||
|           - manual_move_e_origin | ||||
|         #endif | ||||
|       )); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| inline void lcd_move_e() { _lcd_move_e(); } | ||||
| #if E_MANUAL > 1 | ||||
|   inline void lcd_move_e0() { _lcd_move_e(0); } | ||||
|   inline void lcd_move_e1() { _lcd_move_e(1); } | ||||
|   #if E_MANUAL > 2 | ||||
|     inline void lcd_move_e2() { _lcd_move_e(2); } | ||||
|     #if E_MANUAL > 3 | ||||
|       inline void lcd_move_e3() { _lcd_move_e(3); } | ||||
|       #if E_MANUAL > 4 | ||||
|         inline void lcd_move_e4() { _lcd_move_e(4); } | ||||
|         #if E_MANUAL > 5 | ||||
|           inline void lcd_move_e5() { _lcd_move_e(5); } | ||||
|         #endif // E_MANUAL > 5 | ||||
|       #endif // E_MANUAL > 4 | ||||
|     #endif // E_MANUAL > 3 | ||||
|   #endif // E_MANUAL > 2 | ||||
| #endif // E_MANUAL > 1 | ||||
|   inline void lcd_move_e() { _lcd_move_e(); } | ||||
|   #if E_MANUAL > 1 | ||||
|     inline void lcd_move_e0() { _lcd_move_e(0); } | ||||
|     inline void lcd_move_e1() { _lcd_move_e(1); } | ||||
|     #if E_MANUAL > 2 | ||||
|       inline void lcd_move_e2() { _lcd_move_e(2); } | ||||
|       #if E_MANUAL > 3 | ||||
|         inline void lcd_move_e3() { _lcd_move_e(3); } | ||||
|         #if E_MANUAL > 4 | ||||
|           inline void lcd_move_e4() { _lcd_move_e(4); } | ||||
|           #if E_MANUAL > 5 | ||||
|             inline void lcd_move_e5() { _lcd_move_e(5); } | ||||
|           #endif // E_MANUAL > 5 | ||||
|         #endif // E_MANUAL > 4 | ||||
|       #endif // E_MANUAL > 3 | ||||
|     #endif // E_MANUAL > 2 | ||||
|   #endif // E_MANUAL > 1 | ||||
|  | ||||
| #endif // E_MANUAL | ||||
|  | ||||
| // | ||||
| // "Motion" > "Move Xmm" > "Move XYZ" submenu | ||||
| @@ -295,23 +300,26 @@ void _menu_move_distance(const AxisEnum axis, const screenFunc_t func, const int | ||||
| void lcd_move_get_x_amount() { _menu_move_distance(X_AXIS, lcd_move_x); } | ||||
| void lcd_move_get_y_amount() { _menu_move_distance(Y_AXIS, lcd_move_y); } | ||||
| void lcd_move_get_z_amount() { _menu_move_distance(Z_AXIS, lcd_move_z); } | ||||
| void lcd_move_get_e_amount() { _menu_move_distance(E_AXIS, lcd_move_e, -1); } | ||||
| #if E_MANUAL > 1 | ||||
|   void lcd_move_get_e0_amount()     { _menu_move_distance(E_AXIS, lcd_move_e0, 0); } | ||||
|   void lcd_move_get_e1_amount()     { _menu_move_distance(E_AXIS, lcd_move_e1, 1); } | ||||
|   #if E_MANUAL > 2 | ||||
|     void lcd_move_get_e2_amount()   { _menu_move_distance(E_AXIS, lcd_move_e2, 2); } | ||||
|     #if E_MANUAL > 3 | ||||
|       void lcd_move_get_e3_amount() { _menu_move_distance(E_AXIS, lcd_move_e3, 3); } | ||||
|       #if E_MANUAL > 4 | ||||
|         void lcd_move_get_e4_amount() { _menu_move_distance(E_AXIS, lcd_move_e4, 4); } | ||||
|         #if E_MANUAL > 5 | ||||
|           void lcd_move_get_e5_amount() { _menu_move_distance(E_AXIS, lcd_move_e5, 5); } | ||||
|         #endif // E_MANUAL > 5 | ||||
|       #endif // E_MANUAL > 4 | ||||
|     #endif // E_MANUAL > 3 | ||||
|   #endif // E_MANUAL > 2 | ||||
| #endif // E_MANUAL > 1 | ||||
|  | ||||
| #if E_MANUAL | ||||
|   void lcd_move_get_e_amount() { _menu_move_distance(E_AXIS, lcd_move_e, -1); } | ||||
|   #if E_MANUAL > 1 | ||||
|     void lcd_move_get_e0_amount()     { _menu_move_distance(E_AXIS, lcd_move_e0, 0); } | ||||
|     void lcd_move_get_e1_amount()     { _menu_move_distance(E_AXIS, lcd_move_e1, 1); } | ||||
|     #if E_MANUAL > 2 | ||||
|       void lcd_move_get_e2_amount()   { _menu_move_distance(E_AXIS, lcd_move_e2, 2); } | ||||
|       #if E_MANUAL > 3 | ||||
|         void lcd_move_get_e3_amount() { _menu_move_distance(E_AXIS, lcd_move_e3, 3); } | ||||
|         #if E_MANUAL > 4 | ||||
|           void lcd_move_get_e4_amount() { _menu_move_distance(E_AXIS, lcd_move_e4, 4); } | ||||
|           #if E_MANUAL > 5 | ||||
|             void lcd_move_get_e5_amount() { _menu_move_distance(E_AXIS, lcd_move_e5, 5); } | ||||
|           #endif // E_MANUAL > 5 | ||||
|         #endif // E_MANUAL > 4 | ||||
|       #endif // E_MANUAL > 3 | ||||
|     #endif // E_MANUAL > 2 | ||||
|   #endif // E_MANUAL > 1 | ||||
| #endif // E_MANUAL | ||||
|  | ||||
| #if ENABLED(DELTA) | ||||
|   void lcd_lower_z_to_clip_height() { | ||||
| @@ -396,39 +404,43 @@ void menu_move() { | ||||
|  | ||||
|   #endif | ||||
|  | ||||
|   #if EITHER(SWITCHING_EXTRUDER, SWITCHING_NOZZLE) | ||||
|   #if E_MANUAL | ||||
|  | ||||
|     #if EITHER(SWITCHING_EXTRUDER, SWITCHING_NOZZLE) | ||||
|  | ||||
|       // Only the current... | ||||
|       MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_get_e_amount); | ||||
|       // ...and the non-switching | ||||
|       #if E_MANUAL == 5 | ||||
|         MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E5, lcd_move_get_e4_amount); | ||||
|       #elif E_MANUAL == 3 | ||||
|         MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E3, lcd_move_get_e2_amount); | ||||
|       #endif | ||||
|  | ||||
|     #else | ||||
|  | ||||
|       // Independent extruders with one E-stepper per hotend | ||||
|       MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_get_e_amount); | ||||
|       #if E_MANUAL > 1 | ||||
|         MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E1, lcd_move_get_e0_amount); | ||||
|         MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E2, lcd_move_get_e1_amount); | ||||
|         #if E_MANUAL > 2 | ||||
|           MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E3, lcd_move_get_e2_amount); | ||||
|           #if E_MANUAL > 3 | ||||
|             MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E4, lcd_move_get_e3_amount); | ||||
|             #if E_MANUAL > 4 | ||||
|               MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E5, lcd_move_get_e4_amount); | ||||
|               #if E_MANUAL > 5 | ||||
|                 MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E6, lcd_move_get_e5_amount); | ||||
|               #endif // E_MANUAL > 5 | ||||
|             #endif // E_MANUAL > 4 | ||||
|           #endif // E_MANUAL > 3 | ||||
|         #endif // E_MANUAL > 2 | ||||
|       #endif // E_MANUAL > 1 | ||||
|  | ||||
|     // Only the current... | ||||
|     MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_get_e_amount); | ||||
|     // ...and the non-switching | ||||
|     #if E_MANUAL == 5 | ||||
|       MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E5, lcd_move_get_e4_amount); | ||||
|     #elif E_MANUAL == 3 | ||||
|       MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E3, lcd_move_get_e2_amount); | ||||
|     #endif | ||||
|  | ||||
|   #else | ||||
|  | ||||
|     // Independent extruders with one E-stepper per hotend | ||||
|     MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_get_e_amount); | ||||
|     #if E_MANUAL > 1 | ||||
|       MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E1, lcd_move_get_e0_amount); | ||||
|       MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E2, lcd_move_get_e1_amount); | ||||
|       #if E_MANUAL > 2 | ||||
|         MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E3, lcd_move_get_e2_amount); | ||||
|         #if E_MANUAL > 3 | ||||
|           MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E4, lcd_move_get_e3_amount); | ||||
|           #if E_MANUAL > 4 | ||||
|             MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E5, lcd_move_get_e4_amount); | ||||
|             #if E_MANUAL > 5 | ||||
|               MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E6, lcd_move_get_e5_amount); | ||||
|             #endif // E_MANUAL > 5 | ||||
|           #endif // E_MANUAL > 4 | ||||
|         #endif // E_MANUAL > 3 | ||||
|       #endif // E_MANUAL > 2 | ||||
|     #endif // E_MANUAL > 1 | ||||
|  | ||||
|   #endif | ||||
|   #endif // E_MANUAL | ||||
|  | ||||
|   END_MENU(); | ||||
| } | ||||
|   | ||||
| @@ -48,7 +48,9 @@ uint8_t MarlinUI::preheat_fan_speed[2]; | ||||
| // | ||||
|  | ||||
| void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb, const uint8_t fan) { | ||||
|   if (temph > 0) thermalManager.setTargetHotend(_MIN(heater_maxtemp[endnum] - 15, temph), endnum); | ||||
|   #if HOTENDS | ||||
|     if (temph > 0) thermalManager.setTargetHotend(_MIN(heater_maxtemp[endnum] - 15, temph), endnum); | ||||
|   #endif | ||||
|   #if HAS_HEATED_BED | ||||
|     if (tempb >= 0) thermalManager.setTargetBed(tempb); | ||||
|   #else | ||||
| @@ -165,12 +167,16 @@ void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb | ||||
|  | ||||
| #if HAS_TEMP_HOTEND || HAS_HEATED_BED | ||||
|  | ||||
|   void lcd_preheat_m1_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); } | ||||
|   void lcd_preheat_m2_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); } | ||||
|   #if HOTENDS | ||||
|     void lcd_preheat_m1_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); } | ||||
|     void lcd_preheat_m2_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); } | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_HEATED_BED | ||||
|     void lcd_preheat_m1_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); } | ||||
|     void lcd_preheat_m2_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); } | ||||
|     #if HOTENDS | ||||
|       void lcd_preheat_m1_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); } | ||||
|       void lcd_preheat_m2_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); } | ||||
|     #endif | ||||
|     void lcd_preheat_m1_bedonly() { _lcd_preheat(0, 0, ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); } | ||||
|     void lcd_preheat_m2_bedonly() { _lcd_preheat(0, 0, ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); } | ||||
|   #endif | ||||
| @@ -313,7 +319,7 @@ void menu_temperature() { | ||||
|   // | ||||
|   #if HOTENDS == 1 | ||||
|     MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE, &thermalManager.temp_hotend[0].target, 0, HEATER_0_MAXTEMP - 15, thermalManager.start_watching_E0); | ||||
|   #else // HOTENDS > 1 | ||||
|   #elif HOTENDS > 1 | ||||
|     #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) | ||||
|     EDIT_TARGET(0); | ||||
|     EDIT_TARGET(1); | ||||
|   | ||||
| @@ -144,7 +144,7 @@ void menu_tune() { | ||||
|   // | ||||
|   #if HOTENDS == 1 | ||||
|     MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3, MSG_NOZZLE, &thermalManager.temp_hotend[0].target, 0, HEATER_0_MAXTEMP - 15, thermalManager.start_watching_E0); | ||||
|   #else // HOTENDS > 1 | ||||
|   #elif HOTENDS > 1 | ||||
|     #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) | ||||
|     EDIT_NOZZLE(0); | ||||
|     EDIT_NOZZLE(1); | ||||
|   | ||||
| @@ -309,7 +309,9 @@ typedef struct SettingsDataStruct { | ||||
|   // | ||||
|   // ADVANCED_PAUSE_FEATURE | ||||
|   // | ||||
|   fil_change_settings_t fc_settings[EXTRUDERS];         // M603 T U L | ||||
|   #if EXTRUDERS | ||||
|     fil_change_settings_t fc_settings[EXTRUDERS];       // M603 T U L | ||||
|   #endif | ||||
|  | ||||
|   // | ||||
|   // Tool-change settings | ||||
| @@ -367,7 +369,7 @@ void MarlinSettings::postprocess() { | ||||
|  | ||||
|   #if DISABLED(NO_VOLUMETRICS) | ||||
|     planner.calculate_volumetric_multipliers(); | ||||
|   #else | ||||
|   #elif EXTRUDERS | ||||
|     for (uint8_t i = COUNT(planner.e_factor); i--;) | ||||
|       planner.refresh_e_factor(i); | ||||
|   #endif | ||||
| @@ -759,7 +761,7 @@ void MarlinSettings::postprocess() { | ||||
|     { | ||||
|       _FIELD_TEST(ui_preheat_hotend_temp); | ||||
|  | ||||
|       #if HAS_LCD_MENU | ||||
|       #if HOTENDS && HAS_LCD_MENU | ||||
|         const int16_t (&ui_preheat_hotend_temp)[2]  = ui.preheat_hotend_temp, | ||||
|                       (&ui_preheat_bed_temp)[2]     = ui.preheat_bed_temp; | ||||
|         const uint8_t (&ui_preheat_fan_speed)[2]    = ui.preheat_fan_speed; | ||||
| @@ -1164,6 +1166,7 @@ void MarlinSettings::postprocess() { | ||||
|     // | ||||
|     // Advanced Pause filament load & unload lengths | ||||
|     // | ||||
|     #if EXTRUDERS | ||||
|     { | ||||
|       #if DISABLED(ADVANCED_PAUSE_FEATURE) | ||||
|         const fil_change_settings_t fc_settings[EXTRUDERS] = { 0, 0 }; | ||||
| @@ -1171,6 +1174,7 @@ void MarlinSettings::postprocess() { | ||||
|       _FIELD_TEST(fc_settings); | ||||
|       EEPROM_WRITE(fc_settings); | ||||
|     } | ||||
|     #endif | ||||
|  | ||||
|     // | ||||
|     // Multiple Extruders | ||||
| @@ -1560,7 +1564,7 @@ void MarlinSettings::postprocess() { | ||||
|       { | ||||
|         _FIELD_TEST(ui_preheat_hotend_temp); | ||||
|  | ||||
|         #if HAS_LCD_MENU | ||||
|         #if HOTENDS && HAS_LCD_MENU | ||||
|           int16_t (&ui_preheat_hotend_temp)[2]  = ui.preheat_hotend_temp, | ||||
|                   (&ui_preheat_bed_temp)[2]     = ui.preheat_bed_temp; | ||||
|           uint8_t (&ui_preheat_fan_speed)[2]    = ui.preheat_fan_speed; | ||||
| @@ -1968,6 +1972,7 @@ void MarlinSettings::postprocess() { | ||||
|       // | ||||
|       // Advanced Pause filament load & unload lengths | ||||
|       // | ||||
|       #if EXTRUDERS | ||||
|       { | ||||
|         #if DISABLED(ADVANCED_PAUSE_FEATURE) | ||||
|           fil_change_settings_t fc_settings[EXTRUDERS]; | ||||
| @@ -1975,6 +1980,7 @@ void MarlinSettings::postprocess() { | ||||
|         _FIELD_TEST(fc_settings); | ||||
|         EEPROM_READ(fc_settings); | ||||
|       } | ||||
|       #endif | ||||
|  | ||||
|       // | ||||
|       // Tool-change settings | ||||
| @@ -2410,7 +2416,7 @@ void MarlinSettings::reset() { | ||||
|   // Preheat parameters | ||||
|   // | ||||
|  | ||||
|   #if HAS_LCD_MENU | ||||
|   #if HOTENDS && HAS_LCD_MENU | ||||
|     ui.preheat_hotend_temp[0] = PREHEAT_1_TEMP_HOTEND; | ||||
|     ui.preheat_hotend_temp[1] = PREHEAT_2_TEMP_HOTEND; | ||||
|     ui.preheat_bed_temp[0] = PREHEAT_1_TEMP_BED; | ||||
| @@ -2956,7 +2962,7 @@ void MarlinSettings::reset() { | ||||
|  | ||||
|     #endif // [XYZ]_DUAL_ENDSTOPS | ||||
|  | ||||
|     #if HAS_LCD_MENU | ||||
|     #if HOTENDS && HAS_LCD_MENU | ||||
|  | ||||
|       CONFIG_ECHO_HEADING("Material heatup parameters:"); | ||||
|       for (uint8_t i = 0; i < COUNT(ui.preheat_hotend_temp); i++) { | ||||
|   | ||||
| @@ -124,8 +124,10 @@ XYZ_DEFS(signed char, home_dir, HOME_DIR); | ||||
| #if HAS_HOTEND_OFFSET | ||||
|   extern float hotend_offset[XYZ][HOTENDS]; | ||||
|   void reset_hotend_offsets(); | ||||
| #else | ||||
| #elif HOTENDS > 0 | ||||
|   constexpr float hotend_offset[XYZ][HOTENDS] = { { 0 }, { 0 }, { 0 } }; | ||||
| #else | ||||
|   constexpr float hotend_offset[XYZ][1] = { { 0 }, { 0 }, { 0 } }; | ||||
| #endif | ||||
|  | ||||
| typedef struct { float min, max; } axis_limits_t; | ||||
|   | ||||
| @@ -147,9 +147,10 @@ float Planner::steps_to_mm[XYZE_N];           // (mm) Millimeters per step | ||||
|   uint8_t Planner::last_extruder = 0;     // Respond to extruder change | ||||
| #endif | ||||
|  | ||||
| int16_t Planner::flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100); // Extrusion factor for each extruder | ||||
|  | ||||
| float Planner::e_factor[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0f); // The flow percentage and volumetric multiplier combine to scale E movement | ||||
| #if EXTRUDERS | ||||
|   int16_t Planner::flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100); // Extrusion factor for each extruder | ||||
|   float Planner::e_factor[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0f); // The flow percentage and volumetric multiplier combine to scale E movement | ||||
| #endif | ||||
|  | ||||
| #if DISABLED(NO_VOLUMETRICS) | ||||
|   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, | ||||
|                 db = target[B_AXIS] - position[B_AXIS], | ||||
|                 dc = target[C_AXIS] - position[C_AXIS]; | ||||
|  | ||||
|   int32_t de = target[E_AXIS] - position[E_AXIS]; | ||||
|   #if EXTRUDERS | ||||
|     int32_t de = target[E_AXIS] - position[E_AXIS]; | ||||
|   #else | ||||
|     constexpr int32_t de = 0; | ||||
|   #endif | ||||
|  | ||||
|   /* <-- add a slash to enable | ||||
|     SERIAL_ECHOPAIR("  _populate_block FR:", fr_mm_s); | ||||
| @@ -1642,8 +1647,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, | ||||
|     SERIAL_ECHOPAIR(" (", db); | ||||
|     SERIAL_ECHOPAIR(" steps) C:", target[C_AXIS]); | ||||
|     SERIAL_ECHOPAIR(" (", dc); | ||||
|     SERIAL_ECHOPAIR(" steps) E:", target[E_AXIS]); | ||||
|     SERIAL_ECHOPAIR(" (", de); | ||||
|     #if EXTRUDERS | ||||
|       SERIAL_ECHOPAIR(" steps) E:", target[E_AXIS]); | ||||
|       SERIAL_ECHOPAIR(" (", de); | ||||
|     #endif | ||||
|     SERIAL_ECHOLNPGM(" steps)"); | ||||
|   //*/ | ||||
|  | ||||
| @@ -1712,8 +1719,12 @@ bool Planner::_populate_block(block_t * const block, bool split_move, | ||||
|   #endif | ||||
|   if (de < 0) SBI(dm, E_AXIS); | ||||
|  | ||||
|   const float esteps_float = de * e_factor[extruder]; | ||||
|   const uint32_t esteps = ABS(esteps_float) + 0.5f; | ||||
|   #if EXTRUDERS | ||||
|     const float esteps_float = de * e_factor[extruder]; | ||||
|     const uint32_t esteps = ABS(esteps_float) + 0.5f; | ||||
|   #else | ||||
|     constexpr uint32_t esteps = 0; | ||||
|   #endif | ||||
|  | ||||
|   // Clear all flags, including the "busy" bit | ||||
|   block->flag = 0x00; | ||||
| @@ -1781,10 +1792,17 @@ bool Planner::_populate_block(block_t * const block, bool split_move, | ||||
|     delta_mm[B_AXIS] = db * steps_to_mm[B_AXIS]; | ||||
|     delta_mm[C_AXIS] = dc * steps_to_mm[C_AXIS]; | ||||
|   #endif | ||||
|   delta_mm[E_AXIS] = esteps_float * steps_to_mm[E_AXIS_N(extruder)]; | ||||
|  | ||||
|   #if EXTRUDERS | ||||
|     delta_mm[E_AXIS] = esteps_float * steps_to_mm[E_AXIS_N(extruder)]; | ||||
|   #endif | ||||
|  | ||||
|   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) { | ||||
|     block->millimeters = ABS(delta_mm[E_AXIS]); | ||||
|     block->millimeters = (0 | ||||
|       #if EXTRUDERS | ||||
|         + ABS(delta_mm[E_AXIS]) | ||||
|       #endif | ||||
|     ); | ||||
|   } | ||||
|   else { | ||||
|     if (millimeters) | ||||
| @@ -1816,7 +1834,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   block->steps[E_AXIS] = esteps; | ||||
|   #if EXTRUDERS | ||||
|     block->steps[E_AXIS] = esteps; | ||||
|   #endif | ||||
|  | ||||
|   block->step_event_count = _MAX(block->steps[A_AXIS], block->steps[B_AXIS], block->steps[C_AXIS], esteps); | ||||
|  | ||||
|   // Bail if this is a zero-length block | ||||
| @@ -1874,129 +1895,131 @@ bool Planner::_populate_block(block_t * const block, bool split_move, | ||||
|   #endif | ||||
|  | ||||
|   // Enable extruder(s) | ||||
|   if (esteps) { | ||||
|     #if ENABLED(AUTO_POWER_CONTROL) | ||||
|       powerManager.power_on(); | ||||
|     #endif | ||||
|   #if EXTRUDERS | ||||
|     if (esteps) { | ||||
|       #if ENABLED(AUTO_POWER_CONTROL) | ||||
|         powerManager.power_on(); | ||||
|       #endif | ||||
|  | ||||
|     #if ENABLED(DISABLE_INACTIVE_EXTRUDER) // Enable only the selected extruder | ||||
|       #if ENABLED(DISABLE_INACTIVE_EXTRUDER) // Enable only the selected extruder | ||||
|  | ||||
|       #define DISABLE_IDLE_E(N) if (!g_uc_extruder_last_move[N]) disable_E##N(); | ||||
|         #define DISABLE_IDLE_E(N) if (!g_uc_extruder_last_move[N]) disable_E##N(); | ||||
|  | ||||
|       for (uint8_t i = 0; i < EXTRUDERS; i++) | ||||
|         if (g_uc_extruder_last_move[i] > 0) g_uc_extruder_last_move[i]--; | ||||
|         for (uint8_t i = 0; i < EXTRUDERS; i++) | ||||
|           if (g_uc_extruder_last_move[i] > 0) g_uc_extruder_last_move[i]--; | ||||
|  | ||||
|       switch (extruder) { | ||||
|         case 0: | ||||
|         switch (extruder) { | ||||
|           case 0: | ||||
|             #if EXTRUDERS > 1 | ||||
|               DISABLE_IDLE_E(1); | ||||
|               #if EXTRUDERS > 2 | ||||
|                 DISABLE_IDLE_E(2); | ||||
|                 #if EXTRUDERS > 3 | ||||
|                   DISABLE_IDLE_E(3); | ||||
|                   #if EXTRUDERS > 4 | ||||
|                     DISABLE_IDLE_E(4); | ||||
|                     #if EXTRUDERS > 5 | ||||
|                       DISABLE_IDLE_E(5); | ||||
|                     #endif // EXTRUDERS > 5 | ||||
|                   #endif // EXTRUDERS > 4 | ||||
|                 #endif // EXTRUDERS > 3 | ||||
|               #endif // EXTRUDERS > 2 | ||||
|             #endif // EXTRUDERS > 1 | ||||
|             enable_E0(); | ||||
|             g_uc_extruder_last_move[0] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|             #if HAS_DUPLICATION_MODE | ||||
|               if (extruder_duplication_enabled) { | ||||
|                 enable_E1(); | ||||
|                 g_uc_extruder_last_move[1] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|               } | ||||
|             #endif | ||||
|           break; | ||||
|           #if EXTRUDERS > 1 | ||||
|             DISABLE_IDLE_E(1); | ||||
|             case 1: | ||||
|               DISABLE_IDLE_E(0); | ||||
|               #if EXTRUDERS > 2 | ||||
|                 DISABLE_IDLE_E(2); | ||||
|                 #if EXTRUDERS > 3 | ||||
|                   DISABLE_IDLE_E(3); | ||||
|                   #if EXTRUDERS > 4 | ||||
|                     DISABLE_IDLE_E(4); | ||||
|                     #if EXTRUDERS > 5 | ||||
|                       DISABLE_IDLE_E(5); | ||||
|                     #endif // EXTRUDERS > 5 | ||||
|                   #endif // EXTRUDERS > 4 | ||||
|                 #endif // EXTRUDERS > 3 | ||||
|               #endif // EXTRUDERS > 2 | ||||
|               enable_E1(); | ||||
|               g_uc_extruder_last_move[1] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|             break; | ||||
|             #if EXTRUDERS > 2 | ||||
|               DISABLE_IDLE_E(2); | ||||
|               case 2: | ||||
|                 DISABLE_IDLE_E(0); | ||||
|                 DISABLE_IDLE_E(1); | ||||
|                 #if EXTRUDERS > 3 | ||||
|                   DISABLE_IDLE_E(3); | ||||
|                   #if EXTRUDERS > 4 | ||||
|                     DISABLE_IDLE_E(4); | ||||
|                     #if EXTRUDERS > 5 | ||||
|                       DISABLE_IDLE_E(5); | ||||
|                     #endif | ||||
|                   #endif | ||||
|                 #endif | ||||
|                 enable_E2(); | ||||
|                 g_uc_extruder_last_move[2] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|               break; | ||||
|               #if EXTRUDERS > 3 | ||||
|                 DISABLE_IDLE_E(3); | ||||
|                 case 3: | ||||
|                   DISABLE_IDLE_E(0); | ||||
|                   DISABLE_IDLE_E(1); | ||||
|                   DISABLE_IDLE_E(2); | ||||
|                   #if EXTRUDERS > 4 | ||||
|                     DISABLE_IDLE_E(4); | ||||
|                     #if EXTRUDERS > 5 | ||||
|                       DISABLE_IDLE_E(5); | ||||
|                     #endif | ||||
|                   #endif | ||||
|                   enable_E3(); | ||||
|                   g_uc_extruder_last_move[3] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|                 break; | ||||
|                 #if EXTRUDERS > 4 | ||||
|                   DISABLE_IDLE_E(4); | ||||
|                   case 4: | ||||
|                     DISABLE_IDLE_E(0); | ||||
|                     DISABLE_IDLE_E(1); | ||||
|                     DISABLE_IDLE_E(2); | ||||
|                     DISABLE_IDLE_E(3); | ||||
|                     #if EXTRUDERS > 5 | ||||
|                       DISABLE_IDLE_E(5); | ||||
|                     #endif | ||||
|                     enable_E4(); | ||||
|                     g_uc_extruder_last_move[4] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|                   break; | ||||
|                   #if EXTRUDERS > 5 | ||||
|                     DISABLE_IDLE_E(5); | ||||
|                     case 5: | ||||
|                       DISABLE_IDLE_E(0); | ||||
|                       DISABLE_IDLE_E(1); | ||||
|                       DISABLE_IDLE_E(2); | ||||
|                       DISABLE_IDLE_E(3); | ||||
|                       DISABLE_IDLE_E(4); | ||||
|                       enable_E5(); | ||||
|                       g_uc_extruder_last_move[5] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|                     break; | ||||
|                   #endif // EXTRUDERS > 5 | ||||
|                 #endif // EXTRUDERS > 4 | ||||
|               #endif // EXTRUDERS > 3 | ||||
|             #endif // EXTRUDERS > 2 | ||||
|           #endif // EXTRUDERS > 1 | ||||
|           enable_E0(); | ||||
|           g_uc_extruder_last_move[0] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|           #if HAS_DUPLICATION_MODE | ||||
|             if (extruder_duplication_enabled) { | ||||
|               enable_E1(); | ||||
|               g_uc_extruder_last_move[1] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|             } | ||||
|           #endif | ||||
|         break; | ||||
|         #if EXTRUDERS > 1 | ||||
|           case 1: | ||||
|             DISABLE_IDLE_E(0); | ||||
|             #if EXTRUDERS > 2 | ||||
|               DISABLE_IDLE_E(2); | ||||
|               #if EXTRUDERS > 3 | ||||
|                 DISABLE_IDLE_E(3); | ||||
|                 #if EXTRUDERS > 4 | ||||
|                   DISABLE_IDLE_E(4); | ||||
|                   #if EXTRUDERS > 5 | ||||
|                     DISABLE_IDLE_E(5); | ||||
|                   #endif // EXTRUDERS > 5 | ||||
|                 #endif // EXTRUDERS > 4 | ||||
|               #endif // EXTRUDERS > 3 | ||||
|             #endif // EXTRUDERS > 2 | ||||
|             enable_E1(); | ||||
|             g_uc_extruder_last_move[1] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|           break; | ||||
|           #if EXTRUDERS > 2 | ||||
|             case 2: | ||||
|               DISABLE_IDLE_E(0); | ||||
|               DISABLE_IDLE_E(1); | ||||
|               #if EXTRUDERS > 3 | ||||
|                 DISABLE_IDLE_E(3); | ||||
|                 #if EXTRUDERS > 4 | ||||
|                   DISABLE_IDLE_E(4); | ||||
|                   #if EXTRUDERS > 5 | ||||
|                     DISABLE_IDLE_E(5); | ||||
|                   #endif | ||||
|                 #endif | ||||
|               #endif | ||||
|               enable_E2(); | ||||
|               g_uc_extruder_last_move[2] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|             break; | ||||
|             #if EXTRUDERS > 3 | ||||
|               case 3: | ||||
|                 DISABLE_IDLE_E(0); | ||||
|                 DISABLE_IDLE_E(1); | ||||
|                 DISABLE_IDLE_E(2); | ||||
|                 #if EXTRUDERS > 4 | ||||
|                   DISABLE_IDLE_E(4); | ||||
|                   #if EXTRUDERS > 5 | ||||
|                     DISABLE_IDLE_E(5); | ||||
|                   #endif | ||||
|                 #endif | ||||
|                 enable_E3(); | ||||
|                 g_uc_extruder_last_move[3] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|               break; | ||||
|               #if EXTRUDERS > 4 | ||||
|                 case 4: | ||||
|                   DISABLE_IDLE_E(0); | ||||
|                   DISABLE_IDLE_E(1); | ||||
|                   DISABLE_IDLE_E(2); | ||||
|                   DISABLE_IDLE_E(3); | ||||
|                   #if EXTRUDERS > 5 | ||||
|                     DISABLE_IDLE_E(5); | ||||
|                   #endif | ||||
|                   enable_E4(); | ||||
|                   g_uc_extruder_last_move[4] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|                 break; | ||||
|                 #if EXTRUDERS > 5 | ||||
|                   case 5: | ||||
|                     DISABLE_IDLE_E(0); | ||||
|                     DISABLE_IDLE_E(1); | ||||
|                     DISABLE_IDLE_E(2); | ||||
|                     DISABLE_IDLE_E(3); | ||||
|                     DISABLE_IDLE_E(4); | ||||
|                     enable_E5(); | ||||
|                     g_uc_extruder_last_move[5] = (BLOCK_BUFFER_SIZE) * 2; | ||||
|                   break; | ||||
|                 #endif // EXTRUDERS > 5 | ||||
|               #endif // EXTRUDERS > 4 | ||||
|             #endif // EXTRUDERS > 3 | ||||
|           #endif // EXTRUDERS > 2 | ||||
|         #endif // EXTRUDERS > 1 | ||||
|       } | ||||
|     #else | ||||
|       enable_E0(); | ||||
|       enable_E1(); | ||||
|       enable_E2(); | ||||
|       enable_E3(); | ||||
|       enable_E4(); | ||||
|       enable_E5(); | ||||
|     #endif | ||||
|   } | ||||
|         } | ||||
|       #else | ||||
|         enable_E0(); | ||||
|         enable_E1(); | ||||
|         enable_E2(); | ||||
|         enable_E3(); | ||||
|         enable_E4(); | ||||
|         enable_E5(); | ||||
|       #endif | ||||
|     } | ||||
|   #endif // EXTRUDERS | ||||
|  | ||||
|   if (esteps) | ||||
|     NOLESS(fr_mm_s, settings.min_feedrate_mm_s); | ||||
|   | ||||
| @@ -226,9 +226,10 @@ class Planner { | ||||
|       static uint8_t last_extruder;                 // Respond to extruder change | ||||
|     #endif | ||||
|  | ||||
|     static int16_t flow_percentage[EXTRUDERS];      // Extrusion factor for each extruder | ||||
|  | ||||
|     static float e_factor[EXTRUDERS];               // The flow percentage and volumetric multiplier combine to scale E movement | ||||
|     #if EXTRUDERS | ||||
|       static int16_t flow_percentage[EXTRUDERS];    // Extrusion factor for each extruder | ||||
|       static float e_factor[EXTRUDERS];             // The flow percentage and volumetric multiplier combine to scale E movement | ||||
|     #endif | ||||
|  | ||||
|     #if DISABLED(NO_VOLUMETRICS) | ||||
|       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 { | ||||
|     static void reset_acceleration_rates(); | ||||
|     static void refresh_positioning(); | ||||
|  | ||||
|     FORCE_INLINE static void refresh_e_factor(const uint8_t e) { | ||||
|       e_factor[e] = (flow_percentage[e] * 0.01f | ||||
|         #if DISABLED(NO_VOLUMETRICS) | ||||
|           * volumetric_multiplier[e] | ||||
|         #endif | ||||
|       ); | ||||
|     } | ||||
|     #if EXTRUDERS | ||||
|       FORCE_INLINE static void refresh_e_factor(const uint8_t e) { | ||||
|         e_factor[e] = (flow_percentage[e] * 0.01f | ||||
|           #if DISABLED(NO_VOLUMETRICS) | ||||
|             * volumetric_multiplier[e] | ||||
|           #endif | ||||
|         ); | ||||
|       } | ||||
|     #endif | ||||
|  | ||||
|     // Manage fans, paste pressure, etc. | ||||
|     static void check_axes_activity(); | ||||
|   | ||||
| @@ -112,11 +112,9 @@ Temperature thermalManager; | ||||
|   bool Temperature::adaptive_fan_slowing = true; | ||||
| #endif | ||||
|  | ||||
| hotend_info_t Temperature::temp_hotend[HOTENDS | ||||
|   #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) | ||||
|     + 1 | ||||
|   #endif | ||||
| ]; // = { 0 } | ||||
| #if HOTENDS | ||||
|   hotend_info_t Temperature::temp_hotend[HOTEND_TEMPS]; // = { 0 } | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(AUTO_POWER_E_FANS) | ||||
|   uint8_t Temperature::autofan_speed[HOTENDS]; // = { 0 } | ||||
| @@ -283,15 +281,17 @@ volatile bool Temperature::temp_meas_ready = false; | ||||
|  | ||||
| #define TEMPDIR(N) ((HEATER_##N##_RAW_LO_TEMP) < (HEATER_##N##_RAW_HI_TEMP) ? 1 : -1) | ||||
|  | ||||
| // Init mintemp and maxtemp with extreme values to prevent false errors during startup | ||||
| constexpr temp_range_t sensor_heater_0 { HEATER_0_RAW_LO_TEMP, HEATER_0_RAW_HI_TEMP, 0, 16383 }, | ||||
|                        sensor_heater_1 { HEATER_1_RAW_LO_TEMP, HEATER_1_RAW_HI_TEMP, 0, 16383 }, | ||||
|                        sensor_heater_2 { HEATER_2_RAW_LO_TEMP, HEATER_2_RAW_HI_TEMP, 0, 16383 }, | ||||
|                        sensor_heater_3 { HEATER_3_RAW_LO_TEMP, HEATER_3_RAW_HI_TEMP, 0, 16383 }, | ||||
|                        sensor_heater_4 { HEATER_4_RAW_LO_TEMP, HEATER_4_RAW_HI_TEMP, 0, 16383 }, | ||||
|                        sensor_heater_5 { HEATER_5_RAW_LO_TEMP, HEATER_5_RAW_HI_TEMP, 0, 16383 }; | ||||
| #if HOTENDS | ||||
|   // Init mintemp and maxtemp with extreme values to prevent false errors during startup | ||||
|   constexpr temp_range_t sensor_heater_0 { HEATER_0_RAW_LO_TEMP, HEATER_0_RAW_HI_TEMP, 0, 16383 }, | ||||
|                          sensor_heater_1 { HEATER_1_RAW_LO_TEMP, HEATER_1_RAW_HI_TEMP, 0, 16383 }, | ||||
|                          sensor_heater_2 { HEATER_2_RAW_LO_TEMP, HEATER_2_RAW_HI_TEMP, 0, 16383 }, | ||||
|                          sensor_heater_3 { HEATER_3_RAW_LO_TEMP, HEATER_3_RAW_HI_TEMP, 0, 16383 }, | ||||
|                          sensor_heater_4 { HEATER_4_RAW_LO_TEMP, HEATER_4_RAW_HI_TEMP, 0, 16383 }, | ||||
|                          sensor_heater_5 { HEATER_5_RAW_LO_TEMP, HEATER_5_RAW_HI_TEMP, 0, 16383 }; | ||||
|  | ||||
| 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); | ||||
|   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); | ||||
| #endif | ||||
|  | ||||
| #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED | ||||
|   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 | ||||
|  * Class and Instance Methods | ||||
|  */ | ||||
|  | ||||
| Temperature::Temperature() { } | ||||
|  | ||||
| int16_t Temperature::getHeaterPower(const heater_ind_t heater_id) { | ||||
|   switch (heater_id) { | ||||
|     default: return temp_hotend[heater_id].soft_pwm_amount; | ||||
|     #if HAS_HEATED_BED | ||||
|       case H_BED: return temp_bed.soft_pwm_amount; | ||||
|     #endif | ||||
|     #if HAS_HEATED_CHAMBER | ||||
|       case H_CHAMBER: return temp_chamber.soft_pwm_amount; | ||||
|     #endif | ||||
|     default: | ||||
|       #if HOTENDS | ||||
|         return temp_hotend[heater_id].soft_pwm_amount; | ||||
|       #else | ||||
|         return 0; | ||||
|       #endif | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -816,114 +819,118 @@ void Temperature::min_temp_error(const heater_ind_t heater) { | ||||
|   _temp_error(heater, PSTR(MSG_T_MINTEMP), TEMP_ERR_PSTR(MSG_ERR_MINTEMP, heater)); | ||||
| } | ||||
|  | ||||
| float Temperature::get_pid_output_hotend(const uint8_t e) { | ||||
|   #if HOTENDS == 1 | ||||
|     #define _HOTEND_TEST true | ||||
|   #else | ||||
|     #define _HOTEND_TEST (e == active_extruder) | ||||
|   #endif | ||||
|   E_UNUSED(); | ||||
|   const uint8_t ee = HOTEND_INDEX; | ||||
|   float pid_output; | ||||
|   #if ENABLED(PIDTEMP) | ||||
|     #if DISABLED(PID_OPENLOOP) | ||||
|       static hotend_pid_t work_pid[HOTENDS]; | ||||
|       static float temp_iState[HOTENDS] = { 0 }, | ||||
|                    temp_dState[HOTENDS] = { 0 }; | ||||
|       static bool pid_reset[HOTENDS] = { false }; | ||||
|       const float pid_error = temp_hotend[ee].target - temp_hotend[ee].celsius; | ||||
| #if HOTENDS | ||||
|  | ||||
|       if (temp_hotend[ee].target == 0 | ||||
|         || pid_error < -(PID_FUNCTIONAL_RANGE) | ||||
|         #if HEATER_IDLE_HANDLER | ||||
|           || hotend_idle[ee].timed_out | ||||
|         #endif | ||||
|       ) { | ||||
|         pid_output = 0; | ||||
|         pid_reset[ee] = true; | ||||
|       } | ||||
|       else if (pid_error > PID_FUNCTIONAL_RANGE) { | ||||
|         pid_output = BANG_MAX; | ||||
|         pid_reset[ee] = true; | ||||
|       } | ||||
|       else { | ||||
|         if (pid_reset[ee]) { | ||||
|           temp_iState[ee] = 0.0; | ||||
|           work_pid[ee].Kd = 0.0; | ||||
|           pid_reset[ee] = false; | ||||
|         } | ||||
|  | ||||
|         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); | ||||
|         const float max_power_over_i_gain = float(PID_MAX) / PID_PARAM(Ki, ee) - float(MIN_POWER); | ||||
|         temp_iState[ee] = constrain(temp_iState[ee] + pid_error, 0, max_power_over_i_gain); | ||||
|         work_pid[ee].Kp = PID_PARAM(Kp, ee) * pid_error; | ||||
|         work_pid[ee].Ki = PID_PARAM(Ki, ee) * temp_iState[ee]; | ||||
|  | ||||
|         pid_output = work_pid[ee].Kp + work_pid[ee].Ki + work_pid[ee].Kd + float(MIN_POWER); | ||||
|  | ||||
|         #if ENABLED(PID_EXTRUSION_SCALING) | ||||
|           work_pid[ee].Kc = 0; | ||||
|           if (_HOTEND_TEST) { | ||||
|             const long e_position = stepper.position(E_AXIS); | ||||
|             if (e_position > last_e_position) { | ||||
|               lpq[lpq_ptr] = e_position - last_e_position; | ||||
|               last_e_position = e_position; | ||||
|             } | ||||
|             else | ||||
|               lpq[lpq_ptr] = 0; | ||||
|  | ||||
|             if (++lpq_ptr >= lpq_len) lpq_ptr = 0; | ||||
|             work_pid[ee].Kc = (lpq[lpq_ptr] * planner.steps_to_mm[E_AXIS]) * PID_PARAM(Kc, ee); | ||||
|             pid_output += work_pid[ee].Kc; | ||||
|           } | ||||
|         #endif // PID_EXTRUSION_SCALING | ||||
|  | ||||
|         LIMIT(pid_output, 0, PID_MAX); | ||||
|       } | ||||
|       temp_dState[ee] = temp_hotend[ee].celsius; | ||||
|  | ||||
|     #else // PID_OPENLOOP | ||||
|  | ||||
|       const float pid_output = constrain(temp_hotend[ee].target, 0, PID_MAX); | ||||
|  | ||||
|     #endif // PID_OPENLOOP | ||||
|  | ||||
|     #if ENABLED(PID_DEBUG) | ||||
|       if (e == active_extruder) { | ||||
|         SERIAL_ECHO_START(); | ||||
|         SERIAL_ECHOPAIR( | ||||
|           MSG_PID_DEBUG, ee, | ||||
|           MSG_PID_DEBUG_INPUT, temp_hotend[ee].celsius, | ||||
|           MSG_PID_DEBUG_OUTPUT, pid_output | ||||
|         ); | ||||
|         #if DISABLED(PID_OPENLOOP) | ||||
|           SERIAL_ECHOPAIR( | ||||
|             MSG_PID_DEBUG_PTERM, work_pid[ee].Kp, | ||||
|             MSG_PID_DEBUG_ITERM, work_pid[ee].Ki, | ||||
|             MSG_PID_DEBUG_DTERM, work_pid[ee].Kd | ||||
|             #if ENABLED(PID_EXTRUSION_SCALING) | ||||
|               , MSG_PID_DEBUG_CTERM, work_pid[ee].Kc | ||||
|             #endif | ||||
|           ); | ||||
|         #endif | ||||
|         SERIAL_EOL(); | ||||
|       } | ||||
|     #endif // PID_DEBUG | ||||
|  | ||||
|   #else // No PID enabled | ||||
|  | ||||
|     #if HEATER_IDLE_HANDLER | ||||
|       #define _TIMED_OUT_TEST hotend_idle[ee].timed_out | ||||
|   float Temperature::get_pid_output_hotend(const uint8_t e) { | ||||
|     #if HOTENDS == 1 | ||||
|       #define _HOTEND_TEST true | ||||
|     #else | ||||
|       #define _TIMED_OUT_TEST false | ||||
|       #define _HOTEND_TEST (e == active_extruder) | ||||
|     #endif | ||||
|     pid_output = (!_TIMED_OUT_TEST && temp_hotend[ee].celsius < temp_hotend[ee].target) ? BANG_MAX : 0; | ||||
|     #undef _TIMED_OUT_TEST | ||||
|     E_UNUSED(); | ||||
|     const uint8_t ee = HOTEND_INDEX; | ||||
|     float pid_output; | ||||
|     #if ENABLED(PIDTEMP) | ||||
|       #if DISABLED(PID_OPENLOOP) | ||||
|         static hotend_pid_t work_pid[HOTENDS]; | ||||
|         static float temp_iState[HOTENDS] = { 0 }, | ||||
|                      temp_dState[HOTENDS] = { 0 }; | ||||
|         static bool pid_reset[HOTENDS] = { false }; | ||||
|         const float pid_error = temp_hotend[ee].target - temp_hotend[ee].celsius; | ||||
|  | ||||
|   #endif | ||||
|         if (temp_hotend[ee].target == 0 | ||||
|           || pid_error < -(PID_FUNCTIONAL_RANGE) | ||||
|           #if HEATER_IDLE_HANDLER | ||||
|             || hotend_idle[ee].timed_out | ||||
|           #endif | ||||
|         ) { | ||||
|           pid_output = 0; | ||||
|           pid_reset[ee] = true; | ||||
|         } | ||||
|         else if (pid_error > PID_FUNCTIONAL_RANGE) { | ||||
|           pid_output = BANG_MAX; | ||||
|           pid_reset[ee] = true; | ||||
|         } | ||||
|         else { | ||||
|           if (pid_reset[ee]) { | ||||
|             temp_iState[ee] = 0.0; | ||||
|             work_pid[ee].Kd = 0.0; | ||||
|             pid_reset[ee] = false; | ||||
|           } | ||||
|  | ||||
|   return pid_output; | ||||
| } | ||||
|           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); | ||||
|           const float max_power_over_i_gain = float(PID_MAX) / PID_PARAM(Ki, ee) - float(MIN_POWER); | ||||
|           temp_iState[ee] = constrain(temp_iState[ee] + pid_error, 0, max_power_over_i_gain); | ||||
|           work_pid[ee].Kp = PID_PARAM(Kp, ee) * pid_error; | ||||
|           work_pid[ee].Ki = PID_PARAM(Ki, ee) * temp_iState[ee]; | ||||
|  | ||||
|           pid_output = work_pid[ee].Kp + work_pid[ee].Ki + work_pid[ee].Kd + float(MIN_POWER); | ||||
|  | ||||
|           #if ENABLED(PID_EXTRUSION_SCALING) | ||||
|             work_pid[ee].Kc = 0; | ||||
|             if (_HOTEND_TEST) { | ||||
|               const long e_position = stepper.position(E_AXIS); | ||||
|               if (e_position > last_e_position) { | ||||
|                 lpq[lpq_ptr] = e_position - last_e_position; | ||||
|                 last_e_position = e_position; | ||||
|               } | ||||
|               else | ||||
|                 lpq[lpq_ptr] = 0; | ||||
|  | ||||
|               if (++lpq_ptr >= lpq_len) lpq_ptr = 0; | ||||
|               work_pid[ee].Kc = (lpq[lpq_ptr] * planner.steps_to_mm[E_AXIS]) * PID_PARAM(Kc, ee); | ||||
|               pid_output += work_pid[ee].Kc; | ||||
|             } | ||||
|           #endif // PID_EXTRUSION_SCALING | ||||
|  | ||||
|           LIMIT(pid_output, 0, PID_MAX); | ||||
|         } | ||||
|         temp_dState[ee] = temp_hotend[ee].celsius; | ||||
|  | ||||
|       #else // PID_OPENLOOP | ||||
|  | ||||
|         const float pid_output = constrain(temp_hotend[ee].target, 0, PID_MAX); | ||||
|  | ||||
|       #endif // PID_OPENLOOP | ||||
|  | ||||
|       #if ENABLED(PID_DEBUG) | ||||
|         if (e == active_extruder) { | ||||
|           SERIAL_ECHO_START(); | ||||
|           SERIAL_ECHOPAIR( | ||||
|             MSG_PID_DEBUG, ee, | ||||
|             MSG_PID_DEBUG_INPUT, temp_hotend[ee].celsius, | ||||
|             MSG_PID_DEBUG_OUTPUT, pid_output | ||||
|           ); | ||||
|           #if DISABLED(PID_OPENLOOP) | ||||
|             SERIAL_ECHOPAIR( | ||||
|               MSG_PID_DEBUG_PTERM, work_pid[ee].Kp, | ||||
|               MSG_PID_DEBUG_ITERM, work_pid[ee].Ki, | ||||
|               MSG_PID_DEBUG_DTERM, work_pid[ee].Kd | ||||
|               #if ENABLED(PID_EXTRUSION_SCALING) | ||||
|                 , MSG_PID_DEBUG_CTERM, work_pid[ee].Kc | ||||
|               #endif | ||||
|             ); | ||||
|           #endif | ||||
|           SERIAL_EOL(); | ||||
|         } | ||||
|       #endif // PID_DEBUG | ||||
|  | ||||
|     #else // No PID enabled | ||||
|  | ||||
|       #if HEATER_IDLE_HANDLER | ||||
|         #define _TIMED_OUT_TEST hotend_idle[ee].timed_out | ||||
|       #else | ||||
|         #define _TIMED_OUT_TEST false | ||||
|       #endif | ||||
|       pid_output = (!_TIMED_OUT_TEST && temp_hotend[ee].celsius < temp_hotend[ee].target) ? BANG_MAX : 0; | ||||
|       #undef _TIMED_OUT_TEST | ||||
|  | ||||
|     #endif | ||||
|  | ||||
|     return pid_output; | ||||
|   } | ||||
|  | ||||
| #endif // HOTENDS | ||||
|  | ||||
| #if ENABLED(PIDTEMPBED) | ||||
|  | ||||
| @@ -1025,44 +1032,46 @@ void Temperature::manage_heater() { | ||||
|     if (temp_hotend[1].celsius < _MAX(HEATER_1_MINTEMP, HEATER_1_MAX6675_TMIN + .01)) min_temp_error(H_E1); | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_THERMAL_PROTECTION || DISABLED(PIDTEMPBED) || HAS_AUTO_FAN || HEATER_IDLE_HANDLER | ||||
|     millis_t ms = millis(); | ||||
|   #endif | ||||
|   millis_t ms = millis(); | ||||
|  | ||||
|   HOTEND_LOOP() { | ||||
|     #if ENABLED(THERMAL_PROTECTION_HOTENDS) | ||||
|       if (degHotend(e) > temp_range[e].maxtemp) | ||||
|         _temp_error((heater_ind_t)e, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, e)); | ||||
|     #endif | ||||
|   #if HOTENDS | ||||
|  | ||||
|     #if HEATER_IDLE_HANDLER | ||||
|       hotend_idle[e].update(ms); | ||||
|     #endif | ||||
|     HOTEND_LOOP() { | ||||
|       #if ENABLED(THERMAL_PROTECTION_HOTENDS) | ||||
|         if (degHotend(e) > temp_range[e].maxtemp) | ||||
|           _temp_error((heater_ind_t)e, PSTR(MSG_T_THERMAL_RUNAWAY), TEMP_ERR_PSTR(MSG_THERMAL_RUNAWAY, e)); | ||||
|       #endif | ||||
|  | ||||
|     #if ENABLED(THERMAL_PROTECTION_HOTENDS) | ||||
|       // Check for thermal runaway | ||||
|       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); | ||||
|     #endif | ||||
|       #if HEATER_IDLE_HANDLER | ||||
|         hotend_idle[e].update(ms); | ||||
|       #endif | ||||
|  | ||||
|     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; | ||||
|       #if ENABLED(THERMAL_PROTECTION_HOTENDS) | ||||
|         // Check for thermal runaway | ||||
|         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); | ||||
|       #endif | ||||
|  | ||||
|     #if WATCH_HOTENDS | ||||
|       // Make sure temperature is increasing | ||||
|       if (watch_hotend[e].next_ms && ELAPSED(ms, watch_hotend[e].next_ms)) { // Time to check this extruder? | ||||
|         if (degHotend(e) < watch_hotend[e].target)                             // Failed to increase enough? | ||||
|           _temp_error((heater_ind_t)e, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, e)); | ||||
|         else                                                                 // Start again if the target is still far off | ||||
|           start_watching_hotend(e); | ||||
|       } | ||||
|     #endif | ||||
|       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; | ||||
|  | ||||
|     #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) | ||||
|       // Make sure measured temperatures are close together | ||||
|       if (ABS(temp_hotend[0].celsius - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF) | ||||
|         _temp_error(H_E0, PSTR(MSG_REDUNDANCY), PSTR(MSG_ERR_REDUNDANT_TEMP)); | ||||
|     #endif | ||||
|       #if WATCH_HOTENDS | ||||
|         // Make sure temperature is increasing | ||||
|         if (watch_hotend[e].next_ms && ELAPSED(ms, watch_hotend[e].next_ms)) { // Time to check this extruder? | ||||
|           if (degHotend(e) < watch_hotend[e].target)                             // Failed to increase enough? | ||||
|             _temp_error((heater_ind_t)e, PSTR(MSG_T_HEATING_FAILED), TEMP_ERR_PSTR(MSG_HEATING_FAILED_LCD, e)); | ||||
|           else                                                                 // Start again if the target is still far off | ||||
|             start_watching_hotend(e); | ||||
|         } | ||||
|       #endif | ||||
|  | ||||
|   } // HOTEND_LOOP | ||||
|       #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) | ||||
|         // Make sure measured temperatures are close together | ||||
|         if (ABS(temp_hotend[0].celsius - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF) | ||||
|           _temp_error(H_E0, PSTR(MSG_REDUNDANCY), PSTR(MSG_ERR_REDUNDANT_TEMP)); | ||||
|       #endif | ||||
|  | ||||
|     } // HOTEND_LOOP | ||||
|  | ||||
|   #endif // HOTENDS | ||||
|  | ||||
|   #if HAS_AUTO_FAN | ||||
|     if (ELAPSED(ms, next_auto_fan_check_ms)) { // only need to check fan state very infrequently | ||||
| @@ -1206,6 +1215,8 @@ void Temperature::manage_heater() { | ||||
|     //temp_bed.soft_pwm_amount = WITHIN(temp_chamber.celsius, CHAMBER_MINTEMP, CHAMBER_MAXTEMP) ? (int)get_pid_output_chamber() >> 1 : 0; | ||||
|  | ||||
|   #endif // HAS_HEATED_CHAMBER | ||||
|  | ||||
|   UNUSED(ms); | ||||
| } | ||||
|  | ||||
| #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() { | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| // Derived from RepRap FiveD extruder::getTemperature() | ||||
| // For hot end temperature measurement. | ||||
| float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) { | ||||
|   #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) | ||||
|     if (e > HOTENDS) | ||||
|   #else | ||||
|     if (e >= HOTENDS) | ||||
|   #endif | ||||
|     { | ||||
|       SERIAL_ERROR_START(); | ||||
|       SERIAL_ECHO((int)e); | ||||
|       SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER_NUM); | ||||
|       kill(); | ||||
|       return 0.0; | ||||
| #if HOTENDS | ||||
|   // Derived from RepRap FiveD extruder::getTemperature() | ||||
|   // For hot end temperature measurement. | ||||
|   float Temperature::analog_to_celsius_hotend(const int raw, const uint8_t e) { | ||||
|     #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) | ||||
|       if (e > HOTENDS) | ||||
|     #else | ||||
|       if (e >= HOTENDS) | ||||
|     #endif | ||||
|       { | ||||
|         SERIAL_ERROR_START(); | ||||
|         SERIAL_ECHO((int)e); | ||||
|         SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER_NUM); | ||||
|         kill(); | ||||
|         return 0.0; | ||||
|       } | ||||
|  | ||||
|     switch (e) { | ||||
|       case 0: | ||||
|         #if ENABLED(HEATER_0_USER_THERMISTOR) | ||||
|           return user_thermistor_to_deg_c(CTI_HOTEND_0, raw); | ||||
|         #elif ENABLED(HEATER_0_USES_MAX6675) | ||||
|           return raw * 0.25; | ||||
|         #elif ENABLED(HEATER_0_USES_AD595) | ||||
|           return TEMP_AD595(raw); | ||||
|         #elif ENABLED(HEATER_0_USES_AD8495) | ||||
|           return TEMP_AD8495(raw); | ||||
|         #else | ||||
|           break; | ||||
|         #endif | ||||
|       case 1: | ||||
|         #if ENABLED(HEATER_1_USER_THERMISTOR) | ||||
|           return user_thermistor_to_deg_c(CTI_HOTEND_1, raw); | ||||
|         #elif ENABLED(HEATER_1_USES_MAX6675) | ||||
|           return raw * 0.25; | ||||
|         #elif ENABLED(HEATER_1_USES_AD595) | ||||
|           return TEMP_AD595(raw); | ||||
|         #elif ENABLED(HEATER_1_USES_AD8495) | ||||
|           return TEMP_AD8495(raw); | ||||
|         #else | ||||
|           break; | ||||
|         #endif | ||||
|       case 2: | ||||
|         #if ENABLED(HEATER_2_USER_THERMISTOR) | ||||
|           return user_thermistor_to_deg_c(CTI_HOTEND_2, raw); | ||||
|         #elif ENABLED(HEATER_2_USES_AD595) | ||||
|           return TEMP_AD595(raw); | ||||
|         #elif ENABLED(HEATER_2_USES_AD8495) | ||||
|           return TEMP_AD8495(raw); | ||||
|         #else | ||||
|           break; | ||||
|         #endif | ||||
|       case 3: | ||||
|         #if ENABLED(HEATER_3_USER_THERMISTOR) | ||||
|           return user_thermistor_to_deg_c(CTI_HOTEND_3, raw); | ||||
|         #elif ENABLED(HEATER_3_USES_AD595) | ||||
|           return TEMP_AD595(raw); | ||||
|         #elif ENABLED(HEATER_3_USES_AD8495) | ||||
|           return TEMP_AD8495(raw); | ||||
|         #else | ||||
|           break; | ||||
|         #endif | ||||
|       case 4: | ||||
|         #if ENABLED(HEATER_4_USER_THERMISTOR) | ||||
|           return user_thermistor_to_deg_c(CTI_HOTEND_4, raw); | ||||
|         #elif ENABLED(HEATER_4_USES_AD595) | ||||
|           return TEMP_AD595(raw); | ||||
|         #elif ENABLED(HEATER_4_USES_AD8495) | ||||
|           return TEMP_AD8495(raw); | ||||
|         #else | ||||
|           break; | ||||
|         #endif | ||||
|       case 5: | ||||
|         #if ENABLED(HEATER_5_USER_THERMISTOR) | ||||
|           return user_thermistor_to_deg_c(CTI_HOTEND_5, raw); | ||||
|         #elif ENABLED(HEATER_5_USES_AD595) | ||||
|           return TEMP_AD595(raw); | ||||
|         #elif ENABLED(HEATER_5_USES_AD8495) | ||||
|           return TEMP_AD8495(raw); | ||||
|         #else | ||||
|           break; | ||||
|         #endif | ||||
|       default: break; | ||||
|     } | ||||
|  | ||||
|   switch (e) { | ||||
|     case 0: | ||||
|       #if ENABLED(HEATER_0_USER_THERMISTOR) | ||||
|         return user_thermistor_to_deg_c(CTI_HOTEND_0, raw); | ||||
|       #elif ENABLED(HEATER_0_USES_MAX6675) | ||||
|         return raw * 0.25; | ||||
|       #elif ENABLED(HEATER_0_USES_AD595) | ||||
|         return TEMP_AD595(raw); | ||||
|       #elif ENABLED(HEATER_0_USES_AD8495) | ||||
|         return TEMP_AD8495(raw); | ||||
|       #else | ||||
|         break; | ||||
|       #endif | ||||
|     case 1: | ||||
|       #if ENABLED(HEATER_1_USER_THERMISTOR) | ||||
|         return user_thermistor_to_deg_c(CTI_HOTEND_1, raw); | ||||
|       #elif ENABLED(HEATER_1_USES_MAX6675) | ||||
|         return raw * 0.25; | ||||
|       #elif ENABLED(HEATER_1_USES_AD595) | ||||
|         return TEMP_AD595(raw); | ||||
|       #elif ENABLED(HEATER_1_USES_AD8495) | ||||
|         return TEMP_AD8495(raw); | ||||
|       #else | ||||
|         break; | ||||
|       #endif | ||||
|     case 2: | ||||
|       #if ENABLED(HEATER_2_USER_THERMISTOR) | ||||
|         return user_thermistor_to_deg_c(CTI_HOTEND_2, raw); | ||||
|       #elif ENABLED(HEATER_2_USES_AD595) | ||||
|         return TEMP_AD595(raw); | ||||
|       #elif ENABLED(HEATER_2_USES_AD8495) | ||||
|         return TEMP_AD8495(raw); | ||||
|       #else | ||||
|         break; | ||||
|       #endif | ||||
|     case 3: | ||||
|       #if ENABLED(HEATER_3_USER_THERMISTOR) | ||||
|         return user_thermistor_to_deg_c(CTI_HOTEND_3, raw); | ||||
|       #elif ENABLED(HEATER_3_USES_AD595) | ||||
|         return TEMP_AD595(raw); | ||||
|       #elif ENABLED(HEATER_3_USES_AD8495) | ||||
|         return TEMP_AD8495(raw); | ||||
|       #else | ||||
|         break; | ||||
|       #endif | ||||
|     case 4: | ||||
|       #if ENABLED(HEATER_4_USER_THERMISTOR) | ||||
|         return user_thermistor_to_deg_c(CTI_HOTEND_4, raw); | ||||
|       #elif ENABLED(HEATER_4_USES_AD595) | ||||
|         return TEMP_AD595(raw); | ||||
|       #elif ENABLED(HEATER_4_USES_AD8495) | ||||
|         return TEMP_AD8495(raw); | ||||
|       #else | ||||
|         break; | ||||
|       #endif | ||||
|     case 5: | ||||
|       #if ENABLED(HEATER_5_USER_THERMISTOR) | ||||
|         return user_thermistor_to_deg_c(CTI_HOTEND_5, raw); | ||||
|       #elif ENABLED(HEATER_5_USES_AD595) | ||||
|         return TEMP_AD595(raw); | ||||
|       #elif ENABLED(HEATER_5_USES_AD8495) | ||||
|         return TEMP_AD8495(raw); | ||||
|       #else | ||||
|         break; | ||||
|       #endif | ||||
|     default: break; | ||||
|     #if HOTEND_USES_THERMISTOR | ||||
|       // Thermistor with conversion table? | ||||
|       const short(*tt)[][2] = (short(*)[][2])(heater_ttbl_map[e]); | ||||
|       SCAN_THERMISTOR_TABLE((*tt), heater_ttbllen_map[e]); | ||||
|     #endif | ||||
|  | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   #if HOTEND_USES_THERMISTOR | ||||
|     // Thermistor with conversion table? | ||||
|     const short(*tt)[][2] = (short(*)[][2])(heater_ttbl_map[e]); | ||||
|     SCAN_THERMISTOR_TABLE((*tt), heater_ttbllen_map[e]); | ||||
|   #endif | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
| #endif // HOTENDS | ||||
|  | ||||
| #if HAS_HEATED_BED | ||||
|   // Derived from RepRap FiveD extruder::getTemperature() | ||||
| @@ -1500,7 +1513,9 @@ void Temperature::updateTemperaturesFromRawValues() { | ||||
|   #if ENABLED(HEATER_1_USES_MAX6675) | ||||
|     temp_hotend[1].raw = READ_MAX6675(1); | ||||
|   #endif | ||||
|   HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e); | ||||
|   #if HOTENDS | ||||
|     HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e); | ||||
|   #endif | ||||
|   #if HAS_HEATED_BED | ||||
|     temp_bed.celsius = analog_to_celsius_bed(temp_bed.raw); | ||||
|   #endif | ||||
| @@ -1802,7 +1817,7 @@ void Temperature::init() { | ||||
|       #endif // HOTENDS > 2 | ||||
|     #endif // HOTENDS > 1 | ||||
|  | ||||
|   #endif // HOTENDS > 1 | ||||
|   #endif // HOTENDS | ||||
|  | ||||
|   #if HAS_HEATED_BED | ||||
|     #ifdef BED_MINTEMP | ||||
| @@ -1976,7 +1991,9 @@ void Temperature::disable_all_heaters() { | ||||
|     planner.autotemp_enabled = false; | ||||
|   #endif | ||||
|  | ||||
|   HOTEND_LOOP() setTargetHotend(0, e); | ||||
|   #if HOTENDS | ||||
|     HOTEND_LOOP() setTargetHotend(0, e); | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_HEATED_BED | ||||
|     setTargetBed(0); | ||||
| @@ -2238,9 +2255,11 @@ void Temperature::readings_ready() { | ||||
|     current_raw_filwidth = raw_filwidth_value >> 10;  // Divide to get to 0-16384 range since we used 1/128 IIR filter approach | ||||
|   #endif | ||||
|  | ||||
|   HOTEND_LOOP() temp_hotend[e].reset(); | ||||
|   #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) | ||||
|     temp_hotend[1].reset(); | ||||
|   #if HOTENDS | ||||
|     HOTEND_LOOP() temp_hotend[e].reset(); | ||||
|     #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) | ||||
|       temp_hotend[1].reset(); | ||||
|     #endif | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_HEATED_BED | ||||
| @@ -2261,55 +2280,59 @@ void Temperature::readings_ready() { | ||||
|     joystick.z.reset(); | ||||
|   #endif | ||||
|  | ||||
|   static constexpr int8_t temp_dir[] = { | ||||
|     #if ENABLED(HEATER_0_USES_MAX6675) | ||||
|       0 | ||||
|     #else | ||||
|       TEMPDIR(0) | ||||
|     #endif | ||||
|     #if HOTENDS > 1 | ||||
|       #if ENABLED(HEATER_1_USES_MAX6675) | ||||
|         , 0 | ||||
|       #else | ||||
|         , TEMPDIR(1) | ||||
|       #endif | ||||
|       #if HOTENDS > 2 | ||||
|         , TEMPDIR(2) | ||||
|         #if HOTENDS > 3 | ||||
|           , TEMPDIR(3) | ||||
|           #if HOTENDS > 4 | ||||
|             , TEMPDIR(4) | ||||
|             #if HOTENDS > 5 | ||||
|               , TEMPDIR(5) | ||||
|             #endif // HOTENDS > 5 | ||||
|           #endif // HOTENDS > 4 | ||||
|         #endif // HOTENDS > 3 | ||||
|       #endif // HOTENDS > 2 | ||||
|     #endif // HOTENDS > 1 | ||||
|   }; | ||||
|   #if HOTENDS | ||||
|  | ||||
|   for (uint8_t e = 0; e < COUNT(temp_dir); e++) { | ||||
|     const int8_t tdir = temp_dir[e]; | ||||
|     if (tdir) { | ||||
|       const int16_t rawtemp = temp_hotend[e].raw * tdir; // normal direction, +rawtemp, else -rawtemp | ||||
|       const bool heater_on = (temp_hotend[e].target > 0 | ||||
|         #if ENABLED(PIDTEMP) | ||||
|           || temp_hotend[e].soft_pwm_amount > 0 | ||||
|         #endif | ||||
|       ); | ||||
|       if (rawtemp > temp_range[e].raw_max * tdir) max_temp_error((heater_ind_t)e); | ||||
|       if (heater_on && rawtemp < temp_range[e].raw_min * tdir && !is_preheating(e)) { | ||||
|         #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED | ||||
|           if (++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED) | ||||
|         #endif | ||||
|             min_temp_error((heater_ind_t)e); | ||||
|       } | ||||
|       #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED | ||||
|         else | ||||
|           consecutive_low_temperature_error[e] = 0; | ||||
|     static constexpr int8_t temp_dir[] = { | ||||
|       #if ENABLED(HEATER_0_USES_MAX6675) | ||||
|         0 | ||||
|       #else | ||||
|         TEMPDIR(0) | ||||
|       #endif | ||||
|       #if HOTENDS > 1 | ||||
|         #if ENABLED(HEATER_1_USES_MAX6675) | ||||
|           , 0 | ||||
|         #else | ||||
|           , TEMPDIR(1) | ||||
|         #endif | ||||
|         #if HOTENDS > 2 | ||||
|           , TEMPDIR(2) | ||||
|           #if HOTENDS > 3 | ||||
|             , TEMPDIR(3) | ||||
|             #if HOTENDS > 4 | ||||
|               , TEMPDIR(4) | ||||
|               #if HOTENDS > 5 | ||||
|                 , TEMPDIR(5) | ||||
|               #endif // HOTENDS > 5 | ||||
|             #endif // HOTENDS > 4 | ||||
|           #endif // HOTENDS > 3 | ||||
|         #endif // HOTENDS > 2 | ||||
|       #endif // HOTENDS > 1 | ||||
|     }; | ||||
|  | ||||
|     for (uint8_t e = 0; e < COUNT(temp_dir); e++) { | ||||
|       const int8_t tdir = temp_dir[e]; | ||||
|       if (tdir) { | ||||
|         const int16_t rawtemp = temp_hotend[e].raw * tdir; // normal direction, +rawtemp, else -rawtemp | ||||
|         const bool heater_on = (temp_hotend[e].target > 0 | ||||
|           #if ENABLED(PIDTEMP) | ||||
|             || temp_hotend[e].soft_pwm_amount > 0 | ||||
|           #endif | ||||
|         ); | ||||
|         if (rawtemp > temp_range[e].raw_max * tdir) max_temp_error((heater_ind_t)e); | ||||
|         if (heater_on && rawtemp < temp_range[e].raw_min * tdir && !is_preheating(e)) { | ||||
|           #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED | ||||
|             if (++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED) | ||||
|           #endif | ||||
|               min_temp_error((heater_ind_t)e); | ||||
|         } | ||||
|         #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED | ||||
|           else | ||||
|             consecutive_low_temperature_error[e] = 0; | ||||
|         #endif | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   #endif // HOTENDS | ||||
|  | ||||
|   #if HAS_HEATED_BED | ||||
|     #if TEMPDIR(BED) < 0 | ||||
| @@ -2399,12 +2422,10 @@ void Temperature::isr() { | ||||
|     static bool ADCKey_pressed = false; | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(SLOW_PWM_HEATERS) | ||||
|     static uint8_t slow_pwm_count = 0; | ||||
|   #if HOTENDS | ||||
|     static SoftPWM soft_pwm_hotend[HOTENDS]; | ||||
|   #endif | ||||
|  | ||||
|   static SoftPWM soft_pwm_hotend[HOTENDS]; | ||||
|  | ||||
|   #if HAS_HEATED_BED | ||||
|     static SoftPWM soft_pwm_bed; | ||||
|   #endif | ||||
| @@ -2414,40 +2435,46 @@ void Temperature::isr() { | ||||
|   #endif | ||||
|  | ||||
|   #if DISABLED(SLOW_PWM_HEATERS) | ||||
|     constexpr uint8_t pwm_mask = | ||||
|       #if ENABLED(SOFT_PWM_DITHER) | ||||
|         _BV(SOFT_PWM_SCALE) - 1 | ||||
|       #else | ||||
|         0 | ||||
|       #endif | ||||
|     ; | ||||
|  | ||||
|     #if HOTENDS || HAS_HEATED_BED || HAS_HEATED_CHAMBER | ||||
|       constexpr uint8_t pwm_mask = | ||||
|         #if ENABLED(SOFT_PWM_DITHER) | ||||
|           _BV(SOFT_PWM_SCALE) - 1 | ||||
|         #else | ||||
|           0 | ||||
|         #endif | ||||
|       ; | ||||
|       #define _PWM_MOD(N,S,T) do{                           \ | ||||
|         const bool on = S.add(pwm_mask, T.soft_pwm_amount); \ | ||||
|         WRITE_HEATER_##N(on);                               \ | ||||
|       }while(0) | ||||
|     #endif | ||||
|  | ||||
|     /** | ||||
|      * Standard heater PWM modulation | ||||
|      */ | ||||
|     if (pwm_count_tmp >= 127) { | ||||
|       pwm_count_tmp -= 127; | ||||
|       #define _PWM_MOD(N,S,T) do{                           \ | ||||
|         const bool on = S.add(pwm_mask, T.soft_pwm_amount); \ | ||||
|         WRITE_HEATER_##N(on);                               \ | ||||
|       }while(0) | ||||
|       #define _PWM_MOD_E(N) _PWM_MOD(N,soft_pwm_hotend[N],temp_hotend[N]) | ||||
|       _PWM_MOD_E(0); | ||||
|       #if HOTENDS > 1 | ||||
|         _PWM_MOD_E(1); | ||||
|         #if HOTENDS > 2 | ||||
|           _PWM_MOD_E(2); | ||||
|           #if HOTENDS > 3 | ||||
|             _PWM_MOD_E(3); | ||||
|             #if HOTENDS > 4 | ||||
|               _PWM_MOD_E(4); | ||||
|               #if HOTENDS > 5 | ||||
|                 _PWM_MOD_E(5); | ||||
|               #endif // HOTENDS > 5 | ||||
|             #endif // HOTENDS > 4 | ||||
|           #endif // HOTENDS > 3 | ||||
|         #endif // HOTENDS > 2 | ||||
|       #endif // HOTENDS > 1 | ||||
|  | ||||
|       #if HOTENDS | ||||
|         #define _PWM_MOD_E(N) _PWM_MOD(N,soft_pwm_hotend[N],temp_hotend[N]) | ||||
|         _PWM_MOD_E(0); | ||||
|         #if HOTENDS > 1 | ||||
|           _PWM_MOD_E(1); | ||||
|           #if HOTENDS > 2 | ||||
|             _PWM_MOD_E(2); | ||||
|             #if HOTENDS > 3 | ||||
|               _PWM_MOD_E(3); | ||||
|               #if HOTENDS > 4 | ||||
|                 _PWM_MOD_E(4); | ||||
|                 #if HOTENDS > 5 | ||||
|                   _PWM_MOD_E(5); | ||||
|                 #endif // HOTENDS > 5 | ||||
|               #endif // HOTENDS > 4 | ||||
|             #endif // HOTENDS > 3 | ||||
|           #endif // HOTENDS > 2 | ||||
|         #endif // HOTENDS > 1 | ||||
|       #endif // HOTENDS | ||||
|  | ||||
|       #if HAS_HEATED_BED | ||||
|         _PWM_MOD(BED,soft_pwm_bed,temp_bed); | ||||
| @@ -2538,6 +2565,8 @@ void Temperature::isr() { | ||||
|     #define _SLOW_PWM(NR,PWM,SRC) do{ PWM.count = SRC.soft_pwm_amount; _SLOW_SET(NR,PWM,(PWM.count > 0)); }while(0) | ||||
|     #define _PWM_OFF(NR,PWM) do{ if (PWM.count < slow_pwm_count) _SLOW_SET(NR,PWM,0); }while(0) | ||||
|  | ||||
|     static uint8_t slow_pwm_count = 0; | ||||
|  | ||||
|     if (slow_pwm_count == 0) { | ||||
|  | ||||
|       #if HOTENDS | ||||
| @@ -2634,22 +2663,24 @@ void Temperature::isr() { | ||||
|       slow_pwm_count++; | ||||
|       slow_pwm_count &= 0x7F; | ||||
|  | ||||
|       soft_pwm_hotend[0].dec(); | ||||
|       #if HOTENDS > 1 | ||||
|         soft_pwm_hotend[1].dec(); | ||||
|         #if HOTENDS > 2 | ||||
|           soft_pwm_hotend[2].dec(); | ||||
|           #if HOTENDS > 3 | ||||
|             soft_pwm_hotend[3].dec(); | ||||
|             #if HOTENDS > 4 | ||||
|               soft_pwm_hotend[4].dec(); | ||||
|               #if HOTENDS > 5 | ||||
|                 soft_pwm_hotend[5].dec(); | ||||
|               #endif // HOTENDS > 5 | ||||
|             #endif // HOTENDS > 4 | ||||
|           #endif // HOTENDS > 3 | ||||
|         #endif // HOTENDS > 2 | ||||
|       #endif // HOTENDS > 1 | ||||
|       #if HOTENDS | ||||
|         soft_pwm_hotend[0].dec(); | ||||
|         #if HOTENDS > 1 | ||||
|           soft_pwm_hotend[1].dec(); | ||||
|           #if HOTENDS > 2 | ||||
|             soft_pwm_hotend[2].dec(); | ||||
|             #if HOTENDS > 3 | ||||
|               soft_pwm_hotend[3].dec(); | ||||
|               #if HOTENDS > 4 | ||||
|                 soft_pwm_hotend[4].dec(); | ||||
|                 #if HOTENDS > 5 | ||||
|                   soft_pwm_hotend[5].dec(); | ||||
|                 #endif // HOTENDS > 5 | ||||
|               #endif // HOTENDS > 4 | ||||
|             #endif // HOTENDS > 3 | ||||
|           #endif // HOTENDS > 2 | ||||
|         #endif // HOTENDS > 1 | ||||
|       #endif // HOTENDS | ||||
|       #if HAS_HEATED_BED | ||||
|         soft_pwm_bed.dec(); | ||||
|       #endif | ||||
| @@ -2940,7 +2971,7 @@ void Temperature::isr() { | ||||
|  | ||||
|   #endif // AUTO_REPORT_TEMPERATURES | ||||
|  | ||||
|   #if HAS_DISPLAY | ||||
|   #if HOTENDS && HAS_DISPLAY | ||||
|     void Temperature::set_heating_message(const uint8_t e) { | ||||
|       const bool heating = isHeatingHotend(e); | ||||
|       #if HOTENDS > 1 | ||||
|   | ||||
| @@ -270,11 +270,14 @@ class Temperature { | ||||
|  | ||||
|     static volatile bool in_temp_isr; | ||||
|  | ||||
|     static hotend_info_t temp_hotend[HOTENDS | ||||
|     #if HOTENDS | ||||
|       #if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) | ||||
|         + 1 | ||||
|         #define HOTEND_TEMPS (HOTENDS + 1) | ||||
|       #else | ||||
|         #define HOTEND_TEMPS HOTENDS | ||||
|       #endif | ||||
|     ]; | ||||
|       static hotend_info_t temp_hotend[HOTEND_TEMPS]; | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_HEATED_BED | ||||
|       static bed_info_t temp_bed; | ||||
| @@ -349,7 +352,9 @@ class Temperature { | ||||
|       static lpq_ptr_t lpq_ptr; | ||||
|     #endif | ||||
|  | ||||
|     static temp_range_t temp_range[HOTENDS]; | ||||
|     #if HOTENDS | ||||
|       static temp_range_t temp_range[HOTENDS]; | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_HEATED_BED | ||||
|       #if WATCH_BED | ||||
| @@ -417,8 +422,6 @@ class Temperature { | ||||
|      * Instance Methods | ||||
|      */ | ||||
|  | ||||
|     Temperature(); | ||||
|  | ||||
|     void init(); | ||||
|  | ||||
|     /** | ||||
| @@ -456,7 +459,9 @@ class Temperature { | ||||
|       } | ||||
|     #endif | ||||
|  | ||||
|     static float analog_to_celsius_hotend(const int raw, const uint8_t e); | ||||
|     #if HOTENDS | ||||
|       static float analog_to_celsius_hotend(const int raw, const uint8_t e); | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_HEATED_BED | ||||
|       static float analog_to_celsius_bed(const int raw); | ||||
| @@ -577,19 +582,31 @@ class Temperature { | ||||
|  | ||||
|     FORCE_INLINE static float degHotend(const uint8_t e) { | ||||
|       E_UNUSED(); | ||||
|       return temp_hotend[HOTEND_INDEX].celsius; | ||||
|       #if HOTENDS | ||||
|         return temp_hotend[HOTEND_INDEX].celsius; | ||||
|       #else | ||||
|         return 0; | ||||
|       #endif | ||||
|     } | ||||
|  | ||||
|     #if ENABLED(SHOW_TEMP_ADC_VALUES) | ||||
|       FORCE_INLINE static int16_t rawHotendTemp(const uint8_t e) { | ||||
|         E_UNUSED(); | ||||
|         return temp_hotend[HOTEND_INDEX].raw; | ||||
|         #if HOTENDS | ||||
|           return temp_hotend[HOTEND_INDEX].raw; | ||||
|         #else | ||||
|           return 0; | ||||
|         #endif | ||||
|       } | ||||
|     #endif | ||||
|  | ||||
|     FORCE_INLINE static int16_t degTargetHotend(const uint8_t e) { | ||||
|       E_UNUSED(); | ||||
|       return temp_hotend[HOTEND_INDEX].target; | ||||
|       #if HOTENDS | ||||
|         return temp_hotend[HOTEND_INDEX].target; | ||||
|       #else | ||||
|         return 0; | ||||
|       #endif | ||||
|     } | ||||
|  | ||||
|     #if WATCH_HOTENDS | ||||
| @@ -598,52 +615,56 @@ class Temperature { | ||||
|       static inline void start_watching_hotend(const uint8_t e=0) { UNUSED(e); } | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_LCD_MENU | ||||
|       static inline void start_watching_E0() { start_watching_hotend(0); } | ||||
|       static inline void start_watching_E1() { start_watching_hotend(1); } | ||||
|       static inline void start_watching_E2() { start_watching_hotend(2); } | ||||
|       static inline void start_watching_E3() { start_watching_hotend(3); } | ||||
|       static inline void start_watching_E4() { start_watching_hotend(4); } | ||||
|       static inline void start_watching_E5() { start_watching_hotend(5); } | ||||
|     #endif | ||||
|     #if HOTENDS | ||||
|  | ||||
|     static void setTargetHotend(const int16_t celsius, const uint8_t e) { | ||||
|       E_UNUSED(); | ||||
|       const uint8_t ee = HOTEND_INDEX; | ||||
|       #ifdef MILLISECONDS_PREHEAT_TIME | ||||
|         if (celsius == 0) | ||||
|           reset_preheat_time(ee); | ||||
|         else if (temp_hotend[ee].target == 0) | ||||
|           start_preheat_time(ee); | ||||
|       #if HAS_LCD_MENU | ||||
|         static inline void start_watching_E0() { start_watching_hotend(0); } | ||||
|         static inline void start_watching_E1() { start_watching_hotend(1); } | ||||
|         static inline void start_watching_E2() { start_watching_hotend(2); } | ||||
|         static inline void start_watching_E3() { start_watching_hotend(3); } | ||||
|         static inline void start_watching_E4() { start_watching_hotend(4); } | ||||
|         static inline void start_watching_E5() { start_watching_hotend(5); } | ||||
|       #endif | ||||
|       #if ENABLED(AUTO_POWER_CONTROL) | ||||
|         powerManager.power_on(); | ||||
|       #endif | ||||
|       temp_hotend[ee].target = _MIN(celsius, temp_range[ee].maxtemp - 15); | ||||
|       start_watching_hotend(ee); | ||||
|     } | ||||
|  | ||||
|     FORCE_INLINE static bool isHeatingHotend(const uint8_t e) { | ||||
|       E_UNUSED(); | ||||
|       return temp_hotend[HOTEND_INDEX].target > temp_hotend[HOTEND_INDEX].celsius; | ||||
|     } | ||||
|  | ||||
|     FORCE_INLINE static bool isCoolingHotend(const uint8_t e) { | ||||
|       E_UNUSED(); | ||||
|       return temp_hotend[HOTEND_INDEX].target < temp_hotend[HOTEND_INDEX].celsius; | ||||
|     } | ||||
|  | ||||
|     #if HAS_TEMP_HOTEND | ||||
|       static bool wait_for_hotend(const uint8_t target_extruder, const bool no_wait_for_cooling=true | ||||
|         #if G26_CLICK_CAN_CANCEL | ||||
|           , const bool click_to_cancel=false | ||||
|       static void setTargetHotend(const int16_t celsius, const uint8_t e) { | ||||
|         E_UNUSED(); | ||||
|         const uint8_t ee = HOTEND_INDEX; | ||||
|         #ifdef MILLISECONDS_PREHEAT_TIME | ||||
|           if (celsius == 0) | ||||
|             reset_preheat_time(ee); | ||||
|           else if (temp_hotend[ee].target == 0) | ||||
|             start_preheat_time(ee); | ||||
|         #endif | ||||
|       ); | ||||
|     #endif | ||||
|         #if ENABLED(AUTO_POWER_CONTROL) | ||||
|           powerManager.power_on(); | ||||
|         #endif | ||||
|         temp_hotend[ee].target = _MIN(celsius, temp_range[ee].maxtemp - 15); | ||||
|         start_watching_hotend(ee); | ||||
|       } | ||||
|  | ||||
|     FORCE_INLINE static bool still_heating(const uint8_t e) { | ||||
|       return degTargetHotend(e) > TEMP_HYSTERESIS && ABS(degHotend(e) - degTargetHotend(e)) > TEMP_HYSTERESIS; | ||||
|     } | ||||
|       FORCE_INLINE static bool isHeatingHotend(const uint8_t e) { | ||||
|         E_UNUSED(); | ||||
|         return temp_hotend[HOTEND_INDEX].target > temp_hotend[HOTEND_INDEX].celsius; | ||||
|       } | ||||
|  | ||||
|       FORCE_INLINE static bool isCoolingHotend(const uint8_t e) { | ||||
|         E_UNUSED(); | ||||
|         return temp_hotend[HOTEND_INDEX].target < temp_hotend[HOTEND_INDEX].celsius; | ||||
|       } | ||||
|  | ||||
|       #if HAS_TEMP_HOTEND | ||||
|         static bool wait_for_hotend(const uint8_t target_extruder, const bool no_wait_for_cooling=true | ||||
|           #if G26_CLICK_CAN_CANCEL | ||||
|             , const bool click_to_cancel=false | ||||
|           #endif | ||||
|         ); | ||||
|       #endif | ||||
|  | ||||
|       FORCE_INLINE static bool still_heating(const uint8_t e) { | ||||
|         return degTargetHotend(e) > TEMP_HYSTERESIS && ABS(degHotend(e) - degTargetHotend(e)) > TEMP_HYSTERESIS; | ||||
|       } | ||||
|  | ||||
|     #endif // HOTENDS | ||||
|  | ||||
|     #if HAS_HEATED_BED | ||||
|  | ||||
|   | ||||
| @@ -695,11 +695,13 @@ inline void fast_line_to_current(const AxisEnum fr_axis) { | ||||
|  | ||||
| #endif // ELECTROMAGNETIC_SWITCHING_TOOLHEAD | ||||
|  | ||||
| inline void invalid_extruder_error(const uint8_t e) { | ||||
|   SERIAL_ECHO_START(); | ||||
|   SERIAL_CHAR('T'); SERIAL_ECHO(int(e)); | ||||
|   SERIAL_CHAR(' '); SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER); | ||||
| } | ||||
| #if EXTRUDERS | ||||
|   inline void invalid_extruder_error(const uint8_t e) { | ||||
|     SERIAL_ECHO_START(); | ||||
|     SERIAL_CHAR('T'); SERIAL_ECHO(int(e)); | ||||
|     SERIAL_CHAR(' '); SERIAL_ECHOLNPGM(MSG_INVALID_EXTRUDER); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(DUAL_X_CARRIAGE) | ||||
|  | ||||
| @@ -788,6 +790,11 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { | ||||
|  | ||||
|     mmu2.tool_change(new_tool); | ||||
|  | ||||
|   #elif EXTRUDERS == 0 | ||||
|  | ||||
|     // Nothing to do | ||||
|     UNUSED(new_tool); UNUSED(no_move); | ||||
|  | ||||
|   #elif EXTRUDERS < 2 | ||||
|  | ||||
|     UNUSED(no_move); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user