Skip to content

Commit 7f1e20c

Browse files
lujiosptoal
authored andcommitted
⚡️ Improve Sensorless homing/probing for G28, G33 (MarlinFirmware#21899)
1 parent f17e757 commit 7f1e20c

File tree

10 files changed

+197
-25
lines changed

10 files changed

+197
-25
lines changed

Marlin/src/MarlinCore.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -828,10 +828,8 @@ void idle(bool no_stepper_sleep/*=false*/) {
828828

829829
// Run StallGuard endstop checks
830830
#if ENABLED(SPI_ENDSTOPS)
831-
if (endstops.tmc_spi_homing.any
832-
&& TERN1(IMPROVE_HOMING_RELIABILITY, ELAPSED(millis(), sg_guard_period))
833-
) LOOP_L_N(i, 4) // Read SGT 4 times per idle loop
834-
if (endstops.tmc_spi_homing_check()) break;
831+
if (endstops.tmc_spi_homing.any && TERN1(IMPROVE_HOMING_RELIABILITY, ELAPSED(millis(), sg_guard_period)))
832+
LOOP_L_N(i, 4) if (endstops.tmc_spi_homing_check()) break; // Read SGT 4 times per idle loop
835833
#endif
836834

837835
// Handle SD Card insert / remove

Marlin/src/feature/tmc_util.h

-7
Original file line numberDiff line numberDiff line change
@@ -360,13 +360,6 @@ void test_tmc_connection(LOGICAL_AXIS_DECL(const bool, true));
360360
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
361361
extern millis_t sg_guard_period;
362362
constexpr uint16_t default_sg_guard_duration = 400;
363-
364-
struct motion_state_t {
365-
xy_ulong_t acceleration;
366-
#if HAS_CLASSIC_JERK
367-
xy_float_t jerk_state;
368-
#endif
369-
};
370363
#endif
371364

372365
bool tmc_enable_stallguard(TMC2130Stepper &st);

Marlin/src/gcode/calibrate/G28.cpp

+15-3
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,15 @@
167167
motion_state_t begin_slow_homing() {
168168
motion_state_t motion_state{0};
169169
motion_state.acceleration.set(planner.settings.max_acceleration_mm_per_s2[X_AXIS],
170-
planner.settings.max_acceleration_mm_per_s2[Y_AXIS]);
170+
planner.settings.max_acceleration_mm_per_s2[Y_AXIS]
171+
OPTARG(DELTA, planner.settings.max_acceleration_mm_per_s2[Z_AXIS])
172+
);
171173
planner.settings.max_acceleration_mm_per_s2[X_AXIS] = 100;
172174
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = 100;
175+
TERN_(DELTA, planner.settings.max_acceleration_mm_per_s2[Z_AXIS] = 100);
173176
#if HAS_CLASSIC_JERK
174177
motion_state.jerk_state = planner.max_jerk;
175-
planner.max_jerk.set(0, 0);
178+
planner.max_jerk.set(0, 0 OPTARG(DELTA, 0));
176179
#endif
177180
planner.reset_acceleration_rates();
178181
return motion_state;
@@ -181,6 +184,7 @@
181184
void end_slow_homing(const motion_state_t &motion_state) {
182185
planner.settings.max_acceleration_mm_per_s2[X_AXIS] = motion_state.acceleration.x;
183186
planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = motion_state.acceleration.y;
187+
TERN_(DELTA, planner.settings.max_acceleration_mm_per_s2[Z_AXIS] = motion_state.acceleration.z);
184188
TERN_(HAS_CLASSIC_JERK, planner.max_jerk = motion_state.jerk_state);
185189
planner.reset_acceleration_rates();
186190
}
@@ -259,7 +263,7 @@ void GcodeSuite::G28() {
259263
reset_stepper_timeout();
260264

261265
#define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
262-
#if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2)
266+
#if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2) || (ENABLED(DELTA) && HAS_CURRENT_HOME(Z))
263267
#define HAS_HOMING_CURRENT 1
264268
#endif
265269

@@ -287,6 +291,11 @@ void GcodeSuite::G28() {
287291
stepperY2.rms_current(Y2_CURRENT_HOME);
288292
if (DEBUGGING(LEVELING)) debug_current(PSTR("Y2"), tmc_save_current_Y2, Y2_CURRENT_HOME);
289293
#endif
294+
#if HAS_CURRENT_HOME(Z) && ENABLED(DELTA)
295+
const int16_t tmc_save_current_Z = stepperZ.getMilliamps();
296+
stepperZ.rms_current(Z_CURRENT_HOME);
297+
if (DEBUGGING(LEVELING)) debug_current(PSTR("Z"), tmc_save_current_Z, Z_CURRENT_HOME);
298+
#endif
290299
#endif
291300

292301
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
@@ -497,6 +506,9 @@ void GcodeSuite::G28() {
497506
#if HAS_CURRENT_HOME(Y2)
498507
stepperY2.rms_current(tmc_save_current_Y2);
499508
#endif
509+
#if HAS_CURRENT_HOME(Z) && ENABLED(DELTA)
510+
stepperZ.rms_current(tmc_save_current_Z);
511+
#endif
500512
#if HAS_CURRENT_HOME(I)
501513
stepperI.rms_current(tmc_save_current_I);
502514
#endif

Marlin/src/gcode/calibrate/G33.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ float lcd_probe_pt(const xy_pos_t &xy);
7171

7272
void ac_home() {
7373
endstops.enable(true);
74+
TERN_(SENSORLESS_HOMING, probe.set_homing_current(true));
7475
home_delta();
76+
TERN_(SENSORLESS_HOMING, probe.set_homing_current(false));
7577
endstops.not_homing();
7678
}
7779

@@ -384,6 +386,12 @@ static float auto_tune_a() {
384386
* V3 Report settings and probe results
385387
*
386388
* E Engage the probe for each point
389+
*
390+
* With SENSORLESS_PROBING:
391+
* Use these flags to calibrate stall sensitivity: (e.g., `G33 P1 Y Z` to calibrate X only.)
392+
* X Don't activate stallguard on X.
393+
* Y Don't activate stallguard on Y.
394+
* Z Don't activate stallguard on Z.
387395
*/
388396
void GcodeSuite::G33() {
389397

@@ -417,6 +425,12 @@ void GcodeSuite::G33() {
417425

418426
const bool stow_after_each = parser.seen_test('E');
419427

428+
#if ENABLED(SENSORLESS_PROBING)
429+
probe.test_sensitivity.x = !parser.seen_test('X');
430+
TERN_(HAS_Y_AXIS, probe.test_sensitivity.y = !parser.seen_test('Y'));
431+
TERN_(HAS_Z_AXIS, probe.test_sensitivity.z = !parser.seen_test('Z'));
432+
#endif
433+
420434
const bool _0p_calibration = probe_points == 0,
421435
_1p_calibration = probe_points == 1 || probe_points == -1,
422436
_4p_calibration = probe_points == 2,
@@ -587,7 +601,7 @@ void GcodeSuite::G33() {
587601

588602
// print report
589603

590-
if (verbose_level == 3)
604+
if (verbose_level == 3 || verbose_level == 0)
591605
print_calibration_results(z_at_pt, _tower_results, _opposite_results);
592606

593607
if (verbose_level != 0) { // !dry run

Marlin/src/module/delta.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ void home_delta() {
254254
current_position.z = DIFF_TERN(HAS_BED_PROBE, delta_height + 10, probe.offset.z);
255255
line_to_current_position(homing_feedrate(Z_AXIS));
256256
planner.synchronize();
257+
TERN_(SENSORLESS_PROBING,endstops.report_states());
257258

258259
// Re-enable stealthChop if used. Disable diag1 pin on driver.
259260
#if ENABLED(SENSORLESS_HOMING) && DISABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)

Marlin/src/module/endstops.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -595,9 +595,15 @@ void _O2 Endstops::report_states() {
595595
// The following routines are called from an ISR context. It could be the temperature ISR, the
596596
// endstop ISR or the Stepper ISR.
597597

598-
#define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
599-
#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
600-
#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
598+
#if BOTH(DELTA, SENSORLESS_PROBING)
599+
#define _ENDSTOP(AXIS, MINMAX) AXIS ##_MAX
600+
#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_MAX_PIN
601+
#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_MAX_ENDSTOP_INVERTING
602+
#else
603+
#define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
604+
#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
605+
#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
606+
#endif
601607

602608
// Check endstops - Could be called from Temperature ISR!
603609
void Endstops::update() {

Marlin/src/module/planner.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -1527,6 +1527,34 @@ void Planner::check_axes_activity() {
15271527
}
15281528
#endif
15291529

1530+
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
1531+
1532+
void Planner::enable_stall_prevention(const bool onoff) {
1533+
static motion_state_t saved_motion_state;
1534+
if (onoff) {
1535+
saved_motion_state.acceleration.x = settings.max_acceleration_mm_per_s2[X_AXIS];
1536+
saved_motion_state.acceleration.y = settings.max_acceleration_mm_per_s2[Y_AXIS];
1537+
settings.max_acceleration_mm_per_s2[X_AXIS] = settings.max_acceleration_mm_per_s2[Y_AXIS] = 100;
1538+
#if ENABLED(DELTA)
1539+
saved_motion_state.acceleration.z = settings.max_acceleration_mm_per_s2[Z_AXIS];
1540+
settings.max_acceleration_mm_per_s2[Z_AXIS] = 100;
1541+
#endif
1542+
#if HAS_CLASSIC_JERK
1543+
saved_motion_state.jerk_state = max_jerk;
1544+
max_jerk.set(0, 0 OPTARG(DELTA, 0));
1545+
#endif
1546+
}
1547+
else {
1548+
settings.max_acceleration_mm_per_s2[X_AXIS] = saved_motion_state.acceleration.x;
1549+
settings.max_acceleration_mm_per_s2[Y_AXIS] = saved_motion_state.acceleration.y;
1550+
TERN_(DELTA, settings.max_acceleration_mm_per_s2[Z_AXIS] = saved_motion_state.acceleration.z);
1551+
TERN_(HAS_CLASSIC_JERK, max_jerk = saved_motion_state.jerk_state);
1552+
}
1553+
reset_acceleration_rates();
1554+
}
1555+
1556+
#endif
1557+
15301558
#if HAS_LEVELING
15311559

15321560
constexpr xy_pos_t level_fulcrum = {

Marlin/src/module/planner.h

+13
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,15 @@ typedef struct {
281281
min_travel_feedrate_mm_s; // (mm/s) M205 T - Minimum travel feedrate
282282
} planner_settings_t;
283283

284+
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
285+
struct motion_state_t {
286+
TERN(DELTA, xyz_ulong_t, xy_ulong_t) acceleration;
287+
#if HAS_CLASSIC_JERK
288+
TERN(DELTA, xyz_float_t, xy_float_t) jerk_state;
289+
#endif
290+
};
291+
#endif
292+
284293
#if DISABLED(SKEW_CORRECTION)
285294
#define XY_SKEW_FACTOR 0
286295
#define XZ_SKEW_FACTOR 0
@@ -532,6 +541,10 @@ class Planner {
532541
}
533542
#endif
534543

544+
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
545+
void enable_stall_prevention(const bool onoff);
546+
#endif
547+
535548
#if DISABLED(NO_VOLUMETRICS)
536549

537550
// Update multipliers based on new diameter measurements

Marlin/src/module/probe.cpp

+102-7
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
#include "servo.h"
6969
#endif
7070

71-
#if ENABLED(SENSORLESS_PROBING)
71+
#if EITHER(SENSORLESS_PROBING, SENSORLESS_HOMING)
7272
#include "stepper.h"
7373
#include "../feature/tmc_util.h"
7474
#endif
@@ -92,6 +92,10 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
9292
const xy_pos_t &Probe::offset_xy = Probe::offset;
9393
#endif
9494

95+
#if ENABLED(SENSORLESS_PROBING)
96+
Probe::sense_bool_t Probe::test_sensitivity;
97+
#endif
98+
9599
#if ENABLED(Z_PROBE_SLED)
96100

97101
#ifndef SLED_DOCKING_OFFSET
@@ -493,11 +497,12 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) {
493497
#if ENABLED(SENSORLESS_PROBING)
494498
sensorless_t stealth_states { false };
495499
#if ENABLED(DELTA)
496-
stealth_states.x = tmc_enable_stallguard(stepperX);
497-
stealth_states.y = tmc_enable_stallguard(stepperY);
500+
if (probe.test_sensitivity.x) stealth_states.x = tmc_enable_stallguard(stepperX); // Delta watches all DIAG pins for a stall
501+
if (probe.test_sensitivity.y) stealth_states.y = tmc_enable_stallguard(stepperY);
498502
#endif
499-
stealth_states.z = tmc_enable_stallguard(stepperZ);
503+
if (probe.test_sensitivity.z) stealth_states.z = tmc_enable_stallguard(stepperZ); // All machines will check Z-DIAG for stall
500504
endstops.enable(true);
505+
set_homing_current(true); // The "homing" current also applies to probing
501506
#endif
502507

503508
TERN_(HAS_QUIET_PROBING, set_probing_paused(true));
@@ -520,10 +525,11 @@ bool Probe::probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s) {
520525
#if ENABLED(SENSORLESS_PROBING)
521526
endstops.not_homing();
522527
#if ENABLED(DELTA)
523-
tmc_disable_stallguard(stepperX, stealth_states.x);
524-
tmc_disable_stallguard(stepperY, stealth_states.y);
528+
if (probe.test_sensitivity.x) tmc_disable_stallguard(stepperX, stealth_states.x);
529+
if (probe.test_sensitivity.y) tmc_disable_stallguard(stepperY, stealth_states.y);
525530
#endif
526-
tmc_disable_stallguard(stepperZ, stealth_states.z);
531+
if (probe.test_sensitivity.z) tmc_disable_stallguard(stepperZ, stealth_states.z);
532+
set_homing_current(false);
527533
#endif
528534

529535
if (probe_triggered && TERN0(BLTOUCH_SLOW_MODE, bltouch.stow())) // Stow in LOW SPEED MODE on every trigger
@@ -815,4 +821,93 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai
815821

816822
#endif // HAS_Z_SERVO_PROBE
817823

824+
#if EITHER(SENSORLESS_PROBING, SENSORLESS_HOMING)
825+
826+
sensorless_t stealth_states { false };
827+
828+
/**
829+
* Disable stealthChop if used. Enable diag1 pin on driver.
830+
*/
831+
void Probe::enable_stallguard_diag1() {
832+
#if ENABLED(SENSORLESS_PROBING)
833+
#if ENABLED(DELTA)
834+
stealth_states.x = tmc_enable_stallguard(stepperX);
835+
stealth_states.y = tmc_enable_stallguard(stepperY);
836+
#endif
837+
stealth_states.z = tmc_enable_stallguard(stepperZ);
838+
endstops.enable(true);
839+
#endif
840+
}
841+
842+
/**
843+
* Re-enable stealthChop if used. Disable diag1 pin on driver.
844+
*/
845+
void Probe::disable_stallguard_diag1() {
846+
#if ENABLED(SENSORLESS_PROBING)
847+
endstops.not_homing();
848+
#if ENABLED(DELTA)
849+
tmc_disable_stallguard(stepperX, stealth_states.x);
850+
tmc_disable_stallguard(stepperY, stealth_states.y);
851+
#endif
852+
tmc_disable_stallguard(stepperZ, stealth_states.z);
853+
#endif
854+
}
855+
856+
/**
857+
* Change the current in the TMC drivers to N##_CURRENT_HOME. And we save the current configuration of each TMC driver.
858+
*/
859+
void Probe::set_homing_current(const bool onoff) {
860+
#define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
861+
#if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Z)
862+
#if ENABLED(DELTA)
863+
static int16_t saved_current_X, saved_current_Y;
864+
#endif
865+
#if HAS_CURRENT_HOME(Z)
866+
static int16_t saved_current_Z;
867+
#endif
868+
auto debug_current_on = [](PGM_P const s, const int16_t a, const int16_t b) {
869+
if (DEBUGGING(LEVELING)) { DEBUG_ECHOPGM_P(s); DEBUG_ECHOLNPAIR(" current: ", a, " -> ", b); }
870+
};
871+
if (onoff) {
872+
#if ENABLED(DELTA)
873+
#if HAS_CURRENT_HOME(X)
874+
saved_current_X = stepperX.getMilliamps();
875+
stepperX.rms_current(X_CURRENT_HOME);
876+
debug_current_on(PSTR("X"), saved_current_X, X_CURRENT_HOME);
877+
#endif
878+
#if HAS_CURRENT_HOME(Y)
879+
saved_current_Y = stepperY.getMilliamps();
880+
stepperY.rms_current(Y_CURRENT_HOME);
881+
debug_current_on(PSTR("Y"), saved_current_Y, Y_CURRENT_HOME);
882+
#endif
883+
#endif
884+
#if HAS_CURRENT_HOME(Z)
885+
saved_current_Z = stepperZ.getMilliamps();
886+
stepperZ.rms_current(Z_CURRENT_HOME);
887+
debug_current_on(PSTR("Z"), saved_current_Z, Z_CURRENT_HOME);
888+
#endif
889+
TERN_(IMPROVE_HOMING_RELIABILITY, planner.enable_stall_prevention(true));
890+
}
891+
else {
892+
#if ENABLED(DELTA)
893+
#if HAS_CURRENT_HOME(X)
894+
stepperX.rms_current(saved_current_X);
895+
debug_current_on(PSTR("X"), X_CURRENT_HOME, saved_current_X);
896+
#endif
897+
#if HAS_CURRENT_HOME(Y)
898+
stepperY.rms_current(saved_current_Y);
899+
debug_current_on(PSTR("Y"), Y_CURRENT_HOME, saved_current_Y);
900+
#endif
901+
#endif
902+
#if HAS_CURRENT_HOME(Z)
903+
stepperZ.rms_current(saved_current_Z);
904+
debug_current_on(PSTR("Z"), Z_CURRENT_HOME, saved_current_Z);
905+
#endif
906+
TERN_(IMPROVE_HOMING_RELIABILITY, planner.enable_stall_prevention(false));
907+
}
908+
#endif
909+
}
910+
911+
#endif // SENSORLESS_PROBING
912+
818913
#endif // HAS_BED_PROBE

Marlin/src/module/probe.h

+12
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@
5656
class Probe {
5757
public:
5858

59+
#if ENABLED(SENSORLESS_PROBING)
60+
typedef struct { bool x:1, y:1, z:1; } sense_bool_t;
61+
static sense_bool_t test_sensitivity;
62+
#endif
63+
5964
#if HAS_BED_PROBE
6065

6166
static xyz_pos_t offset;
@@ -256,6 +261,13 @@ class Probe {
256261
static bool tare();
257262
#endif
258263

264+
// Basic functions for Sensorless Homing and Probing
265+
#if EITHER(SENSORLESS_HOMING, SENSORLESS_PROBING)
266+
static void enable_stallguard_diag1();
267+
static void disable_stallguard_diag1();
268+
static void set_homing_current(const bool onoff);
269+
#endif
270+
259271
private:
260272
static bool probe_down_to_z(const_float_t z, const_feedRate_t fr_mm_s);
261273
static void do_z_raise(const float z_raise);

0 commit comments

Comments
 (0)