tmc2130: Rework current selection to prefer vsense=1

It is preferable to program the tmc drivers with an irun (or cs)
setting near 31, as otherwise the driver may have reduced microstep
precision.  It was possible for the driver to be programmed with
irun=16 or irun=17 when it could have been configured with irun=31
with vsense=1 instead.  This would occur on tmc2130/tmc2208/tmc2209
drivers for values around 0.900 to 1.000 amps (when using a typical
sense_resistor settings of 0.110 Ohms).

Change the code to prefer using vsense=1 to avoid this issue.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2022-01-12 23:43:11 -05:00
parent 89b4fecac4
commit 34a1ce4837
3 changed files with 45 additions and 27 deletions

View File

@ -8,6 +8,12 @@ All dates in this document are approximate.
## Changes ## Changes
20220116: The tmc2130, tmc2208, tmc2209, and tmc2660 `run_current`
calculation code has changed. For some `run_current` settings the
drivers may now be configured differently. This new configuration
should be more accurate, but it may invalidate previous tmc driver
tuning.
20211230: Scripts to tune input shaper (`scripts/calibrate_shaper.py` 20211230: Scripts to tune input shaper (`scripts/calibrate_shaper.py`
and `scripts/graph_accelerometer.py`) were migrated to use Python3 and `scripts/graph_accelerometer.py`) were migrated to use Python3
by default. As a result, users must install Python3 versions of certain by default. As a result, users must install Python3 versions of certain

View File

@ -116,30 +116,33 @@ class TMCCurrentHelper:
vref = 0.32 vref = 0.32
if vsense: if vsense:
vref = 0.18 vref = 0.18
cs = int(32. * current * sense_resistor * math.sqrt(2.) / vref cs = int(32. * sense_resistor * current * math.sqrt(2.) / vref + .5) - 1
- 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_from_bits(self, cs, vsense):
vsense = False
irun = self._calc_current_bits(run_current, vsense)
ihold = self._calc_current_bits(min(hold_current, run_current),
vsense)
if irun < 16 and ihold < 16:
vsense = True
irun = self._calc_current_bits(run_current, vsense)
ihold = self._calc_current_bits(min(hold_current, run_current),
vsense)
return vsense, irun, ihold
def _calc_current_from_field(self, field_name):
bits = self.fields.get_field(field_name)
sense_resistor = self.sense_resistor + 0.020 sense_resistor = self.sense_resistor + 0.020
vref = 0.32 vref = 0.32
if self.fields.get_field("vsense"): if vsense:
vref = 0.18 vref = 0.18
return (bits + 1) * vref / (32 * sense_resistor * math.sqrt(2.)) return (cs + 1) * vref / (32. * sense_resistor * math.sqrt(2.))
def _calc_current(self, run_current, hold_current):
vsense = True
irun = self._calc_current_bits(run_current, True)
if irun == 31:
cur = self._calc_current_from_bits(irun, True)
if cur < run_current:
irun2 = self._calc_current_bits(run_current, False)
cur2 = self._calc_current_from_bits(irun2, False)
if abs(run_current - cur2) < abs(run_current - cur):
vsense = False
irun = irun2
ihold = self._calc_current_bits(min(hold_current, run_current), vsense)
return vsense, irun, ihold
def get_current(self): def get_current(self):
run_current = self._calc_current_from_field("irun") irun = self.fields.get_field("irun")
hold_current = self._calc_current_from_field("ihold") ihold = self.fields.get_field("ihold")
vsense = self.fields.get_field("vsense")
run_current = self._calc_current_from_bits(irun, vsense)
hold_current = self._calc_current_from_bits(ihold, vsense)
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

View File

@ -136,17 +136,26 @@ class TMC2660CurrentHelper:
def _calc_current_bits(self, current, vsense): def _calc_current_bits(self, current, vsense):
vref = 0.165 if vsense else 0.310 vref = 0.165 if vsense else 0.310
cs = int(32 * current * self.sense_resistor * math.sqrt(2.) / vref sr = self.sense_resistor
- 1. + .5) cs = int(32. * sr * current * math.sqrt(2.) / vref + .5) - 1
return max(0, min(31, cs)) return max(0, min(31, cs))
def _calc_current_from_bits(self, cs, vsense):
vref = 0.165 if vsense else 0.310
return (cs + 1) * vref / (32. * self.sense_resistor * math.sqrt(2.))
def _calc_current(self, run_current): def _calc_current(self, run_current):
vsense = False vsense = True
cs = self._calc_current_bits(run_current, vsense) irun = self._calc_current_bits(run_current, True)
if cs < 16: if irun == 31:
vsense = True cur = self._calc_current_from_bits(irun, True)
cs = self._calc_current_bits(run_current, vsense) if cur < run_current:
return vsense, cs irun2 = self._calc_current_bits(run_current, False)
cur2 = self._calc_current_from_bits(irun2, False)
if abs(run_current - cur2) < abs(run_current - cur):
vsense = False
irun = irun2
return vsense, irun
def _handle_printing(self, print_time): def _handle_printing(self, print_time):
print_time -= 0.100 # Schedule slightly before deadline print_time -= 0.100 # Schedule slightly before deadline