Skip to content

Commit 356dec7

Browse files
Fabi0SanEmmanuel Viala
authored and
Emmanuel Viala
committed
Trinamic steppers Homing Phase (MarlinFirmware#17299)
1 parent db2c5ad commit 356dec7

File tree

3 files changed

+104
-8
lines changed

3 files changed

+104
-8
lines changed

Marlin/Configuration_adv.h

+15-3
Original file line numberDiff line numberDiff line change
@@ -2272,9 +2272,9 @@
22722272
#define CHOPPER_TIMING CHOPPER_DEFAULT_12V
22732273

22742274
/**
2275-
* Monitor Trinamic drivers for error conditions,
2276-
* like overtemperature and short to ground.
2277-
* In the case of overtemperature Marlin can decrease the driver current until error condition clears.
2275+
* Monitor Trinamic drivers
2276+
* for error conditions like overtemperature and short to ground.
2277+
* To manage over-temp Marlin can decrease the driver current until the error condition clears.
22782278
* Other detected conditions can be used to stop the current print.
22792279
* Relevant g-codes:
22802280
* M906 - Set or get motor current in milliamps using axis codes X, Y, Z, E. Report values if no axis codes given.
@@ -2351,6 +2351,18 @@
23512351
//#define IMPROVE_HOMING_RELIABILITY
23522352
#endif
23532353

2354+
/**
2355+
* TMC Homing stepper phase.
2356+
*
2357+
* Improve homing repeatability by homing to stepper coil's nearest absolute
2358+
* phase position. Trinamic drivers use a stepper phase table with 1024 values
2359+
* spanning 4 full steps with 256 positions each (ergo, 1024 positions).
2360+
* Full step positions (128, 384, 640, 896) have the highest holding torque.
2361+
*
2362+
* Values from 0..1023, -1 to disable homing phase for that axis.
2363+
*/
2364+
//#define TMC_HOME_PHASE { 896, 896, 896 }
2365+
23542366
/**
23552367
* Beta feature!
23562368
* Create a 50/50 square wave step pulse optimal for stepper drivers.

Marlin/src/feature/tmc_util.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ class TMCMarlin : public TMC, public TMCStorage<AXIS_LETTER, DRIVER_ID> {
105105
this->val_mA = mA;
106106
TMC::rms_current(mA, mult);
107107
}
108-
108+
inline uint16_t get_microstep_counter() { return TMC::MSCNT(); }
109+
109110
#if HAS_STEALTHCHOP
110111
inline void refresh_stepping_mode() { this->en_pwm_mode(this->stored.stealthChop_enabled); }
111112
inline bool get_stealthChop_status() { return this->en_pwm_mode(); }
@@ -170,6 +171,7 @@ class TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> : public TMC220
170171
this->val_mA = mA;
171172
TMC2208Stepper::rms_current(mA, mult);
172173
}
174+
inline uint16_t get_microstep_counter() { return TMC2208Stepper::MSCNT(); }
173175

174176
#if HAS_STEALTHCHOP
175177
inline void refresh_stepping_mode() { en_spreadCycle(!this->stored.stealthChop_enabled); }
@@ -216,6 +218,7 @@ class TMCMarlin<TMC2209Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> : public TMC220
216218
this->val_mA = mA;
217219
TMC2209Stepper::rms_current(mA, mult);
218220
}
221+
inline uint16_t get_microstep_counter() { return TMC2209Stepper::MSCNT(); }
219222

220223
#if HAS_STEALTHCHOP
221224
inline void refresh_stepping_mode() { en_spreadCycle(!this->stored.stealthChop_enabled); }
@@ -273,6 +276,7 @@ class TMCMarlin<TMC2660Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> : public TMC266
273276
this->val_mA = mA;
274277
TMC2660Stepper::rms_current(mA);
275278
}
279+
inline uint16_t get_microstep_counter() { return TMC2660Stepper::mstep(); }
276280

277281
#if USE_SENSORLESS
278282
inline int16_t homing_threshold() { return TMC2660Stepper::sgt(); }

Marlin/src/module/motion.cpp

+84-4
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,80 @@ void set_axis_not_trusted(const AxisEnum axis) {
14831483
#endif
14841484
}
14851485

1486+
/**
1487+
* Move the axis back to its home_phase if set and driver is capable (TMC)
1488+
*
1489+
* Improves homing repeatability by homing to stepper coil's nearest absolute
1490+
* phase position. Trinamic drivers use a stepper phase table with 1024 values
1491+
* spanning 4 full steps with 256 positions each (ergo, 1024 positions).
1492+
*/
1493+
void backout_to_tmc_homing_phase(const AxisEnum axis) {
1494+
#ifdef TMC_HOME_PHASE
1495+
const abc_long_t home_phase = TMC_HOME_PHASE;
1496+
1497+
// check if home phase is disabled for this axis.
1498+
if (home_phase[axis] < 0) return;
1499+
1500+
int16_t axisMicrostepSize;
1501+
int16_t phaseCurrent;
1502+
bool invertDir;
1503+
1504+
switch (axis) {
1505+
#ifdef X_MICROSTEPS
1506+
case X_AXIS:
1507+
axisMicrostepSize = 256 / (X_MICROSTEPS);
1508+
phaseCurrent = stepperX.get_microstep_counter();
1509+
invertDir = INVERT_X_DIR;
1510+
break;
1511+
#endif
1512+
#ifdef Y_MICROSTEPS
1513+
case Y_AXIS:
1514+
axisMicrostepSize = 256 / (Y_MICROSTEPS);
1515+
phaseCurrent = stepperY.get_microstep_counter();
1516+
invertDir = INVERT_Y_DIR;
1517+
break;
1518+
#endif
1519+
#ifdef Z_MICROSTEPS
1520+
case Z_AXIS:
1521+
axisMicrostepSize = 256 / (Z_MICROSTEPS);
1522+
phaseCurrent = stepperZ.get_microstep_counter();
1523+
invertDir = INVERT_Z_DIR;
1524+
break;
1525+
#endif
1526+
default: return;
1527+
}
1528+
1529+
// Depending on invert dir measure the distance to nearest home phase.
1530+
int16_t phaseDelta = (invertDir ? -1 : 1) * (home_phase[axis] - phaseCurrent);
1531+
1532+
// Check if home distance within endstop assumed repeatability noise of .05mm and warn.
1533+
if (ABS(phaseDelta) * planner.steps_to_mm[axis] / axisMicrostepSize < 0.05f)
1534+
DEBUG_ECHOLNPAIR("Selected home phase ", home_phase[axis],
1535+
" too close to endstop trigger phase ", phaseCurrent,
1536+
". Pick a different phase for ", axis_codes[axis]);
1537+
1538+
// Skip to next if target position is behind current. So it only moves away from endstop.
1539+
if (phaseDelta < 0) phaseDelta += 1024;
1540+
1541+
// Get the integer µsteps to target. Unreachable phase? Consistently stop at the µstep before / after based on invertDir.
1542+
const float mmDelta = -(int16_t(phaseDelta / axisMicrostepSize) * planner.steps_to_mm[axis] * (Z_HOME_DIR));
1543+
1544+
// optional debug messages.
1545+
if (DEBUGGING(LEVELING)) {
1546+
DEBUG_ECHOLNPAIR(
1547+
"Endstop ", axis_codes[axis], " hit at Phase:", phaseCurrent,
1548+
" Delta:", phaseDelta, " Distance:", mmDelta
1549+
);
1550+
}
1551+
1552+
if (mmDelta != 0) {
1553+
// retrace by the amount computed in mmDelta.
1554+
do_homing_move(axis, mmDelta, get_homing_bump_feedrate(axis));
1555+
}
1556+
#endif
1557+
}
1558+
1559+
14861560
/**
14871561
* Home an individual "raw axis" to its endstop.
14881562
* This applies to XYZ on Cartesian and Core robots, and
@@ -1742,6 +1816,9 @@ void homeaxis(const AxisEnum axis) {
17421816
}
17431817
#endif
17441818

1819+
// move back to homing phase if configured and capable
1820+
backout_to_tmc_homing_phase(axis);
1821+
17451822
#if IS_SCARA
17461823

17471824
set_axis_is_at_home(axis);
@@ -1753,10 +1830,13 @@ void homeaxis(const AxisEnum axis) {
17531830
// so here it re-homes each tower in turn.
17541831
// Delta homing treats the axes as normal linear axes.
17551832

1756-
// retrace by the amount specified in delta_endstop_adj + additional dist in order to have minimum steps
1757-
if (delta_endstop_adj[axis] * Z_HOME_DIR <= 0) {
1758-
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("delta_endstop_adj:");
1759-
do_homing_move(axis, delta_endstop_adj[axis] - (MIN_STEPS_PER_SEGMENT + 1) * planner.steps_to_mm[axis] * Z_HOME_DIR);
1833+
const float adjDistance = delta_endstop_adj[axis],
1834+
minDistance = (MIN_STEPS_PER_SEGMENT) * planner.steps_to_mm[axis];
1835+
1836+
// Retrace by the amount specified in delta_endstop_adj if more than min steps.
1837+
if (adjDistance * (Z_HOME_DIR) < 0 && ABS(adjDistance) > minDistance) { // away from endstop, more than min distance
1838+
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("adjDistance:", adjDistance);
1839+
do_homing_move(axis, adjDistance, get_homing_bump_feedrate(axis));
17601840
}
17611841

17621842
#else // CARTESIAN / CORE

0 commit comments

Comments
 (0)