My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

M911-M914.cpp 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "../../../inc/MarlinConfig.h"
  23. #if HAS_TRINAMIC_CONFIG
  24. #include "../../gcode.h"
  25. #include "../../../feature/tmc_util.h"
  26. #include "../../../module/stepper/indirection.h"
  27. #include "../../../module/planner.h"
  28. #include "../../queue.h"
  29. #if ENABLED(MONITOR_DRIVER_STATUS)
  30. #define M91x_USE(ST) (AXIS_DRIVER_TYPE(ST, TMC2130) || AXIS_DRIVER_TYPE(ST, TMC2160) || AXIS_DRIVER_TYPE(ST, TMC2208) || AXIS_DRIVER_TYPE(ST, TMC2209) || AXIS_DRIVER_TYPE(ST, TMC2660) || AXIS_DRIVER_TYPE(ST, TMC5130) || AXIS_DRIVER_TYPE(ST, TMC5160))
  31. #define M91x_USE_E(N) (E_STEPPERS > N && M91x_USE(E##N))
  32. #if M91x_USE(X) || M91x_USE(X2)
  33. #define M91x_SOME_X 1
  34. #endif
  35. #if LINEAR_AXES >= 2 && (M91x_USE(Y) || M91x_USE(Y2))
  36. #define M91x_SOME_Y 1
  37. #endif
  38. #if HAS_Z_AXIS && (M91x_USE(Z) || M91x_USE(Z2) || M91x_USE(Z3) || M91x_USE(Z4))
  39. #define M91x_SOME_Z 1
  40. #endif
  41. #if LINEAR_AXES >= 4 && M91x_USE(I)
  42. #define M91x_USE_I 1
  43. #endif
  44. #if LINEAR_AXES >= 5 && M91x_USE(J)
  45. #define M91x_USE_J 1
  46. #endif
  47. #if LINEAR_AXES >= 6 && M91x_USE(K)
  48. #define M91x_USE_K 1
  49. #endif
  50. #if M91x_USE_E(0) || M91x_USE_E(1) || M91x_USE_E(2) || M91x_USE_E(3) || M91x_USE_E(4) || M91x_USE_E(5) || M91x_USE_E(6) || M91x_USE_E(7)
  51. #define M91x_SOME_E 1
  52. #endif
  53. #if !M91x_SOME_X && !M91x_SOME_Y && !M91x_SOME_Z && !M91x_USE_I && !M91x_USE_J && !M91x_USE_K && !M91x_SOME_E
  54. #error "MONITOR_DRIVER_STATUS requires at least one TMC2130, 2160, 2208, 2209, 2660, 5130, or 5160."
  55. #endif
  56. /**
  57. * M911: Report TMC stepper driver overtemperature pre-warn flag
  58. * This flag is held by the library, persisting until cleared by M912
  59. */
  60. void GcodeSuite::M911() {
  61. #if M91x_USE(X)
  62. tmc_report_otpw(stepperX);
  63. #endif
  64. #if M91x_USE(X2)
  65. tmc_report_otpw(stepperX2);
  66. #endif
  67. #if M91x_USE(Y)
  68. tmc_report_otpw(stepperY);
  69. #endif
  70. #if M91x_USE(Y2)
  71. tmc_report_otpw(stepperY2);
  72. #endif
  73. #if M91x_USE(Z)
  74. tmc_report_otpw(stepperZ);
  75. #endif
  76. #if M91x_USE(Z2)
  77. tmc_report_otpw(stepperZ2);
  78. #endif
  79. #if M91x_USE(Z3)
  80. tmc_report_otpw(stepperZ3);
  81. #endif
  82. #if M91x_USE(Z4)
  83. tmc_report_otpw(stepperZ4);
  84. #endif
  85. TERN_(M91x_USE_I, tmc_report_otpw(stepperI));
  86. TERN_(M91x_USE_J, tmc_report_otpw(stepperJ));
  87. TERN_(M91x_USE_K, tmc_report_otpw(stepperK));
  88. #if M91x_USE_E(0)
  89. tmc_report_otpw(stepperE0);
  90. #endif
  91. #if M91x_USE_E(1)
  92. tmc_report_otpw(stepperE1);
  93. #endif
  94. #if M91x_USE_E(2)
  95. tmc_report_otpw(stepperE2);
  96. #endif
  97. #if M91x_USE_E(3)
  98. tmc_report_otpw(stepperE3);
  99. #endif
  100. #if M91x_USE_E(4)
  101. tmc_report_otpw(stepperE4);
  102. #endif
  103. #if M91x_USE_E(5)
  104. tmc_report_otpw(stepperE5);
  105. #endif
  106. #if M91x_USE_E(6)
  107. tmc_report_otpw(stepperE6);
  108. #endif
  109. #if M91x_USE_E(7)
  110. tmc_report_otpw(stepperE7);
  111. #endif
  112. }
  113. /**
  114. * M912: Clear TMC stepper driver overtemperature pre-warn flag held by the library
  115. * Specify one or more axes with X, Y, Z, X1, Y1, Z1, X2, Y2, Z2, Z3, Z4 and E[index].
  116. * If no axes are given, clear all.
  117. *
  118. * Examples:
  119. * M912 X ; clear X and X2
  120. * M912 X1 ; clear X1 only
  121. * M912 X2 ; clear X2 only
  122. * M912 X E ; clear X, X2, and all E
  123. * M912 E1 ; clear E1 only
  124. */
  125. void GcodeSuite::M912() {
  126. const bool hasX = TERN0(M91x_SOME_X, parser.seen(axis_codes.x)),
  127. hasY = TERN0(M91x_SOME_Y, parser.seen(axis_codes.y)),
  128. hasZ = TERN0(M91x_SOME_Z, parser.seen(axis_codes.z)),
  129. hasI = TERN0(M91x_USE_I, parser.seen(axis_codes.i)),
  130. hasJ = TERN0(M91x_USE_J, parser.seen(axis_codes.j)),
  131. hasK = TERN0(M91x_USE_K, parser.seen(axis_codes.k)),
  132. hasE = TERN0(M91x_SOME_E, parser.seen(axis_codes.e));
  133. const bool hasNone = !hasE && !hasX && !hasY && !hasZ && !hasI && !hasJ && !hasK;
  134. #if M91x_SOME_X
  135. const int8_t xval = int8_t(parser.byteval(axis_codes.x, 0xFF));
  136. #if M91x_USE(X)
  137. if (hasNone || xval == 1 || (hasX && xval < 0)) tmc_clear_otpw(stepperX);
  138. #endif
  139. #if M91x_USE(X2)
  140. if (hasNone || xval == 2 || (hasX && xval < 0)) tmc_clear_otpw(stepperX2);
  141. #endif
  142. #endif
  143. #if M91x_SOME_Y
  144. const int8_t yval = int8_t(parser.byteval(axis_codes.y, 0xFF));
  145. #if M91x_USE(Y)
  146. if (hasNone || yval == 1 || (hasY && yval < 0)) tmc_clear_otpw(stepperY);
  147. #endif
  148. #if M91x_USE(Y2)
  149. if (hasNone || yval == 2 || (hasY && yval < 0)) tmc_clear_otpw(stepperY2);
  150. #endif
  151. #endif
  152. #if M91x_SOME_Z
  153. const int8_t zval = int8_t(parser.byteval(axis_codes.z, 0xFF));
  154. #if M91x_USE(Z)
  155. if (hasNone || zval == 1 || (hasZ && zval < 0)) tmc_clear_otpw(stepperZ);
  156. #endif
  157. #if M91x_USE(Z2)
  158. if (hasNone || zval == 2 || (hasZ && zval < 0)) tmc_clear_otpw(stepperZ2);
  159. #endif
  160. #if M91x_USE(Z3)
  161. if (hasNone || zval == 3 || (hasZ && zval < 0)) tmc_clear_otpw(stepperZ3);
  162. #endif
  163. #if M91x_USE(Z4)
  164. if (hasNone || zval == 4 || (hasZ && zval < 0)) tmc_clear_otpw(stepperZ4);
  165. #endif
  166. #endif
  167. #if M91x_USE_I
  168. const int8_t ival = int8_t(parser.byteval(axis_codes.i, 0xFF));
  169. if (hasNone || ival == 1 || (hasI && ival < 0)) tmc_clear_otpw(stepperI);
  170. #endif
  171. #if M91x_USE_J
  172. const int8_t jval = int8_t(parser.byteval(axis_codes.j, 0xFF));
  173. if (hasNone || jval == 1 || (hasJ && jval < 0)) tmc_clear_otpw(stepperJ);
  174. #endif
  175. #if M91x_USE_K
  176. const int8_t kval = int8_t(parser.byteval(axis_codes.k, 0xFF));
  177. if (hasNone || kval == 1 || (hasK && kval < 0)) tmc_clear_otpw(stepperK);
  178. #endif
  179. #if M91x_SOME_E
  180. const int8_t eval = int8_t(parser.byteval(axis_codes.e, 0xFF));
  181. #if M91x_USE_E(0)
  182. if (hasNone || eval == 0 || (hasE && eval < 0)) tmc_clear_otpw(stepperE0);
  183. #endif
  184. #if M91x_USE_E(1)
  185. if (hasNone || eval == 1 || (hasE && eval < 0)) tmc_clear_otpw(stepperE1);
  186. #endif
  187. #if M91x_USE_E(2)
  188. if (hasNone || eval == 2 || (hasE && eval < 0)) tmc_clear_otpw(stepperE2);
  189. #endif
  190. #if M91x_USE_E(3)
  191. if (hasNone || eval == 3 || (hasE && eval < 0)) tmc_clear_otpw(stepperE3);
  192. #endif
  193. #if M91x_USE_E(4)
  194. if (hasNone || eval == 4 || (hasE && eval < 0)) tmc_clear_otpw(stepperE4);
  195. #endif
  196. #if M91x_USE_E(5)
  197. if (hasNone || eval == 5 || (hasE && eval < 0)) tmc_clear_otpw(stepperE5);
  198. #endif
  199. #if M91x_USE_E(6)
  200. if (hasNone || eval == 6 || (hasE && eval < 0)) tmc_clear_otpw(stepperE6);
  201. #endif
  202. #if M91x_USE_E(7)
  203. if (hasNone || eval == 7 || (hasE && eval < 0)) tmc_clear_otpw(stepperE7);
  204. #endif
  205. #endif
  206. }
  207. #endif // MONITOR_DRIVER_STATUS
  208. /**
  209. * M913: Set HYBRID_THRESHOLD speed.
  210. */
  211. #if ENABLED(HYBRID_THRESHOLD)
  212. void GcodeSuite::M913() {
  213. #define TMC_SAY_PWMTHRS(A,Q) tmc_print_pwmthrs(stepper##Q)
  214. #define TMC_SET_PWMTHRS(A,Q) stepper##Q.set_pwm_thrs(value)
  215. #define TMC_SAY_PWMTHRS_E(E) tmc_print_pwmthrs(stepperE##E)
  216. #define TMC_SET_PWMTHRS_E(E) stepperE##E.set_pwm_thrs(value)
  217. bool report = true;
  218. #if AXIS_IS_TMC(X) || AXIS_IS_TMC(X2) || AXIS_IS_TMC(Y) || AXIS_IS_TMC(Y2) || AXIS_IS_TMC(Z) || AXIS_IS_TMC(Z2) || AXIS_IS_TMC(Z3) || AXIS_IS_TMC(Z4) || AXIS_IS_TMC(I) || AXIS_IS_TMC(J) || AXIS_IS_TMC(K)
  219. const uint8_t index = parser.byteval('I');
  220. #endif
  221. LOOP_LOGICAL_AXES(i) if (int32_t value = parser.longval(axis_codes[i])) {
  222. report = false;
  223. switch (i) {
  224. case X_AXIS:
  225. TERN_(X_HAS_STEALTHCHOP, if (index < 2) TMC_SET_PWMTHRS(X,X));
  226. TERN_(X2_HAS_STEALTHCHOP, if (!(index & 1)) TMC_SET_PWMTHRS(X,X2));
  227. break;
  228. case Y_AXIS:
  229. TERN_(Y_HAS_STEALTHCHOP, if (index < 2) TMC_SET_PWMTHRS(Y,Y));
  230. TERN_(Y2_HAS_STEALTHCHOP, if (!(index & 1)) TMC_SET_PWMTHRS(Y,Y2));
  231. break;
  232. #if I_HAS_STEALTHCHOP
  233. case I_AXIS: TMC_SET_PWMTHRS(I,I); break;
  234. #endif
  235. #if J_HAS_STEALTHCHOP
  236. case J_AXIS: TMC_SET_PWMTHRS(J,J); break;
  237. #endif
  238. #if K_HAS_STEALTHCHOP
  239. case K_AXIS: TMC_SET_PWMTHRS(K,K); break;
  240. #endif
  241. case Z_AXIS:
  242. TERN_(Z_HAS_STEALTHCHOP, if (index < 2) TMC_SET_PWMTHRS(Z,Z));
  243. TERN_(Z2_HAS_STEALTHCHOP, if (index == 0 || index == 2) TMC_SET_PWMTHRS(Z,Z2));
  244. TERN_(Z3_HAS_STEALTHCHOP, if (index == 0 || index == 3) TMC_SET_PWMTHRS(Z,Z3));
  245. TERN_(Z4_HAS_STEALTHCHOP, if (index == 0 || index == 4) TMC_SET_PWMTHRS(Z,Z4));
  246. break;
  247. #if E_STEPPERS
  248. case E_AXIS: {
  249. const int8_t target_e_stepper = get_target_e_stepper_from_command();
  250. if (target_e_stepper < 0) return;
  251. switch (target_e_stepper) {
  252. TERN_(E0_HAS_STEALTHCHOP, case 0: TMC_SET_PWMTHRS_E(0); break;)
  253. TERN_(E1_HAS_STEALTHCHOP, case 1: TMC_SET_PWMTHRS_E(1); break;)
  254. TERN_(E2_HAS_STEALTHCHOP, case 2: TMC_SET_PWMTHRS_E(2); break;)
  255. TERN_(E3_HAS_STEALTHCHOP, case 3: TMC_SET_PWMTHRS_E(3); break;)
  256. TERN_(E4_HAS_STEALTHCHOP, case 4: TMC_SET_PWMTHRS_E(4); break;)
  257. TERN_(E5_HAS_STEALTHCHOP, case 5: TMC_SET_PWMTHRS_E(5); break;)
  258. TERN_(E6_HAS_STEALTHCHOP, case 6: TMC_SET_PWMTHRS_E(6); break;)
  259. TERN_(E7_HAS_STEALTHCHOP, case 7: TMC_SET_PWMTHRS_E(7); break;)
  260. }
  261. } break;
  262. #endif // E_STEPPERS
  263. }
  264. }
  265. if (report) {
  266. TERN_( X_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(X,X));
  267. TERN_(X2_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(X,X2));
  268. TERN_( Y_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(Y,Y));
  269. TERN_(Y2_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(Y,Y2));
  270. TERN_( Z_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(Z,Z));
  271. TERN_(Z2_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(Z,Z2));
  272. TERN_(Z3_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(Z,Z3));
  273. TERN_(Z4_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(Z,Z4));
  274. TERN_( I_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(I,I));
  275. TERN_( J_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(J,J));
  276. TERN_( K_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(K,K));
  277. TERN_(E0_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(0));
  278. TERN_(E1_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(1));
  279. TERN_(E2_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(2));
  280. TERN_(E3_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(3));
  281. TERN_(E4_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(4));
  282. TERN_(E5_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(5));
  283. TERN_(E6_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(6));
  284. TERN_(E7_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(7));
  285. }
  286. }
  287. void GcodeSuite::M913_report(const bool forReplay/*=true*/) {
  288. report_heading(forReplay, PSTR(STR_HYBRID_THRESHOLD));
  289. auto say_M913 = [](const bool forReplay) {
  290. report_echo_start(forReplay);
  291. SERIAL_ECHOPGM(" M913");
  292. };
  293. #if X_HAS_STEALTHCHOP || Y_HAS_STEALTHCHOP || Z_HAS_STEALTHCHOP
  294. say_M913(forReplay);
  295. #if X_HAS_STEALTHCHOP
  296. SERIAL_ECHOPGM_P(SP_X_STR, stepperX.get_pwm_thrs());
  297. #endif
  298. #if Y_HAS_STEALTHCHOP
  299. SERIAL_ECHOPGM_P(SP_Y_STR, stepperY.get_pwm_thrs());
  300. #endif
  301. #if Z_HAS_STEALTHCHOP
  302. SERIAL_ECHOPGM_P(SP_Z_STR, stepperZ.get_pwm_thrs());
  303. #endif
  304. SERIAL_EOL();
  305. #endif
  306. #if X2_HAS_STEALTHCHOP || Y2_HAS_STEALTHCHOP || Z2_HAS_STEALTHCHOP
  307. say_M913(forReplay);
  308. SERIAL_ECHOPGM(" I1");
  309. #if X2_HAS_STEALTHCHOP
  310. SERIAL_ECHOPGM_P(SP_X_STR, stepperX2.get_pwm_thrs());
  311. #endif
  312. #if Y2_HAS_STEALTHCHOP
  313. SERIAL_ECHOPGM_P(SP_Y_STR, stepperY2.get_pwm_thrs());
  314. #endif
  315. #if Z2_HAS_STEALTHCHOP
  316. SERIAL_ECHOPGM_P(SP_Z_STR, stepperZ2.get_pwm_thrs());
  317. #endif
  318. SERIAL_EOL();
  319. #endif
  320. #if Z3_HAS_STEALTHCHOP
  321. say_M913(forReplay);
  322. SERIAL_ECHOLNPGM(" I2 Z", stepperZ3.get_pwm_thrs());
  323. #endif
  324. #if Z4_HAS_STEALTHCHOP
  325. say_M913(forReplay);
  326. SERIAL_ECHOLNPGM(" I3 Z", stepperZ4.get_pwm_thrs());
  327. #endif
  328. #if I_HAS_STEALTHCHOP
  329. say_M913(forReplay);
  330. SERIAL_ECHOLNPGM_P(SP_I_STR, stepperI.get_pwm_thrs());
  331. #endif
  332. #if J_HAS_STEALTHCHOP
  333. say_M913(forReplay);
  334. SERIAL_ECHOLNPGM_P(SP_J_STR, stepperJ.get_pwm_thrs());
  335. #endif
  336. #if K_HAS_STEALTHCHOP
  337. say_M913(forReplay);
  338. SERIAL_ECHOLNPGM_P(SP_K_STR, stepperK.get_pwm_thrs());
  339. #endif
  340. #if E0_HAS_STEALTHCHOP
  341. say_M913(forReplay);
  342. SERIAL_ECHOLNPGM(" T0 E", stepperE0.get_pwm_thrs());
  343. #endif
  344. #if E1_HAS_STEALTHCHOP
  345. say_M913(forReplay);
  346. SERIAL_ECHOLNPGM(" T1 E", stepperE1.get_pwm_thrs());
  347. #endif
  348. #if E2_HAS_STEALTHCHOP
  349. say_M913(forReplay);
  350. SERIAL_ECHOLNPGM(" T2 E", stepperE2.get_pwm_thrs());
  351. #endif
  352. #if E3_HAS_STEALTHCHOP
  353. say_M913(forReplay);
  354. SERIAL_ECHOLNPGM(" T3 E", stepperE3.get_pwm_thrs());
  355. #endif
  356. #if E4_HAS_STEALTHCHOP
  357. say_M913(forReplay);
  358. SERIAL_ECHOLNPGM(" T4 E", stepperE4.get_pwm_thrs());
  359. #endif
  360. #if E5_HAS_STEALTHCHOP
  361. say_M913(forReplay);
  362. SERIAL_ECHOLNPGM(" T5 E", stepperE5.get_pwm_thrs());
  363. #endif
  364. #if E6_HAS_STEALTHCHOP
  365. say_M913(forReplay);
  366. SERIAL_ECHOLNPGM(" T6 E", stepperE6.get_pwm_thrs());
  367. #endif
  368. #if E7_HAS_STEALTHCHOP
  369. say_M913(forReplay);
  370. SERIAL_ECHOLNPGM(" T7 E", stepperE7.get_pwm_thrs());
  371. #endif
  372. SERIAL_EOL();
  373. }
  374. #endif // HYBRID_THRESHOLD
  375. /**
  376. * M914: Set StallGuard sensitivity.
  377. */
  378. #if USE_SENSORLESS
  379. void GcodeSuite::M914() {
  380. bool report = true;
  381. const uint8_t index = parser.byteval('I');
  382. LOOP_LINEAR_AXES(i) if (parser.seen(AXIS_CHAR(i))) {
  383. const int16_t value = parser.value_int();
  384. report = false;
  385. switch (i) {
  386. #if X_SENSORLESS
  387. case X_AXIS:
  388. #if AXIS_HAS_STALLGUARD(X)
  389. if (index < 2) stepperX.homing_threshold(value);
  390. #endif
  391. #if AXIS_HAS_STALLGUARD(X2)
  392. if (!(index & 1)) stepperX2.homing_threshold(value);
  393. #endif
  394. break;
  395. #endif
  396. #if Y_SENSORLESS
  397. case Y_AXIS:
  398. #if AXIS_HAS_STALLGUARD(Y)
  399. if (index < 2) stepperY.homing_threshold(value);
  400. #endif
  401. #if AXIS_HAS_STALLGUARD(Y2)
  402. if (!(index & 1)) stepperY2.homing_threshold(value);
  403. #endif
  404. break;
  405. #endif
  406. #if Z_SENSORLESS
  407. case Z_AXIS:
  408. #if AXIS_HAS_STALLGUARD(Z)
  409. if (index < 2) stepperZ.homing_threshold(value);
  410. #endif
  411. #if AXIS_HAS_STALLGUARD(Z2)
  412. if (index == 0 || index == 2) stepperZ2.homing_threshold(value);
  413. #endif
  414. #if AXIS_HAS_STALLGUARD(Z3)
  415. if (index == 0 || index == 3) stepperZ3.homing_threshold(value);
  416. #endif
  417. #if AXIS_HAS_STALLGUARD(Z4)
  418. if (index == 0 || index == 4) stepperZ4.homing_threshold(value);
  419. #endif
  420. break;
  421. #endif
  422. #if I_SENSORLESS && AXIS_HAS_STALLGUARD(I)
  423. case I_AXIS: stepperI.homing_threshold(value); break;
  424. #endif
  425. #if J_SENSORLESS && AXIS_HAS_STALLGUARD(J)
  426. case J_AXIS: stepperJ.homing_threshold(value); break;
  427. #endif
  428. #if K_SENSORLESS && AXIS_HAS_STALLGUARD(K)
  429. case K_AXIS: stepperK.homing_threshold(value); break;
  430. #endif
  431. }
  432. }
  433. if (report) {
  434. #if X_SENSORLESS
  435. #if AXIS_HAS_STALLGUARD(X)
  436. tmc_print_sgt(stepperX);
  437. #endif
  438. #if AXIS_HAS_STALLGUARD(X2)
  439. tmc_print_sgt(stepperX2);
  440. #endif
  441. #endif
  442. #if Y_SENSORLESS
  443. #if AXIS_HAS_STALLGUARD(Y)
  444. tmc_print_sgt(stepperY);
  445. #endif
  446. #if AXIS_HAS_STALLGUARD(Y2)
  447. tmc_print_sgt(stepperY2);
  448. #endif
  449. #endif
  450. #if Z_SENSORLESS
  451. #if AXIS_HAS_STALLGUARD(Z)
  452. tmc_print_sgt(stepperZ);
  453. #endif
  454. #if AXIS_HAS_STALLGUARD(Z2)
  455. tmc_print_sgt(stepperZ2);
  456. #endif
  457. #if AXIS_HAS_STALLGUARD(Z3)
  458. tmc_print_sgt(stepperZ3);
  459. #endif
  460. #if AXIS_HAS_STALLGUARD(Z4)
  461. tmc_print_sgt(stepperZ4);
  462. #endif
  463. #endif
  464. #if I_SENSORLESS && AXIS_HAS_STALLGUARD(I)
  465. tmc_print_sgt(stepperI);
  466. #endif
  467. #if J_SENSORLESS && AXIS_HAS_STALLGUARD(J)
  468. tmc_print_sgt(stepperJ);
  469. #endif
  470. #if K_SENSORLESS && AXIS_HAS_STALLGUARD(K)
  471. tmc_print_sgt(stepperK);
  472. #endif
  473. }
  474. }
  475. void GcodeSuite::M914_report(const bool forReplay/*=true*/) {
  476. report_heading(forReplay, PSTR(STR_STALLGUARD_THRESHOLD));
  477. auto say_M914 = [](const bool forReplay) {
  478. report_echo_start(forReplay);
  479. SERIAL_ECHOPGM(" M914");
  480. };
  481. #if X_SENSORLESS || Y_SENSORLESS || Z_SENSORLESS
  482. say_M914(forReplay);
  483. #if X_SENSORLESS
  484. SERIAL_ECHOPGM_P(SP_X_STR, stepperX.homing_threshold());
  485. #endif
  486. #if Y_SENSORLESS
  487. SERIAL_ECHOPGM_P(SP_Y_STR, stepperY.homing_threshold());
  488. #endif
  489. #if Z_SENSORLESS
  490. SERIAL_ECHOPGM_P(SP_Z_STR, stepperZ.homing_threshold());
  491. #endif
  492. SERIAL_EOL();
  493. #endif
  494. #if X2_SENSORLESS || Y2_SENSORLESS || Z2_SENSORLESS
  495. say_M914(forReplay);
  496. SERIAL_ECHOPGM(" I1");
  497. #if X2_SENSORLESS
  498. SERIAL_ECHOPGM_P(SP_X_STR, stepperX2.homing_threshold());
  499. #endif
  500. #if Y2_SENSORLESS
  501. SERIAL_ECHOPGM_P(SP_Y_STR, stepperY2.homing_threshold());
  502. #endif
  503. #if Z2_SENSORLESS
  504. SERIAL_ECHOPGM_P(SP_Z_STR, stepperZ2.homing_threshold());
  505. #endif
  506. SERIAL_EOL();
  507. #endif
  508. #if Z3_SENSORLESS
  509. say_M914(forReplay);
  510. SERIAL_ECHOLNPGM(" I2 Z", stepperZ3.homing_threshold());
  511. #endif
  512. #if Z4_SENSORLESS
  513. say_M914(forReplay);
  514. SERIAL_ECHOLNPGM(" I3 Z", stepperZ4.homing_threshold());
  515. #endif
  516. #if I_SENSORLESS
  517. say_M914(forReplay);
  518. SERIAL_ECHOLNPGM_P(SP_I_STR, stepperI.homing_threshold());
  519. #endif
  520. #if J_SENSORLESS
  521. say_M914(forReplay);
  522. SERIAL_ECHOLNPGM_P(SP_J_STR, stepperJ.homing_threshold());
  523. #endif
  524. #if K_SENSORLESS
  525. say_M914(forReplay);
  526. SERIAL_ECHOLNPGM_P(SP_K_STR, stepperK.homing_threshold());
  527. #endif
  528. }
  529. #endif // USE_SENSORLESS
  530. #endif // HAS_TRINAMIC_CONFIG