My Marlin configs for Fabrikator Mini and CTC i3 Pro B
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

trinamic.cpp 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  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. /**
  23. * stepper/trinamic.cpp
  24. * Stepper driver indirection for Trinamic
  25. */
  26. #include "../../inc/MarlinConfig.h"
  27. #if HAS_TRINAMIC_CONFIG
  28. #include "trinamic.h"
  29. #include "../stepper.h"
  30. #include <HardwareSerial.h>
  31. #include <SPI.h>
  32. enum StealthIndex : uint8_t {
  33. LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z)
  34. };
  35. #define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE)
  36. // IC = TMC model number
  37. // ST = Stepper object letter
  38. // L = Label characters
  39. // AI = Axis Enum Index
  40. // SWHW = SW/SH UART selection
  41. #if ENABLED(TMC_USE_SW_SPI)
  42. #define __TMC_SPI_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_CS_PIN, float(ST##_RSENSE), TMC_SW_MOSI, TMC_SW_MISO, TMC_SW_SCK, ST##_CHAIN_POS)
  43. #else
  44. #define __TMC_SPI_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_CS_PIN, float(ST##_RSENSE), ST##_CHAIN_POS)
  45. #endif
  46. #if ENABLED(TMC_SERIAL_MULTIPLEXER)
  47. #define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS, SERIAL_MUL_PIN1, SERIAL_MUL_PIN2)
  48. #else
  49. #define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
  50. #endif
  51. #define TMC_UART_SW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_SERIAL_RX_PIN, ST##_SERIAL_TX_PIN, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
  52. #define _TMC_SPI_DEFINE(IC, ST, AI) __TMC_SPI_DEFINE(IC, ST, TMC_##ST##_LABEL, AI)
  53. #define TMC_SPI_DEFINE(ST, AI) _TMC_SPI_DEFINE(ST##_DRIVER_TYPE, ST, AI##_AXIS)
  54. #define _TMC_UART_DEFINE(SWHW, IC, ST, AI) TMC_UART_##SWHW##_DEFINE(IC, ST, TMC_##ST##_LABEL, AI)
  55. #define TMC_UART_DEFINE(SWHW, ST, AI) _TMC_UART_DEFINE(SWHW, ST##_DRIVER_TYPE, ST, AI##_AXIS)
  56. #if ENABLED(DISTINCT_E_FACTORS)
  57. #define TMC_SPI_DEFINE_E(AI) TMC_SPI_DEFINE(E##AI, E##AI)
  58. #define TMC_UART_DEFINE_E(SWHW, AI) TMC_UART_DEFINE(SWHW, E##AI, E##AI)
  59. #else
  60. #define TMC_SPI_DEFINE_E(AI) TMC_SPI_DEFINE(E##AI, E)
  61. #define TMC_UART_DEFINE_E(SWHW, AI) TMC_UART_DEFINE(SWHW, E##AI, E)
  62. #endif
  63. // Stepper objects of TMC2130/TMC2160/TMC2660/TMC5130/TMC5160 steppers used
  64. #if AXIS_HAS_SPI(X)
  65. TMC_SPI_DEFINE(X, X);
  66. #endif
  67. #if AXIS_HAS_SPI(X2)
  68. TMC_SPI_DEFINE(X2, X);
  69. #endif
  70. #if AXIS_HAS_SPI(Y)
  71. TMC_SPI_DEFINE(Y, Y);
  72. #endif
  73. #if AXIS_HAS_SPI(Y2)
  74. TMC_SPI_DEFINE(Y2, Y);
  75. #endif
  76. #if AXIS_HAS_SPI(Z)
  77. TMC_SPI_DEFINE(Z, Z);
  78. #endif
  79. #if AXIS_HAS_SPI(Z2)
  80. TMC_SPI_DEFINE(Z2, Z);
  81. #endif
  82. #if AXIS_HAS_SPI(Z3)
  83. TMC_SPI_DEFINE(Z3, Z);
  84. #endif
  85. #if AXIS_HAS_SPI(Z4)
  86. TMC_SPI_DEFINE(Z4, Z);
  87. #endif
  88. #if AXIS_HAS_SPI(E0)
  89. TMC_SPI_DEFINE_E(0);
  90. #endif
  91. #if AXIS_HAS_SPI(E1)
  92. TMC_SPI_DEFINE_E(1);
  93. #endif
  94. #if AXIS_HAS_SPI(E2)
  95. TMC_SPI_DEFINE_E(2);
  96. #endif
  97. #if AXIS_HAS_SPI(E3)
  98. TMC_SPI_DEFINE_E(3);
  99. #endif
  100. #if AXIS_HAS_SPI(E4)
  101. TMC_SPI_DEFINE_E(4);
  102. #endif
  103. #if AXIS_HAS_SPI(E5)
  104. TMC_SPI_DEFINE_E(5);
  105. #endif
  106. #if AXIS_HAS_SPI(E6)
  107. TMC_SPI_DEFINE_E(6);
  108. #endif
  109. #if AXIS_HAS_SPI(E7)
  110. TMC_SPI_DEFINE_E(7);
  111. #endif
  112. #ifndef TMC_BAUD_RATE
  113. // Reduce baud rate for boards not already overriding TMC_BAUD_RATE for software serial.
  114. // Testing has shown that 115200 is not 100% reliable on AVR platforms, occasionally
  115. // failing to read status properly. 32-bit platforms typically define an even lower
  116. // TMC_BAUD_RATE, due to differences in how SoftwareSerial libraries work on different
  117. // platforms.
  118. #define TMC_BAUD_RATE TERN(HAS_TMC_SW_SERIAL, 57600, 115200)
  119. #endif
  120. #if HAS_DRIVER(TMC2130)
  121. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  122. void tmc_init(TMCMarlin<TMC2130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
  123. st.begin();
  124. CHOPCONF_t chopconf{0};
  125. chopconf.tbl = 0b01;
  126. chopconf.toff = chop_init.toff;
  127. chopconf.intpol = interpolate;
  128. chopconf.hend = chop_init.hend + 3;
  129. chopconf.hstrt = chop_init.hstrt - 1;
  130. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  131. st.CHOPCONF(chopconf.sr);
  132. st.rms_current(mA, HOLD_MULTIPLIER);
  133. st.microsteps(microsteps);
  134. st.iholddelay(10);
  135. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  136. st.en_pwm_mode(stealth);
  137. st.stored.stealthChop_enabled = stealth;
  138. PWMCONF_t pwmconf{0};
  139. pwmconf.pwm_freq = 0b01; // f_pwm = 2/683 f_clk
  140. pwmconf.pwm_autoscale = true;
  141. pwmconf.pwm_grad = 5;
  142. pwmconf.pwm_ampl = 180;
  143. st.PWMCONF(pwmconf.sr);
  144. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  145. st.GSTAT(); // Clear GSTAT
  146. }
  147. #endif // TMC2130
  148. #if HAS_DRIVER(TMC2160)
  149. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  150. void tmc_init(TMCMarlin<TMC2160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
  151. st.begin();
  152. CHOPCONF_t chopconf{0};
  153. chopconf.tbl = 0b01;
  154. chopconf.toff = chop_init.toff;
  155. chopconf.intpol = interpolate;
  156. chopconf.hend = chop_init.hend + 3;
  157. chopconf.hstrt = chop_init.hstrt - 1;
  158. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  159. st.CHOPCONF(chopconf.sr);
  160. st.rms_current(mA, HOLD_MULTIPLIER);
  161. st.microsteps(microsteps);
  162. st.iholddelay(10);
  163. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  164. st.en_pwm_mode(stealth);
  165. st.stored.stealthChop_enabled = stealth;
  166. TMC2160_n::PWMCONF_t pwmconf{0};
  167. pwmconf.pwm_lim = 12;
  168. pwmconf.pwm_reg = 8;
  169. pwmconf.pwm_autograd = true;
  170. pwmconf.pwm_autoscale = true;
  171. pwmconf.pwm_freq = 0b01;
  172. pwmconf.pwm_grad = 14;
  173. pwmconf.pwm_ofs = 36;
  174. st.PWMCONF(pwmconf.sr);
  175. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  176. st.GSTAT(); // Clear GSTAT
  177. }
  178. #endif // TMC2160
  179. //
  180. // TMC2208/2209 Driver objects and inits
  181. //
  182. #if HAS_TMC220x
  183. #if AXIS_HAS_UART(X)
  184. #ifdef X_HARDWARE_SERIAL
  185. TMC_UART_DEFINE(HW, X, X);
  186. #define X_HAS_HW_SERIAL 1
  187. #else
  188. TMC_UART_DEFINE(SW, X, X);
  189. #define X_HAS_SW_SERIAL 1
  190. #endif
  191. #endif
  192. #if AXIS_HAS_UART(X2)
  193. #ifdef X2_HARDWARE_SERIAL
  194. TMC_UART_DEFINE(HW, X2, X);
  195. #define X2_HAS_HW_SERIAL 1
  196. #else
  197. TMC_UART_DEFINE(SW, X2, X);
  198. #define X2_HAS_SW_SERIAL 1
  199. #endif
  200. #endif
  201. #if AXIS_HAS_UART(Y)
  202. #ifdef Y_HARDWARE_SERIAL
  203. TMC_UART_DEFINE(HW, Y, Y);
  204. #define Y_HAS_HW_SERIAL 1
  205. #else
  206. TMC_UART_DEFINE(SW, Y, Y);
  207. #define Y_HAS_SW_SERIAL 1
  208. #endif
  209. #endif
  210. #if AXIS_HAS_UART(Y2)
  211. #ifdef Y2_HARDWARE_SERIAL
  212. TMC_UART_DEFINE(HW, Y2, Y);
  213. #define Y2_HAS_HW_SERIAL 1
  214. #else
  215. TMC_UART_DEFINE(SW, Y2, Y);
  216. #define Y2_HAS_SW_SERIAL 1
  217. #endif
  218. #endif
  219. #if AXIS_HAS_UART(Z)
  220. #ifdef Z_HARDWARE_SERIAL
  221. TMC_UART_DEFINE(HW, Z, Z);
  222. #define Z_HAS_HW_SERIAL 1
  223. #else
  224. TMC_UART_DEFINE(SW, Z, Z);
  225. #define Z_HAS_SW_SERIAL 1
  226. #endif
  227. #endif
  228. #if AXIS_HAS_UART(Z2)
  229. #ifdef Z2_HARDWARE_SERIAL
  230. TMC_UART_DEFINE(HW, Z2, Z);
  231. #define Z2_HAS_HW_SERIAL 1
  232. #else
  233. TMC_UART_DEFINE(SW, Z2, Z);
  234. #define Z2_HAS_SW_SERIAL 1
  235. #endif
  236. #endif
  237. #if AXIS_HAS_UART(Z3)
  238. #ifdef Z3_HARDWARE_SERIAL
  239. TMC_UART_DEFINE(HW, Z3, Z);
  240. #define Z3_HAS_HW_SERIAL 1
  241. #else
  242. TMC_UART_DEFINE(SW, Z3, Z);
  243. #define Z3_HAS_SW_SERIAL 1
  244. #endif
  245. #endif
  246. #if AXIS_HAS_UART(Z4)
  247. #ifdef Z4_HARDWARE_SERIAL
  248. TMC_UART_DEFINE(HW, Z4, Z);
  249. #define Z4_HAS_HW_SERIAL 1
  250. #else
  251. TMC_UART_DEFINE(SW, Z4, Z);
  252. #define Z4_HAS_SW_SERIAL 1
  253. #endif
  254. #endif
  255. #if AXIS_HAS_UART(E0)
  256. #ifdef E0_HARDWARE_SERIAL
  257. TMC_UART_DEFINE_E(HW, 0);
  258. #define E0_HAS_HW_SERIAL 1
  259. #else
  260. TMC_UART_DEFINE_E(SW, 0);
  261. #define E0_HAS_SW_SERIAL 1
  262. #endif
  263. #endif
  264. #if AXIS_HAS_UART(E1)
  265. #ifdef E1_HARDWARE_SERIAL
  266. TMC_UART_DEFINE_E(HW, 1);
  267. #define E1_HAS_HW_SERIAL 1
  268. #else
  269. TMC_UART_DEFINE_E(SW, 1);
  270. #define E1_HAS_SW_SERIAL 1
  271. #endif
  272. #endif
  273. #if AXIS_HAS_UART(E2)
  274. #ifdef E2_HARDWARE_SERIAL
  275. TMC_UART_DEFINE_E(HW, 2);
  276. #define E2_HAS_HW_SERIAL 1
  277. #else
  278. TMC_UART_DEFINE_E(SW, 2);
  279. #define E2_HAS_SW_SERIAL 1
  280. #endif
  281. #endif
  282. #if AXIS_HAS_UART(E3)
  283. #ifdef E3_HARDWARE_SERIAL
  284. TMC_UART_DEFINE_E(HW, 3);
  285. #define E3_HAS_HW_SERIAL 1
  286. #else
  287. TMC_UART_DEFINE_E(SW, 3);
  288. #define E3_HAS_SW_SERIAL 1
  289. #endif
  290. #endif
  291. #if AXIS_HAS_UART(E4)
  292. #ifdef E4_HARDWARE_SERIAL
  293. TMC_UART_DEFINE_E(HW, 4);
  294. #define E4_HAS_HW_SERIAL 1
  295. #else
  296. TMC_UART_DEFINE_E(SW, 4);
  297. #define E4_HAS_SW_SERIAL 1
  298. #endif
  299. #endif
  300. #if AXIS_HAS_UART(E5)
  301. #ifdef E5_HARDWARE_SERIAL
  302. TMC_UART_DEFINE_E(HW, 5);
  303. #define E5_HAS_HW_SERIAL 1
  304. #else
  305. TMC_UART_DEFINE_E(SW, 5);
  306. #define E5_HAS_SW_SERIAL 1
  307. #endif
  308. #endif
  309. #if AXIS_HAS_UART(E6)
  310. #ifdef E6_HARDWARE_SERIAL
  311. TMC_UART_DEFINE_E(HW, 6);
  312. #define E6_HAS_HW_SERIAL 1
  313. #else
  314. TMC_UART_DEFINE_E(SW, 6);
  315. #define E6_HAS_SW_SERIAL 1
  316. #endif
  317. #endif
  318. #if AXIS_HAS_UART(E7)
  319. #ifdef E7_HARDWARE_SERIAL
  320. TMC_UART_DEFINE_E(HW, 7);
  321. #define E7_HAS_HW_SERIAL 1
  322. #else
  323. TMC_UART_DEFINE_E(SW, 7);
  324. #define E7_HAS_SW_SERIAL 1
  325. #endif
  326. #endif
  327. enum TMCAxis : uint8_t { LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7, TOTAL };
  328. void tmc_serial_begin() {
  329. #if HAS_TMC_HW_SERIAL
  330. struct {
  331. const void *ptr[TMCAxis::TOTAL];
  332. bool began(const TMCAxis a, const void * const p) {
  333. LOOP_L_N(i, a) if (p == ptr[i]) return true;
  334. ptr[a] = p; return false;
  335. };
  336. } sp_helper;
  337. #define HW_SERIAL_BEGIN(A) do{ if (!sp_helper.began(TMCAxis::A, &A##_HARDWARE_SERIAL)) \
  338. A##_HARDWARE_SERIAL.begin(TMC_BAUD_RATE); }while(0)
  339. #endif
  340. #if AXIS_HAS_UART(X)
  341. #ifdef X_HARDWARE_SERIAL
  342. HW_SERIAL_BEGIN(X);
  343. #else
  344. stepperX.beginSerial(TMC_BAUD_RATE);
  345. #endif
  346. #endif
  347. #if AXIS_HAS_UART(X2)
  348. #ifdef X2_HARDWARE_SERIAL
  349. HW_SERIAL_BEGIN(X2);
  350. #else
  351. stepperX2.beginSerial(TMC_BAUD_RATE);
  352. #endif
  353. #endif
  354. #if AXIS_HAS_UART(Y)
  355. #ifdef Y_HARDWARE_SERIAL
  356. HW_SERIAL_BEGIN(Y);
  357. #else
  358. stepperY.beginSerial(TMC_BAUD_RATE);
  359. #endif
  360. #endif
  361. #if AXIS_HAS_UART(Y2)
  362. #ifdef Y2_HARDWARE_SERIAL
  363. HW_SERIAL_BEGIN(Y2);
  364. #else
  365. stepperY2.beginSerial(TMC_BAUD_RATE);
  366. #endif
  367. #endif
  368. #if AXIS_HAS_UART(Z)
  369. #ifdef Z_HARDWARE_SERIAL
  370. HW_SERIAL_BEGIN(Z);
  371. #else
  372. stepperZ.beginSerial(TMC_BAUD_RATE);
  373. #endif
  374. #endif
  375. #if AXIS_HAS_UART(Z2)
  376. #ifdef Z2_HARDWARE_SERIAL
  377. HW_SERIAL_BEGIN(Z2);
  378. #else
  379. stepperZ2.beginSerial(TMC_BAUD_RATE);
  380. #endif
  381. #endif
  382. #if AXIS_HAS_UART(Z3)
  383. #ifdef Z3_HARDWARE_SERIAL
  384. HW_SERIAL_BEGIN(Z3);
  385. #else
  386. stepperZ3.beginSerial(TMC_BAUD_RATE);
  387. #endif
  388. #endif
  389. #if AXIS_HAS_UART(Z4)
  390. #ifdef Z4_HARDWARE_SERIAL
  391. HW_SERIAL_BEGIN(Z4);
  392. #else
  393. stepperZ4.beginSerial(TMC_BAUD_RATE);
  394. #endif
  395. #endif
  396. #if AXIS_HAS_UART(E0)
  397. #ifdef E0_HARDWARE_SERIAL
  398. HW_SERIAL_BEGIN(E0);
  399. #else
  400. stepperE0.beginSerial(TMC_BAUD_RATE);
  401. #endif
  402. #endif
  403. #if AXIS_HAS_UART(E1)
  404. #ifdef E1_HARDWARE_SERIAL
  405. HW_SERIAL_BEGIN(E1);
  406. #else
  407. stepperE1.beginSerial(TMC_BAUD_RATE);
  408. #endif
  409. #endif
  410. #if AXIS_HAS_UART(E2)
  411. #ifdef E2_HARDWARE_SERIAL
  412. HW_SERIAL_BEGIN(E2);
  413. #else
  414. stepperE2.beginSerial(TMC_BAUD_RATE);
  415. #endif
  416. #endif
  417. #if AXIS_HAS_UART(E3)
  418. #ifdef E3_HARDWARE_SERIAL
  419. HW_SERIAL_BEGIN(E3);
  420. #else
  421. stepperE3.beginSerial(TMC_BAUD_RATE);
  422. #endif
  423. #endif
  424. #if AXIS_HAS_UART(E4)
  425. #ifdef E4_HARDWARE_SERIAL
  426. HW_SERIAL_BEGIN(E4);
  427. #else
  428. stepperE4.beginSerial(TMC_BAUD_RATE);
  429. #endif
  430. #endif
  431. #if AXIS_HAS_UART(E5)
  432. #ifdef E5_HARDWARE_SERIAL
  433. HW_SERIAL_BEGIN(E5);
  434. #else
  435. stepperE5.beginSerial(TMC_BAUD_RATE);
  436. #endif
  437. #endif
  438. #if AXIS_HAS_UART(E6)
  439. #ifdef E6_HARDWARE_SERIAL
  440. HW_SERIAL_BEGIN(E6);
  441. #else
  442. stepperE6.beginSerial(TMC_BAUD_RATE);
  443. #endif
  444. #endif
  445. #if AXIS_HAS_UART(E7)
  446. #ifdef E7_HARDWARE_SERIAL
  447. HW_SERIAL_BEGIN(E7);
  448. #else
  449. stepperE7.beginSerial(TMC_BAUD_RATE);
  450. #endif
  451. #endif
  452. }
  453. #endif
  454. #if HAS_DRIVER(TMC2208)
  455. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  456. void tmc_init(TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
  457. TMC2208_n::GCONF_t gconf{0};
  458. gconf.pdn_disable = true; // Use UART
  459. gconf.mstep_reg_select = true; // Select microsteps with UART
  460. gconf.i_scale_analog = false;
  461. gconf.en_spreadcycle = !stealth;
  462. st.GCONF(gconf.sr);
  463. st.stored.stealthChop_enabled = stealth;
  464. TMC2208_n::CHOPCONF_t chopconf{0};
  465. chopconf.tbl = 0b01; // blank_time = 24
  466. chopconf.toff = chop_init.toff;
  467. chopconf.intpol = interpolate;
  468. chopconf.hend = chop_init.hend + 3;
  469. chopconf.hstrt = chop_init.hstrt - 1;
  470. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  471. st.CHOPCONF(chopconf.sr);
  472. st.rms_current(mA, HOLD_MULTIPLIER);
  473. st.microsteps(microsteps);
  474. st.iholddelay(10);
  475. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  476. TMC2208_n::PWMCONF_t pwmconf{0};
  477. pwmconf.pwm_lim = 12;
  478. pwmconf.pwm_reg = 8;
  479. pwmconf.pwm_autograd = true;
  480. pwmconf.pwm_autoscale = true;
  481. pwmconf.pwm_freq = 0b01;
  482. pwmconf.pwm_grad = 14;
  483. pwmconf.pwm_ofs = 36;
  484. st.PWMCONF(pwmconf.sr);
  485. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  486. st.GSTAT(0b111); // Clear
  487. delay(200);
  488. }
  489. #endif // TMC2208
  490. #if HAS_DRIVER(TMC2209)
  491. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  492. void tmc_init(TMCMarlin<TMC2209Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
  493. TMC2208_n::GCONF_t gconf{0};
  494. gconf.pdn_disable = true; // Use UART
  495. gconf.mstep_reg_select = true; // Select microsteps with UART
  496. gconf.i_scale_analog = false;
  497. gconf.en_spreadcycle = !stealth;
  498. st.GCONF(gconf.sr);
  499. st.stored.stealthChop_enabled = stealth;
  500. TMC2208_n::CHOPCONF_t chopconf{0};
  501. chopconf.tbl = 0b01; // blank_time = 24
  502. chopconf.toff = chop_init.toff;
  503. chopconf.intpol = interpolate;
  504. chopconf.hend = chop_init.hend + 3;
  505. chopconf.hstrt = chop_init.hstrt - 1;
  506. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  507. st.CHOPCONF(chopconf.sr);
  508. st.rms_current(mA, HOLD_MULTIPLIER);
  509. st.microsteps(microsteps);
  510. st.iholddelay(10);
  511. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  512. TMC2208_n::PWMCONF_t pwmconf{0};
  513. pwmconf.pwm_lim = 12;
  514. pwmconf.pwm_reg = 8;
  515. pwmconf.pwm_autograd = true;
  516. pwmconf.pwm_autoscale = true;
  517. pwmconf.pwm_freq = 0b01;
  518. pwmconf.pwm_grad = 14;
  519. pwmconf.pwm_ofs = 36;
  520. st.PWMCONF(pwmconf.sr);
  521. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  522. st.GSTAT(0b111); // Clear
  523. delay(200);
  524. }
  525. #endif // TMC2209
  526. #if HAS_DRIVER(TMC2660)
  527. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  528. void tmc_init(TMCMarlin<TMC2660Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t, const bool, const chopper_timing_t &chop_init, const bool interpolate) {
  529. st.begin();
  530. TMC2660_n::CHOPCONF_t chopconf{0};
  531. chopconf.tbl = 0b01;
  532. chopconf.toff = chop_init.toff;
  533. chopconf.hend = chop_init.hend + 3;
  534. chopconf.hstrt = chop_init.hstrt - 1;
  535. st.CHOPCONF(chopconf.sr);
  536. st.sdoff(0);
  537. st.rms_current(mA);
  538. st.microsteps(microsteps);
  539. TERN_(SQUARE_WAVE_STEPPING, st.dedge(true));
  540. st.intpol(interpolate);
  541. st.diss2g(true); // Disable short to ground protection. Too many false readings?
  542. TERN_(TMC_DEBUG, st.rdsel(0b01));
  543. }
  544. #endif // TMC2660
  545. #if HAS_DRIVER(TMC5130)
  546. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  547. void tmc_init(TMCMarlin<TMC5130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
  548. st.begin();
  549. CHOPCONF_t chopconf{0};
  550. chopconf.tbl = 0b01;
  551. chopconf.toff = chop_init.toff;
  552. chopconf.intpol = interpolate;
  553. chopconf.hend = chop_init.hend + 3;
  554. chopconf.hstrt = chop_init.hstrt - 1;
  555. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  556. st.CHOPCONF(chopconf.sr);
  557. st.rms_current(mA, HOLD_MULTIPLIER);
  558. st.microsteps(microsteps);
  559. st.iholddelay(10);
  560. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  561. st.en_pwm_mode(stealth);
  562. st.stored.stealthChop_enabled = stealth;
  563. PWMCONF_t pwmconf{0};
  564. pwmconf.pwm_freq = 0b01; // f_pwm = 2/683 f_clk
  565. pwmconf.pwm_autoscale = true;
  566. pwmconf.pwm_grad = 5;
  567. pwmconf.pwm_ampl = 180;
  568. st.PWMCONF(pwmconf.sr);
  569. TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
  570. st.GSTAT(); // Clear GSTAT
  571. }
  572. #endif // TMC5130
  573. #if HAS_DRIVER(TMC5160)
  574. template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
  575. void tmc_init(TMCMarlin<TMC5160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
  576. st.begin();
  577. CHOPCONF_t chopconf{0};
  578. chopconf.tbl = 0b01;
  579. chopconf.toff = chop_init.toff;
  580. chopconf.intpol = interpolate;
  581. chopconf.hend = chop_init.hend + 3;
  582. chopconf.hstrt = chop_init.hstrt - 1;
  583. TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
  584. st.CHOPCONF(chopconf.sr);
  585. st.rms_current(mA, HOLD_MULTIPLIER);
  586. st.microsteps(microsteps);
  587. st.iholddelay(10);
  588. st.TPOWERDOWN(128); // ~2s until driver lowers to hold current
  589. st.en_pwm_mode(stealth);
  590. st.stored.stealthChop_enabled = stealth;
  591. TMC2160_n::PWMCONF_t pwmconf{0};
  592. pwmconf.pwm_lim = 12;
  593. pwmconf.pwm_reg = 8;
  594. pwmconf.pwm_autograd = true;
  595. pwmconf.pwm_autoscale = true;
  596. pwmconf.pwm_freq = 0b01;
  597. pwmconf.pwm_grad = 14;
  598. pwmconf.pwm_ofs = 36;
  599. st.PWMCONF(pwmconf.sr);
  600. #if ENABLED(HYBRID_THRESHOLD)
  601. st.set_pwm_thrs(hyb_thrs);
  602. #else
  603. UNUSED(hyb_thrs);
  604. #endif
  605. st.GSTAT(); // Clear GSTAT
  606. }
  607. #endif // TMC5160
  608. void restore_trinamic_drivers() {
  609. #if AXIS_IS_TMC(X)
  610. stepperX.push();
  611. #endif
  612. #if AXIS_IS_TMC(X2)
  613. stepperX2.push();
  614. #endif
  615. #if AXIS_IS_TMC(Y)
  616. stepperY.push();
  617. #endif
  618. #if AXIS_IS_TMC(Y2)
  619. stepperY2.push();
  620. #endif
  621. #if AXIS_IS_TMC(Z)
  622. stepperZ.push();
  623. #endif
  624. #if AXIS_IS_TMC(Z2)
  625. stepperZ2.push();
  626. #endif
  627. #if AXIS_IS_TMC(Z3)
  628. stepperZ3.push();
  629. #endif
  630. #if AXIS_IS_TMC(Z4)
  631. stepperZ4.push();
  632. #endif
  633. #if AXIS_IS_TMC(E0)
  634. stepperE0.push();
  635. #endif
  636. #if AXIS_IS_TMC(E1)
  637. stepperE1.push();
  638. #endif
  639. #if AXIS_IS_TMC(E2)
  640. stepperE2.push();
  641. #endif
  642. #if AXIS_IS_TMC(E3)
  643. stepperE3.push();
  644. #endif
  645. #if AXIS_IS_TMC(E4)
  646. stepperE4.push();
  647. #endif
  648. #if AXIS_IS_TMC(E5)
  649. stepperE5.push();
  650. #endif
  651. #if AXIS_IS_TMC(E6)
  652. stepperE6.push();
  653. #endif
  654. #if AXIS_IS_TMC(E7)
  655. stepperE7.push();
  656. #endif
  657. }
  658. void reset_trinamic_drivers() {
  659. static constexpr bool stealthchop_by_axis[] = LOGICAL_AXIS_ARRAY(
  660. ENABLED(STEALTHCHOP_E),
  661. ENABLED(STEALTHCHOP_XY),
  662. ENABLED(STEALTHCHOP_XY),
  663. ENABLED(STEALTHCHOP_Z)
  664. );
  665. #if AXIS_IS_TMC(X)
  666. TMC_INIT(X, STEALTH_AXIS_X);
  667. #endif
  668. #if AXIS_IS_TMC(X2)
  669. TMC_INIT(X2, STEALTH_AXIS_X);
  670. #endif
  671. #if AXIS_IS_TMC(Y)
  672. TMC_INIT(Y, STEALTH_AXIS_Y);
  673. #endif
  674. #if AXIS_IS_TMC(Y2)
  675. TMC_INIT(Y2, STEALTH_AXIS_Y);
  676. #endif
  677. #if AXIS_IS_TMC(Z)
  678. TMC_INIT(Z, STEALTH_AXIS_Z);
  679. #endif
  680. #if AXIS_IS_TMC(Z2)
  681. TMC_INIT(Z2, STEALTH_AXIS_Z);
  682. #endif
  683. #if AXIS_IS_TMC(Z3)
  684. TMC_INIT(Z3, STEALTH_AXIS_Z);
  685. #endif
  686. #if AXIS_IS_TMC(Z4)
  687. TMC_INIT(Z4, STEALTH_AXIS_Z);
  688. #endif
  689. #if AXIS_IS_TMC(E0)
  690. TMC_INIT(E0, STEALTH_AXIS_E);
  691. #endif
  692. #if AXIS_IS_TMC(E1)
  693. TMC_INIT(E1, STEALTH_AXIS_E);
  694. #endif
  695. #if AXIS_IS_TMC(E2)
  696. TMC_INIT(E2, STEALTH_AXIS_E);
  697. #endif
  698. #if AXIS_IS_TMC(E3)
  699. TMC_INIT(E3, STEALTH_AXIS_E);
  700. #endif
  701. #if AXIS_IS_TMC(E4)
  702. TMC_INIT(E4, STEALTH_AXIS_E);
  703. #endif
  704. #if AXIS_IS_TMC(E5)
  705. TMC_INIT(E5, STEALTH_AXIS_E);
  706. #endif
  707. #if AXIS_IS_TMC(E6)
  708. TMC_INIT(E6, STEALTH_AXIS_E);
  709. #endif
  710. #if AXIS_IS_TMC(E7)
  711. TMC_INIT(E7, STEALTH_AXIS_E);
  712. #endif
  713. #if USE_SENSORLESS
  714. #if X_SENSORLESS
  715. stepperX.homing_threshold(X_STALL_SENSITIVITY);
  716. #if AXIS_HAS_STALLGUARD(X2)
  717. stepperX2.homing_threshold(CAT(TERN(X2_SENSORLESS, X2, X), _STALL_SENSITIVITY));
  718. #endif
  719. #endif
  720. #if Y_SENSORLESS
  721. stepperY.homing_threshold(Y_STALL_SENSITIVITY);
  722. #if AXIS_HAS_STALLGUARD(Y2)
  723. stepperY2.homing_threshold(CAT(TERN(Y2_SENSORLESS, Y2, Y), _STALL_SENSITIVITY));
  724. #endif
  725. #endif
  726. #if Z_SENSORLESS
  727. stepperZ.homing_threshold(Z_STALL_SENSITIVITY);
  728. #if AXIS_HAS_STALLGUARD(Z2)
  729. stepperZ2.homing_threshold(CAT(TERN(Z2_SENSORLESS, Z2, Z), _STALL_SENSITIVITY));
  730. #endif
  731. #if AXIS_HAS_STALLGUARD(Z3)
  732. stepperZ3.homing_threshold(CAT(TERN(Z3_SENSORLESS, Z3, Z), _STALL_SENSITIVITY));
  733. #endif
  734. #if AXIS_HAS_STALLGUARD(Z4)
  735. stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY));
  736. #endif
  737. #endif
  738. #endif // USE SENSORLESS
  739. #ifdef TMC_ADV
  740. TMC_ADV()
  741. #endif
  742. stepper.set_directions();
  743. }
  744. // TMC Slave Address Conflict Detection
  745. //
  746. // Conflict detection is performed in the following way. Similar methods are used for
  747. // hardware and software serial, but the implementations are indepenent.
  748. //
  749. // 1. Populate a data structure with UART parameters and addresses for all possible axis.
  750. // If an axis is not in use, populate it with recognizable placeholder data.
  751. // 2. For each axis in use, static_assert using a constexpr function, which counts the
  752. // number of matching/conflicting axis. If the value is not exactly 1, fail.
  753. #if ANY_AXIS_HAS(HW_SERIAL)
  754. // Hardware serial names are compared as strings, since actually resolving them cannot occur in a constexpr.
  755. // Using a fixed-length character array for the port name allows this to be constexpr compatible.
  756. struct SanityHwSerialDetails { const char port[20]; uint32_t address; };
  757. #define TMC_HW_DETAIL_ARGS(A) TERN(A##_HAS_HW_SERIAL, STRINGIFY(A##_HARDWARE_SERIAL), ""), TERN0(A##_HAS_HW_SERIAL, A##_SLAVE_ADDRESS)
  758. #define TMC_HW_DETAIL(A) {TMC_HW_DETAIL_ARGS(A)}
  759. constexpr SanityHwSerialDetails sanity_tmc_hw_details[] = {
  760. TMC_HW_DETAIL(X), TMC_HW_DETAIL(X2),
  761. TMC_HW_DETAIL(Y), TMC_HW_DETAIL(Y2),
  762. TMC_HW_DETAIL(Z), TMC_HW_DETAIL(Z2), TMC_HW_DETAIL(Z3), TMC_HW_DETAIL(Z4),
  763. TMC_HW_DETAIL(E0), TMC_HW_DETAIL(E1), TMC_HW_DETAIL(E2), TMC_HW_DETAIL(E3), TMC_HW_DETAIL(E4), TMC_HW_DETAIL(E5), TMC_HW_DETAIL(E6), TMC_HW_DETAIL(E7)
  764. };
  765. // constexpr compatible string comparison
  766. constexpr bool str_eq_ce(const char * a, const char * b) {
  767. return *a == *b && (*a == '\0' || str_eq_ce(a+1,b+1));
  768. }
  769. constexpr bool sc_hw_done(size_t start, size_t end) { return start == end; }
  770. constexpr bool sc_hw_skip(const char *port_name) { return !(*port_name); }
  771. constexpr bool sc_hw_match(const char *port_name, uint32_t address, size_t start, size_t end) {
  772. return !sc_hw_done(start, end) && !sc_hw_skip(port_name) && (address == sanity_tmc_hw_details[start].address && str_eq_ce(port_name, sanity_tmc_hw_details[start].port));
  773. }
  774. constexpr int count_tmc_hw_serial_matches(const char *port_name, uint32_t address, size_t start, size_t end) {
  775. return sc_hw_done(start, end) ? 0 : ((sc_hw_skip(port_name) ? 0 : (sc_hw_match(port_name, address, start, end) ? 1 : 0)) + count_tmc_hw_serial_matches(port_name, address, start + 1, end));
  776. }
  777. #define TMC_HWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_HARDWARE_SERIAL"
  778. #define SA_NO_TMC_HW_C(A) static_assert(1 >= count_tmc_hw_serial_matches(TMC_HW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_hw_details)), TMC_HWSERIAL_CONFLICT_MSG(A));
  779. SA_NO_TMC_HW_C(X);SA_NO_TMC_HW_C(X2);
  780. SA_NO_TMC_HW_C(Y);SA_NO_TMC_HW_C(Y2);
  781. SA_NO_TMC_HW_C(Z);SA_NO_TMC_HW_C(Z2);SA_NO_TMC_HW_C(Z3);SA_NO_TMC_HW_C(Z4);
  782. SA_NO_TMC_HW_C(E0);SA_NO_TMC_HW_C(E1);SA_NO_TMC_HW_C(E2);SA_NO_TMC_HW_C(E3);SA_NO_TMC_HW_C(E4);SA_NO_TMC_HW_C(E5);SA_NO_TMC_HW_C(E6);SA_NO_TMC_HW_C(E7);
  783. #endif
  784. #if ANY_AXIS_HAS(SW_SERIAL)
  785. struct SanitySwSerialDetails { int32_t txpin; int32_t rxpin; uint32_t address; };
  786. #define TMC_SW_DETAIL_ARGS(A) TERN(A##_HAS_SW_SERIAL, A##_SERIAL_TX_PIN, -1), TERN(A##_HAS_SW_SERIAL, A##_SERIAL_RX_PIN, -1), TERN0(A##_HAS_SW_SERIAL, A##_SLAVE_ADDRESS)
  787. #define TMC_SW_DETAIL(A) TMC_SW_DETAIL_ARGS(A)
  788. constexpr SanitySwSerialDetails sanity_tmc_sw_details[] = {
  789. TMC_SW_DETAIL(X), TMC_SW_DETAIL(X2),
  790. TMC_SW_DETAIL(Y), TMC_SW_DETAIL(Y2),
  791. TMC_SW_DETAIL(Z), TMC_SW_DETAIL(Z2), TMC_SW_DETAIL(Z3), TMC_SW_DETAIL(Z4),
  792. TMC_SW_DETAIL(E0), TMC_SW_DETAIL(E1), TMC_SW_DETAIL(E2), TMC_SW_DETAIL(E3), TMC_SW_DETAIL(E4), TMC_SW_DETAIL(E5), TMC_SW_DETAIL(E6), TMC_SW_DETAIL(E7)
  793. };
  794. constexpr bool sc_sw_done(size_t start, size_t end) { return start == end; }
  795. constexpr bool sc_sw_skip(int32_t txpin) { return txpin < 0; }
  796. constexpr bool sc_sw_match(int32_t txpin, int32_t rxpin, uint32_t address, size_t start, size_t end) {
  797. return !sc_sw_done(start, end) && !sc_sw_skip(txpin) && (txpin == sanity_tmc_sw_details[start].txpin || rxpin == sanity_tmc_sw_details[start].rxpin) && (address == sanity_tmc_sw_details[start].address);
  798. }
  799. constexpr int count_tmc_sw_serial_matches(int32_t txpin, int32_t rxpin, uint32_t address, size_t start, size_t end) {
  800. return sc_sw_done(start, end) ? 0 : ((sc_sw_skip(txpin) ? 0 : (sc_sw_match(txpin, rxpin, address, start, end) ? 1 : 0)) + count_tmc_sw_serial_matches(txpin, rxpin, address, start + 1, end));
  801. }
  802. #define TMC_SWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_SERIAL_RX_PIN or " STRINGIFY(A) "_SERIAL_TX_PIN"
  803. #define SA_NO_TMC_SW_C(A) static_assert(1 >= count_tmc_sw_serial_matches(TMC_SW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_sw_details)), TMC_SWSERIAL_CONFLICT_MSG(A));
  804. SA_NO_TMC_SW_C(X);SA_NO_TMC_SW_C(X2);
  805. SA_NO_TMC_SW_C(Y);SA_NO_TMC_SW_C(Y2);
  806. SA_NO_TMC_SW_C(Z);SA_NO_TMC_SW_C(Z2);SA_NO_TMC_SW_C(Z3);SA_NO_TMC_SW_C(Z4);
  807. SA_NO_TMC_SW_C(E0);SA_NO_TMC_SW_C(E1);SA_NO_TMC_SW_C(E2);SA_NO_TMC_SW_C(E3);SA_NO_TMC_SW_C(E4);SA_NO_TMC_SW_C(E5);SA_NO_TMC_SW_C(E6);SA_NO_TMC_SW_C(E7);
  808. #endif
  809. #endif // HAS_TRINAMIC_CONFIG