diff --git a/Marlin/M100_Free_Mem_Chk.cpp b/Marlin/M100_Free_Mem_Chk.cpp
index c3027794c515634f4f9d83492aaf40519e4077ab..8804bab6a77f28144030315e9a8e90017079ae0b 100644
--- a/Marlin/M100_Free_Mem_Chk.cpp
+++ b/Marlin/M100_Free_Mem_Chk.cpp
@@ -57,9 +57,6 @@ void prt_hex_byte(unsigned int);
 void prt_hex_word(unsigned int);
 int how_many_E5s_are_here(unsigned char*);
 
-
-
-
 void gcode_M100() {
   static int m100_not_initialized = 1;
   unsigned char* sp, *ptr;
@@ -73,49 +70,49 @@ void gcode_M100() {
   // probably caused by bad pointers.  Any unexpected values will be flagged in
   // the right hand column to help spotting them.
   //
-#if ENABLED(M100_FREE_MEMORY_DUMPER) // Disable to remove Dump sub-command
-  if (code_seen('D')) {
-    ptr = (unsigned char*) __brkval;
-    //
-    // We want to start and end the dump on a nice 16 byte boundry even though
-    // the values we are using are not 16 byte aligned.
-    //
-    SERIAL_ECHOPGM("\n__brkval : ");
-    prt_hex_word((unsigned int) ptr);
-    ptr = (unsigned char*)((unsigned long) ptr & 0xfff0);
-    sp = top_of_stack();
-    SERIAL_ECHOPGM("\nStack Pointer : ");
-    prt_hex_word((unsigned int) sp);
-    SERIAL_EOL;
-    sp = (unsigned char*)((unsigned long) sp | 0x000f);
-    n = sp - ptr;
-    //
-    // This is the main loop of the Dump command.
-    //
-    while (ptr < sp) {
-      prt_hex_word((unsigned int) ptr); // Print the address
-      SERIAL_CHAR(':');
-      for (i = 0; i < 16; i++) {      // and 16 data bytes
-        prt_hex_byte(*(ptr + i));
-        SERIAL_CHAR(' ');
-        delay(2);
-      }
-      SERIAL_CHAR('|');         // now show where non 0xE5's are
-      for (i = 0; i < 16; i++) {
-        delay(2);
-        if (*(ptr + i) == 0xe5)
+  #if ENABLED(M100_FREE_MEMORY_DUMPER) // Disable to remove Dump sub-command
+    if (code_seen('D')) {
+      ptr = (unsigned char*) __brkval;
+      //
+      // We want to start and end the dump on a nice 16 byte boundry even though
+      // the values we are using are not 16 byte aligned.
+      //
+      SERIAL_ECHOPGM("\n__brkval : ");
+      prt_hex_word((unsigned int) ptr);
+      ptr = (unsigned char*)((unsigned long) ptr & 0xfff0);
+      sp = top_of_stack();
+      SERIAL_ECHOPGM("\nStack Pointer : ");
+      prt_hex_word((unsigned int) sp);
+      SERIAL_EOL;
+      sp = (unsigned char*)((unsigned long) sp | 0x000f);
+      n = sp - ptr;
+      //
+      // This is the main loop of the Dump command.
+      //
+      while (ptr < sp) {
+        prt_hex_word((unsigned int) ptr); // Print the address
+        SERIAL_CHAR(':');
+        for (i = 0; i < 16; i++) {      // and 16 data bytes
+          prt_hex_byte(*(ptr + i));
           SERIAL_CHAR(' ');
-        else
-          SERIAL_CHAR('?');
+          delay(2);
+        }
+        SERIAL_CHAR('|');         // now show where non 0xE5's are
+        for (i = 0; i < 16; i++) {
+          delay(2);
+          if (*(ptr + i) == 0xe5)
+            SERIAL_CHAR(' ');
+          else
+            SERIAL_CHAR('?');
+        }
+        SERIAL_EOL;
+        ptr += 16;
+        delay(2);
       }
-      SERIAL_EOL;
-      ptr += 16;
-      delay(2);
+      SERIAL_ECHOLNPGM("Done.");
+      return;
     }
-    SERIAL_ECHOLNPGM("Done.");
-    return;
-  }
-#endif
+  #endif
   //
   // M100 F   requests the code to return the number of free bytes in the memory pool along with
   // other vital statistics that define the memory pool.
@@ -158,28 +155,28 @@ void gcode_M100() {
   // M100 C x  Corrupts x locations in the free memory pool and reports the locations of the corruption.
   // This is useful to check the correctness of the M100 D and the M100 F commands.
   //
-#if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
-  if (code_seen('C')) {
-    int x = code_value_int(); // x gets the # of locations to corrupt within the memory pool
-    SERIAL_ECHOLNPGM("Corrupting free memory block.\n");
-    ptr = (unsigned char*) __brkval;
-    SERIAL_ECHOPAIR("\n__brkval : ", ptr);
-    ptr += 8;
-    sp = top_of_stack();
-    SERIAL_ECHOPAIR("\nStack Pointer : ", sp);
-    SERIAL_ECHOLNPGM("\n");
-    n = sp - ptr - 64;    // -64 just to keep us from finding interrupt activity that
-    // has altered the stack.
-    j = n / (x + 1);
-    for (i = 1; i <= x; i++) {
-      *(ptr + (i * j)) = i;
-      SERIAL_ECHOPGM("\nCorrupting address: 0x");
-      prt_hex_word((unsigned int)(ptr + (i * j)));
+  #if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
+    if (code_seen('C')) {
+      int x = code_value_int(); // x gets the # of locations to corrupt within the memory pool
+      SERIAL_ECHOLNPGM("Corrupting free memory block.\n");
+      ptr = (unsigned char*) __brkval;
+      SERIAL_ECHOPAIR("\n__brkval : ", ptr);
+      ptr += 8;
+      sp = top_of_stack();
+      SERIAL_ECHOPAIR("\nStack Pointer : ", sp);
+      SERIAL_ECHOLNPGM("\n");
+      n = sp - ptr - 64;    // -64 just to keep us from finding interrupt activity that
+      // has altered the stack.
+      j = n / (x + 1);
+      for (i = 1; i <= x; i++) {
+        *(ptr + (i * j)) = i;
+        SERIAL_ECHOPGM("\nCorrupting address: 0x");
+        prt_hex_word((unsigned int)(ptr + (i * j)));
+      }
+      SERIAL_ECHOLNPGM("\n");
+      return;
     }
-    SERIAL_ECHOLNPGM("\n");
-    return;
-  }
-#endif
+  #endif
   //
   // M100 I    Initializes the free memory pool so it can be watched and prints vital
   // statistics that define the free memory pool.
diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index 38b69dab0dae6da39993a0da178ade23bf2ea490..89ab4615aaa19235f78ff5197d7bf3f62bb3524c 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -4365,7 +4365,7 @@ inline void gcode_M104() {
       SERIAL_PROTOCOL_F(thermalManager.degTargetBed(), 1);
     #endif
     #if HOTENDS > 1
-      for (int8_t e = 0; e < HOTENDS; ++e) {
+      HOTEND_LOOP() {
         SERIAL_PROTOCOLPGM(" T");
         SERIAL_PROTOCOL(e);
         SERIAL_PROTOCOLCHAR(':');
@@ -4391,7 +4391,7 @@ inline void gcode_M104() {
       SERIAL_PROTOCOL(thermalManager.getHeaterPower(target_extruder));
     #endif
     #if HOTENDS > 1
-      for (int8_t e = 0; e < HOTENDS; ++e) {
+      HOTEND_LOOP() {
         SERIAL_PROTOCOLPGM(" @");
         SERIAL_PROTOCOL(e);
         SERIAL_PROTOCOLCHAR(':');
@@ -4410,13 +4410,13 @@ inline void gcode_M104() {
         SERIAL_PROTOCOLPGM("C->");
         SERIAL_PROTOCOL_F(thermalManager.rawBedTemp() / OVERSAMPLENR, 0);
       #endif
-      for (int8_t cur_hotend = 0; cur_hotend < HOTENDS; ++cur_hotend) {
+      HOTEND_LOOP() {
         SERIAL_PROTOCOLPGM("  T");
-        SERIAL_PROTOCOL(cur_hotend);
+        SERIAL_PROTOCOL(e);
         SERIAL_PROTOCOLCHAR(':');
-        SERIAL_PROTOCOL_F(thermalManager.degHotend(cur_hotend), 1);
+        SERIAL_PROTOCOL_F(thermalManager.degHotend(e), 1);
         SERIAL_PROTOCOLPGM("C->");
-        SERIAL_PROTOCOL_F(thermalManager.rawHotendTemp(cur_hotend) / OVERSAMPLENR, 0);
+        SERIAL_PROTOCOL_F(thermalManager.rawHotendTemp(e) / OVERSAMPLENR, 0);
       }
     #endif
   }
@@ -5436,7 +5436,7 @@ inline void gcode_M206() {
 
     SERIAL_ECHO_START;
     SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
-    for (int e = 0; e < HOTENDS; e++) {
+    HOTEND_LOOP() {
       SERIAL_CHAR(' ');
       SERIAL_ECHO(hotend_offset[X_AXIS][e]);
       SERIAL_CHAR(',');
@@ -7968,8 +7968,9 @@ void prepare_move_to_destination() {
     float max_temp = 0.0;
     if (ELAPSED(millis(), next_status_led_update_ms)) {
       next_status_led_update_ms += 500; // Update every 0.5s
-      for (int8_t cur_hotend = 0; cur_hotend < HOTENDS; ++cur_hotend)
-        max_temp = max(max(max_temp, thermalManager.degHotend(cur_hotend)), thermalManager.degTargetHotend(cur_hotend));
+      HOTEND_LOOP() {
+        max_temp = max(max(max_temp, thermalManager.degHotend(e)), thermalManager.degTargetHotend(e));
+      }
       #if HAS_TEMP_BED
         max_temp = max(max(max_temp, thermalManager.degTargetBed()), thermalManager.degBed());
       #endif
diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp
index 4420a0e1f7d3c8a1bf9a3cabd7409e60e63c80d9..c14e957b22fdc9354305279ad0b6b34c17a702a2 100644
--- a/Marlin/configuration_store.cpp
+++ b/Marlin/configuration_store.cpp
@@ -618,7 +618,7 @@ void Config_ResetDefault() {
 
   #if ENABLED(PIDTEMP)
     #if ENABLED(PID_PARAMS_PER_HOTEND)
-      for (uint8_t e = 0; e < HOTENDS; e++)
+      HOTEND_LOOP
     #else
       int e = 0; UNUSED(e); // only need to write once
     #endif
@@ -834,15 +834,15 @@ void Config_PrintSettings(bool forReplay) {
     #if ENABLED(PIDTEMP)
       #if HOTENDS > 1
         if (forReplay) {
-          for (uint8_t i = 0; i < HOTENDS; i++) {
+          HOTEND_LOOP() {
             CONFIG_ECHO_START;
-            SERIAL_ECHOPAIR("  M301 E", i);
-            SERIAL_ECHOPAIR(" P", PID_PARAM(Kp, i));
-            SERIAL_ECHOPAIR(" I", unscalePID_i(PID_PARAM(Ki, i)));
-            SERIAL_ECHOPAIR(" D", unscalePID_d(PID_PARAM(Kd, i)));
+            SERIAL_ECHOPAIR("  M301 E", e);
+            SERIAL_ECHOPAIR(" P", PID_PARAM(Kp, e));
+            SERIAL_ECHOPAIR(" I", unscalePID_i(PID_PARAM(Ki, e)));
+            SERIAL_ECHOPAIR(" D", unscalePID_d(PID_PARAM(Kd, e)));
             #if ENABLED(PID_ADD_EXTRUSION_RATE)
-              SERIAL_ECHOPAIR(" C", PID_PARAM(Kc, i));
-              if (i == 0) SERIAL_ECHOPAIR(" L", lpq_len);
+              SERIAL_ECHOPAIR(" C", PID_PARAM(Kc, e));
+              if (e == 0) SERIAL_ECHOPAIR(" L", lpq_len);
             #endif
             SERIAL_EOL;
           }
diff --git a/Marlin/dogm_lcd_implementation.h b/Marlin/dogm_lcd_implementation.h
index c71213a2234ce732ca252134e2c422868f9e08aa..16c48e7be408acaa8247e1d95c3a3b265fc0835d 100644
--- a/Marlin/dogm_lcd_implementation.h
+++ b/Marlin/dogm_lcd_implementation.h
@@ -392,7 +392,7 @@ static void lcd_implementation_status_screen() {
   #endif
 
   // Extruders
-  for (int i = 0; i < HOTENDS; i++) _draw_heater_status(5 + i * 25, i);
+  HOTEND_LOOP() _draw_heater_status(5 + e * 25, e);
 
   // Heated bed
   #if HOTENDS < 4 && HAS_TEMP_BED
diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp
index fb9b40cf0ffebad3eca1b123052ea2fe8d88f5b4..f385cd212b308425734054c9031b2fa60ca46457 100644
--- a/Marlin/temperature.cpp
+++ b/Marlin/temperature.cpp
@@ -436,7 +436,7 @@ Temperature::Temperature() { }
 
 void Temperature::updatePID() {
   #if ENABLED(PIDTEMP)
-    for (int e = 0; e < HOTENDS; e++) {
+    HOTEND_LOOP() {
       temp_iState_max[e] = (PID_INTEGRAL_DRIVE_MAX) / PID_PARAM(Ki, e);
       #if ENABLED(PID_ADD_EXTRUSION_RATE)
         last_position[e] = 0;
@@ -465,12 +465,12 @@ int Temperature::getHeaterPower(int heater) {
       EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_2_AUTO_FAN_PIN ? 2 : 3
     };
     uint8_t fanState = 0;
-    for (int f = 0; f < HOTENDS; f++) {
-      if (current_temperature[f] > EXTRUDER_AUTO_FAN_TEMPERATURE)
-        SBI(fanState, fanBit[f]);
+    HOTEND_LOOP() {
+      if (current_temperature[e] > EXTRUDER_AUTO_FAN_TEMPERATURE)
+        SBI(fanState, fanBit[e]);
     }
     uint8_t fanDone = 0;
-    for (int f = 0; f <= 3; f++) {
+    for (int8_t f = 0; f <= 3; f++) {
       int8_t pin = fanPin[f];
       if (pin >= 0 && !TEST(fanDone, fanBit[f])) {
         unsigned char newFanSpeed = TEST(fanState, fanBit[f]) ? EXTRUDER_AUTO_FAN_SPEED : 0;
@@ -507,95 +507,99 @@ void Temperature::_temp_error(int e, const char* serial_msg, const char* lcd_msg
 }
 
 void Temperature::max_temp_error(uint8_t e) {
-  _temp_error(e, PSTR(MSG_T_MAXTEMP), PSTR(MSG_ERR_MAXTEMP));
+  #if HOTENDS == 1
+    UNUSED(e);
+  #endif
+  _temp_error(HOTEND_INDEX, PSTR(MSG_T_MAXTEMP), PSTR(MSG_ERR_MAXTEMP));
 }
 void Temperature::min_temp_error(uint8_t e) {
-  _temp_error(e, PSTR(MSG_T_MINTEMP), PSTR(MSG_ERR_MINTEMP));
+  #if HOTENDS == 1
+    UNUSED(e);
+  #endif
+  _temp_error(HOTEND_INDEX, PSTR(MSG_T_MINTEMP), PSTR(MSG_ERR_MINTEMP));
 }
 
 float Temperature::get_pid_output(int e) {
+  #if HOTENDS == 1
+    UNUSED(e);
+    #define _HOTEND_TEST     true
+    #define _HOTEND_EXTRUDER active_extruder
+  #else
+    #define _HOTEND_TEST     e == active_extruder
+    #define _HOTEND_EXTRUDER e
+  #endif
   float pid_output;
   #if ENABLED(PIDTEMP)
     #if DISABLED(PID_OPENLOOP)
-      pid_error[e] = target_temperature[e] - current_temperature[e];
-      dTerm[e] = K2 * PID_PARAM(Kd, e) * (current_temperature[e] - temp_dState[e]) + K1 * dTerm[e];
-      temp_dState[e] = current_temperature[e];
-      if (pid_error[e] > PID_FUNCTIONAL_RANGE) {
+      pid_error[HOTEND_INDEX] = target_temperature[HOTEND_INDEX] - current_temperature[HOTEND_INDEX];
+      dTerm[HOTEND_INDEX] = K2 * PID_PARAM(Kd, HOTEND_INDEX) * (current_temperature[HOTEND_INDEX] - temp_dState[HOTEND_INDEX]) + K1 * dTerm[HOTEND_INDEX];
+      temp_dState[HOTEND_INDEX] = current_temperature[HOTEND_INDEX];
+      if (pid_error[HOTEND_INDEX] > PID_FUNCTIONAL_RANGE) {
         pid_output = BANG_MAX;
-        pid_reset[e] = true;
+        pid_reset[HOTEND_INDEX] = true;
       }
-      else if (pid_error[e] < -(PID_FUNCTIONAL_RANGE) || target_temperature[e] == 0) {
+      else if (pid_error[HOTEND_INDEX] < -(PID_FUNCTIONAL_RANGE) || target_temperature[HOTEND_INDEX] == 0) {
         pid_output = 0;
-        pid_reset[e] = true;
+        pid_reset[HOTEND_INDEX] = true;
       }
       else {
-        if (pid_reset[e]) {
-          temp_iState[e] = 0.0;
-          pid_reset[e] = false;
+        if (pid_reset[HOTEND_INDEX]) {
+          temp_iState[HOTEND_INDEX] = 0.0;
+          pid_reset[HOTEND_INDEX] = false;
         }
-        pTerm[e] = PID_PARAM(Kp, e) * pid_error[e];
-        temp_iState[e] += pid_error[e];
-        temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
-        iTerm[e] = PID_PARAM(Ki, e) * temp_iState[e];
+        pTerm[HOTEND_INDEX] = PID_PARAM(Kp, HOTEND_INDEX) * pid_error[HOTEND_INDEX];
+        temp_iState[HOTEND_INDEX] += pid_error[HOTEND_INDEX];
+        temp_iState[HOTEND_INDEX] = constrain(temp_iState[HOTEND_INDEX], temp_iState_min[HOTEND_INDEX], temp_iState_max[HOTEND_INDEX]);
+        iTerm[HOTEND_INDEX] = PID_PARAM(Ki, HOTEND_INDEX) * temp_iState[HOTEND_INDEX];
 
-        pid_output = pTerm[e] + iTerm[e] - dTerm[e];
-
-        #if ENABLED(SINGLENOZZLE)
-          #define _NOZZLE_TEST     true
-          #define _NOZZLE_EXTRUDER active_extruder
-          #define _CTERM_INDEX     0
-        #else
-          #define _NOZZLE_TEST     e == active_extruder
-          #define _NOZZLE_EXTRUDER e
-          #define _CTERM_INDEX     e
-        #endif
+        pid_output = pTerm[HOTEND_INDEX] + iTerm[HOTEND_INDEX] - dTerm[HOTEND_INDEX];
 
         #if ENABLED(PID_ADD_EXTRUSION_RATE)
-          cTerm[_CTERM_INDEX] = 0;
-          if (_NOZZLE_TEST) {
+          cTerm[HOTEND_INDEX] = 0;
+          if (_HOTEND_TEST) {
             long e_position = stepper.position(E_AXIS);
-            if (e_position > last_position[_NOZZLE_EXTRUDER]) {
-              lpq[lpq_ptr++] = e_position - last_position[_NOZZLE_EXTRUDER];
-              last_position[_NOZZLE_EXTRUDER] = e_position;
+            if (e_position > last_position[_HOTEND_EXTRUDER]) {
+              lpq[lpq_ptr++] = e_position - last_position[_HOTEND_EXTRUDER];
+              last_position[_HOTEND_EXTRUDER] = e_position;
             }
             else {
               lpq[lpq_ptr++] = 0;
             }
             if (lpq_ptr >= lpq_len) lpq_ptr = 0;
-            cTerm[_CTERM_INDEX] = (lpq[lpq_ptr] / planner.axis_steps_per_mm[E_AXIS]) * PID_PARAM(Kc, e);
-            pid_output += cTerm[e];
+            cTerm[HOTEND_INDEX] = (lpq[lpq_ptr] / planner.axis_steps_per_mm[E_AXIS]) * PID_PARAM(Kc, HOTEND_INDEX);
+            pid_output += cTerm[HOTEND_INDEX];
           }
         #endif //PID_ADD_EXTRUSION_RATE
 
         if (pid_output > PID_MAX) {
-          if (pid_error[e] > 0) temp_iState[e] -= pid_error[e]; // conditional un-integration
+          if (pid_error[HOTEND_INDEX] > 0) temp_iState[HOTEND_INDEX] -= pid_error[HOTEND_INDEX]; // conditional un-integration
           pid_output = PID_MAX;
         }
         else if (pid_output < 0) {
-          if (pid_error[e] < 0) temp_iState[e] -= pid_error[e]; // conditional un-integration
+          if (pid_error[HOTEND_INDEX] < 0) temp_iState[HOTEND_INDEX] -= pid_error[HOTEND_INDEX]; // conditional un-integration
           pid_output = 0;
         }
       }
     #else
-      pid_output = constrain(target_temperature[e], 0, PID_MAX);
+      pid_output = constrain(target_temperature[HOTEND_INDEX], 0, PID_MAX);
     #endif //PID_OPENLOOP
 
     #if ENABLED(PID_DEBUG)
       SERIAL_ECHO_START;
-      SERIAL_ECHOPAIR(MSG_PID_DEBUG, e);
-      SERIAL_ECHOPAIR(MSG_PID_DEBUG_INPUT, current_temperature[e]);
+      SERIAL_ECHOPAIR(MSG_PID_DEBUG, HOTEND_INDEX);
+      SERIAL_ECHOPAIR(MSG_PID_DEBUG_INPUT, current_temperature[HOTEND_INDEX]);
       SERIAL_ECHOPAIR(MSG_PID_DEBUG_OUTPUT, pid_output);
-      SERIAL_ECHOPAIR(MSG_PID_DEBUG_PTERM, pTerm[e]);
-      SERIAL_ECHOPAIR(MSG_PID_DEBUG_ITERM, iTerm[e]);
-      SERIAL_ECHOPAIR(MSG_PID_DEBUG_DTERM, dTerm[e]);
+      SERIAL_ECHOPAIR(MSG_PID_DEBUG_PTERM, pTerm[HOTEND_INDEX]);
+      SERIAL_ECHOPAIR(MSG_PID_DEBUG_ITERM, iTerm[HOTEND_INDEX]);
+      SERIAL_ECHOPAIR(MSG_PID_DEBUG_DTERM, dTerm[HOTEND_INDEX]);
       #if ENABLED(PID_ADD_EXTRUSION_RATE)
-        SERIAL_ECHOPAIR(MSG_PID_DEBUG_CTERM, cTerm[e]);
+        SERIAL_ECHOPAIR(MSG_PID_DEBUG_CTERM, cTerm[HOTEND_INDEX]);
       #endif
       SERIAL_EOL;
     #endif //PID_DEBUG
 
   #else /* PID off */
-    pid_output = (current_temperature[e] < target_temperature[e]) ? PID_MAX : 0;
+    pid_output = (current_temperature[HOTEND_INDEX] < target_temperature[HOTEND_INDEX]) ? PID_MAX : 0;
   #endif
 
   return pid_output;
@@ -672,7 +676,7 @@ void Temperature::manage_heater() {
   #endif
 
   // Loop through all hotends
-  for (int e = 0; e < HOTENDS; e++) {
+  HOTEND_LOOP() {
 
     #if ENABLED(THERMAL_PROTECTION_HOTENDS)
       thermal_runaway_protection(&thermal_runaway_state_machine[e], &thermal_runaway_timer[e], current_temperature[e], target_temperature[e], e, THERMAL_PROTECTION_PERIOD, THERMAL_PROTECTION_HYSTERESIS);
@@ -879,7 +883,7 @@ void Temperature::updateTemperaturesFromRawValues() {
   #if ENABLED(HEATER_0_USES_MAX6675)
     current_temperature_raw[0] = read_max6675();
   #endif
-  for (uint8_t e = 0; e < HOTENDS; e++) {
+  HOTEND_LOOP() {
     current_temperature[e] = Temperature::analog2temp(current_temperature_raw[e], e);
   }
   current_temperature_bed = Temperature::analog2tempBed(current_temperature_bed_raw);
@@ -933,7 +937,7 @@ void Temperature::init() {
   #endif
 
   // Finish init of mult hotend arrays
-  for (int e = 0; e < HOTENDS; e++) {
+  HOTEND_LOOP() {
     // populate with the first value
     maxttemp[e] = maxttemp[0];
     #if ENABLED(PIDTEMP)
@@ -1140,13 +1144,16 @@ void Temperature::init() {
    * their target temperature by a configurable margin.
    * This is called when the temperature is set. (M104, M109)
    */
-  void Temperature::start_watching_heater(int e) {
-    if (degHotend(e) < degTargetHotend(e) - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) {
-      watch_target_temp[e] = degHotend(e) + WATCH_TEMP_INCREASE;
-      watch_heater_next_ms[e] = millis() + (WATCH_TEMP_PERIOD) * 1000UL;
+  void Temperature::start_watching_heater(uint8_t e) {
+    #if HOTENDS == 1
+      UNUSED(e);
+    #endif
+    if (degHotend(HOTEND_INDEX) < degTargetHotend(HOTEND_INDEX) - (WATCH_TEMP_INCREASE + TEMP_HYSTERESIS + 1)) {
+      watch_target_temp[HOTEND_INDEX] = degHotend(HOTEND_INDEX) + WATCH_TEMP_INCREASE;
+      watch_heater_next_ms[HOTEND_INDEX] = millis() + (WATCH_TEMP_PERIOD) * 1000UL;
     }
     else
-      watch_heater_next_ms[e] = 0;
+      watch_heater_next_ms[HOTEND_INDEX] = 0;
   }
 #endif
 
@@ -1224,7 +1231,7 @@ void Temperature::init() {
 #endif // THERMAL_PROTECTION_HOTENDS || THERMAL_PROTECTION_BED
 
 void Temperature::disable_all_heaters() {
-  for (int i = 0; i < HOTENDS; i++) setTargetHotend(0, i);
+  HOTEND_LOOP() setTargetHotend(0, e);
   setTargetBed(0);
 
   // If all heaters go down then for sure our print job has stopped
diff --git a/Marlin/temperature.h b/Marlin/temperature.h
index 60aa80d6a79d3bf2046ce58e8f8b92863905f0b2..311fb4a39d92d0990a7aace285ada9d09f97bdb0 100644
--- a/Marlin/temperature.h
+++ b/Marlin/temperature.h
@@ -38,6 +38,16 @@
   #define SOFT_PWM_SCALE 0
 #endif
 
+#if HOTENDS == 1
+  #define HOTEND_LOOP() const uint8_t e = 0;
+  #define HOTEND_INDEX  0
+  #define EXTRUDER_IDX  0
+#else
+  #define HOTEND_LOOP() for (int8_t e = 0; e < HOTENDS; e++)
+  #define HOTEND_INDEX  e
+  #define EXTRUDER_IDX  active_extruder
+#endif
+
 class Temperature {
 
   public:
@@ -112,7 +122,12 @@ class Temperature {
 
     #if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
       static float extrude_min_temp;
-      static bool tooColdToExtrude(uint8_t e) { return degHotend(e) < extrude_min_temp; }
+      static bool tooColdToExtrude(uint8_t e) {
+        #if HOTENDS == 1
+          UNUSED(e);
+        #endif
+        return degHotend(HOTEND_INDEX) < extrude_min_temp;
+      }
     #else
       static bool tooColdToExtrude(uint8_t e) { UNUSED(e); return false; }
     #endif
@@ -230,53 +245,47 @@ class Temperature {
     //inline so that there is no performance decrease.
     //deg=degreeCelsius
 
-    #if HOTENDS == 1
-      #define HOTEND_ARG 0
-    #else
-      #define HOTEND_ARG hotend
-    #endif
-
-    static float degHotend(uint8_t hotend) {
+    static float degHotend(uint8_t e) {
       #if HOTENDS == 1
-        UNUSED(hotend);
+        UNUSED(e);
       #endif
-      return current_temperature[HOTEND_ARG];
+      return current_temperature[HOTEND_INDEX];
     }
     static float degBed() { return current_temperature_bed; }
 
     #if ENABLED(SHOW_TEMP_ADC_VALUES)
-    static float rawHotendTemp(uint8_t hotend) {
+    static float rawHotendTemp(uint8_t e) {
       #if HOTENDS == 1
-        UNUSED(hotend);
+        UNUSED(e);
       #endif
-      return current_temperature_raw[HOTEND_ARG];
+      return current_temperature_raw[HOTEND_INDEX];
     }
     static float rawBedTemp() { return current_temperature_bed_raw; }
     #endif
 
-    static float degTargetHotend(uint8_t hotend) {
+    static float degTargetHotend(uint8_t e) {
       #if HOTENDS == 1
-        UNUSED(hotend);
+        UNUSED(e);
       #endif
-      return target_temperature[HOTEND_ARG];
+      return target_temperature[HOTEND_INDEX];
     }
     static float degTargetBed() { return target_temperature_bed; }
 
     #if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
-      static void start_watching_heater(int e = 0);
+      static void start_watching_heater(uint8_t e = 0);
     #endif
 
     #if ENABLED(THERMAL_PROTECTION_BED) && WATCH_BED_TEMP_PERIOD > 0
       static void start_watching_bed();
     #endif
 
-    static void setTargetHotend(const float& celsius, uint8_t hotend) {
+    static void setTargetHotend(const float& celsius, uint8_t e) {
       #if HOTENDS == 1
-        UNUSED(hotend);
+        UNUSED(e);
       #endif
-      target_temperature[HOTEND_ARG] = celsius;
+      target_temperature[HOTEND_INDEX] = celsius;
       #if ENABLED(THERMAL_PROTECTION_HOTENDS) && WATCH_TEMP_PERIOD > 0
-        start_watching_heater(HOTEND_ARG);
+        start_watching_heater(HOTEND_INDEX);
       #endif
     }
 
@@ -287,19 +296,19 @@ class Temperature {
       #endif
     }
 
-    static bool isHeatingHotend(uint8_t hotend) {
+    static bool isHeatingHotend(uint8_t e) {
       #if HOTENDS == 1
-        UNUSED(hotend);
+        UNUSED(e);
       #endif
-      return target_temperature[HOTEND_ARG] > current_temperature[HOTEND_ARG];
+      return target_temperature[HOTEND_INDEX] > current_temperature[HOTEND_INDEX];
     }
     static bool isHeatingBed() { return target_temperature_bed > current_temperature_bed; }
 
-    static bool isCoolingHotend(uint8_t hotend) {
+    static bool isCoolingHotend(uint8_t e) {
       #if HOTENDS == 1
-        UNUSED(hotend);
+        UNUSED(e);
       #endif
-      return target_temperature[HOTEND_ARG] < current_temperature[HOTEND_ARG];
+      return target_temperature[HOTEND_INDEX] < current_temperature[HOTEND_INDEX];
     }
     static bool isCoolingBed() { return target_temperature_bed < current_temperature_bed; }
 
@@ -329,8 +338,8 @@ class Temperature {
       #if ENABLED(AUTOTEMP)
         if (planner.autotemp_enabled) {
           planner.autotemp_enabled = false;
-          if (degTargetHotend(active_extruder) > planner.autotemp_min)
-            setTargetHotend(0, active_extruder);
+          if (degTargetHotend(EXTRUDER_IDX) > planner.autotemp_min)
+            setTargetHotend(0, EXTRUDER_IDX);
         }
       #endif
     }