tmc5160: allow changing the globalscaler at runtime

Previously, the globalscaler was calculated during the config parsing and set to a fixed value. If the current was changed for any reason after the initialization, only IRUN and IHOLD would be changed. This however caused issues:
- If the new current was lower, then the resolution of the possible current values would be low since there are only 32 IRUN/IHOLD steps.
- If the new current was higher, it wouldn't actually work since IRUN and IHOLD are capped at 31, so it wouldn't be possible to increase the current without increasing globalscaler.

With this commit, the globalscaler is recalculated whenever necessary in order to ensure the correct range of IRUN/IHOLD is used.

Signed-off-by: Alex Voinea <voinea.dragos.alexandru@gmail.com>
This commit is contained in:
Alex Voinea 2023-03-04 10:25:49 +01:00 committed by KevinOConnor
parent e6307ca9fe
commit bee1c67416
3 changed files with 24 additions and 11 deletions

View File

@ -8,6 +8,14 @@ All dates in this document are approximate.
## Changes ## Changes
20230304: The `SET_TMC_CURRENT` command now properly adjusts the globalscaler
register for drivers that have it. This removes a limitation where on tmc5160,
the currents could not be raised higher with `SET_TMC_CURRENT` than the
`run_current` value set in the config file.
However, this has a side effect: After running `SET_TMC_CURRENT`, the stepper
must be held at standstill for >130ms in case StealthChop2 is used so that the
AT#1 calibration gets executed by the driver.
20230202: The format of the `printer.screws_tilt_adjust` status 20230202: The format of the `printer.screws_tilt_adjust` status
information has changed. The information is now stored as a dictionary of information has changed. The information is now stored as a dictionary of
screws with the resulting measurements. See the screws with the resulting measurements. See the

View File

@ -1226,7 +1226,10 @@ turned off then back on.
#### SET_TMC_CURRENT #### SET_TMC_CURRENT
`SET_TMC_CURRENT STEPPER=<name> CURRENT=<amps> HOLDCURRENT=<amps>`: `SET_TMC_CURRENT STEPPER=<name> CURRENT=<amps> HOLDCURRENT=<amps>`:
This will adjust the run and hold currents of the TMC driver. This will adjust the run and hold currents of the TMC driver.
(HOLDCURRENT is not applicable to tmc2660 drivers.) `HOLDCURRENT` is not applicable to tmc2660 drivers.
When used on a driver which has the `globalscaler` field (tmc5160 and tmc2240),
if StealthChop2 is used, the stepper must be held at standstill for >130ms so
that the driver executes the AT#1 calibration.
#### SET_TMC_FIELD #### SET_TMC_FIELD
`SET_TMC_FIELD STEPPER=<name> FIELD=<field> VALUE=<value>`: This will `SET_TMC_FIELD STEPPER=<name> FIELD=<field> VALUE=<value>`: This will

View File

@ -264,19 +264,18 @@ class TMC5160CurrentHelper:
above=0., maxval=MAX_CURRENT) above=0., maxval=MAX_CURRENT)
self.req_hold_current = hold_current self.req_hold_current = hold_current
self.sense_resistor = config.getfloat('sense_resistor', 0.075, above=0.) self.sense_resistor = config.getfloat('sense_resistor', 0.075, above=0.)
self._set_globalscaler(run_current) gscaler, irun, ihold = self._calc_current(run_current, hold_current)
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("ihold", ihold)
self.fields.set_field("irun", irun) self.fields.set_field("irun", irun)
def _set_globalscaler(self, current): def _calc_globalscaler(self, current):
globalscaler = int((current * 256. * math.sqrt(2.) globalscaler = int((current * 256. * math.sqrt(2.)
* self.sense_resistor / VREF) + .5) * self.sense_resistor / VREF) + .5)
globalscaler = max(32, globalscaler) globalscaler = max(32, globalscaler)
if globalscaler >= 256: if globalscaler >= 256:
globalscaler = 0 globalscaler = 0
self.fields.set_field("globalscaler", globalscaler) return globalscaler
def _calc_current_bits(self, current): def _calc_current_bits(self, current, globalscaler):
globalscaler = self.fields.get_field("globalscaler")
if not globalscaler: if not globalscaler:
globalscaler = 256 globalscaler = 256
cs = int((current * 256. * 32. * math.sqrt(2.) * self.sense_resistor) cs = int((current * 256. * 32. * math.sqrt(2.) * self.sense_resistor)
@ -284,9 +283,10 @@ class TMC5160CurrentHelper:
- 1. + .5) - 1. + .5)
return max(0, min(31, cs)) return max(0, min(31, cs))
def _calc_current(self, run_current, hold_current): def _calc_current(self, run_current, hold_current):
irun = self._calc_current_bits(run_current) gscaler = self._calc_globalscaler(run_current)
ihold = self._calc_current_bits(min(hold_current, run_current)) irun = self._calc_current_bits(run_current, gscaler)
return irun, ihold ihold = self._calc_current_bits(min(hold_current, run_current), gscaler)
return gscaler, irun, ihold
def _calc_current_from_field(self, field_name): def _calc_current_from_field(self, field_name):
globalscaler = self.fields.get_field("globalscaler") globalscaler = self.fields.get_field("globalscaler")
if not globalscaler: if not globalscaler:
@ -300,7 +300,9 @@ class TMC5160CurrentHelper:
return run_current, hold_current, self.req_hold_current, MAX_CURRENT return run_current, hold_current, self.req_hold_current, MAX_CURRENT
def set_current(self, run_current, hold_current, print_time): def set_current(self, run_current, hold_current, print_time):
self.req_hold_current = hold_current self.req_hold_current = hold_current
irun, ihold = self._calc_current(run_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) self.fields.set_field("ihold", ihold)
val = self.fields.set_field("irun", irun) val = self.fields.set_field("irun", irun)
self.mcu_tmc.set_register("IHOLD_IRUN", val, print_time) self.mcu_tmc.set_register("IHOLD_IRUN", val, print_time)