diff --git a/README.md b/README.md index 0cc07003c..602c3510a 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,8 @@ See the [Danger Features document](https://docs.kalico.gg/Danger_Features.html) - [danger_options: configurable homing constants](https://github.com/KalicoCrew/kalico/pull/378) +- [tmc2240: adjustable driver_CS and current_range](https://github.com/KalicoCrew/kalico/pull/556) + If you're feeling adventurous, take a peek at the extra features in the bleeding-edge-v2 branch [feature documentation](docs/Bleeding_Edge.md) and [feature configuration reference](docs/Config_Reference_Bleeding_Edge.md): diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index cc80f34d9..9af66d8aa 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -2634,11 +2634,11 @@ for more detailed information regarding symptoms, configuration and setup. calibrate_start_x: 20 # Defines the minimum X coordinate of the calibration # This should be the X coordinate that positions the nozzle at the starting -# calibration position. +# calibration position. calibrate_end_x: 200 # Defines the maximum X coordinate of the calibration # This should be the X coordinate that positions the nozzle at the ending -# calibration position. +# calibration position. calibrate_y: 112.5 # Defines the Y coordinate of the calibration # This should be the Y coordinate that positions the nozzle during the @@ -4427,6 +4427,13 @@ run_current: # velocity" threshold (THIGH) to. This is typically used to disable # the "CoolStep" feature at high speeds. The default is to not set a # TMC "high velocity" threshold. +#current_range: +# The current_range bit value for the driver. Valid values are 0 and 32-255. +# The defaul is to auto-calculate to match the requested run_current. +# For further information consult the tmc2240 datasheet and tuning table. +#driver_CS: 31 +# The current_scaler value for the driver. The default is 31. +# For further information consult the tmc2240 datasheet and tuning table. #driver_MSLUT0: 2863314260 #driver_MSLUT1: 1251300522 #driver_MSLUT2: 608774441 diff --git a/docs/Kalico_Additions.md b/docs/Kalico_Additions.md index 18c639f89..327cabbe2 100644 --- a/docs/Kalico_Additions.md +++ b/docs/Kalico_Additions.md @@ -55,6 +55,11 @@ - [`[temperature_fan] reverse: True`](./Config_Reference.md#temperature_fan) will let you control a fan in reverse to temperature control. The lower the temperature, the higher the fan runs. - Fans now normalize PWM power within `off_below` and `max_power`, so setting a fan to 10% will get you 10% fan speed within your configured off/max range. + +## TMC Drivers + +- [`[tmc2240] driver_CS and current_range`](./Config_Reference.md#tmc2240) let you tune the current scaler and current range of your tmc2240 drivers. + ## Macros - The jinja `do` extension has been enabled. You can now call functions in your macros without resorting to dirty hacks: `{% do array.append(5) %}` diff --git a/klippy/extras/tmc.py b/klippy/extras/tmc.py index ff699060b..d478c62ae 100644 --- a/klippy/extras/tmc.py +++ b/klippy/extras/tmc.py @@ -773,13 +773,14 @@ def TMCStealthchopHelper(config, mcu_tmc, tmc_freq): class BaseTMCCurrentHelper: - def __init__(self, config, mcu_tmc, max_current): + def __init__(self, config, mcu_tmc, max_current, has_sense_resistor=True): self.printer = config.get_printer() self.name = config.get_name().split()[-1] self.mcu_tmc = mcu_tmc self.fields = mcu_tmc.get_fields() - self.sense_resistor = config.getfloat("sense_resistor", above=0.0) + if has_sense_resistor: + self.sense_resistor = config.getfloat("sense_resistor", above=0.0) # config_{run|hold|home}_current # represents an initial value set via config file diff --git a/klippy/extras/tmc2240.py b/klippy/extras/tmc2240.py index 16a597ae7..c2c358b41 100644 --- a/klippy/extras/tmc2240.py +++ b/klippy/extras/tmc2240.py @@ -263,37 +263,30 @@ # TMC stepper current config helper ###################################################################### +KIFS = [11750.0, 24000.0, 36000.0, 36000.0] +GLOBALSCALER_ERROR = ( + "[tmc2240 %s]\n" + "GLOBALSCALER(%d) calculation out of bounds.\n" + "The target current can't be achieved with the given RREF(%f) " + "and CS(%d). Please adjust your configuration.\n" + "Calculated current_range bit: %s\n" + "Calculated KIFS: %s" +) + class TMC2240CurrentHelper(tmc.BaseTMCCurrentHelper): 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", minval=12000.0, maxval=60000.0) - self.max_current = self._get_ifs_rms(3) - self.config_run_current = config.getfloat( - "run_current", above=0.0, maxval=self.max_current - ) - self.config_hold_current = config.getfloat( - "hold_current", self.max_current, above=0.0, maxval=self.max_current - ) - self.config_home_current = config.getfloat( - "home_current", - self.config_run_current, - above=0.0, - maxval=self.max_current, + super().__init__( + config, mcu_tmc, self._get_ifs_rms(3), has_sense_resistor=False ) - self.current_change_dwell_time = config.getfloat( - "current_change_dwell_time", 0.5, above=0.0 - ) - self.req_run_current = self.config_run_current - self.req_hold_current = self.config_hold_current - self.req_home_current = self.config_home_current - self.actual_current = self.req_run_current current_range = self._calc_current_range(self.actual_current) - self.fields.set_field("current_range", current_range) + self.current_range = config.getint( + "current_range", current_range, minval=current_range, maxval=3 + ) + self.fields.set_field("current_range", self.current_range) + self.cs = config.getint("driver_CS", 31, minval=0, maxval=31) gscaler, irun, ihold = self._calc_current( self.req_run_current, self.req_hold_current ) @@ -304,7 +297,6 @@ def __init__(self, config, mcu_tmc): def _get_ifs_rms(self, current_range=None): if current_range is None: current_range = self.fields.get_field("current_range") - KIFS = [11750.0, 24000.0, 36000.0, 36000.0] return (KIFS[current_range] / self.Rref) / math.sqrt(2.0) def _calc_current_range(self, current): @@ -315,25 +307,30 @@ def _calc_current_range(self, current): def _calc_globalscaler(self, current): ifs_rms = self._get_ifs_rms() - globalscaler = int(((current * 256.0) / ifs_rms) + 0.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.0 * 32.0) / (globalscaler * ifs_rms) - 1.0 + 0.5 + globalscaler = math.floor( + (current * 256.0 * 32) / (ifs_rms * (self.cs + 1)) ) - return max(0, min(31, cs)) + if globalscaler == 256: + return 0 + if 1 <= globalscaler <= 31 or globalscaler > 256: + current_range = self.fields.get_field("current_range") + self.printer.invoke_shutdown( + GLOBALSCALER_ERROR + % ( + self.name, + globalscaler, + self.Rref, + self.cs, + f"{current_range:02b}", + f"{(KIFS[current_range] / 1000):.2f}", + ) + ) + return globalscaler 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) + irun = self.cs + ihold = math.floor((min((hold_current / run_current) * irun, irun))) return gscaler, irun, ihold def _calc_current_from_field(self, field_name): diff --git a/test/klippy/tmc.cfg b/test/klippy/tmc.cfg index 0a55a9977..66c23361e 100644 --- a/test/klippy/tmc.cfg +++ b/test/klippy/tmc.cfg @@ -98,6 +98,8 @@ rotation_distance: 8 cs_pin: PK3 run_current: .5 rref: 12000 +driver_CS: 30 +current_range: 0 [mcu] serial: /dev/ttyACM0