代码工程:
通过网盘分享的文件:CW32L010步进电机正弦微步驱动器.zip
链接: https://pan.baidu.com/s/1pR0wOT3D30N38uOFXtpbDg?pwd=L010 提取码: L010
一、引言
电机驱动开发的第一件事是安全措施。驱动板接上电机与电源后,堵转可能烧毁功率级电路,因此本集的内容是电流监测与过载保护。
本项目只有 ADC,没有专用电流比较器,也没有逐相电流采样。本文讲解在这样的资源条件下实现过载保护的过程。
二、堵转的后果
MCU 可控制的量是驱动信号的频率与占空比。频率影响转速与换相节奏,影响输出功率的是占空比。PWM 的占空比决定施加在线圈上的平均电压,但线圈电流由负载决定。正常旋转时,绕组切割磁感线产生反电动势,与外加电压相抵,电流被反电动势限制在合理范围。堵转发生时反电动势降为零,绕组退化为近似纯电阻,此时电流由欧姆定律决定:
I≈U/R (2-1)
I为占空比决定的平均电压,R为绕组直流电阻。以 12 V 供电、绕组电阻几欧姆估算,电流可达数安培,超出电机与 MOS 管的承受能力。电机停转时电流最大,而这是钻孔的常见状态:钻头刚接触工件、排屑不畅、孔位偏离都会使转速瞬间跌到零。缺少电流反馈的驱动器在这种情况下会烧毁。
电流采样使用 50 mΩ 采样电阻配一级运放,放大后的信号送入 ADC 的通道 9。
图 1 电流采样电路
采样链的换算关系不按器件参数推算,而是由两组实测数据确定:
零电流偏置 840 counts。 电机停转、绕组无电流时 ADC 的读数,是放大电路的直流偏置。运放与 ADC 的零点并不在 0,这一项必须先扣掉,否则算出的电流整体偏大。
灵敏度 170.1 counts/A。 让 MOS 输出若干不同大小的电流,记录电流值与 ADC 读数的对应关系,多组数据线性拟合得到的斜率。
两项合并,得到 ADC 读数与绕组电流的换算关系:
UADC =840+170.1x I (2-2)UADC=840+170.1×I
反解得电流:
I= (UADC - 840)/170.1 (2-3)
过流阈值取 1040 counts,代入上式即约 1.2 A。该值是保护的动作点,不是测量量程的上限:ADC 为 12 位,读数范围 0~4095,可测电流远超 1.2 A。
以上两项标定数据来自本板实测
三、两套成熟方案都依赖本板不具备的硬件
控制电机电流的成熟方案有两套,共同基础是电流反馈。
硬件斩波器用比较器实时比较电流与预设阈值,超过阈值立即关断 MOS,电流回落再重新导通。响应速度在几百纳秒量级,配合电机绕组的低通特性可实现恒流驱动。本板没有专用电流比较器,只有 ADC;用 ADC 加软件判断替代比较器,检测延迟受采样周期限制,最长约 40 μs,与硬件比较器的几百纳秒相差约两个数量级。
软件电流环用 ADC 采集各相电流,再用比例积分控制器调节 PWM 占空比,使电流跟踪目标值,可精确控制任意转子位置上的定子力矩。该方案要求逐相独立采样,而本板只有总线电流采样,各相没有独立采样电阻。电机扭矩是两相电流与转子位置的耦合量:
T=f(i_A,i_B,θ) (3-1)
只有总线电流时,Ai_Ai_A与i_B的分配关系未知。转子停在某一相上时,总线电流可反映该相电流;转子移到两相之间时,同样的总线电流对应不同的转矩。用总线电流做反馈,转矩在同一步内即失控。
两套方案受硬件资源限制,在架构上都不成立。
四、折中的能量过载保护方案
本项目的实现方案是能量过载保护,处理链路为:GTIM 定时器以 25 kHz 触发 ADC 转换 → ADC 采样总线电流 → 多窗口滑动平均 → 与阈值比较 → 超限时累加能量 → 能量超过阈值后锁存停机。
保护动作为:永久刹车、关断全部 MOS、故障灯闪烁、不自动恢复,必须收到停机指令才复位。
实现过载保护有两条路,差别在于保护之后系统能否继续工作,其总体设计要点如下:
避免二元开关。电流超阈值立即停机,电流迅速回落,下一次采样判为正常并重新开启。工况未变时保护会重复动作。停机使电流下降,下降又让控制器认为工况恢复,保护反复触发。对步进电机而言每次断电都是一次失步,反复触发的结果是电机严重失步,必须手动停下重启。
能量积分。能量累积到阈值才停机,短暂过载被泄漏掉,持续过载必然触发。
短暂超限不误触。电流尖峰出现时能量刚开始累积,尖峰过去后电流回落,已累积的能量按比例泄漏。偶尔的扰动不会导致停机。
持续过载必触发。电流持续超限时能量持续累积,泄漏速度远小于累积速度,能量迟早超过阈值。持续过载一定停机。
能量积分方案适用于钻孔这类持续几百毫秒的过载场景。
五、采样数据的滤波与能量积分
5.1 滑动窗口均值滤波
25 kHz 的采样率意味着每 40 μs 得到一个新的电流值。单次采样受开关噪声影响抖动明显,直接用于过载判断会频繁误触,先做滤波。滤波器采用 32 点滑动窗口,用环形缓冲加累计和实现:
/* 滑动窗口平均 — 每次 ADC 采样调用,O(1) 复杂度 */staticuint16_tADC_MovingAverage(uint16_t adcVal){ s_winSum -= s_winBuf[s_winIdx];/* 滑出:减去最旧值 */ s_winBuf[s_winIdx]= adcVal;/* 滑入:写入新值 */ s_winSum += adcVal; s_winIdx =(s_winIdx +1)& ADC_WIN_MASK;/* 环形索引推进 */if(s_winCount < ADC_WIN_SIZE) s_winCount++;if(s_winCount == ADC_WIN_SIZE)return(uint16_t)(s_winSum >> ADC_WIN_SHIFT);/* 满窗:右移代替除法 */elsereturn(uint16_t)(s_winSum / s_winCount);/* 未满:用实际计数 */}
均值的计算没有遍历数组。窗口每次只移出一个旧值、移入一个新值,累计和随之一减一加,时间复杂度为 O(1)。若每次采样都遍历 32 个元素求和,中断耗时会随窗口长度线性增长。
满窗后用右移代替除法。窗口长度取 32 即 2⁵,平均值等于累计和右移 5 位。Cortex-M0+ 内核没有硬件除法指令,一次除法要走软件库调用,代价是几十个周期,右移是一个周期。在每 40 μs 执行一次的中断里,差别不可忽略。
窗口未满时必须用实际计数做除法。上电后最初的 31 次采样窗口尚未填满,右移 5 位会将累计和缩小 32 倍,得到偏小的平均值,导致保护判断失效。该分支只在前 31 次采样里生效。
滑动窗口滤除的是随机噪声。采样与 PWM 载波频率不同步,采样点相对开关沿缓慢漂移,开关噪声在平均之后被抹平,不会与信号同步进入结果。
5.2 能量积分的代码实现
该功能需要模拟热量的累加和泄漏,过载判断在 ADC 中断内完成,状态机有两个状态:CHOP_ON(正常运行)与 CHOP_FAULT(锁存故障)。
/* CHOP_ON 状态:超限累加,回落泄漏 */if(adcValue > threshold){ s_energy +=(uint32_t)(adcValue - threshold);if(s_energy >= FAULT_ENERGY_LIMIT)/* 累积到阈值 → 锁存 */{Timer_Brake_Enable();/* MOE=0,永久刹车 */PA01_SETHIGH();/* 点亮故障灯 */ s_state = CHOP_FAULT;}}elseif(s_energy >0)/* 回落:指数泄漏 */ s_energy -=(s_energy >> FAULT_LEAK_SHIFT);
以上是 Chopper_ProcessFast() 中 CHOP_ON 分支的简化片段,省略了 switch 外壳与 s_lastCurrent 记录。故障状态的分支在源码中是一个空的 case,只保留 break,不做任何恢复动作。
能量积分器模拟热积累,更新式与散热对应:
E+=(I-Ith (超限时) (5-1)
E-=[E/4096] (回落时) (5-2)
式 (5-2) 用右移 12 位实现,每次采样泄漏当前能量的1/4096。泄漏系数决定保护的两个边界:
尖峰不被误触的时长。 能量衰减的时间常数约为 4096×40μs≈164ms,短于该时长的电流尖峰来不及把能量推过阈值。
超限不触发保护的下限。 泄漏量取整为零时能量不再下降,形成约 200000/2¹²≈49 counts 的死区,合 0.29 A。超限幅度小于 0.29 A 的工况不会触发保护。这是泄漏量化的结果,0.29 A 的超限本身不构成危险。
泄漏分支的完整写法还包含清零判断 if (s_energy < 2) s_energy = 0;。该判断不只是清零:若不加此判断,E =1 时 E>>12 等于 0,s_energy -= 0 使能量永远停在 1 不再下降。此后累积过程若持续发生,能量会从 1 重新爬升,基线上残留的能量会在长时间运行中不断累积。加上清零判断后,能量要么有意义地增长,要么归零,不存在卡在极小值反复累积的中间态。
六、阈值标定
阈值标定涉及两个互相独立的量:过流阈值决定电流多大算超限,能量阈值决定超限持续到什么程度才停机。前者随工作点变化,后者是固定值,两者的确定方法不同。
过流阈值(threshold)按”空转电流加裕量”计算。 空转电流指电机在该工作点空载旋转时的电流,从标定表按当前振幅与转速查得。不同工作点的空转电流差别很大,固定阈值会在低速工况误触发、在高速工况保护不足。查询结果加一个固定裕量,最后按硬顶钳位:
threshold=min(I空转+MARGIN,HARD_MAX) (6-1)
式中的MARGIN 取 40 counts,约合 0.24 A,作用是让阈值略高于正常空转电流,避免正常波动被误判为过载;HARD_MAX 取 1040 counts,约合 1.2 A,作用是给保护设一个绝对上限——无论标定表查出什么值,真实电流都不会被允许超过约 1.2 A。
查询过程按运行情形分三条分支:
/* S1: 标定模式 → 返回满量程,屏蔽过流保护 */if(g_calibActive ==1){ s_thrCacheAmp =0xFFFF; s_thrCacheRpm =0xFFFF;/* 同步失效缓存 */return4095;}/* M1: (振幅, 转速) 未变 → 直接返回缓存,不查表 */if(s_thrCacheAmp == s_motor.amplitude && s_thrCacheRpm == s_motor.rpm)return s_thrCacheVal;
标定模式。 自动标定需要测量各工作点的真实空转电流,测量过程电流必然超过正常阈值,因此标定期间阈值返回 ADC 满量程 4095,暂时取消保护,由外部数字电源的限流功能兜底。屏蔽不能通过常规的阈值设置函数完成:该函数会将输入值按 HARD_MAX 钳位,钳位后保护并未真正解除,必须让查询函数本身在标定模式下直接返回满量程。
工况未变。 振幅与转速均未改变时直接返回上一次结果。ADC 中断每 40 μs 执行一次,而工作点在一次钻孔中很少改变,缓存让绝大多数调用退化为一次比较加一次读取。
工况改变。 此时才查表并插值,加裕量后按硬顶钳位。查表失败时回退到当前阈值而非零,零阈值会让保护永不触发。
能量阈值是能量积分的上限,取固定值 200000。 它与过流阈值不是同一件事:过流阈值判断单次采样是否超限,取值在 840~1040 counts 之间随工况变化;能量阈值判断超限已经持续到什么程度,必须固定,否则”持续过载”的判据本身就在动。
能量阈值无法由器件参数推出,只能实测。方法是让数字电源进入限流工作,电流被钳在一个恒定值上形成持续过载,测量从启动到停机的触发时间,再反推能量阈值。
反推的依据是积分过程本身:每次采样(间隔 40 μs,即每秒 25000 次)若电流超过阈值,能量增加一个超限幅度 dd;若未超限,能量按 1⁄4096 的比例泄漏。持续超限时泄漏远小于累积,可以忽略,于是 tt 秒内累积的能量为
t x 25000 x d
触发停机的条件是累积量达到能量阈值 LL,因此
L=t x d x25000 (6-2)
式中 t为触发时间(秒),d为超限幅度(钳位电流对应的 ADC 读数减去过流阈值,单位 counts),25000 为每秒采样次数。
两次实测,限流值都取 1.3 A:
振幅 2200,触发时间 400 ms,反推能量约 210000。
振幅 2000,触发时间 632 ms,反推能量约 205000。
振幅的含义会在后面的篇章说明
两次结果接近,取交点定为 200000。初值曾取 250000,实测触发偏慢,因此下调。限流值取 1.3 A 而非刚好超过 1.2 A,是因为超限幅度 d越大触发越快,泄漏所占比重越小,反推结果受”忽略泄漏”这一近似的影响也越小。
阈值最初的设计是”超限幅度乘以 1.5 倍”。实测发现所有工作点都超过 1040 硬顶,缩放完全退化,方案被废弃,改为”空转电流加固定裕量”。
七、470 nF 电容的作用
采样电路的运放正负输入之间跨接 470 nF 电容(C14),将线性通带限制在约 1 kHz。
图 2 采样电路通带增益
曲线来自电流采样电路幅频特性仿真
本项目对电流量的需求是平均值而非瞬时波形,1 kHz 的通带满足要求:
过载判断需要平滑的平均值,C14 滤除高频成分,ADC 读到稳定均值。
MCU 无 DMA,采样数据靠软件搬运,通带限制缓解高频数据的处理压力。
采样率 25 kHz 远高于 1 kHz 通带,采样点落在通带之外的平坦区。
八、小结
本篇讲解了在本项目资源条件下实现电流过载保护的过程,可以总结为以下四点:
分析堵转工况下电流的失控机制,确认电流监测的必要性
对照硬件斩波器与软件电流环,确认两套方案受硬件资源限制不成立
采用能量积分过载保护,实现短暂的扰动不误停、持续的过载必停机
完成采样滤波、能量积分、变阈值查询三段代码,并用实测标定能量阈值
扫码加入QQ群3群| 610403240
65