My Marlin configs for Fabrikator Mini and CTC i3 Pro B
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

tmc_util.cpp 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "../inc/MarlinConfig.h"
  23. #if HAS_TRINAMIC
  24. #include "tmc_util.h"
  25. #include "../Marlin.h"
  26. #include "../module/stepper_indirection.h"
  27. #include "../module/printcounter.h"
  28. #include "../libs/duration_t.h"
  29. #include "../gcode/gcode.h"
  30. template<typename TMC>
  31. void tmc_get_current(TMC &st, const char name[]) {
  32. SERIAL_ECHO(name);
  33. SERIAL_ECHOPGM(" axis driver current: ");
  34. SERIAL_ECHOLN(st.getCurrent());
  35. }
  36. template<typename TMC>
  37. void tmc_set_current(TMC &st, const char name[], const int mA) {
  38. st.setCurrent(mA, R_SENSE, HOLD_MULTIPLIER);
  39. tmc_get_current(st, name);
  40. }
  41. template<typename TMC>
  42. void tmc_report_otpw(TMC &st, const char name[]) {
  43. SERIAL_ECHO(name);
  44. SERIAL_ECHOPGM(" axis temperature prewarn triggered: ");
  45. serialprintPGM(st.getOTPW() ? PSTR("true") : PSTR("false"));
  46. SERIAL_EOL();
  47. }
  48. template<typename TMC>
  49. void tmc_clear_otpw(TMC &st, const char name[]) {
  50. st.clear_otpw();
  51. SERIAL_ECHO(name);
  52. SERIAL_ECHOLNPGM(" prewarn flag cleared");
  53. }
  54. template<typename TMC>
  55. void tmc_get_pwmthrs(TMC &st, const char name[], const uint16_t spmm) {
  56. SERIAL_ECHO(name);
  57. SERIAL_ECHOPGM(" stealthChop max speed set to ");
  58. SERIAL_ECHOLN(12650000UL * st.microsteps() / (256 * st.TPWMTHRS() * spmm));
  59. }
  60. template<typename TMC>
  61. void tmc_set_pwmthrs(TMC &st, const char name[], const int32_t thrs, const uint32_t spmm) {
  62. st.TPWMTHRS(12650000UL * st.microsteps() / (256 * thrs * spmm));
  63. tmc_get_pwmthrs(st, name, spmm);
  64. }
  65. template<typename TMC>
  66. void tmc_get_sgt(TMC &st, const char name[]) {
  67. SERIAL_ECHO(name);
  68. SERIAL_ECHOPGM(" driver homing sensitivity set to ");
  69. MYSERIAL.println(st.sgt(), DEC);
  70. }
  71. template<typename TMC>
  72. void tmc_set_sgt(TMC &st, const char name[], const int8_t sgt_val) {
  73. st.sgt(sgt_val);
  74. tmc_get_sgt(st, name);
  75. }
  76. /*
  77. * Check for over temperature or short to ground error flags.
  78. * Report and log warning of overtemperature condition.
  79. * Reduce driver current in a persistent otpw condition.
  80. * Keep track of otpw counter so we don't reduce current on a single instance,
  81. * and so we don't repeatedly report warning before the condition is cleared.
  82. */
  83. #if ENABLED(MONITOR_DRIVER_STATUS)
  84. struct TMC_driver_data {
  85. uint32_t drv_status;
  86. bool is_otpw;
  87. bool is_ot;
  88. bool is_error;
  89. };
  90. #if ENABLED(HAVE_TMC2130)
  91. static uint32_t get_pwm_scale(TMC2130Stepper &st) { return st.PWM_SCALE(); }
  92. static uint8_t get_status_response(TMC2130Stepper &st) { return st.status_response&0xF; }
  93. static TMC_driver_data get_driver_data(TMC2130Stepper &st) {
  94. constexpr uint32_t OTPW_bm = 0x4000000UL;
  95. constexpr uint8_t OTPW_bp = 26;
  96. constexpr uint32_t OT_bm = 0x2000000UL;
  97. constexpr uint8_t OT_bp = 25;
  98. constexpr uint8_t DRIVER_ERROR_bm = 0x2UL;
  99. constexpr uint8_t DRIVER_ERROR_bp = 1;
  100. TMC_driver_data data;
  101. data.drv_status = st.DRV_STATUS();
  102. data.is_otpw = (data.drv_status & OTPW_bm)>>OTPW_bp;
  103. data.is_ot = (data.drv_status & OT_bm)>>OT_bp;
  104. data.is_error = (st.status_response & DRIVER_ERROR_bm)>>DRIVER_ERROR_bp;
  105. return data;
  106. }
  107. #endif
  108. #if ENABLED(HAVE_TMC2208)
  109. static uint32_t get_pwm_scale(TMC2208Stepper &st) { return st.pwm_scale_sum(); }
  110. static uint8_t get_status_response(TMC2208Stepper &st) {
  111. uint32_t drv_status = st.DRV_STATUS();
  112. uint8_t gstat = st.GSTAT();
  113. uint8_t response = 0;
  114. response |= (drv_status >> (31-3)) & 0b1000;
  115. response |= gstat & 0b11;
  116. return response;
  117. }
  118. static TMC_driver_data get_driver_data(TMC2208Stepper &st) {
  119. constexpr uint32_t OTPW_bm = 0b1ul;
  120. constexpr uint8_t OTPW_bp = 0;
  121. constexpr uint32_t OT_bm = 0b10ul;
  122. constexpr uint8_t OT_bp = 1;
  123. TMC_driver_data data;
  124. data.drv_status = st.DRV_STATUS();
  125. data.is_otpw = (data.drv_status & OTPW_bm)>>OTPW_bp;
  126. data.is_ot = (data.drv_status & OT_bm)>>OT_bp;
  127. data.is_error = st.drv_err();
  128. return data;
  129. }
  130. #endif
  131. template<typename TMC>
  132. uint8_t monitor_tmc_driver(TMC &st, const char axisID, uint8_t otpw_cnt) {
  133. TMC_driver_data data = get_driver_data(st);
  134. #if ENABLED(STOP_ON_ERROR)
  135. if (data.is_error) {
  136. SERIAL_EOL();
  137. SERIAL_ECHO(axisID);
  138. SERIAL_ECHO(" driver error detected:");
  139. if (data.is_ot) SERIAL_ECHO("\novertemperature");
  140. if (st.s2ga()) SERIAL_ECHO("\nshort to ground (coil A)");
  141. if (st.s2gb()) SERIAL_ECHO("\nshort to ground (coil B)");
  142. SERIAL_EOL();
  143. #if ENABLED(TMC_DEBUG)
  144. _M122();
  145. #endif
  146. kill(PSTR("Driver error"));
  147. }
  148. #endif
  149. // Report if a warning was triggered
  150. if (data.is_otpw && otpw_cnt==0) {
  151. char timestamp[10];
  152. duration_t elapsed = print_job_timer.duration();
  153. const bool has_days = (elapsed.value > 60*60*24L);
  154. (void)elapsed.toDigital(timestamp, has_days);
  155. SERIAL_EOL();
  156. SERIAL_ECHO(timestamp);
  157. SERIAL_ECHOPGM(": ");
  158. SERIAL_ECHO(axisID);
  159. SERIAL_ECHOPGM(" driver overtemperature warning! (");
  160. SERIAL_ECHO(st.getCurrent());
  161. SERIAL_ECHOLN("mA)");
  162. }
  163. #if CURRENT_STEP_DOWN > 0
  164. // Decrease current if is_otpw is true and driver is enabled and there's been more then 4 warnings
  165. if (data.is_otpw && !st.isEnabled() && otpw_cnt > 4) {
  166. st.setCurrent(st.getCurrent() - CURRENT_STEP_DOWN, R_SENSE, HOLD_MULTIPLIER);
  167. #if ENABLED(REPORT_CURRENT_CHANGE)
  168. SERIAL_ECHO(axisID);
  169. SERIAL_ECHOLNPAIR(" current decreased to ", st.getCurrent());
  170. #endif
  171. }
  172. #endif
  173. if (data.is_otpw) {
  174. otpw_cnt++;
  175. st.flag_otpw = true;
  176. }
  177. else if (otpw_cnt>0) otpw_cnt--;
  178. if (report_tmc_status) {
  179. const uint32_t pwm_scale = get_pwm_scale(st);
  180. SERIAL_ECHO(axisID);
  181. SERIAL_ECHOPAIR(":", pwm_scale);
  182. SERIAL_ECHO(" |0b"); MYSERIAL.print(get_status_response(st), BIN);
  183. SERIAL_ECHO("| ");
  184. if (data.is_error) SERIAL_ECHO('E');
  185. else if (data.is_ot) SERIAL_ECHO('O');
  186. else if (data.is_otpw) SERIAL_ECHO('W');
  187. else if (otpw_cnt>0) MYSERIAL.print(otpw_cnt, DEC);
  188. else if (st.flag_otpw) SERIAL_ECHO('F');
  189. SERIAL_ECHO("\t");
  190. }
  191. return otpw_cnt;
  192. }
  193. #define HAS_HW_COMMS(ST) ENABLED(ST##_IS_TMC2130)|| (ENABLED(ST##_IS_TMC2208) && defined(ST##_HARDWARE_SERIAL))
  194. void monitor_tmc_driver() {
  195. static millis_t next_cOT = 0;
  196. if (ELAPSED(millis(), next_cOT)) {
  197. next_cOT = millis() + 500;
  198. #if HAS_HW_COMMS(X) || ENABLED(IS_TRAMS)
  199. static uint8_t x_otpw_cnt = 0;
  200. x_otpw_cnt = monitor_tmc_driver(stepperX, axis_codes[X_AXIS], x_otpw_cnt);
  201. #endif
  202. #if HAS_HW_COMMS(Y) || ENABLED(IS_TRAMS)
  203. static uint8_t y_otpw_cnt = 0;
  204. y_otpw_cnt = monitor_tmc_driver(stepperY, axis_codes[Y_AXIS], y_otpw_cnt);
  205. #endif
  206. #if HAS_HW_COMMS(Z) || ENABLED(IS_TRAMS)
  207. static uint8_t z_otpw_cnt = 0;
  208. z_otpw_cnt = monitor_tmc_driver(stepperZ, axis_codes[Z_AXIS], z_otpw_cnt);
  209. #endif
  210. #if HAS_HW_COMMS(X2)
  211. static uint8_t x2_otpw_cnt = 0;
  212. x2_otpw_cnt = monitor_tmc_driver(stepperX2, axis_codes[X_AXIS], x2_otpw_cnt);
  213. #endif
  214. #if HAS_HW_COMMS(Y2)
  215. static uint8_t y2_otpw_cnt = 0;
  216. y2_otpw_cnt = monitor_tmc_driver(stepperY2, axis_codes[Y_AXIS], y2_otpw_cnt);
  217. #endif
  218. #if HAS_HW_COMMS(Z2)
  219. static uint8_t z2_otpw_cnt = 0;
  220. z2_otpw_cnt = monitor_tmc_driver(stepperZ2, axis_codes[Z_AXIS], z2_otpw_cnt);
  221. #endif
  222. #if HAS_HW_COMMS(E0) || ENABLED(IS_TRAMS)
  223. static uint8_t e0_otpw_cnt = 0;
  224. e0_otpw_cnt = monitor_tmc_driver(stepperE0, axis_codes[E_AXIS], e0_otpw_cnt);
  225. #endif
  226. #if HAS_HW_COMMS(E1)
  227. static uint8_t e1_otpw_cnt = 0;
  228. e1_otpw_cnt = monitor_tmc_driver(stepperE1, axis_codes[E_AXIS], e1_otpw_cnt);
  229. #endif
  230. #if HAS_HW_COMMS(E2)
  231. static uint8_t e2_otpw_cnt = 0;
  232. e2_otpw_cnt = monitor_tmc_driver(stepperE2, axis_codes[E_AXIS], e2_otpw_cnt);
  233. #endif
  234. #if HAS_HW_COMMS(E3)
  235. static uint8_t e3_otpw_cnt = 0;
  236. e3_otpw_cnt = monitor_tmc_driver(stepperE3, axis_codes[E_AXIS], e3_otpw_cnt);
  237. #endif
  238. #if HAS_HW_COMMS(E4)
  239. static uint8_t e4_otpw_cnt = 0;
  240. e4_otpw_cnt = monitor_tmc_driver(stepperE4, axis_codes[E_AXIS], e4_otpw_cnt);
  241. #endif
  242. if (report_tmc_status) SERIAL_EOL();
  243. }
  244. }
  245. #endif // MONITOR_DRIVER_STATUS
  246. #endif // HAS_TRINAMIC