电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 成果帖|步进电机四档状态识别(NanoEdgeAI+频域核对)

共1条 1/1 1 跳转至页

成果帖|步进电机四档状态识别(NanoEdgeAI+频域核对)

菜鸟
2026-11-14 20:29:35     打赏

一块 NUCLEO-H533RE 贴在 28BYJ-48 步进电机旁边,用一颗 LIS3DH 加速度计采振动,判断电机此刻处在四个状态里的哪一个:停止、3ms 档、5ms 档、8ms 档。识别全部在片内完成,不联网,一次判决含频域核对 331 微秒,独立验证 169 帧全对。

做这个方向的起因是工业现场大量小型电机装上去就没人管,风机、泵、传送带、阀门执行器,坏了才知道。给每台配振动监测仪成本太高,接云端又要流量和网关。旁边一颗几块钱的 MCU 能一直听,只在异常时上报一条,成本、功耗、流量一起省下来。这类场景真正的要求不是"能跑",而是换一台设备、换一次安装之后还能不能准。

系统分两块板。香橙派 Zero3 按自己的节拍给 ULN2003 送四相时序,随机模式下每 3 秒从空档、3ms、5ms、8ms 里等概率抽一个,不与上一次重复。NUCLEO 只干另一件事:I²C 400 千赫兹读 LIS3DH,DWT 定拍 1344 赫兹采 512 点凑一窗,合 0.381 秒,同一窗数据同时喂给 NanoEdge AI 和一段 16 点 Goertzel 频域核对,最后按主频出结论。两块板之间没有信号线,不共享时钟也不共享代码,唯一耦合是机械振动——所以"电机在第几档"这个真值不是被测系统自己说的。

系统框图_v2.png

电路上香橙派侧只要四根信号线加电源:物理针脚 12、15、16、18 接 ULN2003 的 IN1 到 IN4(sysfs 编号 75、72、79、78,芯片脚 PC11、PC8、PC15、PC14);GND 走 14 脚,驱动板 VCC 走 2 脚或 4 脚。NUCLEO 侧 D14(PB7)接 SDA,D15(PB6)接 SCL,3V3 供电,D2 到 D5 悬空——驱动已经搬走了。ULN2003 是七路达林顿阵列,单路持续灌 500 毫安,内部并了续流二极管,COM 脚必须接正 5 伏才能构成泄放回路,所以外面不用再并 1N4007。

接线原理图_v2.png

实物接线_标注.png

硬件四件:NUCLEO-H533RE(STM32H533RET6,Cortex-M33 250 兆,512 KB Flash,272 KB 内存,板载 ST-Link V3,一根 USB 兼做供电、下载和虚拟串口)、Seeed 114020121(LIS3DHTR,三轴 ±2g,12 位,I²C 地址 0x19,内建 32 级 FIFO)、Seeed 105990072(ULN2003 加 28BYJ-48,5 伏,减速比 1:64,一圈 4096 个半步)、香橙派 Zero3(全志 H618)做外部驱动。

LIS3DH 要和电机外壳或底座刚性固定,不能悬在杜邦线上,也别用胶带——胶带会蠕变,半小时内位姿就漂。安装位置一变,振动传递路径就变,特征跟着变。

软件参数是钉死的。CTRL_REG1 写 0x97,ODR 1344 赫兹、normal 模式、三轴全开;采样节拍用 DWT 数机器周期,250 兆除以 1344 得 186011 拍,实测 1343 赫兹。原来配的是 400 赫兹,3ms 档 333 赫兹早超过奈奎斯特 200 赫兹会混叠,换到 1344 后奈奎斯特 672 赫兹,三档的 333、200、126 全在带内,谱线才分得开。窗口 512 点不重叠,正好 0.381 秒。

模型接入有三处要注意:输入必须三轴逐点交错,x0、y0、z0、x1、y1、z1 这样铺,按轴块铺 Studio 不收;导出的库是 hard-float 编的,整个工程要加 -mfloat-abi=hard 和 -fshort-enums 重编;freestanding 没有 libm,tanhf 和 expf 得自己补。

数据集四类各 100 帧,每帧 512 点,采完先算类间可分性,不可分就别浪费训练时间。下面这张是 Studio 里四个类别的原始波形和对应频谱:上排三轴时域,下排三轴 FFT,每类 100 条、1536 列,横轴是归一化频率。当前显示的是 5ms 档,Z 轴主峰落在 0.148,乘上 1344 赫兹的采样率就是 199 赫兹,和后来实测的 198 赫兹对得上。谱线能这样干干净净分开,才有后面训练的事。

Studio_Signals_四类样本.png

Studio 里建 4 个类别、每类 100 个信号、窗口 512 点,训练完导出的库内部 benchmark 是 100%。这个分数要说清楚:它在训练集上算的,只能说明模型记住了,不能说明模型认得出,真正的验证得另采数据。

Studio_Benchmark_99pts.png

一共跑了 19664 个候选库做横向比较,满分的不止一个。排在最前面的是 48 号 CNN:Quality Index 99 分、平衡准确率 100%、RAM 2.4 KB、Flash 1.5 KB、单次推理 0.9 毫秒。没再往下挑,是因为它直接对时序做卷积,跟这类振动信号对路,而后面几个同分的 SVM、XGB 是先把波形压成统计量再分类。

Studio_Validation_19664库.png

换成香橙派驱动后独立实测掉到 67.8%,5ms 档几乎全判成 8ms。对比两边统计量:训练时 Y 轴最安静(标准差 23 到 27),现场 Y 轴成了主振方向(48 到 85);训练时 5ms 振动最大,现场是 8ms 最大,强弱顺序反了。而静止类两边几乎一致(5.4、3.3、11.0 对 5.5、3.4、10.9)——静止时传感器只感受重力,跟谁驱动无关;一转起来,振动要经电机外壳、支架、传感器这条路径,驱动方式改了激励频谱和传递函数。试过用轴向增益把现场数据掰回训练域,X 轴上 5ms 要乘 1.38、8ms 要乘 0.71,方向相反,三类无法同时落回。

剩下能用的量是主频,它只由每拍间隔决定,跟传递路径无关。3ms 档标称 333 赫兹实测 84(失步态),5ms 标称 200 实测 198,8ms 标称 126 实测 126。8ms 档幅度从 25 毫克跳到 141 毫克,5.6 倍,主频一动不动。实现是 16 次 Goertzel,4 个频带各 4 个频点,系数在 1344 赫兹下预算成常量写死。模型照常跑,两者分歧时以主频为准,并把模型原始判定打印成 AI=G3_8MS 留痕。另加两帧去抖,因为香橙派换档有软启动扫频,8ms 档从 50 赫兹升到 126 赫兹时会经过 84 赫兹。

g_ai = AIE_ClassGear(cls);                     /* 模型自己说的 */
FG_Run(win, SAMPLE_HZ, &fg);                   /* 频域核对 */

/* 连续两帧一致才认,滤掉软启动扫频路过的频点 */
if (fg.gear == s_g_cand) { if (s_g_cnt < 3u) s_g_cnt++; }
else                     { s_g_cand = fg.gear; s_g_cnt = 1u; }
if (s_g_cnt >= 2u) s_g_out = s_g_cand;

g = s_g_out;
if (g_ai <= 3u && g != g_ai) fixed = 1u;       /* 分歧标记 */

改造后每档采 18 秒共 169 帧:IDLE 42 帧模型单独 100%、最终 100%;G1_3MS 42 帧模型单独 0%、最终 100%;G2_5MS 43 帧模型单独 0%、最终 100%;G3_8MS 42 帧两边都是 100%。合计模型单独 49.7%,最终 100%,错的 85 帧全部塌到 G3_8MS。所以这套系统的 100% 主要由频域核对贡献,模型单独只有 49.7%,这一点写明不藏。

主要参数全部实测:采样率 1344 赫兹(实测 1343,偏 0.07%);窗口 512 点合 0.381 秒不重叠;类别 4;档位 3、5、8 毫秒每拍,标称 333、200、126 赫兹,实测主频 84、198、126 赫兹;单次推理含频域核对 330 到 332 微秒;Flash 占用 52284 字节合 51.1 KB;静态 RAM 12060 字节合 11.8 KB;系统准确率 169 帧全对,模型单独 49.7%;换档稳定延迟约 2 帧、0.8 秒;香橙派步进节拍最大偏 0.197 毫秒。

实现步骤按顺序走:先点灯、串口能打印,确认工具链、下载链、串口链三条都通;再接 LIS3DH,I²C 400 千赫兹,扫 0x18 和 0x19,WHO_AM_I 应为 0x33,静止时某轴约 1000 毫克即 1g;然后把采样节拍钉到 1344 赫兹,串口回读误差小于 1% 才算过关;接着让步进电机按 8 拍半步转起来,停机时四相全拉低,否则线圈持续发烫;然后采数据集,采完立刻算可分性;再进 Studio 训练、导出库、接进工程;最后上外部驱动测真实准确率,加频域核对和去抖复测。

如何开启运行有两种接法。A 是只用 NUCLEO 自驱自检:D2 到 D5 接 ULN2003 的 IN1 到 IN4,D14 和 D15 接 LIS3DH 的 SDA 和 SCL,共地,USB 上电。B 是外部驱动,也就是本帖用法:拔掉 NUCLEO 到 ULN2003 的四根线,改接香橙派针脚 12、15、16、18,GND 接 14,驱动板 VCC 接 2 或 4。

固件用 bash build_zig.sh 编译出 firmware/MotorAI_T4.bin,pyocd flash --target stm32h533retx -f 2500k 烧入。串口 115200 八位无校验,走 ST-Link 虚拟串口。命令行 i 开关推理输出(每 0.381 秒一行),p 打印引擎状态与推理耗时,e 切换外部驱动和板载驱动,z 打印电机状态,c 采一窗并打印原始值用于导出 CSV,y dump 最近一窗的 512×3 原始值,g0 到 g3 在板载驱动时设档位。香橙派那侧:gcc -O2 -Wall -o motor_pi motor_pi.c,echo g2 > /tmp/motor.ctl 固定 5ms 档,echo rnd 进随机,cat /tmp/motor.state 查状态,开机自启交给 systemd,FIFO 建完 chmod 666。

效果演示,串口输出长这样:

[137.533s] G3_8MS  prob=61.430%  sense=gear3  f=126Hz/25.408mg
[138.382s] G3_8MS  prob=60.403%  sense=gear3  f=126Hz/113.321mg
[141.353s] G2_5MS  prob=65.061%  sense=gear2  f=198Hz/30.433mg  AI=G3_8MS
[143.469s] IDLE    prob=58.692%  sense=stop   f=84Hz/2.339mg

第一段是最终输出,sense=stop 或 gearN 是同一结论的另一种写法。f 和 mg 是当帧原始频域测量,不是去抖后的,所以换档瞬间会看到"结论还是 gear2,f 已经变成 126 赫兹"。行尾的 AI=G3_8MS 表示模型与频域不一致,系统采用频域结论并留痕,稳态时这一行不出现。

串口输出.png

四档逐一识别:空档输出 IDLE,幅度 1.7 到 2.8 毫克;3ms 档输出 G1_3MS,主频 84 赫兹,幅度 38 到 40 毫克;5ms 档输出 G2_5MS,主频 198 赫兹,幅度 33 到 49 毫克;8ms 档输出 G3_8MS,主频 126 赫兹,幅度 25 到 141 毫克。随机换档连续跑,香橙派每 3 秒抽一个,NUCLEO 只靠振动跟,26 秒内 61 帧,换档处最多一帧过渡。

不足有三处。3ms 档在香橙派上转子跟不上,实测 84 赫兹正好是 333 除以 4,每 4 拍才真走一步,脉冲时序本身是准的,这是从静止直接拉到 333 步每秒的扭矩限制,所以 84 赫兹特征稳定可判,但实际转速不是标称值。堵转和负载突变没有覆盖,这是命题里"异常状态"的缺口,堵转时主频会掉、幅度也会变,需要另一套判据。验证范围也窄,169 帧都在同一安装、同一批器件、同一环境下采。

小结。这套系统交出来的是三样东西:一个可复现的实验结构,真值由另一块板子独立给出;一份按实测确定的参数配置,采样率、窗口、类别、排列方向都有依据;一个不随安装和驱动变化的判据,8ms 档幅度从 25 毫克漂到 141 毫克,主频始终 126 赫兹。

感谢得捷和 EEPW 提供这次机会,也感谢活动里各位先行者公开的调试记录。

【【let's do|2026年第3期】基于边缘AI的电机状态检测成果视频】 https://www.bilibili.com/video/BV1cdsV6zEAg/?share_source=copy_web&vd_source=42d951dc5e0576960e261aea008613b9



共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]