TMC2160 步进驱动调试:从高速丢步到 400 rpm 验证

作者:Felix (Haro 协作整理)

这次调试的对象是一块板载 TMC2160 步进驱动,目标是驱动一颗 57 步进电机跑到接近外置驱动器的高速表现。最初现象很明确:同一颗电机用外置驱动器空载可以接近 400 rpm,而板载 TMC2160 初始配置在 300 rpm 左右就开始明显丢步。低速能动,高速有电流但不跟转;单纯提高电流也没有根本改善。

最后的结果是:板载 TMC2160 在 64 细分下可以实测达到 400 rpm,400 rpm 偶发丢步,表现已经接近外置驱动器;380 rpm 则更适合作为工程上的稳定工作点。真正起作用的不是某一个“神奇参数”,而是先确认硬件配置脚,再确认驱动模式和速度读回,最后围绕细分和模式切换建立可验证的基线。

最终稳定基线

当前保留下来的运动基线是 200 full steps/rev、64 微步,也就是每圈 12800 个 STEP 脉冲:

#define MOTOR_FULL_STEPS_PER_ROUND 200U
#define MOTOR_MICROSTEP_PER_FULL_STEP 64U
#define MOTOR_PULSE_PER_ROUND (MOTOR_FULL_STEPS_PER_ROUND * MOTOR_MICROSTEP_PER_FULL_STEP)

#define TMC2160_CHOPCONF_SPREADCYCLE_64MICROSTEP_INTPOL 0x120100C3U
#define TMC2160_CHOPCONF_MICROSTEP_INTPOL TMC2160_CHOPCONF_SPREADCYCLE_64MICROSTEP_INTPOL

Motor0 的关键配置如下:

#define TMC2160_MOTOR0_GCONF_TEST TMC2160_GCONF_STEALTHCHOP_SPREADCYCLE
#define TMC2160_MOTOR0_IHOLD_IRUN_TEST 0x61A02U
#define TMC2160_MOTOR0_TPWM_THRS_TEST 0x96U

PWMCONF = 0xC4002228
CHOPCONF = 0x120100C3
  • GCONF=0x2C:开启 stealthChop,同时保留原有 step filter / diag 配置。
  • CHOPCONF=0x120100C3:64 细分,开启 INTPOL,使用 spreadCycle baseline。
  • IHOLD_IRUN=0x61A02IHOLD=2IRUN=26,按 0.05 ohm 采样电阻估算约 4A RMS。
  • TPWM_THRS=0x96:低速 stealthChop,高速 spreadCycle,切换点约 94 rpm。
  • PWMCONF=0xC4002228:固定 stealthChop 前馈基线,暂不使用自动整定。

第一件事:确认 DCEN 没有误进入 dcStep

这次最关键的硬件问题是 DCEN_CFG4。如果 DCEN 为高,TMC2160 会启用 dcStep 相关功能。dcStep 不是普通开环 STEP/DIR 高速运行所需要的模式,它会改变驱动器对运动的处理方式,高速时可能出现“有电流但电机不按 STEP 走”的现象。

项目原理图里 DCEN 相关网络接到了 MCU IO,因此调试时先通过软件把对应 IO 配成开漏输出低:

static void TMC2160_Disable_Dcstep_Pin(void)
{
    LL_GPIO_ResetOutputPin(TMC2160_DCEN0_PORT, TMC2160_DCEN0_PIN);
    LL_GPIO_ResetOutputPin(TMC2160_DCEN1_PORT, TMC2160_DCEN1_PIN);
    LL_GPIO_ResetOutputPin(TMC2160_DCEN2_PORT, TMC2160_DCEN2_PIN);
    LL_GPIO_ResetOutputPin(TMC2160_DCEN3_PORT, TMC2160_DCEN3_PIN);

    GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
    ...
}

随后读取 IOIN 确认实际电平:

m0 ioin=30000040 step=0 dir=0 dcen=0 dcin=0 drv_enn=0 dco=0 ver=30
m1 ioin=30000040 step=0 dir=0 dcen=0 dcin=0 drv_enn=0 dco=0 ver=30
m2 ioin=30000040 step=0 dir=0 dcen=0 dcin=0 drv_enn=0 dco=0 ver=30
m3 ioin=30000040 step=0 dir=0 dcen=0 dcin=0 drv_enn=0 dco=0 ver=30

这里最重要的是 dcen=0。调 TMC2160 这类芯片时,不能只看 SPI 寄存器写入值;硬件配置脚也必须通过 IOIN 读回确认。

不要把高速丢步简单归因于电流不足

早期尝试过提高电流,Motor0 提到 IRUN=26,按实际 0.05 ohm 采样电阻估算约 4A RMS。电流变大以后,16 细分下 400 rpm 仍然不稳定,高速段还是可能丢步。这说明主因不是单纯的“电流不够”。

如果电机已经明显发热、电流也已经很大,而高速仍然不跟转,就应该回到更基础的问题:

  • 驱动器是否进入了错误模式,例如 dcStep。
  • spreadCycle 参数是否被过度试验,偏离了可用 baseline。
  • STEP 输入频率是否真实到达目标速度。
  • 细分是否带来了共振、振动或换相不平滑。
  • 负载、方向、行程位置是否影响高速稳定性。

本次最后保留约 4A RMS,是因为温升可以接受,而且 400 rpm 已经接近机械系统边界;但它不是唯一决定因素。

低速和高速分工:stealthChop + spreadCycle

TMC2160 常用的两个工作方式各有侧重:stealthChop 是电压 PWM 模式,低速安静、平顺;spreadCycle 是周期电流控制,高速动态和负载响应更好。本项目最后采用低速 stealthChop、高速 spreadCycle 的组合。

切换点由 TPWM_THRS 决定:

#define TMC2160_TPWM_THRS_100RPM 0x96U

TMC2160 的 TSTEP 按 256 微步归一化。按 12 MHz 内部时钟估算,200 步电机在 100 rpm 附近:

TSTEP ~= 12 MHz / (100 rpm * 200 fullstep/rev * 256 / 60)
      ~= 140.6

0x96 = 150,对应约 94 rpm。这样设置的好处是:模式切换发生在较低速度,避免 400 rpm 高速区再发生切换冲击;同时起步和低速段仍保留 stealthChop 的平顺性。400 rpm 实际运行时已经处在 spreadCycle 区间,因此高速能力主要由 spreadCycle、细分、机械负载和供电电流决定。

64 细分对高速平顺性很关键

16 细分时,400 rpm 曾出现明显高速丢步,噪音和振动也更大。切到 64 细分后,振动明显下降,380 rpm 完全稳定,400 rpm 可以达到,偶发丢步已经接近外置驱动器的表现。

代价是 STEP 频率提高。400 rpm、64 细分时:

pulse/rev = 200 * 64 = 12800
rev/s = 400 / 60 = 6.6667
STEP/s = 12800 * 6.6667 = 85333 Hz

也就是约 85.3 kHz STEP 输入。当前 STM32 定时器输出可以承受这个频率,所以 64 细分在这个系统里是值得保留的。

如何确认真的跑到了 400 rpm

高速调试不能只靠肉眼判断。这里从两个角度验证:固件规划输出的 STEP 数,以及 TMC2160 读回的 TSTEP

当前固件插补周期是 2 ms。400 rpm、64 细分时,每 2 ms 应输出:

400 * 12800 / 60 * 0.002 = 170.67 pulse

RTT 日志中可以看到:

m0 rt=350 out=171 ts=35 drv=1A003F cs=26 sg=63 stl=0 fs=0
m0 rt=452 out=171 ts=35 drv=1A0048 cs=26 sg=72 stl=0 fs=0
m0 rt=552 out=170 ts=35 drv=1A0074 cs=26 sg=116 stl=0 fs=0
...
m0 rt=350 out=171 ts=35 drv=1A0057 cs=26 sg=87 stl=0 fs=0
m0 rt=450 out=170 ts=35 drv=1A0056 cs=26 sg=86 stl=0 fs=0

out=170~171 与 400 rpm 的规划输出吻合。再看 TSTEP,仍按 12 MHz 和 256 微步归一化估算:

TSTEP ~= 12 MHz / (400 rpm * 200 fullstep/rev * 256 / 60)
      ~= 35.16

日志中 ts=35,也吻合。也就是说,这次不是“看起来快”,而是 STEP 规划输出和驱动器寄存器读回都确认已经到 400 rpm。

关于 PWMCONF:为什么暂时不用自动整定

当前 PWMCONF=0xC4002228,拆开看是:

PWM_LIM = 12
PWM_REG = 4
PWM_OFS = 40
PWM_GRAD = 34
pwm_autoscale = 0
pwm_autograd = 0

这是一组固定前馈值,而不是 stealthChop2 自动整定。TMC2160 的自动整定通常需要两个阶段:AT#1 在电机静止且处于运行电流时等待驱动器建立 PWM_OFS_AUTO;AT#2 在中速运行一段时间,让驱动器修正 PWM_GRAD_AUTO

这套流程在评估板或长行程系统里比较容易做。但当前项目运动行程较短,而且高速运行已经切到 spreadCycle,stealthChop 主要用于起步和低速段。贸然打开自动整定,可能在短行程里引入新的不确定性。因此本次保留已实测稳定的固定前馈值,不把自动整定纳入当前稳定基线。

简单估算一下,在约 100 rpm 切换点附近:

PWM_GRAD * 256 / TSTEP ~= 34 * 256 / 141 ~= 62

再加上 PWM_OFS 按当前电流比例折算,大约在 90 多的量级,离 255 还有余量;低速时也不会过度推高 PWM。作为工程基线,这组固定值是合理的。后续如果要做量产级标定,再单独设计 AT#1/AT#2 测试流程,读取 PWM_AUTO 里的结果,再固化 PWM_OFSPWM_GRAD

中间验证过但没有保留的方向

这次调试里也排除了一些看似可能、但最终价值不大的方向:

  • 单纯提高电流不能解决 16 细分下的高速失步。
  • VHIGHFS 强制高速 fullstep 不适合这个系统,容易带来更明显的振动或失步。
  • 过度调整 spreadCycle 的 HENDTPFDVHIGHCHM,不如先回到 datasheet baseline,再围绕细分和模式切换做验证。
  • 只看“电机有没有动”不够,必须结合 TSTEPDRV_STATUS 和固件输出脉冲数判断。

一个比较重要的判断是:当 400 rpm 在板载 TMC2160 和外置驱动器上都偶发失步时,问题已经更像电机和机械系统的上限,而不是 TMC2160 配置仍存在明显错误。

工程建议

基于这轮验证,当前建议如下:

  • 额定速度优先使用 380 rpm。
  • 400 rpm 可作为极限或短时测试速度。
  • 继续保留 64 细分。
  • DCEN 必须保持低电平,并通过 IOIN 读回确认。
  • 低速 stealthChop、高速 spreadCycle 的组合继续保留。
  • TPWM_THRS=0x96 作为当前切换点是合适的。
  • PWMCONF=0xC4002228 可以作为当前固定前馈基线。

如果后续继续优化,可以按顺序做几件事:先设计专门的自动整定流程并记录 PWM_OFS_AUTOPWM_GRAD_AUTO;再对比固定前馈和自动整定后的低速温升、噪声、启动一致性;然后在有示波器或电流探头的前提下评估 DRV_CONF 里的 FILT_ISENSE、门极驱动强度和死区时间;最后做带负载、不同方向、不同位置的 380/400 rpm 重复测试。

TMC2160 的参数很多,很容易陷入“每个寄存器都试一下”的循环。更稳的方式是先保证硬件模式正确,再建立一个能被 STEP 输出和驱动器读回共同验证的基线,然后每次只改一个变量。