[tmc2209] Add chopper and PWM tuning actions (#20753)

This commit is contained in:
Remco van Essen
2026-10-14 08:59:21 -10:00
committed by GitHub
parent 3fa72e61c6
commit 15fb7f775e
4 changed files with 123 additions and 0 deletions
+77
View File
@@ -24,7 +24,9 @@ CONF_CLOCK_FREQUENCY = "clock_frequency"
CONF_DIAG_PIN = "diag_pin"
CONF_ENABLE_SPREADCYCLE = "enable_spreadcycle"
CONF_ENN_PIN = "enn_pin"
CONF_HEND = "hend"
CONF_HOLD_CURRENT = "hold_current"
CONF_HSTRT = "hstrt"
CONF_IHOLD = "ihold"
CONF_IHOLDDELAY = "iholddelay"
CONF_INDEX_PIN = "index_pin"
@@ -34,9 +36,18 @@ CONF_IRUN = "irun"
CONF_MICROSTEPS = "microsteps"
CONF_ON_STATUS = "on_status"
CONF_OTTRIM = "ottrim"
CONF_PWM_AUTOGRAD = "pwm_autograd"
CONF_PWM_AUTOSCALE = "pwm_autoscale"
CONF_PWM_FREQ = "pwm_freq"
CONF_PWM_GRAD = "pwm_grad"
CONF_PWM_LIM = "pwm_lim"
CONF_PWM_OFS = "pwm_ofs"
CONF_PWM_REG = "pwm_reg"
CONF_RSENSE = "rsense"
CONF_RUN_CURRENT = "run_current"
CONF_STANDSTILL_MODE = "standstill_mode"
CONF_TBL = "tbl"
CONF_TOFF = "toff"
CONF_TPOWERDOWN = "tpowerdown"
CONF_TPWM_THRESHOLD = "tpwm_threshold"
CONF_VSENSE = "vsense"
@@ -110,6 +121,29 @@ def _validate_analog_current_scale(config: ConfigType) -> ConfigType:
return config
def _validate_chopconf(config: ConfigType) -> ConfigType:
# Only values given as constants can be checked here, not lambdas
toff, tbl = config.get(CONF_TOFF), config.get(CONF_TBL)
# TBL is never written at setup, so the chip may still hold a blank time below 2
if toff == 1 and (tbl is None or (isinstance(tbl, int) and tbl < 2)):
raise cv.Invalid(
f"'{CONF_TOFF}: 1' needs '{CONF_TBL}' set to 2 or higher in the same "
"action",
path=[CONF_TOFF],
)
hend, hstrt = config.get(CONF_HEND), config.get(CONF_HSTRT)
# Register values are offsets: HEND 0-15 is -3 to 12, HSTRT 0-7 is 1 to 8
if isinstance(hend, int) and isinstance(hstrt, int):
hysteresis = (hend - 3) + (hstrt + 1)
if hysteresis > 16:
raise cv.Invalid(
f"'{CONF_HEND}' and '{CONF_HSTRT}' give a hysteresis of "
f"{hysteresis}, the limit is 16",
path=[CONF_HEND],
)
return config
def final_validate(config: ConfigType) -> ConfigType:
"""Reject two drivers of the family with the same address on one UART bus."""
for other in fv.full_config.get().get("stepper", []):
@@ -225,3 +259,46 @@ def register_actions(domain: str, cls: MockObjClass) -> None:
CONF_STANDSTILL_MODE, "set_standstill_mode", StandstillMode
),
)
automation.register_apply_action(
f"{domain}.chopconf",
cv.All(
cv.Schema(
{
**id_schema,
cv.Optional(CONF_TOFF): cv.templatable(cv.int_range(1, 15)),
cv.Optional(CONF_TBL): cv.templatable(cv.int_range(0, 3)),
cv.Optional(CONF_HEND): cv.templatable(cv.int_range(0, 15)),
cv.Optional(CONF_HSTRT): cv.templatable(cv.int_range(0, 7)),
}
),
_validate_chopconf,
),
automation.ApplyField(CONF_TOFF, "set_toff", cg.uint8),
automation.ApplyField(CONF_TBL, "set_tbl", cg.uint8),
automation.ApplyField(CONF_HEND, "set_hend", cg.uint8),
automation.ApplyField(CONF_HSTRT, "set_hstrt", cg.uint8),
)
automation.register_apply_action(
f"{domain}.pwmconf",
cv.Schema(
{
**id_schema,
cv.Optional(CONF_PWM_OFS): cv.templatable(cv.uint8_t),
cv.Optional(CONF_PWM_GRAD): cv.templatable(cv.uint8_t),
cv.Optional(CONF_PWM_FREQ): cv.templatable(cv.int_range(0, 3)),
cv.Optional(CONF_PWM_AUTOSCALE): cv.templatable(cv.boolean),
cv.Optional(CONF_PWM_AUTOGRAD): cv.templatable(cv.boolean),
cv.Optional(CONF_PWM_REG): cv.templatable(cv.int_range(1, 15)),
cv.Optional(CONF_PWM_LIM): cv.templatable(cv.int_range(0, 15)),
}
),
automation.ApplyField(CONF_PWM_OFS, "set_pwm_ofs", cg.uint8),
automation.ApplyField(CONF_PWM_GRAD, "set_pwm_grad", cg.uint8),
automation.ApplyField(CONF_PWM_FREQ, "set_pwm_freq", cg.uint8),
automation.ApplyField(CONF_PWM_AUTOSCALE, "set_pwm_autoscale", cg.bool_),
automation.ApplyField(CONF_PWM_AUTOGRAD, "set_pwm_autograd", cg.bool_),
automation.ApplyField(CONF_PWM_REG, "set_pwm_reg", cg.uint8),
automation.ApplyField(CONF_PWM_LIM, "set_pwm_lim", cg.uint8),
)
+7
View File
@@ -362,6 +362,13 @@ void TMC22XXStepper::set_enabled(bool enabled) {
this->enabled_ = enabled;
}
void TMC22XXStepper::set_toff(uint8_t toff) {
this->toff_ = toff;
// Without an ENN pin, TOFF=0 is what keeps the outputs disabled
if (this->enabled_ || this->enn_pin_ != nullptr)
this->write_field(TOFF, toff);
}
void TMC22XXStepper::set_microsteps(uint16_t microsteps) {
for (uint8_t mres = 0; mres <= 8; mres++) {
if ((256u >> mres) == microsteps) {
+24
View File
@@ -57,12 +57,22 @@ static constexpr RegisterField TPOWERDOWN{REG_TPOWERDOWN, 0, 8, false};
static constexpr RegisterField TPWMTHRS{REG_TPWMTHRS, 0, 20, false};
static constexpr RegisterField VACTUAL{REG_VACTUAL, 0, 24, true};
static constexpr RegisterField TOFF{REG_CHOPCONF, 0, 4, false};
static constexpr RegisterField HSTRT{REG_CHOPCONF, 4, 3, false};
static constexpr RegisterField HEND{REG_CHOPCONF, 7, 4, false};
static constexpr RegisterField TBL{REG_CHOPCONF, 15, 2, false};
static constexpr RegisterField VSENSE{REG_CHOPCONF, 17, 1, false};
static constexpr RegisterField MRES{REG_CHOPCONF, 24, 4, false};
static constexpr RegisterField INTPOL{REG_CHOPCONF, 28, 1, false};
static constexpr RegisterField DEDGE{REG_CHOPCONF, 29, 1, false};
static constexpr RegisterField CS_ACTUAL{REG_DRV_STATUS, 16, 5, false};
static constexpr RegisterField PWM_OFS{REG_PWMCONF, 0, 8, false};
static constexpr RegisterField PWM_GRAD{REG_PWMCONF, 8, 8, false};
static constexpr RegisterField PWM_FREQ{REG_PWMCONF, 16, 2, false};
static constexpr RegisterField PWM_AUTOSCALE{REG_PWMCONF, 18, 1, false};
static constexpr RegisterField PWM_AUTOGRAD{REG_PWMCONF, 19, 1, false};
static constexpr RegisterField FREEWHEEL{REG_PWMCONF, 20, 2, false};
static constexpr RegisterField PWM_REG{REG_PWMCONF, 24, 4, false};
static constexpr RegisterField PWM_LIM{REG_PWMCONF, 28, 4, false};
static constexpr RegisterField PWM_SCALE_SUM{REG_PWM_SCALE, 0, 8, false};
static constexpr RegisterField PWM_SCALE_AUTO{REG_PWM_SCALE, 16, 9, true};
static constexpr RegisterField PWM_OFS_AUTO{REG_PWM_AUTO, 0, 8, false};
@@ -160,6 +170,20 @@ class TMC22XXStepper : public stepper::Stepper, public Component, public uart::U
void set_iholddelay(uint8_t delay) { this->write_field(IHOLDDELAY, delay); }
void set_tpowerdown(uint8_t tpowerdown) { this->write_field(TPOWERDOWN, tpowerdown); }
void set_standstill_mode(StandstillMode mode) { this->write_field(FREEWHEEL, mode); }
/// Chopper off time (1-15). TOFF=0 is used to disable the outputs, so this is applied on the next enable.
void set_toff(uint8_t toff);
void set_tbl(uint8_t tbl) { this->write_field(TBL, tbl); }
void set_hend(uint8_t hend) { this->write_field(HEND, hend); }
void set_hstrt(uint8_t hstrt) { this->write_field(HSTRT, hstrt); }
void set_pwm_ofs(uint8_t ofs) { this->write_field(PWM_OFS, ofs); }
void set_pwm_grad(uint8_t grad) { this->write_field(PWM_GRAD, grad); }
void set_pwm_freq(uint8_t freq) { this->write_field(PWM_FREQ, freq); }
void set_pwm_autoscale(bool enable) { this->write_field(PWM_AUTOSCALE, enable); }
void set_pwm_autograd(bool enable) { this->write_field(PWM_AUTOGRAD, enable); }
void set_pwm_reg(uint8_t reg) { this->write_field(PWM_REG, reg); }
void set_pwm_lim(uint8_t lim) { this->write_field(PWM_LIM, lim); }
/// Convert a current scale (0-31) to A RMS, without analog current scale.
float scale_to_current(uint8_t scale);
+15
View File
@@ -78,6 +78,21 @@ esphome:
seup: 1
sedn: 0
seimin: true
- tmc2209.chopconf:
id: tmc2209_step_dir
toff: 4
tbl: 2
hend: 0
hstrt: !lambda "return 5;"
- tmc2209.pwmconf:
id: tmc2209_serial
pwm_ofs: 36
pwm_grad: 14
pwm_freq: 1
pwm_autoscale: true
pwm_autograd: true
pwm_reg: 4
pwm_lim: 12
- tmc2209.enable: tmc2209_serial
- stepper.set_target:
id: tmc2209_serial