diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index b6d81f4ef8b00ff8210bff2ea7da3fb384c842ef..f8edb87305fc74b4a11b6b84b6e2070ab9271c49 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -61,6 +61,7 @@
  * G30 - Single Z probe, probes bed at X Y location (defaults to current XY location)
  * G31 - Dock sled (Z_PROBE_SLED only)
  * G32 - Undock sled (Z_PROBE_SLED only)
+ * G33 - Delta '4-point' auto calibration iteration
  * G38 - Probe target - similar to G28 except it uses the Z_MIN_PROBE for all three axes
  * G90 - Use Absolute Coordinates
  * G91 - Use Relative Coordinates
@@ -1443,7 +1444,7 @@ bool get_target_extruder_from_command(int code) {
 
 #endif // NO_WORKSPACE_OFFSETS
 
-#if DISABLED(NO_WORKSPACE_OFFSETS)
+#if DISABLED(NO_WORKSPACE_OFFSETS) && DISABLED(DELTA)
   /**
    * Change the home offset for an axis, update the current
    * position and the software endstops to retain the same
@@ -1457,7 +1458,7 @@ bool get_target_extruder_from_command(int code) {
     home_offset[axis] = v;
     update_software_endstops(axis);
   }
-#endif // NO_WORKSPACE_OFFSETS
+#endif // !NO_WORKSPACE_OFFSETS && !DELTA
 
 /**
  * Set an axis' current position to its home position (after homing).
@@ -2299,7 +2300,7 @@ static void clean_up_after_endstop_or_probe_move() {
       SERIAL_PROTOCOLPGM(" Y: ");
       SERIAL_PROTOCOL_F(y, 3);
       SERIAL_PROTOCOLPGM(" Z: ");
-      SERIAL_PROTOCOL_F(FIXFLOAT(measured_z), 3);
+      SERIAL_PROTOCOL_F(measured_z, 3);
       SERIAL_EOL;
     }
 
@@ -4901,8 +4902,366 @@ inline void gcode_G28() {
 
   #endif // Z_PROBE_SLED
 
+  #if ENABLED(DELTA_AUTO_CALIBRATION)
+    /**
+     * G33: Delta '4-point' auto calibration iteration
+     *
+     * Usage: G33 <Cn> <Vn>
+     *
+     *  C  (default) = Calibrate endstops, height and delta radius
+     *
+     *  -2, 1-4: n x n probe points, default 3 x 3
+     *
+     *    1: probe center
+     *       set height only - useful when z_offset is changed
+     *    2: probe center and towers
+     *       solve one '4 point' calibration
+     *   -2: probe center and opposite the towers
+     *       solve one '4 point' calibration
+     *    3: probe 3 center points, towers and opposite-towers
+     *       averages between 2 '4 point' calibrations
+     *    4: probe 4 center points, towers, opposite-towers and itermediate points
+     *       averages between 4 '4 point' calibrations
+     *
+     *  V  Verbose level (0-3, default 1)
+     *
+     *    0: Dry-run mode: no calibration
+     *    1: Settings
+     *    2: Setting + probe results
+     *    3: Expert mode: setting + iteration factors (see Configuration_adv.h)
+     *       This prematurely stops the iteration process when factors are found
+     */
+    inline void gcode_G33() {
+
+      stepper.synchronize();
+
+      #if PLANNER_LEVELING
+        set_bed_leveling_enabled(false);
+      #endif
+
+      const int8_t pp = code_seen('C') ? code_value_int() : DELTA_CALIBRATION_DEFAULT_POINTS,
+                   probe_points = (WITHIN(pp, 1, 4) || pp == -2) ? pp : DELTA_CALIBRATION_DEFAULT_POINTS;
+
+      int8_t verbose_level = code_seen('V') ? code_value_byte() : 1;
+
+      #if ENABLED(DELTA_CALIBRATE_EXPERT_MODE)
+        #define _MAX_M33_V 3
+        if (verbose_level == 3 && probe_points == 1) verbose_level--; // needs at least 4 points
+      #else
+        #define _MAX_M33_V 2
+        if (verbose_level > 2)
+          SERIAL_PROTOCOLLNPGM("Enable DELTA_CALIBRATE_EXPERT_MODE in Configuration_adv.h");
+      #endif
+
+      if (!WITHIN(verbose_level, 0, _MAX_M33_V)) verbose_level = 1;
+
+      float zero_std_dev = verbose_level ? 999.0 : 0.0; // 0.0 in dry-run mode : forced end
+
+      gcode_G28();
+
+      float e_old[XYZ],
+            dr_old = delta_radius,
+            zh_old = home_offset[Z_AXIS];
+      COPY(e_old,endstop_adj);
+      #if ENABLED(DELTA_CALIBRATE_EXPERT_MODE)
+        // expert variables
+        float h_f_old = 1.00, r_f_old = 0.00,
+              h_diff_min = 1.00, r_diff_max = 0.10;
+      #endif
+
+      // print settings
+
+      SERIAL_PROTOCOLLNPGM("G33 Auto Calibrate");
+      SERIAL_PROTOCOLPGM("Checking... AC");
+      if (verbose_level == 0) SERIAL_PROTOCOLPGM(" (DRY-RUN)");
+      #if ENABLED(DELTA_CALIBRATE_EXPERT_MODE)
+        if (verbose_level == 3) SERIAL_PROTOCOLPGM(" (EXPERT)");
+      #endif
+      SERIAL_EOL;
+      LCD_MESSAGEPGM("Checking... AC");
+
+      SERIAL_PROTOCOLPAIR("Height:", DELTA_HEIGHT + home_offset[Z_AXIS]);
+      if (abs(probe_points) > 1) {
+        SERIAL_PROTOCOLPGM("    Ex:");
+        if (endstop_adj[A_AXIS] >= 0) SERIAL_CHAR('+');
+        SERIAL_PROTOCOL_F(endstop_adj[A_AXIS], 2);
+        SERIAL_PROTOCOLPGM("  Ey:");
+        if (endstop_adj[B_AXIS] >= 0) SERIAL_CHAR('+');
+        SERIAL_PROTOCOL_F(endstop_adj[B_AXIS], 2);
+        SERIAL_PROTOCOLPGM("  Ez:");
+        if (endstop_adj[C_AXIS] >= 0) SERIAL_CHAR('+');
+        SERIAL_PROTOCOL_F(endstop_adj[C_AXIS], 2);
+        SERIAL_PROTOCOLPAIR("    Radius:", delta_radius);
+      }
+      SERIAL_EOL;
+
+      #if ENABLED(Z_PROBE_SLED)
+        DEPLOY_PROBE();
+      #endif
+
+      float test_precision;
+      int8_t iterations = 0;
+
+      do { // start iterations
+
+        setup_for_endstop_or_probe_move();
+
+        test_precision =
+          #if ENABLED(DELTA_CALIBRATE_EXPERT_MODE)
+            // Expert mode : forced end at std_dev < 0.1
+            (verbose_level == 3 && zero_std_dev < 0.1) ? 0.0 :
+          #endif
+          zero_std_dev
+        ;
+
+        float z_at_pt[13] = { 0 };
+
+        iterations++;
+
+        // probe the points
+
+        int16_t center_points = 0;
+
+        if (probe_points != 3) {
+          z_at_pt[0] += probe_pt(0.0, 0.0 , true, 1);
+          center_points = 1;
+        }
+
+        int16_t step_axis = 4;
+        if (probe_points >= 3) {
+          for (int8_t axis = 9; axis > 0; axis -= step_axis) { // uint8_t starts endless loop
+            z_at_pt[0] += probe_pt(
+              0.1 * cos(RADIANS(180 + 30 * axis)) * (DELTA_CALIBRATION_RADIUS),
+              0.1 * sin(RADIANS(180 + 30 * axis)) * (DELTA_CALIBRATION_RADIUS), true, 1);
+          }
+          center_points += 3;
+          z_at_pt[0] /= center_points;
+        }
+
+        float S1 = z_at_pt[0], S2 = sq(S1);
+
+        int16_t N = 1, start = (probe_points == -2) ? 3 : 1;
+        step_axis = (abs(probe_points) == 2) ? 4 : (probe_points == 3) ? 2 : 1;
+
+        if (probe_points != 1) {
+          for (uint8_t axis = start; axis < 13; axis += step_axis)
+            z_at_pt[axis] += probe_pt(
+              cos(RADIANS(180 + 30 * axis)) * (DELTA_CALIBRATION_RADIUS),
+              sin(RADIANS(180 + 30 * axis)) * (DELTA_CALIBRATION_RADIUS), true, 1
+            );
+
+          if (probe_points == 4) step_axis = 2;
+        }
+
+        for (uint8_t axis = start; axis < 13; axis += step_axis) {
+          if (probe_points == 4)
+            z_at_pt[axis] = (z_at_pt[axis] + (z_at_pt[axis + 1] + z_at_pt[(axis + 10) % 12 + 1]) / 2.0) / 2.0;
+
+          S1 += z_at_pt[axis];
+          S2 += sq(z_at_pt[axis]);
+          N++;
+        }
+        zero_std_dev = round(sqrt(S2 / N) * 1000.0) / 1000.0 + 0.00001; // deviation from zero plane
+
+        // Solve matrices
+
+        if (zero_std_dev < test_precision) {
+          COPY(e_old, endstop_adj);
+          dr_old = delta_radius;
+          zh_old = home_offset[Z_AXIS];
+
+          float e_delta[XYZ] = { 0.0 }, r_delta = 0.0;
+
+          #if ENABLED(DELTA_CALIBRATE_EXPERT_MODE)
+            float h_f_new = 0.0, r_f_new = 0.0 , t_f_new = 0.0,
+                  h_diff = 0.00, r_diff = 0.00;
+          #endif
+
+          #define ZP(N,I) ((N) * z_at_pt[I])
+          #define Z1000(I) ZP(1.00, I)
+          #define Z1050(I) ZP(H_FACTOR, I)
+          #define Z0700(I) ZP((H_FACTOR) * 2.0 / 3.00, I)
+          #define Z0350(I) ZP((H_FACTOR) / 3.00, I)
+          #define Z0175(I) ZP((H_FACTOR) / 6.00, I)
+          #define Z2250(I) ZP(R_FACTOR, I)
+          #define Z0750(I) ZP((R_FACTOR) / 3.00, I)
+          #define Z0375(I) ZP((R_FACTOR) / 6.00, I)
+
+          switch (probe_points) {
+            case 1:
+              LOOP_XYZ(i) e_delta[i] = Z1000(0);
+              r_delta = 0.00;
+              break;
+
+            case 2:
+              e_delta[X_AXIS] = Z1050(0) + Z0700(1) - Z0350(5) - Z0350(9);
+              e_delta[Y_AXIS] = Z1050(0) - Z0350(1) + Z0700(5) - Z0350(9);
+              e_delta[Z_AXIS] = Z1050(0) - Z0350(1) - Z0350(5) + Z0700(9);
+              r_delta         = Z2250(0) - Z0750(1) - Z0750(5) - Z0750(9);
+              break;
+
+            case -2:
+              e_delta[X_AXIS] = Z1050(0) - Z0700(7) + Z0350(11) + Z0350(3);
+              e_delta[Y_AXIS] = Z1050(0) + Z0350(7) - Z0700(11) + Z0350(3);
+              e_delta[Z_AXIS] = Z1050(0) + Z0350(7) + Z0350(11) - Z0700(3);
+              r_delta         = Z2250(0) - Z0750(7) - Z0750(11) - Z0750(3);
+              break;
+
+            default:
+              e_delta[X_AXIS] = Z1050(0) + Z0350(1) - Z0175(5) - Z0175(9) - Z0350(7) + Z0175(11) + Z0175(3);
+              e_delta[Y_AXIS] = Z1050(0) - Z0175(1) + Z0350(5) - Z0175(9) + Z0175(7) - Z0350(11) + Z0175(3);
+              e_delta[Z_AXIS] = Z1050(0) - Z0175(1) - Z0175(5) + Z0350(9) + Z0175(7) + Z0175(11) - Z0350(3);
+              r_delta         = Z2250(0) - Z0375(1) - Z0375(5) - Z0375(9) - Z0375(7) - Z0375(11) - Z0375(3);
+              break;
+          }
+
+          #if ENABLED(DELTA_CALIBRATE_EXPERT_MODE)
+            // Calculate h & r factors
+            if (verbose_level == 3) {
+              LOOP_XYZ(axis) h_f_new += e_delta[axis] / 3;
+              r_f_new = r_delta;
+              h_diff = (1.0 / H_FACTOR) * (h_f_old - h_f_new) / h_f_old;
+              if (h_diff < h_diff_min && h_diff > 0.9) h_diff_min = h_diff;
+              if (r_f_old != 0)
+                r_diff = (   0.0301 * sq(R_FACTOR) * R_FACTOR
+                           + 0.311  * sq(R_FACTOR)
+                           + 1.1493 * R_FACTOR
+                           + 1.7952
+                         ) * (r_f_old - r_f_new) / r_f_old;
+              if (r_diff > r_diff_max && r_diff < 0.4444) r_diff_max = r_diff;
+              SERIAL_EOL;
+
+              h_f_old = h_f_new;
+              r_f_old = r_f_new;
+            }
+          #endif // DELTA_CALIBRATE_EXPERT_MODE
+
+          // Adjust delta_height and endstops by the max amount
+          LOOP_XYZ(axis) endstop_adj[axis] += e_delta[axis];
+          delta_radius += r_delta;
+
+          const float z_temp = MAX3(endstop_adj[0], endstop_adj[1], endstop_adj[2]);
+          home_offset[Z_AXIS] -= z_temp;
+          LOOP_XYZ(i) endstop_adj[i] -= z_temp;
+
+          recalc_delta_settings(delta_radius, delta_diagonal_rod);
+        }
+        else { // !iterate
+          // step one back
+          COPY(endstop_adj, e_old);
+          delta_radius = dr_old;
+          home_offset[Z_AXIS] = zh_old;
+
+          recalc_delta_settings(delta_radius, delta_diagonal_rod);
+        }
+
+        // print report
+
+        #if ENABLED(DELTA_CALIBRATE_EXPERT_MODE)
+          if (verbose_level == 3) {
+            const float r_factor =   22.902 * sq(r_diff_max) * r_diff_max
+                                   - 44.988 * sq(r_diff_max)
+                                   + 31.697 * r_diff_max
+                                   - 9.4439;
+            SERIAL_PROTOCOLPAIR("h_factor:", 1.0 / h_diff_min);
+            SERIAL_PROTOCOLPAIR("              r_factor:", r_factor);
+            SERIAL_EOL;
+          }
+        #endif
+        if (verbose_level == 2) {
+          SERIAL_PROTOCOLPGM(".     c:");
+          if (z_at_pt[0] > 0) SERIAL_CHAR('+');
+          SERIAL_PROTOCOL_F(z_at_pt[0], 2);
+          if (probe_points > 1) {
+            SERIAL_PROTOCOLPGM("     x:");
+            if (z_at_pt[1] >= 0) SERIAL_CHAR('+');
+            SERIAL_PROTOCOL_F(z_at_pt[1], 2);
+            SERIAL_PROTOCOLPGM("   y:");
+            if (z_at_pt[5] >= 0) SERIAL_CHAR('+');
+            SERIAL_PROTOCOL_F(z_at_pt[5], 2);
+            SERIAL_PROTOCOLPGM("   z:");
+            if (z_at_pt[9] >= 0) SERIAL_CHAR('+');
+            SERIAL_PROTOCOL_F(z_at_pt[9], 2);
+          }
+          if (probe_points > 0) SERIAL_EOL;
+          if (probe_points > 2 || probe_points == -2) {
+            if (probe_points > 2) SERIAL_PROTOCOLPGM(".            ");
+            SERIAL_PROTOCOLPGM("    yz:");
+            if (z_at_pt[7] >= 0) SERIAL_CHAR('+');
+            SERIAL_PROTOCOL_F(z_at_pt[7], 2);
+            SERIAL_PROTOCOLPGM("  zx:");
+            if (z_at_pt[11] >= 0) SERIAL_CHAR('+');
+            SERIAL_PROTOCOL_F(z_at_pt[11], 2);
+            SERIAL_PROTOCOLPGM("  xy:");
+            if (z_at_pt[3] >= 0) SERIAL_CHAR('+');
+            SERIAL_PROTOCOL_F(z_at_pt[3], 2);
+            SERIAL_EOL;
+          }
+        }
+        if (test_precision != 0.0) {            // !forced end
+          if (zero_std_dev >= test_precision) {
+            SERIAL_PROTOCOLPGM("Calibration OK");
+            SERIAL_PROTOCOLLNPGM("                                   rolling back 1");
+            LCD_MESSAGEPGM("Calibration OK");
+            SERIAL_EOL;
+          }
+          else {                                // !end iterations
+            char mess[15] = "No convergence";
+            if (iterations < 31)
+              sprintf_P(mess, PSTR("Iteration : %02i"), (int)iterations);
+            SERIAL_PROTOCOL(mess);
+            SERIAL_PROTOCOLPGM("                                   std dev:");
+            SERIAL_PROTOCOL_F(zero_std_dev, 3);
+            SERIAL_EOL;
+            lcd_setstatus(mess);
+          }
+          SERIAL_PROTOCOLPAIR("Height:", DELTA_HEIGHT + home_offset[Z_AXIS]);
+          if (abs(probe_points) > 1) {
+            SERIAL_PROTOCOLPGM("    Ex:");
+            if (endstop_adj[A_AXIS] >= 0) SERIAL_CHAR('+');
+            SERIAL_PROTOCOL_F(endstop_adj[A_AXIS], 2);
+            SERIAL_PROTOCOLPGM("  Ey:");
+            if (endstop_adj[B_AXIS] >= 0) SERIAL_CHAR('+');
+            SERIAL_PROTOCOL_F(endstop_adj[B_AXIS], 2);
+            SERIAL_PROTOCOLPGM("  Ez:");
+            if (endstop_adj[C_AXIS] >= 0) SERIAL_CHAR('+');
+            SERIAL_PROTOCOL_F(endstop_adj[C_AXIS], 2);
+            SERIAL_PROTOCOLPAIR("    Radius:", delta_radius);
+          }
+          SERIAL_EOL;
+          if (zero_std_dev >= test_precision)
+            SERIAL_PROTOCOLLNPGM("Save with M500");
+        }
+        else {                                  // forced end
+          #if ENABLED(DELTA_CALIBRATE_EXPERT_MODE)
+            if (verbose_level == 3)
+              SERIAL_PROTOCOLLNPGM("Copy to Configuration_adv.h");
+            else
+          #endif
+            {
+              SERIAL_PROTOCOLPGM("End DRY-RUN                                      std dev:");
+              SERIAL_PROTOCOL_F(zero_std_dev, 3);
+              SERIAL_EOL;
+            }
+        }
+
+        clean_up_after_endstop_or_probe_move();
+        stepper.synchronize();
+
+        gcode_G28();
+
+      } while (zero_std_dev < test_precision && iterations < 31);
+
+      #if ENABLED(Z_PROBE_SLED)
+        RETRACT_PROBE();
+      #endif
+    }
+
+  #endif // DELTA_AUTO_CALIBRATION
+
 #endif // HAS_BED_PROBE
 
+
 #if ENABLED(G38_PROBE_TARGET)
 
   static bool G38_run_probe() {
@@ -5631,7 +5990,7 @@ inline void gcode_M42() {
 
     if (axis_unhomed_error(true, true, true)) return;
 
-    int8_t verbose_level = code_seen('V') ? code_value_byte() : 1;
+    const int8_t verbose_level = code_seen('V') ? code_value_byte() : 1;
     if (!WITHIN(verbose_level, 0, 4)) {
       SERIAL_PROTOCOLLNPGM("?Verbose Level not plausible (0-4).");
       return;
@@ -7023,7 +7382,7 @@ inline void gcode_M205() {
   if (code_seen('E')) planner.max_jerk[E_AXIS] = code_value_axis_units(E_AXIS);
 }
 
-#if DISABLED(NO_WORKSPACE_OFFSETS)
+#if DISABLED(NO_WORKSPACE_OFFSETS) && DISABLED(DELTA)
 
   /**
    * M206: Set Additional Homing Offset (X Y Z). SCARA aliases T=X, P=Y
@@ -7048,6 +7407,7 @@ inline void gcode_M205() {
   /**
    * M665: Set delta configurations
    *
+   *    H = diagonal rod // AC-version
    *    L = diagonal rod
    *    R = delta radius
    *    S = segments per second
@@ -7056,6 +7416,12 @@ inline void gcode_M205() {
    *    C = Gamma (Tower 3) diagonal rod trim
    */
   inline void gcode_M665() {
+    if (code_seen('H')) {
+      home_offset[Z_AXIS] = code_value_linear_units() - DELTA_HEIGHT;
+      current_position[Z_AXIS] += code_value_linear_units() - DELTA_HEIGHT - home_offset[Z_AXIS];
+      home_offset[Z_AXIS] = code_value_linear_units() - DELTA_HEIGHT;
+      update_software_endstops(Z_AXIS);
+    }
     if (code_seen('L')) delta_diagonal_rod = code_value_linear_units();
     if (code_seen('R')) delta_radius = code_value_linear_units();
     if (code_seen('S')) delta_segments_per_second = code_value_float();
@@ -7914,7 +8280,7 @@ void quickstop_stepper() {
 
 #endif
 
-#if DISABLED(NO_WORKSPACE_OFFSETS)
+#if DISABLED(NO_WORKSPACE_OFFSETS) && DISABLED(DELTA)
 
   /**
    * M428: Set home_offset based on the distance between the
@@ -9203,6 +9569,15 @@ void process_next_command() {
               break;
 
         #endif // Z_PROBE_SLED
+
+        #if ENABLED(DELTA_AUTO_CALIBRATION)
+
+          case 33: // G33: Delta Auto Calibrate
+            gcode_G33();
+            break;
+
+        #endif // DELTA_AUTO_CALIBRATION
+
       #endif // HAS_BED_PROBE
 
       #if ENABLED(G38_PROBE_TARGET)
@@ -9520,7 +9895,7 @@ void process_next_command() {
         gcode_M205();
         break;
 
-      #if DISABLED(NO_WORKSPACE_OFFSETS)
+      #if DISABLED(NO_WORKSPACE_OFFSETS) && DISABLED(DELTA)
         case 206: // M206: Set home offsets
           gcode_M206();
           break;
@@ -9688,7 +10063,7 @@ void process_next_command() {
           break;
       #endif
 
-      #if DISABLED(NO_WORKSPACE_OFFSETS)
+      #if DISABLED(NO_WORKSPACE_OFFSETS) && DISABLED(DELTA)
         case 428: // M428: Apply current_position to home_offset
           gcode_M428();
           break;
@@ -11054,6 +11429,9 @@ void disable_all_steppers() {
       #if ENABLED(E3_IS_TMC2130)
         automatic_current_control(stepperE3);
       #endif
+      #if ENABLED(E4_IS_TMC2130)
+        automatic_current_control(stepperE4);
+      #endif
     }
   }
 
diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h
index 35d0b5f4405262baef31232ccc36551b58a0b1b5..362681b332f60a004c3827a17333dc0dfb00b58c 100644
--- a/Marlin/SanityCheck.h
+++ b/Marlin/SanityCheck.h
@@ -395,7 +395,7 @@
  * Delta Auto calibration
  */
 #if ENABLED(DELTA_AUTO_CALIBRATION) && ENABLED(NO_WORKSPACE_OFFSETS)
-  #error "To use DELTA_AUTO_CALIBRATION you must disable NO_WORKSPACE_OFFSETS."
+  #error "DELTA_AUTO_CALIBRATION is incompatible with NO_WORKSPACE_OFFSETS."
 #endif
 
 /**
diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp
index 72cf680a010e2ccb0daccae673cc592627c2eeb2..b85d7e152cad43a348d4a873f0ea7c12cb857685 100644
--- a/Marlin/configuration_store.cpp
+++ b/Marlin/configuration_store.cpp
@@ -47,7 +47,7 @@
  *  100  Version                                    (char x4)
  *  104  EEPROM Checksum                            (uint16_t)
  *
- *  106            E_STEPPERS (uint8_t)
+ *  106            E_STEPPERS                       (uint8_t)
  *  107  M92 XYZE  planner.axis_steps_per_mm        (float x4 ... x8)
  *  123  M203 XYZE planner.max_feedrate_mm_s        (float x4 ... x8)
  *  139  M201 XYZE planner.max_acceleration_mm_per_s2 (uint32_t x4 ... x8)
@@ -300,9 +300,17 @@ void MarlinSettings::postprocess() {
     EEPROM_WRITE(planner.min_segment_time);
     EEPROM_WRITE(planner.max_jerk);
     #if ENABLED(NO_WORKSPACE_OFFSETS)
-      float home_offset[XYZ] = { 0 };
+      const float home_offset[XYZ] = { 0 };
+    #endif
+    #if ENABLED(DELTA)
+      dummy = 0.0;
+      EEPROM_WRITE(dummy);
+      EEPROM_WRITE(dummy);
+      dummy = DELTA_HEIGHT + home_offset[Z_AXIS];
+      EEPROM_WRITE(dummy);
+    #else
+      EEPROM_WRITE(home_offset);
     #endif
-    EEPROM_WRITE(home_offset);
 
     #if HOTENDS > 1
       // Skip hotend 0 which must be 0
@@ -488,7 +496,7 @@ void MarlinSettings::postprocess() {
       EEPROM_WRITE(dummy);
     }
 
-    // Save TCM2130 Configuration, and placeholder values
+    // Save TMC2130 Configuration, and placeholder values
     uint16_t val;
     #if ENABLED(HAVE_TMC2130)
       #if ENABLED(X_IS_TMC2130)
@@ -551,6 +559,12 @@ void MarlinSettings::postprocess() {
         val = 0;
       #endif
       EEPROM_WRITE(val);
+      #if ENABLED(E4_IS_TMC2130)
+        val = stepperE4.getCurrent();
+      #else
+        val = 0;
+      #endif
+      EEPROM_WRITE(val);
     #else
       val = 0;
       for (uint8_t q = 0; q < 11; ++q) EEPROM_WRITE(val);
@@ -644,6 +658,12 @@ void MarlinSettings::postprocess() {
       #endif
       EEPROM_READ(home_offset);
 
+      #if ENABLED(DELTA)
+        home_offset[X_AXIS] = 0.0;
+        home_offset[Y_AXIS] = 0.0;
+        home_offset[Z_AXIS] -= DELTA_HEIGHT;
+      #endif
+
       #if HOTENDS > 1
         // Skip hotend 0 which must be 0
         for (uint8_t e = 1; e < HOTENDS; e++)
@@ -1019,6 +1039,9 @@ void MarlinSettings::reset() {
     delta_segments_per_second = DELTA_SEGMENTS_PER_SECOND;
     COPY(delta_diagonal_rod_trim, drt);
     COPY(delta_tower_angle_trim, dta);
+    #if ENABLED(DELTA)
+      home_offset[Z_AXIS] = 0;
+    #endif
   #elif ENABLED(Z_DUAL_ENDSTOPS)
     float z_endstop_adj =
       #ifdef Z_DUAL_ENDSTOPS_ADJUSTMENT
@@ -1143,7 +1166,7 @@ void MarlinSettings::reset() {
 
   /**
    * M503 - Report current settings in RAM
-   *   
+   *
    * Unless specifically disabled, M503 is available even without EEPROM
    */
   void MarlinSettings::report(bool forReplay) {
@@ -1231,7 +1254,7 @@ void MarlinSettings::reset() {
     SERIAL_ECHOPAIR(" E", planner.max_jerk[E_AXIS]);
     SERIAL_EOL;
 
-    #if DISABLED(NO_WORKSPACE_OFFSETS)
+    #if DISABLED(NO_WORKSPACE_OFFSETS) && DISABLED(DELTA)
       CONFIG_ECHO_START;
       if (!forReplay) {
         SERIAL_ECHOLNPGM("Home offset (mm)");
@@ -1346,11 +1369,12 @@ void MarlinSettings::reset() {
       SERIAL_EOL;
       CONFIG_ECHO_START;
       if (!forReplay) {
-        SERIAL_ECHOLNPGM("Delta settings: L=diagonal rod, R=radius, S=segments-per-second, ABC=diagonal rod trim, IJK=tower angle trim");
+        SERIAL_ECHOLNPGM("Delta settings: L=diagonal_rod, R=radius, H=height, S=segments_per_second, ABC=diagonal_rod_trim_tower_[123]");
         CONFIG_ECHO_START;
       }
       SERIAL_ECHOPAIR("  M665 L", delta_diagonal_rod);
       SERIAL_ECHOPAIR(" R", delta_radius);
+      SERIAL_ECHOPAIR(" H", DELTA_HEIGHT + home_offset[Z_AXIS]);
       SERIAL_ECHOPAIR(" S", delta_segments_per_second);
       SERIAL_ECHOPAIR(" A", delta_diagonal_rod_trim[A_AXIS]);
       SERIAL_ECHOPAIR(" B", delta_diagonal_rod_trim[B_AXIS]);
diff --git a/Marlin/language_en.h b/Marlin/language_en.h
index e6c285a1aa88b7800cde9cd8a4e33955acca29fc..ffa0d66941e20ce166404a21bb85e68400d063f4 100644
--- a/Marlin/language_en.h
+++ b/Marlin/language_en.h
@@ -498,6 +498,12 @@
 #ifndef MSG_DELTA_CALIBRATE_CENTER
   #define MSG_DELTA_CALIBRATE_CENTER          _UxGT("Calibrate Center")
 #endif
+#ifndef MSG_DELTA_AUTO_CALIBRATE
+  #define MSG_DELTA_AUTO_CALIBRATE            _UxGT("Auto Calibration")
+#endif
+#ifndef MSG_DELTA_HEIGHT_CALIBRATE
+  #define MSG_DELTA_HEIGHT_CALIBRATE          _UxGT("Set Delta Height")
+#endif
 #ifndef MSG_INFO_MENU
   #define MSG_INFO_MENU                       _UxGT("About Printer")
 #endif
diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp
index dfd9fd4eac5435ed08722f7e022bacd41302ac0f..29f462247701dbfefd52f274c7bc6dc6a00063b4 100755
--- a/Marlin/ultralcd.cpp
+++ b/Marlin/ultralcd.cpp
@@ -817,7 +817,7 @@ void kill_screen(const char* lcd_msg) {
    *
    */
 
-  #if DISABLED(NO_WORKSPACE_OFFSETS)
+  #if DISABLED(NO_WORKSPACE_OFFSETS) && DISABLED(DELTA)
     /**
      * Set the home offset based on the current_position
      */
@@ -1672,7 +1672,7 @@ void kill_screen(const char* lcd_msg) {
 
     #endif
 
-    #if DISABLED(NO_WORKSPACE_OFFSETS)
+    #if DISABLED(NO_WORKSPACE_OFFSETS) && DISABLED(DELTA)
       //
       // Set Home Offsets
       //
@@ -1770,14 +1770,20 @@ void kill_screen(const char* lcd_msg) {
       lcd_goto_screen(_lcd_calibrate_homing);
     }
 
+    #if ENABLED(DELTA_AUTO_CALIBRATION)
+      #define _DELTA_TOWER_MOVE_RADIUS DELTA_CALIBRATION_RADIUS
+    #else
+      #define _DELTA_TOWER_MOVE_RADIUS DELTA_PRINTABLE_RADIUS
+    #endif
+
     // Move directly to the tower position with uninterpolated moves
     // If we used interpolated moves it would cause this to become re-entrant
     void _goto_tower_pos(const float &a) {
       current_position[Z_AXIS] = max(Z_HOMING_HEIGHT, Z_CLEARANCE_BETWEEN_PROBES) + (DELTA_PRINTABLE_RADIUS) / 5;
       line_to_current(Z_AXIS);
 
-      current_position[X_AXIS] = a < 0 ? X_HOME_POS : sin(a) * -(DELTA_PRINTABLE_RADIUS);
-      current_position[Y_AXIS] = a < 0 ? Y_HOME_POS : cos(a) *  (DELTA_PRINTABLE_RADIUS);
+      current_position[X_AXIS] = a < 0 ? LOGICAL_X_POSITION(X_HOME_POS) : sin(a) * -(_DELTA_TOWER_MOVE_RADIUS);
+      current_position[Y_AXIS] = a < 0 ? LOGICAL_Y_POSITION(Y_HOME_POS) : cos(a) *  (_DELTA_TOWER_MOVE_RADIUS);
       line_to_current(Z_AXIS);
 
       current_position[Z_AXIS] = 4.0;
@@ -1797,6 +1803,10 @@ void kill_screen(const char* lcd_msg) {
     void lcd_delta_calibrate_menu() {
       START_MENU();
       MENU_BACK(MSG_MAIN);
+      #if ENABLED(DELTA_AUTO_CALIBRATION)
+        MENU_ITEM(gcode, MSG_DELTA_AUTO_CALIBRATE, PSTR("G33 C"));
+        MENU_ITEM(gcode, MSG_DELTA_HEIGHT_CALIBRATE, PSTR("G33 C1"));
+      #endif
       MENU_ITEM(submenu, MSG_AUTO_HOME, _lcd_delta_calibrate_home);
       if (axis_homed[Z_AXIS]) {
         MENU_ITEM(submenu, MSG_DELTA_CALIBRATE_X, _goto_tower_x);