diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 39cc1d5689c7..0b5d0a1e088c 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -3453,6 +3453,13 @@ //#define W_STALL_SENSITIVITY 8 //#define SPI_ENDSTOPS // TMC2130/TMC5160 only //#define IMPROVE_HOMING_RELIABILITY + + // When homing a "trusted" axis, verify Stallguard results by timing the move + //#define SENSORLESS_HOMING_VALIDATION + #if ENABLED(SENSORLESS_HOMING_VALIDATION) + #define SHV_STARTUP_COMPENSATION 200 // (ms) + #define SHV_ERROR_MARGIN 50 // (mm) + #endif #endif // @section tmc/config diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index 820089d7eeda..ec53bc19e063 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -2439,8 +2439,30 @@ void prepare_line_to_destination() { const bool is_home_dir = (axis_home_dir > 0) == (distance > 0); #if ENABLED(SENSORLESS_HOMING) + sensorless_t stealth_states; - #endif + + #if ENABLED(SENSORLESS_HOMING_VALIDATION) + + static float expected_distance = 0; // Known coordinates after homing routine sets to 0 + + if (is_home_dir) { + // Sensorless homing moves by a backoff. This accounts for that distance. + expected_distance += -axis_home_dir * planner.get_axis_position_mm(axis); + } + else { + // In Stallguard context, a backoff distance is done first, + // so this is where the expected printer position is captured. + const float axis_pos = planner.get_axis_position_mm(axis), + expected_distance = axis_home_dir > 0 ? (base_max_pos(axis) - axis_pos) : (base_min_pos(axis) + axis_pos); + } + + const millis_t time_to_stop = static_cast((expected_distance / home_fr_mm_s) * 1000.0f), + expected_stop_time = millis() + time_to_stop + SHV_STARTUP_COMPENSATION; + + #endif + + #endif // SENSORLESS_HOMING if (is_home_dir) { @@ -2493,6 +2515,15 @@ void prepare_line_to_destination() { if (is_home_dir) { + #if ENABLED(SENSORLESS_HOMING_VALIDATION) + const int32_t time_delta = static_cast(millis() - expected_stop_time); + const bool bad_home = !WITHIN(time_delta, -SHV_ERROR_MARGIN, SHV_ERROR_MARGIN); + if (DEBUGGING(INFO)) + SERIAL_ECHOLNPGM("Axis:", C(AXIS_CHAR(axis)), " Distance:", expected_distance, " Feedrate:", home_fr_mm_s, " Expected stop time:", time_to_stop, " Difference:", time_delta); + if (DEBUGGING(ERRORS) && bad_home) + SERIAL_ECHOLNPGM("Homing fault! Time difference: ", time_delta, ", Axis: ", C(AXIS_CHAR(axis))); + #endif + #if HOMING_Z_WITH_PROBE && HAS_QUIET_PROBING if (axis == Z_AXIS && final_approach) probe.set_probing_paused(false); #endif diff --git a/buildroot/tests/teensy35 b/buildroot/tests/teensy35 index 0e149e73d9d0..48bd185165aa 100755 --- a/buildroot/tests/teensy35 +++ b/buildroot/tests/teensy35 @@ -91,7 +91,7 @@ opt_set MOTHERBOARD BOARD_TEENSY35_36 \ X_CURRENT_HOME 750 Y_CURRENT_HOME 750 \ X_MIN_ENDSTOP_HIT_STATE LOW Y_MIN_ENDSTOP_HIT_STATE LOW \ X_CS_PIN 46 Y_CS_PIN 47 -opt_enable COREXY MONITOR_DRIVER_STATUS SENSORLESS_HOMING X_STALL_SENSITIVITY Y_STALL_SENSITIVITY +opt_enable COREXY MONITOR_DRIVER_STATUS SENSORLESS_HOMING SENSORLESS_HOMING_VALIDATION X_STALL_SENSITIVITY Y_STALL_SENSITIVITY exec_test $1 $2 "Teensy 3.5/3.6 COREXY" "$3" #