aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/Config_Reference.md119
-rw-r--r--klippy/extras/angle.py3
-rw-r--r--klippy/extras/endstop_phase.py3
-rw-r--r--klippy/extras/tmc2240.py397
-rw-r--r--test/klippy/tmc.cfg11
-rw-r--r--test/klippy/tmc.test4
6 files changed, 535 insertions, 2 deletions
diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md
index dda7266b..494a4733 100644
--- a/docs/Config_Reference.md
+++ b/docs/Config_Reference.md
@@ -3307,6 +3307,125 @@ run_current:
# HDEC) is interpreted as the MSB of HSTRT in this case).
```
+### [tmc2240]
+
+Configure a TMC2240 stepper motor driver via SPI bus. To use this
+feature, define a config section with a "tmc2240" prefix followed by
+the name of the corresponding stepper config section (for example,
+"[tmc2240 stepper_x]").
+
+```
+[tmc2240 stepper_x]
+cs_pin:
+# The pin corresponding to the TMC2240 chip select line. This pin
+# will be set to low at the start of SPI messages and raised to high
+# after the message completes. This parameter must be provided.
+#spi_speed:
+#spi_bus:
+#spi_software_sclk_pin:
+#spi_software_mosi_pin:
+#spi_software_miso_pin:
+# See the "common SPI settings" section for a description of the
+# above parameters.
+#chain_position:
+#chain_length:
+# These parameters configure an SPI daisy chain. The two parameters
+# define the stepper position in the chain and the total chain length.
+# Position 1 corresponds to the stepper that connects to the MOSI signal.
+# The default is to not use an SPI daisy chain.
+#interpolate: True
+# If true, enable step interpolation (the driver will internally
+# step at a rate of 256 micro-steps). The default is True.
+run_current:
+# The amount of current (in amps RMS) to configure the driver to use
+# during stepper movement. This parameter must be provided.
+#hold_current:
+# The amount of current (in amps RMS) to configure the driver to use
+# when the stepper is not moving. Setting a hold_current is not
+# recommended (see TMC_Drivers.md for details). The default is to
+# not reduce the current.
+#rref: 12000
+# The resistance (in ohms) of the resistor between IREF and GND. The
+# default is 12000.
+#stealthchop_threshold: 0
+# The velocity (in mm/s) to set the "stealthChop" threshold to. When
+# set, "stealthChop" mode will be enabled if the stepper motor
+# velocity is below this value. The default is 0, which disables
+# "stealthChop" mode.
+#driver_MSLUT0: 2863314260
+#driver_MSLUT1: 1251300522
+#driver_MSLUT2: 608774441
+#driver_MSLUT3: 269500962
+#driver_MSLUT4: 4227858431
+#driver_MSLUT5: 3048961917
+#driver_MSLUT6: 1227445590
+#driver_MSLUT7: 4211234
+#driver_W0: 2
+#driver_W1: 1
+#driver_W2: 1
+#driver_W3: 1
+#driver_X1: 128
+#driver_X2: 255
+#driver_X3: 255
+#driver_START_SIN: 0
+#driver_START_SIN90: 247
+#driver_OFFSET_SIN90: 0
+# These fields control the Microstep Table registers directly. The optimal
+# wave table is specific to each motor and might vary with current. An
+# optimal configuration will have minimal print artifacts caused by
+# non-linear stepper movement. The values specified above are the default
+# values used by the driver. The value must be specified as a decimal integer
+# (hex form is not supported). In order to compute the wave table fields,
+# see the tmc2130 "Calculation Sheet" from the Trinamic website.
+# Additionally, this driver also has the OFFSET_SIN90 field which can be used
+# to tune a motor with unbalanced coils. See the `Sine Wave Lookup Table`
+# section in the datasheet for information about this field and how to tune
+# it.
+#driver_IHOLDDELAY: 6
+#driver_IRUNDELAY: 4
+#driver_TPOWERDOWN: 10
+#driver_TBL: 2
+#driver_TOFF: 3
+#driver_HEND: 2
+#driver_HSTRT: 5
+#driver_FD3: 0
+#driver_TPFD: 4
+#driver_CHM: 0
+#driver_VHIGHFS: 0
+#driver_VHIGHCHM: 0
+#driver_DISS2G: 0
+#driver_DISS2VS: 0
+#driver_PWM_AUTOSCALE: True
+#driver_PWM_AUTOGRAD: True
+#driver_PWM_FREQ: 0
+#driver_FREEWHEEL: 0
+#driver_PWM_GRAD: 0
+#driver_PWM_OFS: 29
+#driver_PWM_REG: 4
+#driver_PWM_LIM: 12
+#driver_SGT: 0
+#driver_SEMIN: 0
+#driver_SEUP: 0
+#driver_SEMAX: 0
+#driver_SEDN: 0
+#driver_SEIMIN: 0
+#driver_SFILT: 0
+# Set the given register during the configuration of the TMC2240
+# chip. This may be used to set custom motor parameters. The
+# defaults for each parameter are next to the parameter name in the
+# above list.
+#diag0_pin:
+#diag1_pin:
+# The micro-controller pin attached to one of the DIAG lines of the
+# TMC2240 chip. Only a single diag pin should be specified. The pin
+# is "active low" and is thus normally prefaced with "^!". Setting
+# this creates a "tmc2240_stepper_x:virtual_endstop" virtual pin
+# which may be used as the stepper's endstop_pin. Doing this enables
+# "sensorless homing". (Be sure to also set driver_SGT to an
+# appropriate sensitivity value.) The default is to not enable
+# sensorless homing.
+```
+
### [tmc5160]
Configure a TMC5160 stepper motor driver via SPI bus. To use this
diff --git a/klippy/extras/angle.py b/klippy/extras/angle.py
index d61a7634..2e17749e 100644
--- a/klippy/extras/angle.py
+++ b/klippy/extras/angle.py
@@ -9,7 +9,8 @@ from . import bus, motion_report
MIN_MSG_TIME = 0.100
TCODE_ERROR = 0xff
-TRINAMIC_DRIVERS = ["tmc2130", "tmc2208", "tmc2209", "tmc2660", "tmc5160"]
+TRINAMIC_DRIVERS = ["tmc2130", "tmc2208", "tmc2209", "tmc2240", "tmc2660",
+ "tmc5160"]
CALIBRATION_BITS = 6 # 64 entries
ANGLE_BITS = 16 # angles range from 0..65535
diff --git a/klippy/extras/endstop_phase.py b/klippy/extras/endstop_phase.py
index bd34ddbe..feb9e8b8 100644
--- a/klippy/extras/endstop_phase.py
+++ b/klippy/extras/endstop_phase.py
@@ -6,7 +6,8 @@
import math, logging
import stepper
-TRINAMIC_DRIVERS = ["tmc2130", "tmc2208", "tmc2209", "tmc2660", "tmc5160"]
+TRINAMIC_DRIVERS = ["tmc2130", "tmc2208", "tmc2209", "tmc2240", "tmc2660",
+ "tmc5160"]
# Calculate the trigger phase of a stepper motor
class PhaseCalc:
diff --git a/klippy/extras/tmc2240.py b/klippy/extras/tmc2240.py
new file mode 100644
index 00000000..45570625
--- /dev/null
+++ b/klippy/extras/tmc2240.py
@@ -0,0 +1,397 @@
+# TMC2240 configuration
+#
+# Copyright (C) 2018-2023 Kevin O'Connor <kevin@koconnor.net>
+# Copyright (C) 2023 Alex Voinea <voinea.dragos.alexandru@gmail.com>
+#
+# This file may be distributed under the terms of the GNU GPLv3 license.
+import math, logging
+from . import bus, tmc, tmc2130
+
+TMC_FREQUENCY=12500000.
+
+Registers = {
+ "GCONF": 0x00,
+ "GSTAT": 0x01,
+ "IFCNT": 0x02,
+ "NODECONF": 0x03,
+ "IOIN": 0x04,
+ "DRV_CONF": 0x0A,
+ "GLOBALSCALER": 0x0B,
+ "IHOLD_IRUN": 0x10,
+ "TPOWERDOWN": 0x11,
+ "TSTEP": 0x12,
+ "TPWMTHRS": 0x13,
+ "TCOOLTHRS": 0x14,
+ "THIGH": 0x15,
+ "DIRECT_MODE": 0x2D,
+ "ENCMODE": 0x38,
+ "X_ENC": 0x39,
+ "ENC_CONST": 0x3A,
+ "ENC_STATUS": 0x3B,
+ "ENC_LATCH": 0x3C,
+ "ADC_VSUPPLY_AIN": 0x50,
+ "ADC_TEMP": 0x51,
+ "OTW_OV_VTH": 0x52,
+ "MSLUT0": 0x60,
+ "MSLUT1": 0x61,
+ "MSLUT2": 0x62,
+ "MSLUT3": 0x63,
+ "MSLUT4": 0x64,
+ "MSLUT5": 0x65,
+ "MSLUT6": 0x66,
+ "MSLUT7": 0x67,
+ "MSLUTSEL": 0x68,
+ "MSLUTSTART": 0x69,
+ "MSCNT": 0x6A,
+ "MSCURACT": 0x6B,
+ "CHOPCONF": 0x6C,
+ "COOLCONF": 0x6D,
+ "DRV_STATUS": 0x6F,
+ "PWMCONF": 0x70,
+ "PWM_SCALE": 0x71,
+ "PWM_AUTO": 0x72,
+ "SG4_THRS": 0x74,
+ "SG4_RESULT": 0x75,
+ "SG4_IND": 0x76,
+}
+
+ReadRegisters = [
+ "GCONF", "GSTAT", "IOIN", "DRV_CONF", "GLOBALSCALER", "IHOLD_IRUN",
+ "TPOWERDOWN", "TSTEP", "TPWMTHRS", "TCOOLTHRS", "THIGH", "ADC_VSUPPLY_AIN",
+ "ADC_TEMP", "MSCNT", "MSCURACT", "CHOPCONF", "COOLCONF", "DRV_STATUS",
+ "PWMCONF", "PWM_SCALE", "PWM_AUTO", "SG4_THRS", "SG4_RESULT", "SG4_IND"
+]
+
+Fields = {}
+Fields["COOLCONF"] = {
+ "semin": 0x0F << 0,
+ "seup": 0x03 << 5,
+ "semax": 0x0F << 8,
+ "sedn": 0x03 << 13,
+ "seimin": 0x01 << 15,
+ "sgt": 0x7F << 16,
+ "sfilt": 0x01 << 24
+}
+Fields["CHOPCONF"] = {
+ "toff": 0x0F << 0,
+ "hstrt": 0x07 << 4,
+ "hend": 0x0F << 7,
+ "fd3": 0x01 << 11,
+ "disfdcc": 0x01 << 12,
+ "chm": 0x01 << 14,
+ "tbl": 0x03 << 15,
+ "vhighfs": 0x01 << 18,
+ "vhighchm": 0x01 << 19,
+ "tpfd": 0x0F << 20, # midrange resonances
+ "mres": 0x0F << 24,
+ "intpol": 0x01 << 28,
+ "dedge": 0x01 << 29,
+ "diss2g": 0x01 << 30,
+ "diss2vs": 0x01 << 31
+}
+Fields["DRV_STATUS"] = {
+ "sg_result": 0x3FF << 0,
+ "s2vsa": 0x01 << 12,
+ "s2vsb": 0x01 << 13,
+ "stealth": 0x01 << 14,
+ "fsactive": 0x01 << 15,
+ "csactual": 0x1F << 16,
+ "stallguard": 0x01 << 24,
+ "ot": 0x01 << 25,
+ "otpw": 0x01 << 26,
+ "s2ga": 0x01 << 27,
+ "s2gb": 0x01 << 28,
+ "ola": 0x01 << 29,
+ "olb": 0x01 << 30,
+ "stst": 0x01 << 31
+}
+Fields["GCONF"] = {
+ "faststandstill": 0x01 << 1,
+ "en_pwm_mode": 0x01 << 2,
+ "multistep_filt": 0x01 << 3,
+ "shaft": 0x01 << 4,
+ "diag0_error": 0x01 << 5,
+ "diag0_otpw": 0x01 << 6,
+ "diag0_stall": 0x01 << 7,
+ "diag1_stall": 0x01 << 8,
+ "diag1_index": 0x01 << 9,
+ "diag1_onstate": 0x01 << 10,
+ "diag0_pushpull": 0x01 << 12,
+ "diag1_pushpull": 0x01 << 13,
+ "small_hysteresis": 0x01 << 14,
+ "stop_enable": 0x01 << 15,
+ "direct_mode": 0x01 << 16
+}
+Fields["GSTAT"] = {
+ "reset": 0x01 << 0,
+ "drv_err": 0x01 << 1,
+ "uv_cp": 0x01 << 2,
+ "register_reset": 0x01 << 3,
+ "vm_uvlo": 0x01 << 4
+}
+Fields["GLOBALSCALER"] = {
+ "globalscaler": 0xFF << 0
+}
+Fields["IHOLD_IRUN"] = {
+ "ihold": 0x1F << 0,
+ "irun": 0x1F << 8,
+ "iholddelay": 0x0F << 16,
+ "irundelay": 0x0F << 24
+}
+Fields["IOIN"] = {
+ "step": 0x01 << 0,
+ "dir": 0x01 << 1,
+ "encb": 0x01 << 2,
+ "enca": 0x01 << 3,
+ "drv_enn": 0x01 << 4,
+ "encn": 0x01 << 5,
+ "uart_en": 0x01 << 6,
+ "comp_a": 0x01 << 8,
+ "comp_b": 0x01 << 9,
+ "comp_a1_a2": 0x01 << 10,
+ "comp_b1_b2": 0x01 << 11,
+ "output": 0x01 << 12,
+ "ext_res_det": 0x01 << 13,
+ "ext_clk": 0x01 << 14,
+ "adc_err": 0x01 << 15,
+ "silicon_rv": 0x07 << 16,
+ "version": 0xFF << 24
+}
+Fields["MSLUT0"] = { "mslut0": 0xffffffff }
+Fields["MSLUT1"] = { "mslut1": 0xffffffff }
+Fields["MSLUT2"] = { "mslut2": 0xffffffff }
+Fields["MSLUT3"] = { "mslut3": 0xffffffff }
+Fields["MSLUT4"] = { "mslut4": 0xffffffff }
+Fields["MSLUT5"] = { "mslut5": 0xffffffff }
+Fields["MSLUT6"] = { "mslut6": 0xffffffff }
+Fields["MSLUT7"] = { "mslut7": 0xffffffff }
+Fields["MSLUTSEL"] = {
+ "x3": 0xFF << 24,
+ "x2": 0xFF << 16,
+ "x1": 0xFF << 8,
+ "w3": 0x03 << 6,
+ "w2": 0x03 << 4,
+ "w1": 0x03 << 2,
+ "w0": 0x03 << 0,
+}
+Fields["MSLUTSTART"] = {
+ "start_sin": 0xFF << 0,
+ "start_sin90": 0xFF << 16,
+ "offset_sin90": 0xFF << 24,
+}
+Fields["MSCNT"] = {
+ "mscnt": 0x3ff << 0
+}
+Fields["MSCURACT"] = {
+ "cur_a": 0x1ff << 0,
+ "cur_b": 0x1ff << 16
+}
+Fields["PWM_AUTO"] = {
+ "pwm_ofs_auto": 0xff << 0,
+ "pwm_grad_auto": 0xff << 16
+}
+Fields["PWMCONF"] = {
+ "pwm_ofs": 0xFF << 0,
+ "pwm_grad": 0xFF << 8,
+ "pwm_freq": 0x03 << 16,
+ "pwm_autoscale": 0x01 << 18,
+ "pwm_autograd": 0x01 << 19,
+ "freewheel": 0x03 << 20,
+ "pwm_meas_sd_enable": 0x01 << 22,
+ "pwm_dis_reg_stst": 0x01 << 23,
+ "pwm_reg": 0x0F << 24,
+ "pwm_lim": 0x0F << 28
+}
+Fields["PWM_SCALE"] = {
+ "pwm_scale_sum": 0x3ff << 0,
+ "pwm_scale_auto": 0x1ff << 16
+}
+Fields["TPOWERDOWN"] = {
+ "tpowerdown": 0xff << 0
+}
+Fields["TPWMTHRS"] = {
+ "tpwmthrs": 0xfffff << 0
+}
+Fields["TCOOLTHRS"] = {
+ "tcoolthrs": 0xfffff << 0
+}
+Fields["TSTEP"] = {
+ "tstep": 0xfffff << 0
+}
+Fields["THIGH"] = {
+ "thigh": 0xfffff << 0
+}
+Fields["DRV_CONF"] = {
+ "current_range": 0x03 << 0,
+ "slope_control": 0x03 << 4
+}
+Fields["ADC_VSUPPLY_AIN"] = {
+ "adc_vsupply": 0x1fff << 0,
+ "adc_ain": 0x1fff << 16
+}
+Fields["ADC_TEMP"] = {
+ "adc_temp": 0x1fff << 0
+}
+Fields["OTW_OV_VTH"] = {
+ "overvoltage_vth": 0x1fff << 0,
+ "overtempprewarning_vth": 0x1fff << 16
+}
+Fields["SG4_THRS"] = {
+ "sg4_thrs": 0xFF << 0,
+ "sg4_filt_en": 0x01 << 8,
+ "sg4_angle_offset": 0x01 << 9
+}
+Fields["SG4_RESULT"] = {
+ "sg4_result": 0x3FF << 0
+}
+Fields["SG4_IND"] = {
+ "sg4_ind_0": 0xFF << 0,
+ "sg4_ind_1": 0xFF << 8,
+ "sg4_ind_2": 0xFF << 16,
+ "sg4_ind_3": 0xFF << 24
+}
+
+
+SignedFields = ["cur_a", "cur_b", "sgt", "pwm_scale_auto", "offset_sin90"]
+
+FieldFormatters = dict(tmc2130.FieldFormatters)
+FieldFormatters.update({
+ "s2vsa": (lambda v: "1(ShortToSupply_A!)" if v else ""),
+ "s2vsb": (lambda v: "1(ShortToSupply_B!)" if v else ""),
+ "adc_temp": (lambda v: "0x%04x(%.1fC)" % (v, ((v - 2038) / 7.7))),
+})
+
+
+######################################################################
+# TMC stepper current config helper
+######################################################################
+
+class TMC2240CurrentHelper:
+ def __init__(self, config, mcu_tmc):
+ self.printer = config.get_printer()
+ self.name = config.get_name().split()[-1]
+ self.mcu_tmc = mcu_tmc
+ self.fields = mcu_tmc.get_fields()
+ self.Rref = config.getfloat('rref', 12000.,
+ minval=12000., maxval=60000.)
+ max_cur = self._get_ifs_rms(3)
+ run_current = config.getfloat('run_current', above=0., maxval=max_cur)
+ hold_current = config.getfloat('hold_current', max_cur,
+ above=0., maxval=max_cur)
+ self.req_hold_current = hold_current
+ current_range = self._calc_current_range(run_current)
+ self.fields.set_field("current_range", current_range)
+ gscaler, irun, ihold = self._calc_current(run_current, hold_current)
+ self.fields.set_field("globalscaler", gscaler)
+ self.fields.set_field("ihold", ihold)
+ self.fields.set_field("irun", irun)
+ def _get_ifs_rms(self, current_range=None):
+ if current_range is None:
+ current_range = self.fields.get_field("current_range")
+ KIFS = [11750., 24000., 36000., 36000.]
+ return (KIFS[current_range] / self.Rref) / math.sqrt(2.)
+ def _calc_current_range(self, current):
+ for current_range in range(4):
+ if current <= self._get_ifs_rms(current_range):
+ break
+ return current_range
+ def _calc_globalscaler(self, current):
+ ifs_rms = self._get_ifs_rms()
+ globalscaler = int(((current * 256.) / ifs_rms) + .5)
+ globalscaler = max(32, globalscaler)
+ if globalscaler >= 256:
+ globalscaler = 0
+ return globalscaler
+ def _calc_current_bits(self, current, globalscaler):
+ ifs_rms = self._get_ifs_rms()
+ if not globalscaler:
+ globalscaler = 256
+ cs = int((current * 256. * 32.) / (globalscaler * ifs_rms) - 1. + .5)
+ return max(0, min(31, cs))
+ def _calc_current(self, run_current, hold_current):
+ gscaler = self._calc_globalscaler(run_current)
+ irun = self._calc_current_bits(run_current, gscaler)
+ ihold = self._calc_current_bits(min(hold_current, run_current), gscaler)
+ return gscaler, irun, ihold
+ def _calc_current_from_field(self, field_name):
+ ifs_rms = self._get_ifs_rms()
+ globalscaler = self.fields.get_field("globalscaler")
+ if not globalscaler:
+ globalscaler = 256
+ bits = self.fields.get_field(field_name)
+ return globalscaler * (bits + 1) * ifs_rms / (256. * 32.)
+ def get_current(self):
+ ifs_rms = self._get_ifs_rms()
+ run_current = self._calc_current_from_field("irun")
+ hold_current = self._calc_current_from_field("ihold")
+ return (run_current, hold_current, self.req_hold_current, ifs_rms)
+ def set_current(self, run_current, hold_current, print_time):
+ self.req_hold_current = hold_current
+ gscaler, irun, ihold = self._calc_current(run_current, hold_current)
+ val = self.fields.set_field("globalscaler", gscaler)
+ self.mcu_tmc.set_register("GLOBALSCALER", val, print_time)
+ self.fields.set_field("ihold", ihold)
+ val = self.fields.set_field("irun", irun)
+ self.mcu_tmc.set_register("IHOLD_IRUN", val, print_time)
+
+
+######################################################################
+# TMC2240 printer object
+######################################################################
+
+class TMC2240:
+ def __init__(self, config):
+ # Setup mcu communication
+ self.fields = tmc.FieldHelper(Fields, SignedFields, FieldFormatters)
+ self.mcu_tmc = tmc2130.MCU_TMC_SPI(config, Registers, self.fields)
+ # Allow virtual pins to be created
+ tmc.TMCVirtualPinHelper(config, self.mcu_tmc)
+ # Register commands
+ current_helper = TMC2240CurrentHelper(config, self.mcu_tmc)
+ cmdhelper = tmc.TMCCommandHelper(config, self.mcu_tmc, current_helper)
+ cmdhelper.setup_register_dump(ReadRegisters)
+ self.get_phase_offset = cmdhelper.get_phase_offset
+ self.get_status = cmdhelper.get_status
+ # Setup basic register values
+ tmc.TMCWaveTableHelper(config, self.mcu_tmc)
+ self.fields.set_config_field(config, "offset_sin90", 0)
+ tmc.TMCStealthchopHelper(config, self.mcu_tmc, TMC_FREQUENCY)
+ # CHOPCONF
+ set_config_field = self.fields.set_config_field
+ set_config_field(config, "toff", 3)
+ set_config_field(config, "hstrt", 5)
+ set_config_field(config, "hend", 2)
+ set_config_field(config, "fd3", 0)
+ set_config_field(config, "disfdcc", 0)
+ set_config_field(config, "chm", 0)
+ set_config_field(config, "tbl", 2)
+ set_config_field(config, "vhighfs", 0)
+ set_config_field(config, "vhighchm", 0)
+ set_config_field(config, "tpfd", 4)
+ set_config_field(config, "diss2g", 0)
+ set_config_field(config, "diss2vs", 0)
+ # COOLCONF
+ set_config_field(config, "semin", 0)
+ set_config_field(config, "seup", 0)
+ set_config_field(config, "semax", 0)
+ set_config_field(config, "sedn", 0)
+ set_config_field(config, "seimin", 0)
+ set_config_field(config, "sgt", 0)
+ set_config_field(config, "sfilt", 0)
+ # IHOLDIRUN
+ set_config_field(config, "iholddelay", 6)
+ set_config_field(config, "irundelay", 4)
+ # PWMCONF
+ set_config_field(config, "pwm_ofs", 29)
+ set_config_field(config, "pwm_grad", 0)
+ set_config_field(config, "pwm_freq", 0)
+ set_config_field(config, "pwm_autoscale", True)
+ set_config_field(config, "pwm_autograd", True)
+ set_config_field(config, "freewheel", 0)
+ set_config_field(config, "pwm_reg", 4)
+ set_config_field(config, "pwm_lim", 12)
+ # TPOWERDOWN
+ set_config_field(config, "tpowerdown", 10)
+
+def load_config_prefix(config):
+ return TMC2240(config)
diff --git a/test/klippy/tmc.cfg b/test/klippy/tmc.cfg
index ffdb93f3..4ae85f44 100644
--- a/test/klippy/tmc.cfg
+++ b/test/klippy/tmc.cfg
@@ -84,6 +84,17 @@ cs_pin: PK1
run_current: .5
sense_resistor: 0.220
+[stepper_z2]
+step_pin: PH1
+dir_pin: PA2
+enable_pin: !PA3
+microsteps: 16
+rotation_distance: 8
+
+[tmc2240 stepper_z2]
+cs_pin: PK3
+run_current: .5
+
[mcu]
serial: /dev/ttyACM0
diff --git a/test/klippy/tmc.test b/test/klippy/tmc.test
index 44053463..d8af0e6a 100644
--- a/test/klippy/tmc.test
+++ b/test/klippy/tmc.test
@@ -19,6 +19,7 @@ DUMP_TMC STEPPER=stepper_y
DUMP_TMC STEPPER=stepper_y1
DUMP_TMC STEPPER=stepper_z
DUMP_TMC STEPPER=stepper_z1
+DUMP_TMC STEPPER=stepper_z2
; Test INIT_TMC commands
INIT_TMC STEPPER=stepper_x
@@ -27,6 +28,7 @@ INIT_TMC STEPPER=stepper_y
INIT_TMC STEPPER=stepper_y1
INIT_TMC STEPPER=stepper_z
INIT_TMC STEPPER=stepper_z1
+INIT_TMC STEPPER=stepper_z2
; Test SET_TMC_CURRENT commands
SET_TMC_CURRENT STEPPER=stepper_x CURRENT=.7
@@ -35,6 +37,7 @@ SET_TMC_CURRENT STEPPER=stepper_y CURRENT=.7
SET_TMC_CURRENT STEPPER=stepper_y1 CURRENT=.7
SET_TMC_CURRENT STEPPER=stepper_z CURRENT=.7
SET_TMC_CURRENT STEPPER=stepper_z1 CURRENT=.7
+SET_TMC_CURRENT STEPPER=stepper_z2 CURRENT=.6
; Test SET_TMC_FIELD commands
SET_TMC_FIELD STEPPER=stepper_x FIELD=intpol VALUE=0
@@ -43,3 +46,4 @@ SET_TMC_FIELD STEPPER=stepper_y FIELD=intpol VALUE=0
SET_TMC_FIELD STEPPER=stepper_y1 FIELD=intpol VALUE=0
SET_TMC_FIELD STEPPER=stepper_z FIELD=intpol VALUE=0
SET_TMC_FIELD STEPPER=stepper_z1 FIELD=intpol VALUE=0
+SET_TMC_FIELD STEPPER=stepper_z2 FIELD=intpol VALUE=0