diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index 7527eb5978f2e93f20d4aa19715b9a1c07ed2076..3c37b14a8aef2991bddf27d62d756e7b93edb832 100755
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -3145,7 +3145,7 @@ inline void gcode_G4() {
       if (DEBUGGING(LEVELING)) DEBUG_POS(">>> home_delta", current_position);
     #endif
     // Init the current position of all carriages to 0,0,0
-    memset(current_position, 0, sizeof(current_position));
+    ZERO(current_position);
     sync_plan_position();
 
     // Move all carriages together linearly until an endstop is hit.
diff --git a/Marlin/SdBaseFile.cpp b/Marlin/SdBaseFile.cpp
index 95765f9c18c1df875846222fe1572b51d08f6624..412292b9af126d9ee8d4a79e7cd21fd0f57f8577 100644
--- a/Marlin/SdBaseFile.cpp
+++ b/Marlin/SdBaseFile.cpp
@@ -674,7 +674,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
       index = 0;
     }
     // initialize as empty file
-    memset(p, 0, sizeof(dir_t));
+    ZERO(p);
     memcpy(p->name, dname, 11);
 
     // set timestamps
diff --git a/Marlin/cardreader.cpp b/Marlin/cardreader.cpp
index 67dd5371e597fafdf7d3843a98f1eecf669092ce..5f004d2f712e06bb28e48b4becfa2c51ba8b4e0f 100644
--- a/Marlin/cardreader.cpp
+++ b/Marlin/cardreader.cpp
@@ -36,7 +36,7 @@ CardReader::CardReader() {
   sdpos = 0;
   workDirDepth = 0;
   file_subcall_ctr = 0;
-  memset(workDirParents, 0, sizeof(workDirParents));
+  ZERO(workDirParents);
 
   autostart_stilltocheck = true; //the SD start is delayed, because otherwise the serial cannot answer fast enough to make contact with the host software.
   autostart_index = 0;
diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp
index cb958d9772a3aa268835b45fa1188d4626063fea..d46217f575a225b46fcdccd24689c570e8e36bd2 100644
--- a/Marlin/configuration_store.cpp
+++ b/Marlin/configuration_store.cpp
@@ -40,7 +40,6 @@
 
 // Change EEPROM version if these are changed:
 #define EEPROM_OFFSET 100
-#define MAX_EXTRUDERS 4
 
 /**
  * V24 EEPROM Layout:
diff --git a/Marlin/macros.h b/Marlin/macros.h
index 56b5c8bbaae105abe9581aa2a5f41f9e90abbe24..f1c991981c9057844c91f9df039d7eced7db7c89 100644
--- a/Marlin/macros.h
+++ b/Marlin/macros.h
@@ -78,6 +78,7 @@
 #define NUMERIC(a) ((a) >= '0' && '9' >= (a))
 #define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-')
 #define COUNT(a) (sizeof(a)/sizeof(*a))
+#define ZERO(a) memset(a,0,sizeof(a))
 
 // Macros for initializing arrays
 #define ARRAY_6(v1, v2, v3, v4, v5, v6, args...) { v1, v2, v3, v4, v5, v6 }
diff --git a/Marlin/mesh_bed_leveling.cpp b/Marlin/mesh_bed_leveling.cpp
index babad8aaaede64543d972fa3c495d9da3ef2522d..fa45198c6f48ceb24846e17984bc0579f6f5fd4f 100644
--- a/Marlin/mesh_bed_leveling.cpp
+++ b/Marlin/mesh_bed_leveling.cpp
@@ -31,7 +31,7 @@
   void mesh_bed_leveling::reset() {
     status = MBL_STATUS_NONE;
     z_offset = 0;
-    memset(z_values, 0, sizeof(z_values));
+    ZERO(z_values);
   }
 
 #endif  // MESH_BED_LEVELING
diff --git a/Marlin/pins.h b/Marlin/pins.h
index bfb30abec46f61c5f29883e5eae56f8e8b206ccb..f0720d7bf3bb2d35703a89d563187f87d5d29629 100644
--- a/Marlin/pins.h
+++ b/Marlin/pins.h
@@ -275,6 +275,10 @@
   #define SUICIDE_PIN -1
 #endif
 
+#ifndef MAX_EXTRUDERS
+  #define MAX_EXTRUDERS 4
+#endif
+
 // Marlin needs to account for pins that equal -1
 #define marlinAnalogInputToDigitalPin(p) ((p) == -1 ? -1 : analogInputToDigitalPin(p))
 
diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp
index cfc23dfd368185b020f47cccd666f9ba3287ab09..5487195565e0df71bb2b35ce9f4c995108a27e17 100644
--- a/Marlin/planner.cpp
+++ b/Marlin/planner.cpp
@@ -137,8 +137,8 @@ Planner::Planner() { init(); }
 
 void Planner::init() {
   block_buffer_head = block_buffer_tail = 0;
-  memset(position, 0, sizeof(position));
-  memset(previous_speed, 0, sizeof(previous_speed));
+  ZERO(position);
+  ZERO(previous_speed);
   previous_nominal_speed = 0.0;
   #if ABL_PLANAR
     bed_level_matrix.set_to_identity();
@@ -1266,7 +1266,7 @@ void Planner::_set_position_mm(const float &a, const float &b, const float &c, c
   stepper.set_position(na, nb, nc, ne);
   previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest.
 
-  memset(previous_speed, 0, sizeof(previous_speed));
+  ZERO(previous_speed);
 }
 
 void Planner::set_position_mm_kinematic(const float position[NUM_AXIS]) {
diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp
index 731dae9c756716fd6e330766ae3fa9b0ad3ef84c..617d9e3f0fd88489823c1c1654561a62bcef0b65 100644
--- a/Marlin/temperature.cpp
+++ b/Marlin/temperature.cpp
@@ -151,7 +151,7 @@ volatile bool Temperature::temp_meas_ready = false;
   millis_t Temperature::next_bed_check_ms;
 #endif
 
-unsigned long Temperature::raw_temp_value[4] = { 0 };
+unsigned long Temperature::raw_temp_value[MAX_EXTRUDERS] = { 0 };
 unsigned long Temperature::raw_temp_bed_value = 0;
 
 // Init min and max temp with extreme values to prevent false errors during startup
@@ -1758,6 +1758,9 @@ void Temperature::isr() {
   } // switch(temp_state)
 
   if (temp_count >= OVERSAMPLENR) { // 10 * 16 * 1/(16000000/64/256)  = 164ms.
+
+    temp_count = 0;
+
     // Update the raw values if they've been read. Else we could be updating them during reading.
     if (!temp_meas_ready) set_current_temp_raw();
 
@@ -1766,85 +1769,54 @@ void Temperature::isr() {
       current_raw_filwidth = raw_filwidth_value >> 10;  // Divide to get to 0-16384 range since we used 1/128 IIR filter approach
     #endif
 
-    temp_count = 0;
-    for (int i = 0; i < 4; i++) raw_temp_value[i] = 0;
+    ZERO(raw_temp_value);
     raw_temp_bed_value = 0;
 
-    #if HAS_TEMP_0 && DISABLED(HEATER_0_USES_MAX6675)
-      #if HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP
-        #define GE0 <=
+    int constexpr temp_dir[] = {
+      #if ENABLED(HEATER_0_USES_MAX6675)
+         0
+      #elif HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP
+        -1
       #else
-        #define GE0 >=
+         1
       #endif
-      if (current_temperature_raw[0] GE0 maxttemp_raw[0]) max_temp_error(0);
-      if (minttemp_raw[0] GE0 current_temperature_raw[0] && !is_preheating(0) && target_temperature[0] > 0.0f) {
-        #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
-          if (++consecutive_low_temperature_error[0] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED)
+      #if HAS_TEMP_1 && HOTENDS > 1
+        #if HEATER_1_RAW_LO_TEMP > HEATER_1_RAW_HI_TEMP
+          , -1
+        #else
+          ,  1
         #endif
-            min_temp_error(0);
-      }
-      #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
-        else
-          consecutive_low_temperature_error[0] = 0;
       #endif
-    #endif
-
-    #if HAS_TEMP_1 && HOTENDS > 1
-      #if HEATER_1_RAW_LO_TEMP > HEATER_1_RAW_HI_TEMP
-        #define GE1 <=
-      #else
-        #define GE1 >=
-      #endif
-      if (current_temperature_raw[1] GE1 maxttemp_raw[1]) max_temp_error(1);
-      if (minttemp_raw[1] GE1 current_temperature_raw[1] && !is_preheating(1) && target_temperature[1] > 0.0f) {
-        #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
-          if (++consecutive_low_temperature_error[1] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED)
+      #if HAS_TEMP_2 && HOTENDS > 2
+        #if HEATER_2_RAW_LO_TEMP > HEATER_2_RAW_HI_TEMP
+          , -1
+        #else
+          ,  1
         #endif
-          min_temp_error(1);
-      }
-      #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
-        else
-          consecutive_low_temperature_error[1] = 0;
-      #endif
-    #endif // TEMP_SENSOR_1
-
-    #if HAS_TEMP_2 && HOTENDS > 2
-      #if HEATER_2_RAW_LO_TEMP > HEATER_2_RAW_HI_TEMP
-        #define GE2 <=
-      #else
-        #define GE2 >=
       #endif
-      if (current_temperature_raw[2] GE2 maxttemp_raw[2]) max_temp_error(2);
-      if (minttemp_raw[2] GE2 current_temperature_raw[2] && !is_preheating(2) && target_temperature[2] > 0.0f) {
-        #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
-          if (++consecutive_low_temperature_error[2] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED)
+      #if HAS_TEMP_3 && HOTENDS > 3
+        #if HEATER_3_RAW_LO_TEMP > HEATER_3_RAW_HI_TEMP
+          , -1
+        #else
+          ,  1
         #endif
-          min_temp_error(2);
-      }
-      #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
-        else
-          consecutive_low_temperature_error[2] = 0;
       #endif
-    #endif // TEMP_SENSOR_2
+    };
 
-    #if HAS_TEMP_3 && HOTENDS > 3
-      #if HEATER_3_RAW_LO_TEMP > HEATER_3_RAW_HI_TEMP
-        #define GE3 <=
-      #else
-        #define GE3 >=
-      #endif
-      if (current_temperature_raw[3] GE3 maxttemp_raw[3]) max_temp_error(3);
-      if (minttemp_raw[3] GE3 current_temperature_raw[3] && !is_preheating(3) && target_temperature[3] > 0.0f) {
+    for (uint8_t e = 0; e < COUNT(temp_dir); e++) {
+      const int tdir = temp_dir[e], rawtemp = current_temperature_raw[e] * tdir;
+      if (rawtemp > maxttemp_raw[e] * tdir) max_temp_error(e);
+      if (rawtemp < minttemp_raw[e] * tdir && !is_preheating(e) && target_temperature[e] > 0.0f) {
         #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
-          if (++consecutive_low_temperature_error[3] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED)
+          if (++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED)
         #endif
-          min_temp_error(3);
+            min_temp_error(e);
       }
       #ifdef MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED
         else
-          consecutive_low_temperature_error[3] = 0;
+          consecutive_low_temperature_error[e] = 0;
       #endif
-    #endif // TEMP_SENSOR_3
+    }
 
     #if HAS_TEMP_BED
       #if HEATER_BED_RAW_LO_TEMP > HEATER_BED_RAW_HI_TEMP