作者: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=0x61A02:IHOLD=2,IRUN=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_OFS 和 PWM_GRAD。
中间验证过但没有保留的方向
这次调试里也排除了一些看似可能、但最终价值不大的方向:
- 单纯提高电流不能解决 16 细分下的高速失步。
VHIGHFS强制高速 fullstep 不适合这个系统,容易带来更明显的振动或失步。- 过度调整 spreadCycle 的
HEND、TPFD、VHIGHCHM,不如先回到 datasheet baseline,再围绕细分和模式切换做验证。 - 只看“电机有没有动”不够,必须结合
TSTEP、DRV_STATUS和固件输出脉冲数判断。
一个比较重要的判断是:当 400 rpm 在板载 TMC2160 和外置驱动器上都偶发失步时,问题已经更像电机和机械系统的上限,而不是 TMC2160 配置仍存在明显错误。
工程建议
基于这轮验证,当前建议如下:
- 额定速度优先使用 380 rpm。
- 400 rpm 可作为极限或短时测试速度。
- 继续保留 64 细分。
- DCEN 必须保持低电平,并通过
IOIN读回确认。 - 低速 stealthChop、高速 spreadCycle 的组合继续保留。
TPWM_THRS=0x96作为当前切换点是合适的。PWMCONF=0xC4002228可以作为当前固定前馈基线。
如果后续继续优化,可以按顺序做几件事:先设计专门的自动整定流程并记录 PWM_OFS_AUTO、PWM_GRAD_AUTO;再对比固定前馈和自动整定后的低速温升、噪声、启动一致性;然后在有示波器或电流探头的前提下评估 DRV_CONF 里的 FILT_ISENSE、门极驱动强度和死区时间;最后做带负载、不同方向、不同位置的 380/400 rpm 重复测试。
TMC2160 的参数很多,很容易陷入“每个寄存器都试一下”的循环。更稳的方式是先保证硬件模式正确,再建立一个能被 STEP 输出和驱动器读回共同验证的基线,然后每次只改一个变量。