diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index b4e19d90d1efe40f570807eda58d6a0a16568d19..79e091dc51de0dc99cbc076a5d3055586d0fdfd9 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -86,7 +86,7 @@
 // User-specified version info of this build to display in [Pronterface, etc] terminal window during
 // startup. Implementation of an idea by Prof Braino to inform user that any changes made to this
 // build by the user have been successfully uploaded into firmware.
-#define STRING_CONFIG_H_AUTHOR "Bob Kuhn, G2/G3 radius testing" // Who made the changes.
+#define STRING_CONFIG_H_AUTHOR "(none, default config)" // Who made the changes.
 #define SHOW_BOOTSCREEN
 #define STRING_SPLASH_LINE1 SHORT_BUILD_VERSION // will be shown during bootup in line 1
 #define STRING_SPLASH_LINE2 WEBSITE_URL         // will be shown during bootup in line 2
@@ -105,15 +105,24 @@
 //#define SHOW_CUSTOM_BOOTSCREEN
 // @section machine
 
-// SERIAL_PORT selects which serial port should be used for communication with the host.
-// This allows the connection of wireless adapters (for instance) to non-default port pins.
-// Serial port 0 is still used by the Arduino bootloader regardless of this setting.
-// :[0,1,2,3,4,5,6,7]
+/**
+ * Select which serial port on the board will be used for communication with the host.
+ * This allows the connection of wireless adapters (for instance) to non-default port pins.
+ * Serial port 0 is always used by the Arduino bootloader regardless of this setting.
+ *
+ * :[0,1,2,3,4,5,6,7]
+ */
 #define SERIAL_PORT 0
 
-// This determines the communication speed of the printer
-// :[2400,9600,19200,38400,57600,115200,250000]
-#define BAUDRATE 115200
+#define BAUDRATE 250000
+/**
+ * This setting determines the communication speed of the printer.
+ *
+ * 250000 works in most cases, but you might try a lower speed if
+ * you commonly experience drop-outs during host printing.
+ *
+ * :[2400,9600,19200,38400,57600,115200,250000]
+ */
 
 // Enable the Bluetooth serial interface on AT90USB devices
 //#define BLUETOOTH
@@ -121,7 +130,7 @@
 // The following define selects which electronics board you have.
 // Please choose the name from boards.h that matches your setup
 #ifndef MOTHERBOARD
-  #define MOTHERBOARD BOARD_AZTEEG_X3_PRO     
+  #define MOTHERBOARD BOARD_RAMPS_14_EFB
 #endif
 
 // Optional custom name for your RepStrap or other custom machine
@@ -169,14 +178,22 @@
 //#define HOTEND_OFFSET_X {0.0, 20.00} // (in mm) for each extruder, offset of the hotend on the X axis
 //#define HOTEND_OFFSET_Y {0.0, 5.00}  // (in mm) for each extruder, offset of the hotend on the Y axis
 
-//// The following define selects which power supply you have. Please choose the one that matches your setup
-// 1 = ATX
-// 2 = X-Box 360 203Watts (the blue wire connected to PS_ON and the red wire to VCC)
-// :{1:'ATX',2:'X-Box 360'}
-#define POWER_SUPPLY 1
+/**
+ * Select your power supply here. Use 0 if you haven't connected the PS_ON_PIN
+ *
+ * 0 = No Power Switch
+ * 1 = ATX
+ * 2 = X-Box 360 203Watts (the blue wire connected to PS_ON and the red wire to VCC)
+ *
+ * :{0:'No power switch',1:'ATX',2:'X-Box 360'}
+ */
+#define POWER_SUPPLY 0
 
-// Define this to have the electronics keep the power supply off on startup. If you don't know what this is leave it.
-//#define PS_DEFAULT_OFF
+#if POWER_SUPPLY > 0
+  // Enable this option to leave the PSU off at startup.
+  // Power to steppers and heaters will need to be turned on with M80.
+  //#define PS_DEFAULT_OFF
+#endif
 
 // @section temperature
 
@@ -222,10 +239,10 @@
 // 110 is Pt100 with 1k pullup (non standard)
 // 998 and 999 are Dummy Tables. They will ALWAYS read 25°C or the temperature defined below.
 //     Use it for Testing or Development purposes. NEVER for production machine.
-#define DUMMY_THERMISTOR_998_VALUE 25
+//#define DUMMY_THERMISTOR_998_VALUE 25
 //#define DUMMY_THERMISTOR_999_VALUE 100
 // :{ '0': "Not used",'1':"100k / 4.7k - EPCOS",'2':"200k / 4.7k - ATC Semitec 204GT-2",'3':"Mendel-parts / 4.7k",'4':"10k !! do not use for a hotend. Bad resolution at high temp. !!",'5':"100K / 4.7k - ATC Semitec 104GT-2 (Used in ParCan & J-Head)",'6':"100k / 4.7k EPCOS - Not as accurate as Table 1",'7':"100k / 4.7k Honeywell 135-104LAG-J01",'8':"100k / 4.7k 0603 SMD Vishay NTCS0603E3104FXT",'9':"100k / 4.7k GE Sensing AL03006-58.2K-97-G1",'10':"100k / 4.7k RS 198-961",'11':"100k / 4.7k beta 3950 1%",'12':"100k / 4.7k 0603 SMD Vishay NTCS0603E3104FXT (calibrated for Makibox hot bed)",'13':"100k Hisens 3950  1% up to 300°C for hotend 'Simple ONE ' & hotend 'All In ONE'",'20':"PT100 (Ultimainboard V2.x)",'51':"100k / 1k - EPCOS",'52':"200k / 1k - ATC Semitec 204GT-2",'55':"100k / 1k - ATC Semitec 104GT-2 (Used in ParCan & J-Head)",'60':"100k Maker's Tool Works Kapton Bed Thermistor beta=3950",'66':"Dyze Design 4.7M High Temperature thermistor",'70':"the 100K thermistor found in the bq Hephestos 2",'71':"100k / 4.7k Honeywell 135-104LAF-J01",'147':"Pt100 / 4.7k",'1047':"Pt1000 / 4.7k",'110':"Pt100 / 1k (non-standard)",'1010':"Pt1000 / 1k (non standard)",'-3':"Thermocouple + MAX31855 (only for sensor 0)",'-2':"Thermocouple + MAX6675 (only for sensor 0)",'-1':"Thermocouple + AD595",'998':"Dummy 1",'999':"Dummy 2" }
-#define TEMP_SENSOR_0 998
+#define TEMP_SENSOR_0 1
 #define TEMP_SENSOR_1 0
 #define TEMP_SENSOR_2 0
 #define TEMP_SENSOR_3 0
@@ -355,8 +372,9 @@
 #define EXTRUDE_MINTEMP 170
 
 // This option prevents a single extrusion longer than EXTRUDE_MAXLENGTH.
+// Note that for Bowden Extruders a too-small value here may prevent loading.
 #define PREVENT_LENGTHY_EXTRUDE
-#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH)
+#define EXTRUDE_MAXLENGTH 200
 
 //===========================================================================
 //======================== Thermal Runaway Protection =======================
@@ -403,9 +421,9 @@
 #define USE_XMIN_PLUG
 #define USE_YMIN_PLUG
 #define USE_ZMIN_PLUG
-#define USE_XMAX_PLUG
-#define USE_YMAX_PLUG
-#define USE_ZMAX_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
 
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
@@ -422,13 +440,13 @@
 #endif
 
 // Mechanical endstop with COM to ground and NC to Signal uses "false" here (most common setup).
-#define X_MIN_ENDSTOP_INVERTING true // set to true to invert the logic of the endstop.
-#define Y_MIN_ENDSTOP_INVERTING true // set to true to invert the logic of the endstop.
-#define Z_MIN_ENDSTOP_INVERTING true // set to true to invert the logic of the endstop.
-#define X_MAX_ENDSTOP_INVERTING true // set to true to invert the logic of the endstop.
-#define Y_MAX_ENDSTOP_INVERTING true // set to true to invert the logic of the endstop.
-#define Z_MAX_ENDSTOP_INVERTING true // set to true to invert the logic of the endstop.
-#define Z_MIN_PROBE_ENDSTOP_INVERTING true // set to true to invert the logic of the endstop.
+#define X_MIN_ENDSTOP_INVERTING false // set to true to invert the logic of the endstop.
+#define Y_MIN_ENDSTOP_INVERTING false // set to true to invert the logic of the endstop.
+#define Z_MIN_ENDSTOP_INVERTING false // set to true to invert the logic of the endstop.
+#define X_MAX_ENDSTOP_INVERTING false // set to true to invert the logic of the endstop.
+#define Y_MAX_ENDSTOP_INVERTING false // set to true to invert the logic of the endstop.
+#define Z_MAX_ENDSTOP_INVERTING false // set to true to invert the logic of the endstop.
+#define Z_MIN_PROBE_ENDSTOP_INVERTING false // set to true to invert the logic of the endstop.
 
 
 //=============================================================================
@@ -436,20 +454,56 @@
 //=============================================================================
 // @section motion
 
-#define DEFAULT_AXIS_STEPS_PER_UNIT   {8*24.8139,8*24.8139,8*24.8139,100}  
-#define DEFAULT_MAX_FEEDRATE          {35, 35, 25, 25}        // (mm/sec)
-#define DEFAULT_MAX_ACCELERATION      {3000,3000,100,10000}    // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for Skeinforge 40+, for older versions raise them a lot.
+/**
+ * Default Settings
+ *
+ * These settings can be reset by M502
+ *
+ * Note that if EEPROM is enabled, saved values will override these.
+ */
+
+/**
+ * Default Axis Steps Per Unit (steps/mm)
+ * Override with M92
+ */
+#define DEFAULT_AXIS_STEPS_PER_UNIT   { 80, 80, 4000, 500 }
+
+/**
+ * Default Max Feed Rate (mm/s)
+ * Override with M203
+ */
+#define DEFAULT_MAX_FEEDRATE          { 300, 300, 5, 25 }
+
+/**
+ * Default Max Acceleration (change/s) change = mm/s
+ * Override with M201
+ *
+ * Maximum start speed for accelerated moves: { X, Y, Z, E }
+ */
+#define DEFAULT_MAX_ACCELERATION      { 3000, 3000, 100, 10000 }
 
-#define DEFAULT_ACCELERATION          3000    // X, Y, Z and E acceleration in mm/s^2 for printing moves
-#define DEFAULT_RETRACT_ACCELERATION  3000    // E acceleration in mm/s^2 for retracts
-#define DEFAULT_TRAVEL_ACCELERATION   3000    // X, Y, Z acceleration in mm/s^2 for travel (non printing) moves
+/**
+ * Default Acceleration (change/s) change = mm/s
+ * Override with M204
+ *
+ *   M204 P    Acceleration
+ *   M204 R    Retract Acceleration
+ *   M204 T    Travel Acceleration
+ */
+#define DEFAULT_ACCELERATION          3000    // X, Y, Z and E acceleration for printing moves
+#define DEFAULT_RETRACT_ACCELERATION  3000    // E acceleration for retracts
+#define DEFAULT_TRAVEL_ACCELERATION   3000    // X, Y, Z acceleration for travel (non printing) moves
 
-// "Jerk" specifies the minimum speed change that requires acceleration.
-// When changing speed and direction, if the difference is less than the
-// value set here, it may happen instantaneously.
-#define DEFAULT_XYJERK                20.0    // (mm/sec)
-#define DEFAULT_ZJERK                  0.4    // (mm/sec)
-#define DEFAULT_EJERK                  5.0    // (mm/sec)
+/**
+ * Defult Jerk (mm/s)
+ *
+ * "Jerk" specifies the minimum speed change that requires acceleration.
+ * When changing speed and direction, if the difference is less than the
+ * value set here, it may happen instantaneously.
+ */
+#define DEFAULT_XYJERK                20.0
+#define DEFAULT_ZJERK                  0.4
+#define DEFAULT_EJERK                  5.0
 
 
 //===========================================================================
@@ -474,6 +528,7 @@
 //#define FIX_MOUNTED_PROBE
 
 // The BLTouch probe emulates a servo probe.
+// The default connector is SERVO 0. Set Z_ENDSTOP_SERVO_NR below to override.
 //#define BLTOUCH
 
 // Z Servo Probe, such as an endstop switch on a rotating arm.
@@ -610,9 +665,9 @@
 // @section machine
 
 // Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
-#define INVERT_X_DIR true    // positive is away from the motor
-#define INVERT_Y_DIR false    // positive is towards the motor
-#define INVERT_Z_DIR true    // positive is away from the motor
+#define INVERT_X_DIR false
+#define INVERT_Y_DIR true
+#define INVERT_Z_DIR false
 
 // @section extruder
 
@@ -640,12 +695,12 @@
 // @section machine
 
 // Travel limits after homing (units are in mm)
-#define X_MIN_POS -100
-#define Y_MIN_POS -100
-#define Z_MIN_POS -100
-#define X_MAX_POS 375
-#define Y_MAX_POS 450
-#define Z_MAX_POS 450
+#define X_MIN_POS 0
+#define Y_MIN_POS 0
+#define Z_MIN_POS 0
+#define X_MAX_POS 200
+#define Y_MAX_POS 200
+#define Z_MAX_POS 200
 
 //===========================================================================
 //========================= Filament Runout Sensor ==========================
@@ -1005,7 +1060,7 @@
 // SD Card support is disabled by default. If your controller has an SD slot,
 // you must uncomment the following option or it won't work.
 //
-#define SDSUPPORT
+//#define SDSUPPORT
 
 //
 // SD CARD: SPI SPEED
@@ -1022,7 +1077,7 @@
 //
 // Use CRC checks and retries on the SD communication.
 //
-#define SD_CHECK_AND_RETRY
+//#define SD_CHECK_AND_RETRY
 
 //
 // ENCODER SETTINGS
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 751da7fb828e2e2fb1bb360110c813049f434a2b..545f5ce8bda756d908de899fb01af955d1f41ce6 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -244,16 +244,16 @@
 // Dual Y Steppers
 // Uncomment this option to drive two Y axis motors.
 // The next unused E driver will be assigned to the second Y stepper.
-#define Y_DUAL_STEPPER_DRIVERS
+//#define Y_DUAL_STEPPER_DRIVERS
 #if ENABLED(Y_DUAL_STEPPER_DRIVERS)
   // Set true if the two Y motors need to rotate in opposite directions
-  #define INVERT_Y2_VS_Y_DIR false
+  #define INVERT_Y2_VS_Y_DIR true
 #endif
 
 // A single Z stepper driver is usually used to drive 2 stepper motors.
 // Uncomment this option to use a separate stepper driver for each Z axis motor.
 // The next unused E driver will be assigned to the second Z stepper.
-#define Z_DUAL_STEPPER_DRIVERS
+//#define Z_DUAL_STEPPER_DRIVERS
 
 #if ENABLED(Z_DUAL_STEPPER_DRIVERS)
 
@@ -532,6 +532,12 @@
 // Support for G5 with XYZE destination and IJPQ offsets. Requires ~2666 bytes.
 //#define BEZIER_CURVE_SUPPORT
 
+// G38 Probe Target
+//#define G38_2_3
+#if ENABLED(G38_2_3)
+  #define G38_MINIMUM_MOVE 0.0275 // minimum distance in mm that will produce a move (determined using the print statement in check_move)
+#endif
+
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h
index bebc91cf89634e5880993dea8c15b5483d7e9f33..8fd720cd4da86ffecf45326e9dbc7ce188573b6d 100644
--- a/Marlin/Marlin.h
+++ b/Marlin/Marlin.h
@@ -209,10 +209,9 @@ void manage_inactivity(bool ignore_stepper_queue = false);
 
 #endif // !MIXING_EXTRUDER
 
-#define G38_2_3
-#ifdef G38_2_3
-extern bool G38_flag ;   //flag to tell the interrupt handler that a G38 command is being run
-extern bool G38_flag_pass ;   //flag from the interrupt handler to indicate if the endstop went active
+#if ENABLED(G38_2_3)
+  extern bool G38_move,        // flag to tell the interrupt handler that a G38 command is being run
+              G38_endstop_hit; // flag from the interrupt handler to indicate if the endstop went active
 #endif
 
 /**
diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index 98993c8ccf7750a156566c4badb4abc95b81822f..cadb169402e75a4d181648c700b9a339bff9747e 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -117,7 +117,7 @@
  * G30 - Single Z probe, probes bed at current XY location.
  * G31 - Dock sled (Z_PROBE_SLED only)
  * G32 - Undock sled (Z_PROBE_SLED only)
- * G38 - Probe target - similar to G28 except it uses the Z_Probe for all three axis
+ * G38 - Probe target - similar to G28 except it uses the Z_MIN endstop for all three axes
  * G90 - Use Absolute Coordinates
  * G91 - Use Relative Coordinates
  * G92 - Set current position to coordinates given
@@ -277,9 +277,9 @@
   TWIBus i2c;
 #endif
 
-#ifdef G38_2_3
-bool G38_flag = false;   // init G38 flags
-bool G38_flag_pass = false;
+#if ENABLED(G38_2_3)
+  bool G38_move = false,
+       G38_endstop_hit = false;
 #endif
 
 bool Running = true;
@@ -1343,7 +1343,7 @@ static void set_home_offset(AxisEnum axis, float v) {
  * SCARA should wait until all XY homing is done before setting the XY
  * current_position to home, because neither X nor Y is at home until
  * both are at home. Z can however be homed individually.
- * 
+ *
  */
 static void set_axis_is_at_home(AxisEnum axis) {
   #if ENABLED(DEBUG_LEVELING_FEATURE)
@@ -2331,146 +2331,6 @@ static void clean_up_after_endstop_or_probe_move() {
 
 #endif // AUTO_BED_LEVELING_BILINEAR
 
-
-#ifdef G38_2_3
-
-#define G38_minimum_move  0.0275   // minimum distance in mm that will produce a move (determined using the print statement in check_move)
-
-bool check_move()  //checks that at least one of the axis in the command line has an actual move
-                   // motion planner only does moves of 0.001mm and larger
-{
-	
-  bool move_flag = false;
-  for(int8_t i=0; i < 3; i++) {
-/* debug used to determine prints
-		SERIAL_PROTOCOLPGM("axis: ");
-		SERIAL_PROTOCOL(axis_codes[i]);
-		SERIAL_PROTOCOLPGM("  code_seen :  ");
-		SERIAL_PROTOCOL(code_seen(axis_codes[i]));
-		SERIAL_PROTOCOLPGM("  destination : ");
-		SERIAL_PROTOCOL(destination[i]);
-		SERIAL_PROTOCOLPGM("  current : ");
-		SERIAL_PROTOCOL(current_position[i]);
-		SERIAL_PROTOCOLPGM("  dif x 1000 : ");
-		SERIAL_PROTOCOLLN((destination[i] - current_position[i]) * 1000);
- */		
-  if (code_seen(axis_codes[i]) && (fabs(destination[i] - current_position[i]) >= G38_minimum_move)) move_flag = true ;
-/*
- ??  0.0275mm produced a move on my machine along with an updated current position. 
-     0.0265mm did NOT produce a move and did NOT change the current position
-     this is very different than the 0.001 in the planner.
-       0.001" is .0254mm so maybe the 0.0275 observed comes from digital storage limitations/conversion/rounding
- */
-  }
-  return move_flag;
-}
-
-
-static void G38_run_probe(bool *G38_pass_fail) {
- 
-  G38_flag = true;  //tell the interrupt handler that we're doing a G38 probe
-  *G38_pass_fail = false;  
-  
-#ifdef X_HOME_BUMP_MM
-#ifdef Y_HOME_BUMP_MM
-#ifdef Z_HOME_BUMP_MM
-  float G38_X_retract_mm = home_bump_mm(X_AXIS);
-  float G38_Y_retract_mm = home_bump_mm(Y_AXIS);
-  float G38_Z_retract_mm = home_bump_mm(Z_AXIS);
-  
-#else
-    
-  float G38_X_retract_mm = 5;
-  float G38_Y_retract_mm = 5;
-  float G38_Z_retract_mm = 2;
-
-#endif
-#endif  
-#endif  
-  
-  // only retract the axis if the axis is in the command
-  if( (!code_seen('X') || (code_value_axis_units(X_AXIS) == 0)))  G38_X_retract_mm = 0;   
-  if( (!code_seen('Y') || (code_value_axis_units(Y_AXIS) == 0)))  G38_Y_retract_mm = 0;
-  if( (!code_seen('Z') || (code_value_axis_units(Z_AXIS) == 0)))  G38_Z_retract_mm = 0;
-
-  // change the direction of the retract if needed
-  if ((destination[X_AXIS] - current_position[X_AXIS])>0) G38_X_retract_mm = -G38_X_retract_mm;
-  if ((destination[Y_AXIS] - current_position[Y_AXIS])>0) G38_Y_retract_mm = -G38_Y_retract_mm;
-  if ((destination[Z_AXIS] - current_position[Z_AXIS])>0) G38_Z_retract_mm = -G38_Z_retract_mm;
-
-  
-  stepper.synchronize();  // wait until the machine is idle
-  
-  bool save_endstops = endstops.enabled;    //remember state of endstops so we can retore them at the end
-  endstops.enable(true);
-    
-  // move until you reach the destination or hit an endstop or hit the target
-  // it's an error unless have hit the target
-  G38_flag_pass = false;
-  *G38_pass_fail = false;
-  
-  planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate_mm_s, active_extruder);
-  stepper.synchronize();
-
-  // we have to let the planner know where we are right now as it is not where we said to go.
-  //  and we need to update current_position[axis]
-  current_position[X_AXIS] = stepper.get_axis_position_mm(X_AXIS);
-  current_position[Y_AXIS] = stepper.get_axis_position_mm(Y_AXIS);
-  current_position[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
-  planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS] , current_position[Z_AXIS] , current_position[E_AXIS]);
-
-  *G38_pass_fail = G38_flag_pass ;  // only care if hit target on the first move
-    
-  if (*G38_pass_fail) {  // no sense in doing the remaining moves if we didn't hit the endstop  
-    // move away the retract distance
-    float xPosition = current_position[X_AXIS] + G38_X_retract_mm;
-    float yPosition = current_position[Y_AXIS] + G38_Y_retract_mm;
-    float zPosition = current_position[Z_AXIS] + G38_Z_retract_mm;
-     
-
-  
-    // disable endstops on retract otherwise sometimes can't get away  
-    endstops.enable(false);
-    G38_flag = false; 
-    
-    planner.buffer_line(xPosition, yPosition , zPosition , current_position[E_AXIS], feedrate_mm_s/4, active_extruder);
-    stepper.synchronize();
-
-
-    // move back slowly
-    xPosition -= G38_X_retract_mm * 2;
-    yPosition -= G38_Y_retract_mm * 2;
-    zPosition -= G38_Z_retract_mm * 2;
- 
-
-    // enable endstops on move back
-    endstops.enable(true);
-    G38_flag = true; 
-    
-    planner.buffer_line(xPosition, yPosition , zPosition , current_position[E_AXIS], feedrate_mm_s/4, active_extruder);
-    stepper.synchronize();
-
-    // we have to let the planner know where we are right now as it is not where we said to go.
-    //  and we need to update current_position[axis]
-    current_position[X_AXIS] = stepper.get_axis_position_mm(X_AXIS);
-    current_position[Y_AXIS] = stepper.get_axis_position_mm(Y_AXIS);
-    current_position[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
-    planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS] , current_position[Z_AXIS] , current_position[E_AXIS]);
-    
-  }  
-  
-//  clean_up_after_endstop_move();
-
-  endstops.enable(save_endstops);   //restore endstops to same state as when we started
-
-  endstops.hit_on_purpose();
-  G38_flag = false;  //tell the interrupt handler that we're done
-  
-}
-
-#endif  //G38_2_3
-
-
 /**
  * Home an individual linear axis
  */
@@ -4306,25 +4166,93 @@ inline void gcode_G28() {
 
 #endif // HAS_BED_PROBE
 
-#ifdef G38_2_3
-  inline void gcode_G38(float code_num) { 
-  #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) || ENABLED(Z_MIN_PROBE_ENDSTOP)  //must have valid Z_MIN_PROBE definition for this command to work  
-    if ((code_num == 38.2 || code_num == 38.3  ) && (code_seen('X') || code_seen('Y') || code_seen('Z'))) {
-      gcode_get_destination(); // For X Y Z E F
-      if (check_move()) {   // see if the commanded movement will result in a physical movement
-		bool G38_pass_fail = false;
-		G38_run_probe(&G38_pass_fail);
-        if (!G38_pass_fail && (code_num == 38.2) ) SERIAL_PROTOCOLLNPGM(" ERROR - failed to reach target ");
-      }
+#if ENABLED(G38_2_3)
+
+  static bool G38_run_probe() {
+
+    bool G38_pass_fail = false;
+
+    // Get direction of move and retract
+    float retract_mm[XYZ];
+    LOOP_XYZ(i) {
+      float dist = destination[i] - current_position[i];
+      retract_mm[i] = fabs(dist) < G38_MINIMUM_MOVE ? 0 : home_bump_mm(i) * (dist > 0 ? -1 : 1);
     }
+
+    stepper.synchronize();  // wait until the machine is idle
+
+    // Move until destination reached or target hit
+    endstops.enable(true);
+    G38_move = true;
+    G38_endstop_hit = false;
+    prepare_move_to_destination();
+    stepper.synchronize();
+    G38_move = false;
+
+    endstops.hit_on_purpose();
+    set_current_from_steppers_for_axis(ALL_AXES);
+    SYNC_PLAN_POSITION_KINEMATIC();
+
+    // Only do remaining moves if target was hit
+    if (G38_endstop_hit) {
+
+      G38_pass_fail = true;
+
+      // Move away by the retract distance
+      set_destination_to_current();
+      LOOP_XYZ(i) destination[i] += retract_mm[i];
+      endstops.enable(false);
+      prepare_move_to_destination();
+      stepper.synchronize();
+
+      feedrate_mm_s /= 4;
+
+      // Bump the target more slowly
+      LOOP_XYZ(i) destination[i] -= retract_mm[i] * 2;
+
+      endstops.enable(true);
+      G38_move = true;
+      prepare_move_to_destination();
+      stepper.synchronize();
+      G38_move = false;
+
+      set_current_from_steppers_for_axis(ALL_AXES);
+      SYNC_PLAN_POSITION_KINEMATIC();
+    }
+
+    endstops.hit_on_purpose();
+    endstops.not_homing();
+    return G38_pass_fail;
   }
-#else
- 
-    SERIAL_PROTOCOLLNPGM(" ERROR - Z_MIN_PROBE must be enabled ");	
+
+  /**
+   * G38.2 - probe toward workpiece, stop on contact, signal error if failure
+   * G38.3 - probe toward workpiece, stop on contact
+   *
+   * Like G28 except uses Z min endstop for all axes
+   */
+  inline void gcode_G38(bool is_38_2) {
+    // Get X Y Z E F
+    gcode_get_destination();
+
+    setup_for_endstop_or_probe_move();
+
+    // If any axis has enough movement, do the move
+    LOOP_XYZ(i)
+      if (fabs(destination[i] - current_position[i]) >= G38_MINIMUM_MOVE) {
+        if (!code_seen('F')) feedrate_mm_s = homing_feedrate_mm_s[i];
+        // If G38.2 fails throw an error
+        if (!G38_run_probe() && is_38_2) {
+          SERIAL_ERROR_START;
+          SERIAL_ERRORLNPGM("Failed to reach target");
+        }
+        break;
+      }
+
+    clean_up_after_endstop_or_probe_move();
   }
-#endif	
-#endif //G38_2_3
 
+#endif // G38_2_3
 
 /**
  * G92: Set current position to given X Y Z E
@@ -7447,23 +7375,32 @@ void process_next_command() {
   // Skip spaces to get the numeric part
   while (*cmd_ptr == ' ') cmd_ptr++;
 
+  // Allow for decimal point in command
+  #if ENABLED(G38_2_3)
+    uint8_t subcode = 0;
+  #endif
+
   uint16_t codenum = 0; // define ahead of goto
 
   // Bail early if there's no code
   bool code_is_good = NUMERIC(*cmd_ptr);
   if (!code_is_good) goto ExitUnknownCommand;
 
-#ifdef G38_2_3
-  double codenum_float;
-  codenum_float = atof(cmd_ptr);  //allow for decimal point in command
-#endif
-
   // Get and skip the code number
   do {
     codenum = (codenum * 10) + (*cmd_ptr - '0');
     cmd_ptr++;
   } while (NUMERIC(*cmd_ptr));
 
+  // Allow for decimal point in command
+  #if ENABLED(G38_2_3)
+    if (*cmd_ptr == '.') {
+      cmd_ptr++;
+      while (NUMERIC(*cmd_ptr))
+        subcode = (subcode * 10) + (*cmd_ptr++ - '0');
+    }
+  #endif
+
   // Skip all spaces to get to the first argument, or nul
   while (*cmd_ptr == ' ') cmd_ptr++;
 
@@ -7564,12 +7501,13 @@ void process_next_command() {
         #endif // Z_PROBE_SLED
       #endif // HAS_BED_PROBE
 
-      #ifdef G38_2_3
-	   case 38:  //G38.2 & G38.3
-	     gcode_G38(codenum_float);
+      #if ENABLED(G38_2_3)
+        case 38: // G38.2 & G38.3
+          if (subcode == 2 || subcode == 3)
+            gcode_G38(subcode == 2);
           break;
-	 #endif
- 
+      #endif
+
       case 90: // G90
         relative_mode = false;
         break;
@@ -9078,7 +9016,7 @@ void prepare_move_to_destination() {
    * Morgan SCARA Inverse Kinematics. Results in delta[].
    *
    * See http://forums.reprap.org/read.php?185,283327
-   * 
+   *
    * Maths and first version by QHARLEY.
    * Integrated into Marlin and slightly restructured by Joachim Cerny.
    */
diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h
index d14eda635689a95e2c90509b8da61be16044a5d0..2d6414fb27bc2a61083f2b4d0ff215d55a7c77a7 100644
--- a/Marlin/SanityCheck.h
+++ b/Marlin/SanityCheck.h
@@ -851,6 +851,17 @@
   #endif
 #endif
 
+/**
+ * G38 Probe Target
+ */
+#if ENABLED(G38_2_3)
+  #if !HAS_BED_PROBE
+    #error "G38_2_3 requires a bed probe."
+  #elif !IS_CARTESIAN
+    #error "G38_2_3 requires a Cartesian machine."
+  #endif
+#endif
+
 /**
  * Make sure only one display is enabled
  *
diff --git a/Marlin/endstops.cpp b/Marlin/endstops.cpp
index 348d8edb65b2946f981a823cccdf972750a31102..7bb2fda71db4480a719b96d1f966c80addfe9ec9 100644
--- a/Marlin/endstops.cpp
+++ b/Marlin/endstops.cpp
@@ -243,33 +243,27 @@ void Endstops::update() {
   // COPY_BIT: copy the value of COPY_BIT to BIT in bits
   #define COPY_BIT(bits, COPY_BIT, BIT) SET_BIT(bits, BIT, TEST(bits, COPY_BIT))
 
- 
-#if defined(G38_2_3) && defined(Z_MIN_PIN) && Z_MIN_PIN > -1  // If G38 command then check Z_MIN for every axis and every direction  
-  #define UPDATE_ENDSTOP(AXIS,MINMAX) do { \
-      UPDATE_ENDSTOP_BIT(AXIS, MINMAX); \
-      if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX)) && stepper.current_block->steps[_AXIS(AXIS)] > 0) { \
-        _ENDSTOP_HIT(AXIS); \
-        stepper.endstop_triggered(_AXIS(AXIS)); \
-      } \
-      if (G38_flag) {\
-        UPDATE_ENDSTOP_BIT(Z, MIN); \
-        if (TEST_ENDSTOP(_ENDSTOP(Z, MIN)) && stepper.current_block->steps[_AXIS(AXIS)] > 0) { \
-          _ENDSTOP_HIT(AXIS); \
-          stepper.endstop_triggered(_AXIS(AXIS)); \
-		  G38_flag_pass = true;\
-        } \
-      } \
-    } while(0)
-#else	
-  #define UPDATE_ENDSTOP(AXIS,MINMAX) do { \
+  #define _UPDATE_ENDSTOP(AXIS,MINMAX,CODE) do { \
       UPDATE_ENDSTOP_BIT(AXIS, MINMAX); \
       if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX)) && stepper.current_block->steps[_AXIS(AXIS)] > 0) { \
         _ENDSTOP_HIT(AXIS); \
         stepper.endstop_triggered(_AXIS(AXIS)); \
+        CODE; \
       } \
     } while(0)
-	
-#endif	  		
+
+  #if ENABLED(G38_2_3) && PIN_EXISTS(Z_MIN)  // If G38 command then check Z_MIN for every axis and every direction  
+
+    #define UPDATE_ENDSTOP(AXIS,MINMAX) do { \
+        _UPDATE_ENDSTOP(AXIS,MINMAX,NOOP); \
+        if (G38_move) _UPDATE_ENDSTOP(Z, MIN, G38_endstop_hit = true); \
+      } while(0)
+
+  #else	
+
+    #define UPDATE_ENDSTOP(AXIS,MINMAX) _UPDATE_ENDSTOP(AXIS,MINMAX,NOOP)
+
+  #endif
 
   #if ENABLED(COREXY) || ENABLED(COREXZ)
     // Head direction in -X axis for CoreXY and CoreXZ bots.