From 3df0d62725bf1f6292d26e3347c17df48a1f7505 Mon Sep 17 00:00:00 2001 From: Scott Lahteine <github@thinkyhead.com> Date: Tue, 9 Jan 2018 19:05:37 -0600 Subject: [PATCH] Updates to TMC support --- Marlin/Conditionals_post.h | 14 + Marlin/I2CPositionEncoder.h | 2 - Marlin/Marlin.h | 2 + Marlin/MarlinConfig.h | 1 - Marlin/Marlin_main.cpp | 710 ++++----------------------------- Marlin/SanityCheck.h | 40 +- Marlin/configuration_store.cpp | 56 ++- Marlin/serial.h | 18 +- Marlin/tmc_macros.h | 39 -- Marlin/tmc_util.cpp | 568 ++++++++++++++++++++++++++ Marlin/tmc_util.h | 103 +++++ 11 files changed, 811 insertions(+), 742 deletions(-) delete mode 100644 Marlin/tmc_macros.h create mode 100644 Marlin/tmc_util.cpp create mode 100644 Marlin/tmc_util.h diff --git a/Marlin/Conditionals_post.h b/Marlin/Conditionals_post.h index 9b69e1ffcbf..b288c34b0b0 100644 --- a/Marlin/Conditionals_post.h +++ b/Marlin/Conditionals_post.h @@ -635,6 +635,20 @@ #define HAS_E4_MICROSTEPS (PIN_EXISTS(E4_MS1)) #define HAS_SOLENOID_4 (PIN_EXISTS(SOL4)) + // Trinamic Stepper Drivers + #define HAS_TRINAMIC (ENABLED(HAVE_TMC2130) || ENABLED(HAVE_TMC2208) || ENABLED(IS_TRAMS)) + #define X_IS_TRINAMIC (ENABLED( X_IS_TMC2130) || ENABLED( X_IS_TMC2208) || ENABLED(IS_TRAMS)) + #define X2_IS_TRINAMIC (ENABLED(X2_IS_TMC2130) || ENABLED(X2_IS_TMC2208)) + #define Y_IS_TRINAMIC (ENABLED( Y_IS_TMC2130) || ENABLED( Y_IS_TMC2208) || ENABLED(IS_TRAMS)) + #define Y2_IS_TRINAMIC (ENABLED(Y2_IS_TMC2130) || ENABLED(Y2_IS_TMC2208)) + #define Z_IS_TRINAMIC (ENABLED( Z_IS_TMC2130) || ENABLED( Z_IS_TMC2208) || ENABLED(IS_TRAMS)) + #define Z2_IS_TRINAMIC (ENABLED(Z2_IS_TMC2130) || ENABLED(Z2_IS_TMC2208)) + #define E0_IS_TRINAMIC (ENABLED(E0_IS_TMC2130) || ENABLED(E0_IS_TMC2208) || ENABLED(IS_TRAMS)) + #define E1_IS_TRINAMIC (ENABLED(E1_IS_TMC2130) || ENABLED(E1_IS_TMC2208)) + #define E2_IS_TRINAMIC (ENABLED(E2_IS_TMC2130) || ENABLED(E2_IS_TMC2208)) + #define E3_IS_TRINAMIC (ENABLED(E3_IS_TMC2130) || ENABLED(E3_IS_TMC2208)) + #define E4_IS_TRINAMIC (ENABLED(E4_IS_TMC2130) || ENABLED(E4_IS_TMC2208)) + // Endstops and bed probe #define HAS_X_MIN (PIN_EXISTS(X_MIN) && !IS_X2_ENDSTOP(X,MIN) && !IS_Y2_ENDSTOP(X,MIN) && !IS_Z2_OR_PROBE(X,MIN)) #define HAS_X_MAX (PIN_EXISTS(X_MAX) && !IS_X2_ENDSTOP(X,MAX) && !IS_Y2_ENDSTOP(X,MAX) && !IS_Z2_OR_PROBE(X,MAX)) diff --git a/Marlin/I2CPositionEncoder.h b/Marlin/I2CPositionEncoder.h index 8380241855c..60c02928993 100644 --- a/Marlin/I2CPositionEncoder.h +++ b/Marlin/I2CPositionEncoder.h @@ -97,8 +97,6 @@ #define LOOP_PE(VAR) LOOP_L_N(VAR, I2CPE_ENCODER_CNT) #define CHECK_IDX() do{ if (!WITHIN(idx, 0, I2CPE_ENCODER_CNT - 1)) return; }while(0) - extern const char axis_codes[XYZE]; - typedef union { volatile int32_t val = 0; uint8_t bval[4]; diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 438c01f0884..308b9f8501e 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -59,6 +59,8 @@ void idle( void manage_inactivity(bool ignore_stepper_queue = false); +extern const char axis_codes[XYZE]; + #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE) extern bool extruder_duplication_enabled; #endif diff --git a/Marlin/MarlinConfig.h b/Marlin/MarlinConfig.h index fdab3d462ba..64e0bac51fd 100644 --- a/Marlin/MarlinConfig.h +++ b/Marlin/MarlinConfig.h @@ -29,7 +29,6 @@ #include "Version.h" #include "Configuration.h" #include "Conditionals_LCD.h" -#include "tmc_macros.h" #include "Configuration_adv.h" #include "pins.h" #ifndef USBCON diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index deb2bba6ff6..3110ab66095 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -305,6 +305,10 @@ #include <SPI.h> #endif +#if HAS_TRINAMIC + #include "tmc_util.h" +#endif + #if ENABLED(DAC_STEPPER_CURRENT) #include "stepper_dac.h" #endif @@ -2864,29 +2868,6 @@ static void do_homing_move(const AxisEnum axis, const float distance, const floa #endif } -/** - * TMC2130 specific sensorless homing using stallGuard2. - * stallGuard2 only works when in spreadCycle mode. - * spreadCycle and stealthChop are mutually exclusive. - */ -#if ENABLED(SENSORLESS_HOMING) - template<typename TMC> - void tmc_sensorless_homing(TMC &st, bool enable=true) { - #if ENABLED(STEALTHCHOP) - if (enable) { - st.coolstep_min_speed(1024UL * 1024UL - 1UL); - st.stealthChop(0); - } - else { - st.coolstep_min_speed(0); - st.stealthChop(1); - } - #endif - - st.diag1_stall(enable ? 1 : 0); - } -#endif - /** * Home an individual "raw axis" to its endstop. * This applies to XYZ on Cartesian and Core robots, and @@ -10305,379 +10286,14 @@ inline void gcode_M502() { #endif // LIN_ADVANCE #if HAS_TRINAMIC - static bool report_tmc_status = false; - const char extended_axis_codes[11][3] = { "X", "X2", "Y", "Y2", "Z", "Z2", "E0", "E1", "E2", "E3", "E4" }; - enum TMC_AxisEnum { - TMC_X, - TMC_X2, - TMC_Y, - TMC_Y2, - TMC_Z, - TMC_Z2, - TMC_E0, - TMC_E1, - TMC_E2, - TMC_E3, - TMC_E4 - }; #if ENABLED(TMC_DEBUG) - enum TMC_debug_enum { - TMC_CODES, - TMC_ENABLED, - TMC_CURRENT, - TMC_RMS_CURRENT, - TMC_MAX_CURRENT, - TMC_IRUN, - TMC_IHOLD, - TMC_CS_ACTUAL, - TMC_PWM_SCALE, - TMC_VSENSE, - TMC_STEALTHCHOP, - TMC_MICROSTEPS, - TMC_TSTEP, - TMC_TPWMTHRS, - TMC_TPWMTHRS_MMS, - TMC_OTPW, - TMC_OTPW_TRIGGERED, - TMC_TOFF, - TMC_TBL, - TMC_HEND, - TMC_HSTRT, - TMC_SGT - }; - enum TMC_drv_status_enum { - TMC_DRV_CODES, - TMC_STST, - TMC_OLB, - TMC_OLA, - TMC_S2GB, - TMC_S2GA, - TMC_DRV_OTPW, - TMC_OT, - TMC_STALLGUARD, - TMC_DRV_CS_ACTUAL, - TMC_FSACTIVE, - TMC_SG_RESULT, - TMC_DRV_STATUS_HEX, - TMC_T157, - TMC_T150, - TMC_T143, - TMC_T120, - TMC_STEALTH, - TMC_S2VSB, - TMC_S2VSA - }; - static void drv_status_print_hex(const char name[], const uint32_t drv_status) { - SERIAL_ECHO(name); - SERIAL_ECHOPGM(" = 0x"); - for(int B=24; B>=8; B-=8){ - MYSERIAL.print((drv_status>>(B+4))&0xF, HEX); - MYSERIAL.print((drv_status>>B)&0xF, HEX); - MYSERIAL.print(':'); - } - MYSERIAL.print((drv_status>>4)&0xF, HEX); - MYSERIAL.print((drv_status)&0xF, HEX); - SERIAL_EOL(); - } - - #if ENABLED(HAVE_TMC2130) - static void tmc_status(TMC2130Stepper &st, const TMC_debug_enum i) { - switch(i) { - case TMC_PWM_SCALE: MYSERIAL.print(st.PWM_SCALE(), DEC); break; - case TMC_TSTEP: SERIAL_ECHO(st.TSTEP()); break; - case TMC_SGT: MYSERIAL.print(st.sgt(), DEC); break; - case TMC_STEALTHCHOP: serialprintPGM(st.stealthChop() ? PSTR("true") : PSTR("false")); break; - default: break; - } - } - static void tmc_parse_drv_status(TMC2130Stepper &st, const TMC_drv_status_enum i) { - switch(i) { - case TMC_STALLGUARD: if (st.stallguard()) SERIAL_ECHOPGM("X"); break; - case TMC_SG_RESULT: MYSERIAL.print(st.sg_result(), DEC); break; - case TMC_FSACTIVE: if (st.fsactive()) SERIAL_ECHOPGM("X"); break; - default: break; - } - } - #endif - #if ENABLED(HAVE_TMC2208) - static void tmc_status(TMC2208Stepper &st, const TMC_debug_enum i) { - switch(i) { - case TMC_TSTEP: - { - uint32_t data = 0; - st.TSTEP(&data); - MYSERIAL.print(data); - break; - } - case TMC_PWM_SCALE: MYSERIAL.print(st.pwm_scale_sum(), DEC); break; - case TMC_STEALTHCHOP: serialprintPGM(st.stealth() ? PSTR("true") : PSTR("false")); break; - case TMC_S2VSA: if (st.s2vsa()) SERIAL_ECHOPGM("X"); break; - case TMC_S2VSB: if (st.s2vsb()) SERIAL_ECHOPGM("X"); break; - default: break; - } - } - static void tmc_parse_drv_status(TMC2208Stepper &st, const TMC_drv_status_enum i) { - switch(i) { - case TMC_T157: if (st.t157()) SERIAL_ECHOPGM("X"); break; - case TMC_T150: if (st.t150()) SERIAL_ECHOPGM("X"); break; - case TMC_T143: if (st.t143()) SERIAL_ECHOPGM("X"); break; - case TMC_T120: if (st.t120()) SERIAL_ECHOPGM("X"); break; - default: break; - } - } - #endif - template <typename TMC> - static void tmc_status(TMC &st, TMC_AxisEnum axis, const TMC_debug_enum i, const float spmm) { - SERIAL_ECHO('\t'); - switch(i) { - case TMC_CODES: SERIAL_ECHO(extended_axis_codes[axis]); break; - case TMC_ENABLED: serialprintPGM(st.isEnabled() ? PSTR("true") : PSTR("false")); break; - case TMC_CURRENT: SERIAL_ECHO(st.getCurrent()); break; - case TMC_RMS_CURRENT: MYSERIAL.print(st.rms_current()); break; - case TMC_MAX_CURRENT: MYSERIAL.print((float)st.rms_current()*1.41, 0); break; - case TMC_IRUN: - MYSERIAL.print(st.irun(), DEC); - SERIAL_ECHOPGM("/31"); - break; - case TMC_IHOLD: - MYSERIAL.print(st.ihold(), DEC); - SERIAL_ECHOPGM("/31"); - break; - case TMC_CS_ACTUAL: - MYSERIAL.print(st.cs_actual(), DEC); - SERIAL_ECHOPGM("/31"); - break; - - case TMC_VSENSE: serialprintPGM(st.vsense() ? PSTR("1=.18") : PSTR("0=.325")); break; - - case TMC_MICROSTEPS: SERIAL_ECHO(st.microsteps()); break; - case TMC_TPWMTHRS: - { - uint32_t tpwmthrs_val = st.TPWMTHRS(); - SERIAL_ECHO(tpwmthrs_val); - } - break; - case TMC_TPWMTHRS_MMS: - { - uint32_t tpwmthrs_val = st.TPWMTHRS(); - tpwmthrs_val ? SERIAL_ECHO(12650000UL * st.microsteps() / (256 * tpwmthrs_val * spmm)) : SERIAL_ECHO('-'); - } - break; - case TMC_OTPW: serialprintPGM(st.otpw() ? PSTR("true") : PSTR("false")); break; - case TMC_OTPW_TRIGGERED: serialprintPGM(st.getOTPW() ? PSTR("true") : PSTR("false")); break; - case TMC_TOFF: MYSERIAL.print(st.toff(), DEC); break; - case TMC_TBL: MYSERIAL.print(st.blank_time(), DEC); break; - case TMC_HEND: MYSERIAL.print(st.hysterisis_end(), DEC); break; - case TMC_HSTRT: MYSERIAL.print(st.hysterisis_start(), DEC); break; - default: tmc_status(st, i); break; - } - } - template <typename TMC> - static void tmc_parse_drv_status(TMC &st, TMC_AxisEnum axis, const TMC_drv_status_enum i) { - SERIAL_ECHOPGM("\t"); - switch(i) { - case TMC_DRV_CODES: SERIAL_ECHO(extended_axis_codes[axis]); break; - case TMC_STST: if (st.stst()) SERIAL_ECHOPGM("X"); break; - case TMC_OLB: if (st.olb()) SERIAL_ECHOPGM("X"); break; - case TMC_OLA: if (st.ola()) SERIAL_ECHOPGM("X"); break; - case TMC_S2GB: if (st.s2gb()) SERIAL_ECHOPGM("X"); break; - case TMC_S2GA: if (st.s2ga()) SERIAL_ECHOPGM("X"); break; - case TMC_DRV_OTPW: if (st.otpw()) SERIAL_ECHOPGM("X"); break; - case TMC_OT: if (st.ot()) SERIAL_ECHOPGM("X"); break; - case TMC_DRV_CS_ACTUAL: MYSERIAL.print(st.cs_actual(), DEC); break; - case TMC_DRV_STATUS_HEX:drv_status_print_hex(extended_axis_codes[axis], st.DRV_STATUS()); break; - default: tmc_parse_drv_status(st, i); break; - } - } - - static void tmc_debug_loop(const TMC_debug_enum i) { - #if X_IS_TRINAMIC - tmc_status(stepperX, TMC_X, i, planner.axis_steps_per_mm[X_AXIS]); - #endif - #if X2_IS_TRINAMIC - tmc_status(stepperX2, TMC_X2, i, planner.axis_steps_per_mm[X_AXIS]); - #endif - - #if Y_IS_TRINAMIC - tmc_status(stepperY, TMC_Y, i, planner.axis_steps_per_mm[Y_AXIS]); - #endif - #if Y2_IS_TRINAMIC - tmc_status(stepperY2, TMC_Y2, i, planner.axis_steps_per_mm[Y_AXIS]); - #endif - - #if Z_IS_TRINAMIC - tmc_status(stepperZ, TMC_Z, i, planner.axis_steps_per_mm[Z_AXIS]); - #endif - #if Z2_IS_TRINAMIC - tmc_status(stepperZ2, TMC_Z2, i, planner.axis_steps_per_mm[Z_AXIS]); - #endif - - #if E0_IS_TRINAMIC - tmc_status(stepperE0, TMC_E0, i, planner.axis_steps_per_mm[E_AXIS]); - #endif - #if E1_IS_TRINAMIC - tmc_status(stepperE1, TMC_E1, i, planner.axis_steps_per_mm[E_AXIS+1]); - #endif - #if E2_IS_TRINAMIC - tmc_status(stepperE2, TMC_E2, i, planner.axis_steps_per_mm[E_AXIS+2]); - #endif - #if E3_IS_TRINAMIC - tmc_status(stepperE3, TMC_E3, i, planner.axis_steps_per_mm[E_AXIS+3]); - #endif - #if E4_IS_TRINAMIC - tmc_status(stepperE4, TMC_E4, i, planner.axis_steps_per_mm[E_AXIS+4]); - #endif - - SERIAL_EOL(); - } - - static void drv_status_loop(const TMC_drv_status_enum i) { - #if X_IS_TRINAMIC - tmc_parse_drv_status(stepperX, TMC_X, i); - #endif - #if X2_IS_TRINAMIC - tmc_parse_drv_status(stepperX2, TMC_X2, i); - #endif - - #if Y_IS_TRINAMIC - tmc_parse_drv_status(stepperY, TMC_Y, i); - #endif - #if Y2_IS_TRINAMIC - tmc_parse_drv_status(stepperY2, TMC_Y2, i); - #endif - - #if Z_IS_TRINAMIC - tmc_parse_drv_status(stepperZ, TMC_Z, i); - #endif - #if Z2_IS_TRINAMIC - tmc_parse_drv_status(stepperZ2, TMC_Z2, i); - #endif - - #if E0_IS_TRINAMIC - tmc_parse_drv_status(stepperE0, TMC_E0, i); - #endif - #if E1_IS_TRINAMIC - tmc_parse_drv_status(stepperE1, TMC_E1, i); - #endif - #if E2_IS_TRINAMIC - tmc_parse_drv_status(stepperE2, TMC_E2, i); - #endif - #if E3_IS_TRINAMIC - tmc_parse_drv_status(stepperE3, TMC_E3, i); - #endif - #if E4_IS_TRINAMIC - tmc_parse_drv_status(stepperE4, TMC_E4, i); - #endif - - SERIAL_EOL(); - } - inline void gcode_M122() { - if (parser.seen('S')) { - if (parser.value_bool()) { - SERIAL_ECHOLNPGM("axis:pwm_scale |status_response|"); - report_tmc_status = true; - } else - report_tmc_status = false; - } else { - SERIAL_ECHOPGM("\t"); tmc_debug_loop(TMC_CODES); - SERIAL_ECHOPGM("Enabled\t"); tmc_debug_loop(TMC_ENABLED); - SERIAL_ECHOPGM("Set current"); tmc_debug_loop(TMC_CURRENT); - SERIAL_ECHOPGM("RMS current"); tmc_debug_loop(TMC_RMS_CURRENT); - SERIAL_ECHOPGM("MAX current"); tmc_debug_loop(TMC_MAX_CURRENT); - SERIAL_ECHOPGM("Run current"); tmc_debug_loop(TMC_IRUN); - SERIAL_ECHOPGM("Hold current"); tmc_debug_loop(TMC_IHOLD); - SERIAL_ECHOPGM("CS actual\t"); tmc_debug_loop(TMC_CS_ACTUAL); - SERIAL_ECHOPGM("PWM scale"); tmc_debug_loop(TMC_PWM_SCALE); - SERIAL_ECHOPGM("vsense\t"); tmc_debug_loop(TMC_VSENSE); - SERIAL_ECHOPGM("stealthChop"); tmc_debug_loop(TMC_STEALTHCHOP); - SERIAL_ECHOPGM("msteps\t"); tmc_debug_loop(TMC_MICROSTEPS); - SERIAL_ECHOPGM("tstep\t"); tmc_debug_loop(TMC_TSTEP); - SERIAL_ECHOPGM("pwm\nthreshold\t"); tmc_debug_loop(TMC_TPWMTHRS); - SERIAL_ECHOPGM("[mm/s]\t"); tmc_debug_loop(TMC_TPWMTHRS_MMS); - SERIAL_ECHOPGM("OT prewarn"); tmc_debug_loop(TMC_OTPW); - SERIAL_ECHOPGM("OT prewarn has\nbeen triggered"); tmc_debug_loop(TMC_OTPW_TRIGGERED); - SERIAL_ECHOPGM("off time\t"); tmc_debug_loop(TMC_TOFF); - SERIAL_ECHOPGM("blank time"); tmc_debug_loop(TMC_TBL); - SERIAL_ECHOPGM("hysterisis\n-end\t"); tmc_debug_loop(TMC_HEND); - SERIAL_ECHOPGM("-start\t"); tmc_debug_loop(TMC_HSTRT); - SERIAL_ECHOPGM("Stallguard thrs"); tmc_debug_loop(TMC_SGT); - - SERIAL_ECHOPGM("DRVSTATUS"); drv_status_loop(TMC_DRV_CODES); - #if ENABLED(HAVE_TMC2130) - SERIAL_ECHOPGM("stallguard\t"); drv_status_loop(TMC_STALLGUARD); - SERIAL_ECHOPGM("sg_result\t"); drv_status_loop(TMC_SG_RESULT); - SERIAL_ECHOPGM("fsactive\t"); drv_status_loop(TMC_FSACTIVE); - #endif - SERIAL_ECHOPGM("stst\t"); drv_status_loop(TMC_STST); - SERIAL_ECHOPGM("olb\t"); drv_status_loop(TMC_OLB); - SERIAL_ECHOPGM("ola\t"); drv_status_loop(TMC_OLA); - SERIAL_ECHOPGM("s2gb\t"); drv_status_loop(TMC_S2GB); - SERIAL_ECHOPGM("s2ga\t"); drv_status_loop(TMC_S2GA); - SERIAL_ECHOPGM("otpw\t"); drv_status_loop(TMC_DRV_OTPW); - SERIAL_ECHOPGM("ot\t"); drv_status_loop(TMC_OT); - #if ENABLED(HAVE_TMC2208) - SERIAL_ECHOPGM("157C\t"); drv_status_loop(TMC_T157); - SERIAL_ECHOPGM("150C\t"); drv_status_loop(TMC_T150); - SERIAL_ECHOPGM("143C\t"); drv_status_loop(TMC_T143); - SERIAL_ECHOPGM("120C\t"); drv_status_loop(TMC_T120); - SERIAL_ECHOPGM("s2vsa\t"); drv_status_loop(TMC_S2VSA); - SERIAL_ECHOPGM("s2vsb\t"); drv_status_loop(TMC_S2VSB); - #endif - SERIAL_ECHOLNPGM("Driver registers:");drv_status_loop(TMC_DRV_STATUS_HEX); - } + if (parser.seen('S')) + tmc_set_report_status(parser.value_bool()); + else + tmc_report_all(); } - #endif - - template<typename TMC> - static void tmc_get_current(TMC &st, const char name[]) { - SERIAL_ECHO(name); - SERIAL_ECHOPGM(" axis driver current: "); - SERIAL_ECHOLN(st.getCurrent()); - } - template<typename TMC> - static void tmc_set_current(TMC &st, const char name[], const int mA) { - st.setCurrent(mA, R_SENSE, HOLD_MULTIPLIER); - tmc_get_current(st, name); - } - - template<typename TMC> - static void tmc_report_otpw(TMC &st, const char name[]) { - SERIAL_ECHO(name); - SERIAL_ECHOPGM(" axis temperature prewarn triggered: "); - serialprintPGM(st.getOTPW() ? PSTR("true") : PSTR("false")); - SERIAL_EOL(); - } - template<typename TMC> - static void tmc_clear_otpw(TMC &st, const char name[]) { - st.clear_otpw(); - SERIAL_ECHO(name); - SERIAL_ECHOLNPGM(" prewarn flag cleared"); - } - - template<typename TMC> - static void tmc_get_pwmthrs(TMC &st, const char name[], const uint16_t spmm) { - SERIAL_ECHO(name); - SERIAL_ECHOPGM(" stealthChop max speed set to "); - SERIAL_ECHOLN(12650000UL * st.microsteps() / (256 * st.TPWMTHRS() * spmm)); - } - template<typename TMC> - static void tmc_set_pwmthrs(TMC &st, const char name[], const int32_t thrs, const uint32_t spmm) { - st.TPWMTHRS(12650000UL * st.microsteps() / (256 * thrs * spmm)); - tmc_get_pwmthrs(st, name, spmm); - } - - template<typename TMC> - static void tmc_get_sgt(TMC &st, const char name[]) { - SERIAL_ECHO(name); - SERIAL_ECHOPGM(" driver homing sensitivity set to "); - MYSERIAL.println(st.sgt(), DEC); - } - template<typename TMC> - static void tmc_set_sgt(TMC &st, const char name[], const int8_t sgt_val) { - st.sgt(sgt_val); - tmc_get_sgt(st, name); - } + #endif // TMC_DEBUG /** * M906: Set motor current in milliamps using axis codes X, Y, Z, E @@ -10685,54 +10301,45 @@ inline void gcode_M502() { */ inline void gcode_M906() { uint16_t values[XYZE]; - LOOP_XYZE(i) - values[i] = parser.intval(axis_codes[i]); + LOOP_XYZE(i) values[i] = parser.intval(axis_codes[i]); + + #define TMC_SET_GET_CURRENT(P,Q) do { \ + if (values[P##_AXIS]) tmc_set_current(stepper##Q, extended_axis_codes[TMC_##Q], values[P##_AXIS]); \ + else tmc_get_current(stepper##Q, extended_axis_codes[TMC_##Q]); } while(0) #if X_IS_TRINAMIC - if (values[X_AXIS]) tmc_set_current(stepperX, extended_axis_codes[TMC_X], values[X_AXIS]); - else tmc_get_current(stepperX, extended_axis_codes[TMC_X]); + TMC_SET_GET_CURRENT(X,X); #endif #if X2_IS_TRINAMIC - if (values[X_AXIS]) tmc_set_current(stepperX2, extended_axis_codes[TMC_X2], values[X_AXIS]); - else tmc_get_current(stepperX2, extended_axis_codes[TMC_X2]); + TMC_SET_GET_CURRENT(X,X2); #endif #if Y_IS_TRINAMIC - if (values[Y_AXIS]) tmc_set_current(stepperY, extended_axis_codes[TMC_Y], values[Y_AXIS]); - else tmc_get_current(stepperY, extended_axis_codes[TMC_Y]); + TMC_SET_GET_CURRENT(Y,Y); #endif #if Y2_IS_TRINAMIC - if (values[Y_AXIS]) tmc_set_current(stepperY2, extended_axis_codes[TMC_Y2], values[Y_AXIS]); - else tmc_get_current(stepperY2, extended_axis_codes[TMC_Y2]); + TMC_SET_GET_CURRENT(Y,Y2); #endif #if Z_IS_TRINAMIC - if (values[Z_AXIS]) tmc_set_current(stepperZ, extended_axis_codes[TMC_Z], values[Z_AXIS]); - else tmc_get_current(stepperZ, extended_axis_codes[TMC_Z]); + TMC_SET_GET_CURRENT(Z,Z); #endif #if Z2_IS_TRINAMIC - if (values[Z_AXIS]) tmc_set_current(stepperZ2, extended_axis_codes[TMC_Z2], values[Z_AXIS]); - else tmc_get_current(stepperZ2, extended_axis_codes[TMC_Z2]); + TMC_SET_GET_CURRENT(Z,Z2); #endif #if E0_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_current(stepperE0, extended_axis_codes[TMC_E0], values[E_AXIS]); - else tmc_get_current(stepperE0, extended_axis_codes[TMC_E0]); + TMC_SET_GET_CURRENT(E,E0); #endif #if E1_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_current(stepperE1, extended_axis_codes[TMC_E1], values[E_AXIS]); - else tmc_get_current(stepperE1, extended_axis_codes[TMC_E1]); + TMC_SET_GET_CURRENT(E,E1); #endif #if E2_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_current(stepperE2, extended_axis_codes[TMC_E2], values[E_AXIS]); - else tmc_get_current(stepperE2, extended_axis_codes[TMC_E2]); + TMC_SET_GET_CURRENT(E,E2); #endif #if E3_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_current(stepperE3, extended_axis_codes[TMC_E3], values[E_AXIS]); - else tmc_get_current(stepperE3, extended_axis_codes[TMC_E3]); + TMC_SET_GET_CURRENT(E,E3); #endif #if E4_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_current(stepperE4, extended_axis_codes[TMC_E4], values[E_AXIS]); - else tmc_get_current(stepperE4, extended_axis_codes[TMC_E4]); + TMC_SET_GET_CURRENT(E,E4); #endif - } /** @@ -10786,55 +10393,44 @@ inline void gcode_M502() { #if ENABLED(HYBRID_THRESHOLD) inline void gcode_M913() { uint16_t values[XYZE]; - LOOP_XYZE(i) - values[i] = parser.intval(axis_codes[i]); + LOOP_XYZE(i) values[i] = parser.intval(axis_codes[i]); + + #define TMC_SET_GET_PWMTHRS(P,Q) do { \ + if (values[P##_AXIS]) tmc_set_pwmthrs(stepper##Q, extended_axis_codes[TMC_##Q], values[P##_AXIS], planner.axis_steps_per_mm[P##_AXIS]); \ + else tmc_get_pwmthrs(stepper##Q, extended_axis_codes[TMC_##Q], planner.axis_steps_per_mm[P##_AXIS]); } while(0) #if X_IS_TRINAMIC - if (values[X_AXIS]) tmc_set_pwmthrs(stepperX, extended_axis_codes[TMC_X], values[X_AXIS], planner.axis_steps_per_mm[X_AXIS]); - else tmc_get_pwmthrs(stepperX, extended_axis_codes[TMC_X], planner.axis_steps_per_mm[X_AXIS]); + TMC_SET_GET_PWMTHRS(X,X); #endif #if X2_IS_TRINAMIC - if (values[X_AXIS]) tmc_set_pwmthrs(stepperX2, extended_axis_codes[TMC_X2], values[X_AXIS], planner.axis_steps_per_mm[X_AXIS]); - else tmc_get_pwmthrs(stepperX, extended_axis_codes[TMC_X2], planner.axis_steps_per_mm[X_AXIS]); + TMC_SET_GET_PWMTHRS(X,X2); #endif - #if Y_IS_TRINAMIC - if (values[Y_AXIS]) tmc_set_pwmthrs(stepperY, extended_axis_codes[TMC_Y], values[Y_AXIS], planner.axis_steps_per_mm[Y_AXIS]); - else tmc_get_pwmthrs(stepperY, extended_axis_codes[TMC_Y], planner.axis_steps_per_mm[Y_AXIS]); + TMC_SET_GET_PWMTHRS(Y,Y); #endif #if Y2_IS_TRINAMIC - if (values[Y_AXIS]) tmc_set_pwmthrs(stepperY2, extended_axis_codes[TMC_Y2], values[Y_AXIS], planner.axis_steps_per_mm[Y_AXIS]); - else tmc_get_pwmthrs(stepperY, extended_axis_codes[TMC_Y2], planner.axis_steps_per_mm[Y_AXIS]); + TMC_SET_GET_PWMTHRS(Y,Y2); #endif - #if Z_IS_TRINAMIC - if (values[Z_AXIS]) tmc_set_pwmthrs(stepperZ, extended_axis_codes[TMC_Z], values[Z_AXIS], planner.axis_steps_per_mm[Z_AXIS]); - else tmc_get_pwmthrs(stepperZ, extended_axis_codes[TMC_Z], planner.axis_steps_per_mm[Z_AXIS]); + TMC_SET_GET_PWMTHRS(Z,Z); #endif #if Z2_IS_TRINAMIC - if (values[Z_AXIS]) tmc_set_pwmthrs(stepperZ2, extended_axis_codes[TMC_Z2], values[Z_AXIS], planner.axis_steps_per_mm[Z_AXIS]); - else tmc_get_pwmthrs(stepperZ, extended_axis_codes[TMC_Z2], planner.axis_steps_per_mm[Z_AXIS]); + TMC_SET_GET_PWMTHRS(Z,Z2); #endif - #if E0_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_pwmthrs(stepperE0, extended_axis_codes[TMC_E0], values[E_AXIS], planner.axis_steps_per_mm[E_AXIS]); - else tmc_get_pwmthrs(stepperE0, extended_axis_codes[TMC_E0], planner.axis_steps_per_mm[E_AXIS]); + TMC_SET_GET_PWMTHRS(E,E0); #endif #if E1_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_pwmthrs(stepperE1, extended_axis_codes[TMC_E1], values[E_AXIS], planner.axis_steps_per_mm[E_AXIS]); - else tmc_get_pwmthrs(stepperE1, extended_axis_codes[TMC_E1], planner.axis_steps_per_mm[E_AXIS]); + TMC_SET_GET_PWMTHRS(E,E1); #endif #if E2_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_pwmthrs(stepperE2, extended_axis_codes[TMC_E2], values[E_AXIS], planner.axis_steps_per_mm[E_AXIS]); - else tmc_get_pwmthrs(stepperE2, extended_axis_codes[TMC_E2], planner.axis_steps_per_mm[E_AXIS]); + TMC_SET_GET_PWMTHRS(E,E2); #endif #if E3_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_pwmthrs(stepperE3, extended_axis_codes[TMC_E3], values[E_AXIS], planner.axis_steps_per_mm[E_AXIS]); - else tmc_get_pwmthrs(stepperE3, extended_axis_codes[TMC_E3], planner.axis_steps_per_mm[E_AXIS]); + TMC_SET_GET_PWMTHRS(E,E3); #endif #if E4_IS_TRINAMIC - if (values[E_AXIS]) tmc_set_pwmthrs(stepperE4, extended_axis_codes[TMC_E4], values[E_AXIS], planner.axis_steps_per_mm[E_AXIS]); - else tmc_get_pwmthrs(stepperE4, extended_axis_codes[TMC_E4], planner.axis_steps_per_mm[E_AXIS]); + TMC_SET_GET_PWMTHRS(E,E4); #endif } #endif // HYBRID_THRESHOLD @@ -10844,21 +10440,21 @@ inline void gcode_M502() { */ #if ENABLED(SENSORLESS_HOMING) inline void gcode_M914() { + #define TMC_SET_GET_SGT(P,Q) do { \ + if (parser.seen(axis_codes[X_AXIS])) tmc_set_sgt(stepperX, extended_axis_codes[TMC_X], parser.value_int()); \ + else tmc_get_sgt(stepperX, extended_axis_codes[TMC_X]); } while(0) + #if ENABLED(X_IS_TMC2130) || ENABLED(IS_TRAMS) - if (parser.seen(axis_codes[X_AXIS])) tmc_set_sgt(stepperX, extended_axis_codes[TMC_X], parser.value_int()); - else tmc_get_sgt(stepperX, extended_axis_codes[TMC_X]); + TMC_SET_GET_SGT(X,X); #endif #if ENABLED(X2_IS_TMC2130) - if (parser.seen(axis_codes[X_AXIS])) tmc_set_sgt(stepperX2, extended_axis_codes[TMC_X2], parser.value_int()); - else tmc_get_sgt(stepperX2, extended_axis_codes[TMC_X2]); + TMC_SET_GET_SGT(X,X2); #endif #if ENABLED(Y_IS_TMC2130) || ENABLED(IS_TRAMS) - if (parser.seen(axis_codes[Y_AXIS])) tmc_set_sgt(stepperY, extended_axis_codes[TMC_Y], parser.value_int()); - else tmc_get_sgt(stepperY, extended_axis_codes[TMC_Y]); + TMC_SET_GET_SGT(Y,Y); #endif #if ENABLED(Y2_IS_TMC2130) - if (parser.seen(axis_codes[Y_AXIS])) tmc_set_sgt(stepperY2, extended_axis_codes[TMC_Y2], parser.value_int()); - else tmc_get_sgt(stepperY2, extended_axis_codes[TMC_Y2]); + TMC_SET_GET_SGT(Y,Y2); #endif } #endif // SENSORLESS_HOMING @@ -10866,7 +10462,7 @@ inline void gcode_M502() { /** * TMC Z axis calibration routine */ - #if ENABLED(TMC_Z_CALIBRATION) && (Z_IS_TRINAMIC || Z2_IS_TRINAMIC) + #if ENABLED(TMC_Z_CALIBRATION) inline void gcode_M915() { uint16_t _rms = parser.seenval('S') ? parser.value_int() : CALIBRATION_CURRENT; uint16_t _z = parser.seenval('Z') ? parser.value_int() : CALIBRATION_EXTRA_HEIGHT; @@ -10876,25 +10472,33 @@ inline void gcode_M502() { return; } - uint16_t Z_current_1 = stepperZ.getCurrent(); - uint16_t Z2_current_1 = stepperZ.getCurrent(); + #if Z_IS_TRINAMIC + uint16_t Z_current_1 = stepperZ.getCurrent(), + stepperZ.setCurrent(_rms, R_SENSE, HOLD_MULTIPLIER); + #endif + #if Z2_IS_TRINAMIC + uint16_t Z2_current_1 = stepperZ.getCurrent(); + stepperZ2.setCurrent(_rms, R_SENSE, HOLD_MULTIPLIER); + #endif - stepperZ.setCurrent(_rms, R_SENSE, HOLD_MULTIPLIER); - stepperZ2.setCurrent(_rms, R_SENSE, HOLD_MULTIPLIER); SERIAL_ECHOPAIR("\nCalibration current: Z", _rms); soft_endstops_enabled = false; do_blocking_move_to_z(Z_MAX_POS+_z); - stepperZ.setCurrent(Z_current_1, R_SENSE, HOLD_MULTIPLIER); - stepperZ2.setCurrent(Z2_current_1, R_SENSE, HOLD_MULTIPLIER); + #if Z_IS_TRINAMIC + stepperZ.setCurrent(Z_current_1, R_SENSE, HOLD_MULTIPLIER); + #endif + #if Z2_IS_TRINAMIC + stepperZ2.setCurrent(Z2_current_1, R_SENSE, HOLD_MULTIPLIER); + #endif do_blocking_move_to_z(Z_MAX_POS); soft_endstops_enabled = true; - SERIAL_ECHOLNPGM("\nHoming Z because we lost steps"); - home_z_safely(); + SERIAL_ECHOLNPGM("\nHoming Z due to lost steps"); + enqueue_and_echo_commands_P(PSTR("G28 Z")); } #endif @@ -12133,7 +11737,7 @@ void process_parsed_command() { #if ENABLED(SENSORLESS_HOMING) case 914: gcode_M914(); break; // M914: Set SENSORLESS_HOMING sensitivity. #endif - #if ENABLED(TMC_Z_CALIBRATION) && (Z_IS_TRINAMIC || Z2_IS_TRINAMIC) + #if ENABLED(TMC_Z_CALIBRATION) case 915: gcode_M915(); break; // M915: TMC Z axis calibration routine #endif #endif @@ -13536,186 +13140,6 @@ void disable_all_steppers() { disable_e_steppers(); } -#if ENABLED(MONITOR_DRIVER_STATUS) - /* - * Check for over temperature or short to ground error flags. - * Report and log warning of overtemperature condition. - * Reduce driver current in a persistent otpw condition. - * Keep track of otpw counter so we don't reduce current on a single instance, - * and so we don't repeatedly report warning before the condition is cleared. - */ - - struct TMC_driver_data { - uint32_t drv_status; - bool is_otpw; - bool is_ot; - bool is_error; - }; - #if ENABLED(HAVE_TMC2130) - static uint32_t get_pwm_scale(TMC2130Stepper &st) { return st.PWM_SCALE(); } - static uint8_t get_status_response(TMC2130Stepper &st) { return st.status_response&0xF; } - static TMC_driver_data get_driver_data(TMC2130Stepper &st) { - constexpr uint32_t OTPW_bm = 0x4000000UL; - constexpr uint8_t OTPW_bp = 26; - constexpr uint32_t OT_bm = 0x2000000UL; - constexpr uint8_t OT_bp = 25; - constexpr uint8_t DRIVER_ERROR_bm = 0x2UL; - constexpr uint8_t DRIVER_ERROR_bp = 1; - TMC_driver_data data; - data.drv_status = st.DRV_STATUS(); - data.is_otpw = (data.drv_status & OTPW_bm)>>OTPW_bp; - data.is_ot = (data.drv_status & OT_bm)>>OT_bp; - data.is_error = (st.status_response & DRIVER_ERROR_bm)>>DRIVER_ERROR_bp; - return data; - } - #endif - #if ENABLED(HAVE_TMC2208) - static uint32_t get_pwm_scale(TMC2208Stepper &st) { return st.pwm_scale_sum(); } - static uint8_t get_status_response(TMC2208Stepper &st) { - uint32_t drv_status = st.DRV_STATUS(); - uint8_t gstat = st.GSTAT(); - uint8_t response = 0; - response |= (drv_status >> (31-3)) & 0b1000; - response |= gstat & 0b11; - return response; - } - static TMC_driver_data get_driver_data(TMC2208Stepper &st) { - constexpr uint32_t OTPW_bm = 0b1ul; - constexpr uint8_t OTPW_bp = 0; - constexpr uint32_t OT_bm = 0b10ul; - constexpr uint8_t OT_bp = 1; - TMC_driver_data data; - data.drv_status = st.DRV_STATUS(); - data.is_otpw = (data.drv_status & OTPW_bm)>>OTPW_bp; - data.is_ot = (data.drv_status & OT_bm)>>OT_bp; - data.is_error = st.drv_err(); - return data; - } - #endif - - template<typename TMC> - uint8_t monitor_tmc_driver(TMC &st, const char axisID, uint8_t otpw_cnt) { - TMC_driver_data data = get_driver_data(st); - - #if ENABLED(STOP_ON_ERROR) - if (data.is_error) { - SERIAL_EOL(); - SERIAL_ECHO(axisID); - SERIAL_ECHO(" driver error detected:"); - if (data.is_ot) SERIAL_ECHO("\novertemperature"); - if (st.s2ga()) SERIAL_ECHO("\nshort to ground (coil A)"); - if (st.s2gb()) SERIAL_ECHO("\nshort to ground (coil B)"); - SERIAL_EOL(); - #if ENABLED(TMC_DEBUG) - gcode_M122(); - #endif - kill(PSTR("Driver error")); - } - #endif - - // Report if a warning was triggered - if (data.is_otpw && otpw_cnt==0) { - char timestamp[10]; - duration_t elapsed = print_job_timer.duration(); - const bool has_days = (elapsed.value > 60*60*24L); - (void)elapsed.toDigital(timestamp, has_days); - SERIAL_EOL(); - SERIAL_ECHO(timestamp); - SERIAL_ECHOPGM(": "); - SERIAL_ECHO(axisID); - SERIAL_ECHOPGM(" driver overtemperature warning! ("); - SERIAL_ECHO(st.getCurrent()); - SERIAL_ECHOLN("mA)"); - } - #if CURRENT_STEP_DOWN > 0 - // Decrease current if is_otpw is true and driver is enabled and there's been more then 4 warnings - if (data.is_otpw && !st.isEnabled() && otpw_cnt > 4) { - st.setCurrent(st.getCurrent() - CURRENT_STEP_DOWN, R_SENSE, HOLD_MULTIPLIER); - #if ENABLED(REPORT_CURRENT_CHANGE) - SERIAL_ECHO(axisID); - SERIAL_ECHOLNPAIR(" current decreased to ", st.getCurrent()); - #endif - } - #endif - - if (data.is_otpw) { - otpw_cnt++; - st.flag_otpw = true; - } - else if (otpw_cnt>0) otpw_cnt--; - - if (report_tmc_status) { - const uint32_t pwm_scale = get_pwm_scale(st); - SERIAL_ECHO(axisID); - SERIAL_ECHOPAIR(":", pwm_scale); - SERIAL_ECHO(" |0b"); MYSERIAL.print(get_status_response(st), BIN); - SERIAL_ECHO("| "); - if (data.is_error) SERIAL_ECHO('E'); - else if (data.is_ot) SERIAL_ECHO('O'); - else if (data.is_otpw) SERIAL_ECHO('W'); - else if (otpw_cnt>0) MYSERIAL.print(otpw_cnt, DEC); - else if (st.flag_otpw) SERIAL_ECHO('F'); - SERIAL_ECHO("\t"); - } - - return otpw_cnt; - } - - void monitor_tmc_driver() { - static millis_t next_cOT = 0; - if (ELAPSED(millis(), next_cOT)) { - next_cOT = millis() + 500; - #if ENABLED(X_IS_TMC2130)|| (ENABLED(X_IS_TMC2208) && defined(X_HARDWARE_SERIAL)) || ENABLED(IS_TRAMS) - static uint8_t x_otpw_cnt = 0; - x_otpw_cnt = monitor_tmc_driver(stepperX, axis_codes[X_AXIS], x_otpw_cnt); - #endif - #if ENABLED(Y_IS_TMC2130)|| (ENABLED(Y_IS_TMC2208) && defined(Y_HARDWARE_SERIAL)) || ENABLED(IS_TRAMS) - static uint8_t y_otpw_cnt = 0; - y_otpw_cnt = monitor_tmc_driver(stepperY, axis_codes[Y_AXIS], y_otpw_cnt); - #endif - #if ENABLED(Z_IS_TMC2130)|| (ENABLED(Z_IS_TMC2208) && defined(Z_HARDWARE_SERIAL)) || ENABLED(IS_TRAMS) - static uint8_t z_otpw_cnt = 0; - z_otpw_cnt = monitor_tmc_driver(stepperZ, axis_codes[Z_AXIS], z_otpw_cnt); - #endif - #if ENABLED(X2_IS_TMC2130) || (ENABLED(X2_IS_TMC2208) && defined(X2_HARDWARE_SERIAL)) - static uint8_t x2_otpw_cnt = 0; - x2_otpw_cnt = monitor_tmc_driver(stepperX2, axis_codes[X_AXIS], x2_otpw_cnt); - #endif - #if ENABLED(Y2_IS_TMC2130) || (ENABLED(Y2_IS_TMC2208) && defined(Y2_HARDWARE_SERIAL)) - static uint8_t y2_otpw_cnt = 0; - y2_otpw_cnt = monitor_tmc_driver(stepperY2, axis_codes[Y_AXIS], y2_otpw_cnt); - #endif - #if ENABLED(Z2_IS_TMC2130) || (ENABLED(Z2_IS_TMC2208) && defined(Z2_HARDWARE_SERIAL)) - static uint8_t z2_otpw_cnt = 0; - z2_otpw_cnt = monitor_tmc_driver(stepperZ2, axis_codes[Z_AXIS], z2_otpw_cnt); - #endif - #if ENABLED(E0_IS_TMC2130)|| (ENABLED(E0_IS_TMC2208) && defined(E0_HARDWARE_SERIAL)) || ENABLED(IS_TRAMS) - static uint8_t e0_otpw_cnt = 0; - e0_otpw_cnt = monitor_tmc_driver(stepperE0, axis_codes[E_AXIS], e0_otpw_cnt); - #endif - #if ENABLED(E1_IS_TMC2130) || (ENABLED(E1_IS_TMC2208) && defined(E1_HARDWARE_SERIAL)) - static uint8_t e1_otpw_cnt = 0; - e1_otpw_cnt = monitor_tmc_driver(stepperE1, axis_codes[E_AXIS], e1_otpw_cnt); - #endif - #if ENABLED(E2_IS_TMC2130) || (ENABLED(E2_IS_TMC2208) && defined(E2_HARDWARE_SERIAL)) - static uint8_t e2_otpw_cnt = 0; - e2_otpw_cnt = monitor_tmc_driver(stepperE2, axis_codes[E_AXIS], e2_otpw_cnt); - #endif - #if ENABLED(E3_IS_TMC2130) || (ENABLED(E3_IS_TMC2208) && defined(E3_HARDWARE_SERIAL)) - static uint8_t e3_otpw_cnt = 0; - e3_otpw_cnt = monitor_tmc_driver(stepperE3, axis_codes[E_AXIS], e3_otpw_cnt); - #endif - #if ENABLED(E4_IS_TMC2130) || (ENABLED(E4_IS_TMC2208) && defined(E4_HARDWARE_SERIAL)) - static uint8_t e4_otpw_cnt = 0; - e4_otpw_cnt = monitor_tmc_driver(stepperE4, axis_codes[E_AXIS], e4_otpw_cnt); - #endif - - if (report_tmc_status) SERIAL_EOL(); - } - } - -#endif // MONITOR_DRIVER_STATUS - /** * Manage several activities: * - Check for Filament Runout diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h index 75153c843b1..acbfe9560fe 100644 --- a/Marlin/SanityCheck.h +++ b/Marlin/SanityCheck.h @@ -241,6 +241,8 @@ #error "ANET_KEYPAD_LCD is now ZONESTAR_LCD. Please update your configuration." #elif defined(MEASURED_LOWER_LIMIT) || defined(MEASURED_UPPER_LIMIT) #error "MEASURED_(UPPER|LOWER)_LIMIT is now FILWIDTH_ERROR_MARGIN. Please update your configuration." +#elif defined(AUTOMATIC_CURRENT_CONTROL) + #error "AUTOMATIC_CURRENT_CONTROL is now MONITOR_DRIVER_STATUS. Please update your configuration." #endif /** @@ -1444,30 +1446,26 @@ static_assert(1 >= 0 /** * Make sure HAVE_TMC2130 is warranted */ -#if ENABLED(HAVE_TMC2130) - #if !( ENABLED( X_IS_TMC2130 ) \ - || ENABLED( X2_IS_TMC2130 ) \ - || ENABLED( Y_IS_TMC2130 ) \ - || ENABLED( Y2_IS_TMC2130 ) \ - || ENABLED( Z_IS_TMC2130 ) \ - || ENABLED( Z2_IS_TMC2130 ) \ - || ENABLED( E0_IS_TMC2130 ) \ - || ENABLED( E1_IS_TMC2130 ) \ - || ENABLED( E2_IS_TMC2130 ) \ - || ENABLED( E3_IS_TMC2130 ) \ - || ENABLED( E4_IS_TMC2130 ) ) - #error "HAVE_TMC2130 requires at least one TMC2130 stepper to be set." - #elif ENABLED(HYBRID_THRESHOLD) && DISABLED(STEALTHCHOP) - #error "Enable STEALTHCHOP to use HYBRID_THRESHOLD." - #elif defined(AUTOMATIC_CURRENT_CONTROL) - #error "AUTOMATIC_CURRENT_CONTROL is now MONITOR_DRIVER_STATUS. Please update your configuration." - #endif +#if ENABLED(HAVE_TMC2130) && !( \ + ENABLED( X_IS_TMC2130 ) \ + || ENABLED( X2_IS_TMC2130 ) \ + || ENABLED( Y_IS_TMC2130 ) \ + || ENABLED( Y2_IS_TMC2130 ) \ + || ENABLED( Z_IS_TMC2130 ) \ + || ENABLED( Z2_IS_TMC2130 ) \ + || ENABLED( E0_IS_TMC2130 ) \ + || ENABLED( E1_IS_TMC2130 ) \ + || ENABLED( E2_IS_TMC2130 ) \ + || ENABLED( E3_IS_TMC2130 ) \ + || ENABLED( E4_IS_TMC2130 ) ) + #error "HAVE_TMC2130 requires at least one TMC2130 stepper to be set." +#elif ENABLED(SENSORLESS_HOMING) && DISABLED(HAVE_TMC2130) + #error "Enable HAVE_TMC2130 to use SENSORLESS_HOMING." #endif /** * Make sure HAVE_TMC2208 is warranted */ - #if ENABLED(HAVE_TMC2208) && !( \ ENABLED( X_IS_TMC2208 ) \ || ENABLED( X2_IS_TMC2208 ) \ @@ -1486,6 +1484,10 @@ static_assert(1 >= 0 #error "Enable STEALTHCHOP to use HYBRID_THRESHOLD." #endif +#if ENABLED(TMC_Z_CALIBRATION) && !Z_IS_TRINAMIC && !Z2_IS_TRINAMIC + #error "TMC_Z_CALIBRATION requires at least one TMC driver on Z axis" +#endif + /** * Make sure HAVE_L6470DRIVER is warranted */ diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp index 9ad0b8e3705..be379605323 100644 --- a/Marlin/configuration_store.cpp +++ b/Marlin/configuration_store.cpp @@ -736,24 +736,23 @@ void MarlinSettings::postprocess() { // // TMC2130 Sensorless homing threshold // - int16_t thrs; - #if ENABLED(SENSORLESS_HOMING) - #if ENABLED(X_IS_TMC2130) - thrs = stepperX.sgt(); + int16_t thrs[2] = { + #if ENABLED(SENSORLESS_HOMING) + #if ENABLED(X_IS_TMC2130) + stepperX.sgt(), + #else + 0, + #endif + #if ENABLED(Y_IS_TMC2130) + stepperY.sgt() + #else + 0 + #endif #else - thrs = 0; + 0 #endif - EEPROM_WRITE(thrs); - #if ENABLED(Y_IS_TMC2130) - thrs = stepperY.sgt(); - #else - thrs = 0; - #endif - EEPROM_WRITE(thrs); - #else - thrs = 0; - for (uint8_t q = 2; q--;) EEPROM_WRITE(thrs); - #endif + }; + EEPROM_WRITE(thrs); // // Linear Advance @@ -775,8 +774,8 @@ void MarlinSettings::postprocess() { #if HAS_MOTOR_CURRENT_PWM for (uint8_t q = 3; q--;) EEPROM_WRITE(stepper.motor_current_setting[q]); #else - const uint32_t dummyui32 = 0; - for (uint8_t q = 3; q--;) EEPROM_WRITE(dummyui32); + const uint32_t dummyui32[3] = { 0 }; + EEPROM_WRITE(dummyui32); #endif // @@ -1261,28 +1260,23 @@ void MarlinSettings::postprocess() { * X and X2 use the same value * Y and Y2 use the same value */ - int16_t thrs; + int16_t thrs[2]; + EEPROM_READ(thrs); #if ENABLED(SENSORLESS_HOMING) - EEPROM_READ(thrs); if (!validating) { #if ENABLED(X_IS_TMC2130) - stepperX.sgt(thrs); + stepperX.sgt(thrs[0]); #endif #if ENABLED(X2_IS_TMC2130) - stepperX2.sgt(thrs); + stepperX2.sgt(thrs[0]); #endif - } - EEPROM_READ(thrs); - if (!validating) { #if ENABLED(Y_IS_TMC2130) - stepperY.sgt(thrs); + stepperY.sgt(thrs[1]); #endif #if ENABLED(Y2_IS_TMC2130) - stepperY2.sgt(thrs); + stepperY2.sgt(thrs[1]); #endif } - #else - for (uint8_t q = 0; q < 2; q++) EEPROM_READ(thrs); #endif // @@ -1308,8 +1302,8 @@ void MarlinSettings::postprocess() { #if HAS_MOTOR_CURRENT_PWM for (uint8_t q = 3; q--;) EEPROM_READ(stepper.motor_current_setting[q]); #else - uint32_t dummyui32; - for (uint8_t q = 3; q--;) EEPROM_READ(dummyui32); + uint32_t dummyui32[3]; + EEPROM_READ(dummyui32); #endif // diff --git a/Marlin/serial.h b/Marlin/serial.h index a2fd4306d16..1c98c8ee6f7 100644 --- a/Marlin/serial.h +++ b/Marlin/serial.h @@ -43,16 +43,20 @@ extern const char errormagic[] PROGMEM; #define SERIAL_CHAR(x) ((void)MYSERIAL.write(x)) #define SERIAL_EOL() SERIAL_CHAR('\n') +#define SERIAL_PRINT(x,b) MYSERIAL.print(x,b) +#define SERIAL_PRINTLN(x,b) MYSERIAL.println(x,b) +#define SERIAL_PRINTF(args...) MYSERIAL.printf(args) + #define SERIAL_PROTOCOLCHAR(x) SERIAL_CHAR(x) -#define SERIAL_PROTOCOL(x) (MYSERIAL.print(x)) -#define SERIAL_PROTOCOL_F(x,y) (MYSERIAL.print(x,y)) -#define SERIAL_PROTOCOLPGM(x) (serialprintPGM(PSTR(x))) +#define SERIAL_PROTOCOL(x) MYSERIAL.print(x) +#define SERIAL_PROTOCOL_F(x,y) MYSERIAL.print(x,y) +#define SERIAL_PROTOCOLPGM(x) serialprintPGM(PSTR(x)) #define SERIAL_PROTOCOLLN(x) do{ MYSERIAL.print(x); SERIAL_EOL(); }while(0) -#define SERIAL_PROTOCOLLNPGM(x) (serialprintPGM(PSTR(x "\n"))) -#define SERIAL_PROTOCOLPAIR(name, value) (serial_echopair_P(PSTR(name),(value))) +#define SERIAL_PROTOCOLLNPGM(x) serialprintPGM(PSTR(x "\n")) +#define SERIAL_PROTOCOLPAIR(name, value) serial_echopair_P(PSTR(name),(value)) #define SERIAL_PROTOCOLLNPAIR(name, value) do{ SERIAL_PROTOCOLPAIR(name, value); SERIAL_EOL(); }while(0) -#define SERIAL_ECHO_START() (serialprintPGM(echomagic)) +#define SERIAL_ECHO_START() serialprintPGM(echomagic) #define SERIAL_ECHO(x) SERIAL_PROTOCOL(x) #define SERIAL_ECHOPGM(x) SERIAL_PROTOCOLPGM(x) #define SERIAL_ECHOLN(x) SERIAL_PROTOCOLLN(x) @@ -61,7 +65,7 @@ extern const char errormagic[] PROGMEM; #define SERIAL_ECHOLNPAIR(pre,value) SERIAL_PROTOCOLLNPAIR(pre, value) #define SERIAL_ECHO_F(x,y) SERIAL_PROTOCOL_F(x,y) -#define SERIAL_ERROR_START() (serialprintPGM(errormagic)) +#define SERIAL_ERROR_START() serialprintPGM(errormagic) #define SERIAL_ERROR(x) SERIAL_PROTOCOL(x) #define SERIAL_ERRORPGM(x) SERIAL_PROTOCOLPGM(x) #define SERIAL_ERRORLN(x) SERIAL_PROTOCOLLN(x) diff --git a/Marlin/tmc_macros.h b/Marlin/tmc_macros.h deleted file mode 100644 index b98c460e0ba..00000000000 --- a/Marlin/tmc_macros.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Marlin 3D Printer Firmware - * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] - * - * Based on Sprinter and grbl. - * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -#ifndef TMC_MACROS_H -#define TMC_MACROS_H - - // Trinamic Stepper Drivers - #define HAS_TRINAMIC (ENABLED(HAVE_TMC2130) || ENABLED(HAVE_TMC2208) || ENABLED(IS_TRAMS)) - #define X_IS_TRINAMIC (ENABLED( X_IS_TMC2130) || ENABLED( X_IS_TMC2208) || ENABLED(IS_TRAMS)) - #define X2_IS_TRINAMIC (ENABLED(X2_IS_TMC2130) || ENABLED(X2_IS_TMC2208)) - #define Y_IS_TRINAMIC (ENABLED( Y_IS_TMC2130) || ENABLED( Y_IS_TMC2208) || ENABLED(IS_TRAMS)) - #define Y2_IS_TRINAMIC (ENABLED(Y2_IS_TMC2130) || ENABLED(Y2_IS_TMC2208)) - #define Z_IS_TRINAMIC (ENABLED( Z_IS_TMC2130) || ENABLED( Z_IS_TMC2208) || ENABLED(IS_TRAMS)) - #define Z2_IS_TRINAMIC (ENABLED(Z2_IS_TMC2130) || ENABLED(Z2_IS_TMC2208)) - #define E0_IS_TRINAMIC (ENABLED(E0_IS_TMC2130) || ENABLED(E0_IS_TMC2208) || ENABLED(IS_TRAMS)) - #define E1_IS_TRINAMIC (ENABLED(E1_IS_TMC2130) || ENABLED(E1_IS_TMC2208)) - #define E2_IS_TRINAMIC (ENABLED(E2_IS_TMC2130) || ENABLED(E2_IS_TMC2208)) - #define E3_IS_TRINAMIC (ENABLED(E3_IS_TMC2130) || ENABLED(E3_IS_TMC2208)) - #define E4_IS_TRINAMIC (ENABLED(E4_IS_TMC2130) || ENABLED(E4_IS_TMC2208)) - -#endif diff --git a/Marlin/tmc_util.cpp b/Marlin/tmc_util.cpp new file mode 100644 index 00000000000..3cd9091c4b6 --- /dev/null +++ b/Marlin/tmc_util.cpp @@ -0,0 +1,568 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "MarlinConfig.h" + +#if HAS_TRINAMIC + +#include "tmc_util.h" +#include "Marlin.h" +#include "duration_t.h" +#include "stepper_indirection.h" + +#if ENABLED(TMC_DEBUG) + #include "planner.h" +#endif + +bool report_tmc_status = false; +char extended_axis_codes[11][3] = { "X", "X2", "Y", "Y2", "Z", "Z2", "E0", "E1", "E2", "E3", "E4" }; + +/** + * Check for over temperature or short to ground error flags. + * Report and log warning of overtemperature condition. + * Reduce driver current in a persistent otpw condition. + * Keep track of otpw counter so we don't reduce current on a single instance, + * and so we don't repeatedly report warning before the condition is cleared. + */ +#if ENABLED(MONITOR_DRIVER_STATUS) + struct TMC_driver_data { + uint32_t drv_status; + bool is_otpw; + bool is_ot; + bool is_error; + }; + #if ENABLED(HAVE_TMC2130) + static uint32_t get_pwm_scale(TMC2130Stepper &st) { return st.PWM_SCALE(); } + static uint8_t get_status_response(TMC2130Stepper &st) { return st.status_response & 0xF; } + static TMC_driver_data get_driver_data(TMC2130Stepper &st) { + constexpr uint32_t OTPW_bm = 0x4000000UL; + constexpr uint8_t OTPW_bp = 26; + constexpr uint32_t OT_bm = 0x2000000UL; + constexpr uint8_t OT_bp = 25; + constexpr uint8_t DRIVER_ERROR_bm = 0x2UL; + constexpr uint8_t DRIVER_ERROR_bp = 1; + TMC_driver_data data; + data.drv_status = st.DRV_STATUS(); + data.is_otpw = (data.drv_status & OTPW_bm) >> OTPW_bp; + data.is_ot = (data.drv_status & OT_bm) >> OT_bp; + data.is_error = (st.status_response & DRIVER_ERROR_bm) >> DRIVER_ERROR_bp; + return data; + } + #endif + #if ENABLED(HAVE_TMC2208) + static uint32_t get_pwm_scale(TMC2208Stepper &st) { return st.pwm_scale_sum(); } + static uint8_t get_status_response(TMC2208Stepper &st) { + uint32_t drv_status = st.DRV_STATUS(); + uint8_t gstat = st.GSTAT(); + uint8_t response = 0; + response |= (drv_status >> (31-3)) & 0b1000; + response |= gstat & 0b11; + return response; + } + static TMC_driver_data get_driver_data(TMC2208Stepper &st) { + constexpr uint32_t OTPW_bm = 0b1ul; + constexpr uint8_t OTPW_bp = 0; + constexpr uint32_t OT_bm = 0b10ul; + constexpr uint8_t OT_bp = 1; + TMC_driver_data data; + data.drv_status = st.DRV_STATUS(); + data.is_otpw = (data.drv_status & OTPW_bm) >> OTPW_bp; + data.is_ot = (data.drv_status & OT_bm) >> OT_bp; + data.is_error = st.drv_err(); + return data; + } + #endif + + template<typename TMC> + void monitor_tmc_driver(TMC &st, const char axisID, uint8_t &otpw_cnt) { + TMC_driver_data data = get_driver_data(st); + + #if ENABLED(STOP_ON_ERROR) + if (data.is_error) { + SERIAL_EOL(); + SERIAL_ECHO(axisID); + SERIAL_ECHOPGM(" driver error detected:"); + if (data.is_ot) SERIAL_ECHOPGM("\novertemperature"); + if (st.s2ga()) SERIAL_ECHOPGM("\nshort to ground (coil A)"); + if (st.s2gb()) SERIAL_ECHOPGM("\nshort to ground (coil B)"); + SERIAL_EOL(); + #if ENABLED(TMC_DEBUG) + tmc_report_all(); + #endif + kill(PSTR("Driver error")); + } + #endif + + // Report if a warning was triggered + if (data.is_otpw && otpw_cnt == 0) { + char timestamp[10]; + duration_t elapsed = print_job_timer.duration(); + const bool has_days = (elapsed.value > 60*60*24L); + (void)elapsed.toDigital(timestamp, has_days); + SERIAL_EOL(); + SERIAL_ECHO(timestamp); + SERIAL_ECHOPGM(": "); + SERIAL_ECHO(axisID); + SERIAL_ECHOPGM(" driver overtemperature warning! ("); + SERIAL_ECHO(st.getCurrent()); + SERIAL_ECHOLNPGM("mA)"); + } + #if CURRENT_STEP_DOWN > 0 + // Decrease current if is_otpw is true and driver is enabled and there's been more then 4 warnings + if (data.is_otpw && !st.isEnabled() && otpw_cnt > 4) { + st.setCurrent(st.getCurrent() - CURRENT_STEP_DOWN, R_SENSE, HOLD_MULTIPLIER); + #if ENABLED(REPORT_CURRENT_CHANGE) + SERIAL_ECHO(axisID); + SERIAL_ECHOLNPAIR(" current decreased to ", st.getCurrent()); + #endif + } + #endif + + if (data.is_otpw) { + otpw_cnt++; + st.flag_otpw = true; + } + else if (otpw_cnt > 0) otpw_cnt--; + + if (report_tmc_status) { + const uint32_t pwm_scale = get_pwm_scale(st); + SERIAL_ECHO(axisID); + SERIAL_ECHOPAIR(":", pwm_scale); + SERIAL_ECHOPGM(" |0b"); SERIAL_PRINT(get_status_response(st), BIN); + SERIAL_ECHOPGM("| "); + if (data.is_error) SERIAL_CHAR('E'); + else if (data.is_ot) SERIAL_CHAR('O'); + else if (data.is_otpw) SERIAL_CHAR('W'); + else if (otpw_cnt > 0) SERIAL_PRINT(otpw_cnt, DEC); + else if (st.flag_otpw) SERIAL_CHAR('F'); + SERIAL_CHAR('\t'); + } + } + + #define HAS_HW_COMMS(ST) ENABLED(ST##_IS_TMC2130)|| (ENABLED(ST##_IS_TMC2208) && defined(ST##_HARDWARE_SERIAL)) + + void monitor_tmc_driver() { + static millis_t next_cOT = 0; + if (ELAPSED(millis(), next_cOT)) { + next_cOT = millis() + 500; + #if HAS_HW_COMMS(X) || ENABLED(IS_TRAMS) + static uint8_t x_otpw_cnt = 0; + monitor_tmc_driver(stepperX, axis_codes[X_AXIS], x_otpw_cnt); + #endif + #if HAS_HW_COMMS(Y) || ENABLED(IS_TRAMS) + static uint8_t y_otpw_cnt = 0; + monitor_tmc_driver(stepperY, axis_codes[Y_AXIS], y_otpw_cnt); + #endif + #if HAS_HW_COMMS(Z) || ENABLED(IS_TRAMS) + static uint8_t z_otpw_cnt = 0; + monitor_tmc_driver(stepperZ, axis_codes[Z_AXIS], z_otpw_cnt); + #endif + #if HAS_HW_COMMS(X2) + static uint8_t x2_otpw_cnt = 0; + monitor_tmc_driver(stepperX2, axis_codes[X_AXIS], x2_otpw_cnt); + #endif + #if HAS_HW_COMMS(Y2) + static uint8_t y2_otpw_cnt = 0; + monitor_tmc_driver(stepperY2, axis_codes[Y_AXIS], y2_otpw_cnt); + #endif + #if HAS_HW_COMMS(Z2) + static uint8_t z2_otpw_cnt = 0; + monitor_tmc_driver(stepperZ2, axis_codes[Z_AXIS], z2_otpw_cnt); + #endif + #if HAS_HW_COMMS(E0) || ENABLED(IS_TRAMS) + static uint8_t e0_otpw_cnt = 0; + monitor_tmc_driver(stepperE0, axis_codes[E_AXIS], e0_otpw_cnt); + #endif + #if HAS_HW_COMMS(E1) + static uint8_t e1_otpw_cnt = 0; + monitor_tmc_driver(stepperE1, axis_codes[E_AXIS], e1_otpw_cnt); + #endif + #if HAS_HW_COMMS(E2) + static uint8_t e2_otpw_cnt = 0; + monitor_tmc_driver(stepperE2, axis_codes[E_AXIS], e2_otpw_cnt); + #endif + #if HAS_HW_COMMS(E3) + static uint8_t e3_otpw_cnt = 0; + monitor_tmc_driver(stepperE3, axis_codes[E_AXIS], e3_otpw_cnt); + #endif + #if HAS_HW_COMMS(E4) + static uint8_t e4_otpw_cnt = 0; + monitor_tmc_driver(stepperE4, axis_codes[E_AXIS], e4_otpw_cnt); + #endif + + if (report_tmc_status) SERIAL_EOL(); + } + } + +#endif // MONITOR_DRIVER_STATUS + +void _tmc_say_current(const char name[], const uint16_t curr) { + SERIAL_ECHO(name); + SERIAL_ECHOLNPAIR(" axis driver current: ", curr); +} +void _tmc_say_otpw(const char name[], const bool otpw) { + SERIAL_ECHO(name); + SERIAL_ECHOPGM(" axis temperature prewarn triggered: "); + serialprintPGM(otpw ? PSTR("true") : PSTR("false")); + SERIAL_EOL(); +} +void _tmc_say_otpw_cleared(const char name[]) { + SERIAL_ECHO(name); + SERIAL_ECHOLNPGM(" prewarn flag cleared"); +} +void _tmc_say_pwmthrs(const char name[], const uint32_t thrs) { + SERIAL_ECHO(name); + SERIAL_ECHOLNPAIR(" stealthChop max speed set to ", thrs); +} +void _tmc_say_sgt(const char name[], const uint32_t sgt) { + SERIAL_ECHO(name); + SERIAL_ECHOPGM(" driver homing sensitivity set to "); + MYSERIAL.println(sgt, DEC); +} + +#if ENABLED(TMC_DEBUG) + + enum TMC_debug_enum { + TMC_CODES, + TMC_ENABLED, + TMC_CURRENT, + TMC_RMS_CURRENT, + TMC_MAX_CURRENT, + TMC_IRUN, + TMC_IHOLD, + TMC_CS_ACTUAL, + TMC_PWM_SCALE, + TMC_VSENSE, + TMC_STEALTHCHOP, + TMC_MICROSTEPS, + TMC_TSTEP, + TMC_TPWMTHRS, + TMC_TPWMTHRS_MMS, + TMC_OTPW, + TMC_OTPW_TRIGGERED, + TMC_TOFF, + TMC_TBL, + TMC_HEND, + TMC_HSTRT, + TMC_SGT + }; + enum TMC_drv_status_enum { + TMC_DRV_CODES, + TMC_STST, + TMC_OLB, + TMC_OLA, + TMC_S2GB, + TMC_S2GA, + TMC_DRV_OTPW, + TMC_OT, + TMC_STALLGUARD, + TMC_DRV_CS_ACTUAL, + TMC_FSACTIVE, + TMC_SG_RESULT, + TMC_DRV_STATUS_HEX, + TMC_T157, + TMC_T150, + TMC_T143, + TMC_T120, + TMC_STEALTH, + TMC_S2VSB, + TMC_S2VSA + }; + static void drv_status_print_hex(const char name[], const uint32_t drv_status) { + SERIAL_ECHO(name); + SERIAL_ECHOPGM(" = 0x"); + for (int B = 24; B >= 8; B -= 8){ + SERIAL_PRINT((drv_status >> (B + 4)) & 0xF, HEX); + SERIAL_PRINT((drv_status >> B) & 0xF, HEX); + SERIAL_CHAR(':'); + } + SERIAL_PRINT((drv_status >> 4) & 0xF, HEX); + SERIAL_PRINT((drv_status) & 0xF, HEX); + SERIAL_EOL(); + } + + #if ENABLED(HAVE_TMC2130) + static void tmc_status(TMC2130Stepper &st, const TMC_debug_enum i) { + switch(i) { + case TMC_PWM_SCALE: SERIAL_PRINT(st.PWM_SCALE(), DEC); break; + case TMC_TSTEP: SERIAL_ECHO(st.TSTEP()); break; + case TMC_SGT: SERIAL_PRINT(st.sgt(), DEC); break; + case TMC_STEALTHCHOP: serialprintPGM(st.stealthChop() ? PSTR("true") : PSTR("false")); break; + default: break; + } + } + static void tmc_parse_drv_status(TMC2130Stepper &st, const TMC_drv_status_enum i) { + switch(i) { + case TMC_STALLGUARD: if (st.stallguard()) SERIAL_CHAR('X'); break; + case TMC_SG_RESULT: SERIAL_PRINT(st.sg_result(), DEC); break; + case TMC_FSACTIVE: if (st.fsactive()) SERIAL_CHAR('X'); break; + default: break; + } + } + #endif + #if ENABLED(HAVE_TMC2208) + static void tmc_status(TMC2208Stepper &st, const TMC_debug_enum i) { + switch(i) { + case TMC_TSTEP: { + uint32_t data = 0; + st.TSTEP(&data); + MYSERIAL.print(data); + break; + } + case TMC_PWM_SCALE: SERIAL_PRINT(st.pwm_scale_sum(), DEC); break; + case TMC_STEALTHCHOP: serialprintPGM(st.stealth() ? PSTR("true") : PSTR("false")); break; + case TMC_S2VSA: if (st.s2vsa()) SERIAL_CHAR('X'); break; + case TMC_S2VSB: if (st.s2vsb()) SERIAL_CHAR('X'); break; + default: break; + } + } + static void tmc_parse_drv_status(TMC2208Stepper &st, const TMC_drv_status_enum i) { + switch(i) { + case TMC_T157: if (st.t157()) SERIAL_CHAR('X'); break; + case TMC_T150: if (st.t150()) SERIAL_CHAR('X'); break; + case TMC_T143: if (st.t143()) SERIAL_CHAR('X'); break; + case TMC_T120: if (st.t120()) SERIAL_CHAR('X'); break; + default: break; + } + } + #endif + + template <typename TMC> + static void tmc_status(TMC &st, TMC_AxisEnum axis, const TMC_debug_enum i, const float spmm) { + SERIAL_ECHO('\t'); + switch(i) { + case TMC_CODES: SERIAL_ECHO(extended_axis_codes[axis]); break; + case TMC_ENABLED: serialprintPGM(st.isEnabled() ? PSTR("true") : PSTR("false")); break; + case TMC_CURRENT: SERIAL_ECHO(st.getCurrent()); break; + case TMC_RMS_CURRENT: MYSERIAL.print(st.rms_current()); break; + case TMC_MAX_CURRENT: SERIAL_PRINT((float)st.rms_current() * 1.41, 0); break; + case TMC_IRUN: + SERIAL_PRINT(st.irun(), DEC); + SERIAL_ECHOPGM("/31"); + break; + case TMC_IHOLD: + SERIAL_PRINT(st.ihold(), DEC); + SERIAL_ECHOPGM("/31"); + break; + case TMC_CS_ACTUAL: + SERIAL_PRINT(st.cs_actual(), DEC); + SERIAL_ECHOPGM("/31"); + break; + + case TMC_VSENSE: serialprintPGM(st.vsense() ? PSTR("1=.18") : PSTR("0=.325")); break; + + case TMC_MICROSTEPS: SERIAL_ECHO(st.microsteps()); break; + case TMC_TPWMTHRS: { + uint32_t tpwmthrs_val = st.TPWMTHRS(); + SERIAL_ECHO(tpwmthrs_val); + } + break; + case TMC_TPWMTHRS_MMS: { + uint32_t tpwmthrs_val = st.TPWMTHRS(); + tpwmthrs_val ? SERIAL_ECHO(12650000UL * st.microsteps() / (256 * tpwmthrs_val * spmm)) : SERIAL_CHAR('-'); + } + break; + case TMC_OTPW: serialprintPGM(st.otpw() ? PSTR("true") : PSTR("false")); break; + case TMC_OTPW_TRIGGERED: serialprintPGM(st.getOTPW() ? PSTR("true") : PSTR("false")); break; + case TMC_TOFF: SERIAL_PRINT(st.toff(), DEC); break; + case TMC_TBL: SERIAL_PRINT(st.blank_time(), DEC); break; + case TMC_HEND: SERIAL_PRINT(st.hysterisis_end(), DEC); break; + case TMC_HSTRT: SERIAL_PRINT(st.hysterisis_start(), DEC); break; + default: tmc_status(st, i); break; + } + } + + template <typename TMC> + static void tmc_parse_drv_status(TMC &st, TMC_AxisEnum axis, const TMC_drv_status_enum i) { + SERIAL_CHAR('\t'); + switch(i) { + case TMC_DRV_CODES: SERIAL_ECHO(extended_axis_codes[axis]); break; + case TMC_STST: if (st.stst()) SERIAL_CHAR('X'); break; + case TMC_OLB: if (st.olb()) SERIAL_CHAR('X'); break; + case TMC_OLA: if (st.ola()) SERIAL_CHAR('X'); break; + case TMC_S2GB: if (st.s2gb()) SERIAL_CHAR('X'); break; + case TMC_S2GA: if (st.s2ga()) SERIAL_CHAR('X'); break; + case TMC_DRV_OTPW: if (st.otpw()) SERIAL_CHAR('X'); break; + case TMC_OT: if (st.ot()) SERIAL_CHAR('X'); break; + case TMC_DRV_CS_ACTUAL: SERIAL_PRINT(st.cs_actual(), DEC); break; + case TMC_DRV_STATUS_HEX:drv_status_print_hex(extended_axis_codes[axis], st.DRV_STATUS()); break; + default: tmc_parse_drv_status(st, i); break; + } + } + + static void tmc_debug_loop(const TMC_debug_enum i) { + #if X_IS_TRINAMIC + tmc_status(stepperX, TMC_X, i, planner.axis_steps_per_mm[X_AXIS]); + #endif + #if X2_IS_TRINAMIC + tmc_status(stepperX2, TMC_X2, i, planner.axis_steps_per_mm[X_AXIS]); + #endif + + #if Y_IS_TRINAMIC + tmc_status(stepperY, TMC_Y, i, planner.axis_steps_per_mm[Y_AXIS]); + #endif + #if Y2_IS_TRINAMIC + tmc_status(stepperY2, TMC_Y2, i, planner.axis_steps_per_mm[Y_AXIS]); + #endif + + #if Z_IS_TRINAMIC + tmc_status(stepperZ, TMC_Z, i, planner.axis_steps_per_mm[Z_AXIS]); + #endif + #if Z2_IS_TRINAMIC + tmc_status(stepperZ2, TMC_Z2, i, planner.axis_steps_per_mm[Z_AXIS]); + #endif + + #if E0_IS_TRINAMIC + tmc_status(stepperE0, TMC_E0, i, planner.axis_steps_per_mm[E_AXIS]); + #endif + #if E1_IS_TRINAMIC + tmc_status(stepperE1, TMC_E1, i, planner.axis_steps_per_mm[E_AXIS+1]); + #endif + #if E2_IS_TRINAMIC + tmc_status(stepperE2, TMC_E2, i, planner.axis_steps_per_mm[E_AXIS+2]); + #endif + #if E3_IS_TRINAMIC + tmc_status(stepperE3, TMC_E3, i, planner.axis_steps_per_mm[E_AXIS+3]); + #endif + #if E4_IS_TRINAMIC + tmc_status(stepperE4, TMC_E4, i, planner.axis_steps_per_mm[E_AXIS+4]); + #endif + + SERIAL_EOL(); + } + + static void drv_status_loop(const TMC_drv_status_enum i) { + #if X_IS_TRINAMIC + tmc_parse_drv_status(stepperX, TMC_X, i); + #endif + #if X2_IS_TRINAMIC + tmc_parse_drv_status(stepperX2, TMC_X2, i); + #endif + + #if Y_IS_TRINAMIC + tmc_parse_drv_status(stepperY, TMC_Y, i); + #endif + #if Y2_IS_TRINAMIC + tmc_parse_drv_status(stepperY2, TMC_Y2, i); + #endif + + #if Z_IS_TRINAMIC + tmc_parse_drv_status(stepperZ, TMC_Z, i); + #endif + #if Z2_IS_TRINAMIC + tmc_parse_drv_status(stepperZ2, TMC_Z2, i); + #endif + + #if E0_IS_TRINAMIC + tmc_parse_drv_status(stepperE0, TMC_E0, i); + #endif + #if E1_IS_TRINAMIC + tmc_parse_drv_status(stepperE1, TMC_E1, i); + #endif + #if E2_IS_TRINAMIC + tmc_parse_drv_status(stepperE2, TMC_E2, i); + #endif + #if E3_IS_TRINAMIC + tmc_parse_drv_status(stepperE3, TMC_E3, i); + #endif + #if E4_IS_TRINAMIC + tmc_parse_drv_status(stepperE4, TMC_E4, i); + #endif + + SERIAL_EOL(); + } + + /** + * M122 report functions + */ + void tmc_set_report_status(const bool status) { + if ((report_tmc_status = status)) + SERIAL_ECHOLNPGM("axis:pwm_scale |status_response|"); + } + + void tmc_report_all() { + #define TMC_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_debug_loop(ITEM); }while(0) + #define DRV_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); drv_status_loop(ITEM); }while(0) + TMC_REPORT("\t", TMC_CODES); + TMC_REPORT("Enabled\t", TMC_ENABLED); + TMC_REPORT("Set current", TMC_CURRENT); + TMC_REPORT("RMS current", TMC_RMS_CURRENT); + TMC_REPORT("MAX current", TMC_MAX_CURRENT); + TMC_REPORT("Run current", TMC_IRUN); + TMC_REPORT("Hold current", TMC_IHOLD); + TMC_REPORT("CS actual\t", TMC_CS_ACTUAL); + TMC_REPORT("PWM scale", TMC_PWM_SCALE); + TMC_REPORT("vsense\t", TMC_VSENSE); + TMC_REPORT("stealthChop", TMC_STEALTHCHOP); + TMC_REPORT("msteps\t", TMC_MICROSTEPS); + TMC_REPORT("tstep\t", TMC_TSTEP); + TMC_REPORT("pwm\nthreshold\t", TMC_TPWMTHRS); + TMC_REPORT("[mm/s]\t", TMC_TPWMTHRS_MMS); + TMC_REPORT("OT prewarn", TMC_OTPW); + TMC_REPORT("OT prewarn has\n" + "been triggered", TMC_OTPW_TRIGGERED); + TMC_REPORT("off time\t", TMC_TOFF); + TMC_REPORT("blank time", TMC_TBL); + TMC_REPORT("hysterisis\n-end\t", TMC_HEND); + TMC_REPORT("-start\t", TMC_HSTRT); + TMC_REPORT("Stallguard thrs", TMC_SGT); + + DRV_REPORT("DRVSTATUS", TMC_DRV_CODES); + #if ENABLED(HAVE_TMC2130) + DRV_REPORT("stallguard\t", TMC_STALLGUARD); + DRV_REPORT("sg_result\t", TMC_SG_RESULT); + DRV_REPORT("fsactive\t", TMC_FSACTIVE); + #endif + DRV_REPORT("stst\t", TMC_STST); + DRV_REPORT("olb\t", TMC_OLB); + DRV_REPORT("ola\t", TMC_OLA); + DRV_REPORT("s2gb\t", TMC_S2GB); + DRV_REPORT("s2ga\t", TMC_S2GA); + DRV_REPORT("otpw\t", TMC_DRV_OTPW); + DRV_REPORT("ot\t", TMC_OT); + #if ENABLED(HAVE_TMC2208) + DRV_REPORT("157C\t", TMC_T157); + DRV_REPORT("150C\t", TMC_T150); + DRV_REPORT("143C\t", TMC_T143); + DRV_REPORT("120C\t", TMC_T120); + DRV_REPORT("s2vsa\t", TMC_S2VSA); + DRV_REPORT("s2vsb\t", TMC_S2VSB); + #endif + DRV_REPORT("Driver registers:", TMC_DRV_STATUS_HEX); + SERIAL_EOL(); + } + +#endif // TMC_DEBUG + +#if ENABLED(SENSORLESS_HOMING) + + void tmc_sensorless_homing(TMC2130Stepper &st, bool enable/*=true*/) { + #if ENABLED(STEALTHCHOP) + st.coolstep_min_speed(enable ? 1024UL * 1024UL - 1UL : 0); + st.stealthChop(!enable); + #endif + st.diag1_stall(enable ? 1 : 0); + } + +#endif // SENSORLESS_HOMING + +#endif // HAS_TRINAMIC diff --git a/Marlin/tmc_util.h b/Marlin/tmc_util.h new file mode 100644 index 00000000000..14690067efc --- /dev/null +++ b/Marlin/tmc_util.h @@ -0,0 +1,103 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _TMC_UTIL_H_ +#define _TMC_UTIL_H_ + +#include <TMC2130Stepper.h> + +#include "MarlinConfig.h" + +extern bool report_tmc_status; +extern char extended_axis_codes[11][3]; + +enum TMC_AxisEnum { + TMC_X, TMC_X2, TMC_Y, TMC_Y2, TMC_Z, TMC_Z2, + TMC_E0, TMC_E1, TMC_E2, TMC_E3, TMC_E4 +}; + +constexpr uint32_t _tmc_thrs(const uint16_t msteps, const int32_t thrs, const uint32_t spmm) { + return 12650000UL * msteps / (256 * thrs * spmm); +} + +void _tmc_say_current(const char name[], const uint16_t curr); +void _tmc_say_otpw(const char name[], const bool otpw); +void _tmc_say_otpw_cleared(const char name[]); +void _tmc_say_pwmthrs(const char name[], const uint32_t thrs); +void _tmc_say_sgt(const char name[], const uint32_t sgt); + +template<typename TMC> +void tmc_get_current(TMC &st, const char name[]) { + _tmc_say_current(name, st.getCurrent()); +} +template<typename TMC> +void tmc_set_current(TMC &st, const char name[], const int mA) { + st.setCurrent(mA, R_SENSE, HOLD_MULTIPLIER); + tmc_get_current(st, name); +} +template<typename TMC> +void tmc_report_otpw(TMC &st, const char name[]) { + _tmc_say_otpw(name, st.getOTPW()); +} +template<typename TMC> +void tmc_clear_otpw(TMC &st, const char name[]) { + st.clear_otpw(); + _tmc_say_otpw_cleared(name); +} +template<typename TMC> +void tmc_get_pwmthrs(TMC &st, const char name[], const uint16_t spmm) { + _tmc_say_pwmthrs(name, _tmc_thrs(st.microsteps(), st.TPWMTHRS(), spmm)); +} +template<typename TMC> +void tmc_set_pwmthrs(TMC &st, const char name[], const int32_t thrs, const uint32_t spmm) { + st.TPWMTHRS(_tmc_thrs(st.microsteps(), thrs, spmm)); + tmc_get_pwmthrs(st, name, spmm); +} +template<typename TMC> +void tmc_get_sgt(TMC &st, const char name[]) { + _tmc_say_sgt(name, st.sgt()); +} +template<typename TMC> +void tmc_set_sgt(TMC &st, const char name[], const int8_t sgt_val) { + st.sgt(sgt_val); + tmc_get_sgt(st, name); +} + +void monitor_tmc_driver(); + +#if ENABLED(TMC_DEBUG) + void tmc_set_report_status(const bool status); + void tmc_report_all(); +#endif + +/** + * TMC2130 specific sensorless homing using stallGuard2. + * stallGuard2 only works when in spreadCycle mode. + * spreadCycle and stealthChop are mutually exclusive. + * + * Defined here because of limitations with templates and headers. + */ +#if ENABLED(SENSORLESS_HOMING) + void tmc_sensorless_homing(TMC2130Stepper &st, bool enable=true); +#endif + +#endif // _TMC_UTIL_H_