⚡

电机FOC电流采样窗口与霍尔角度诊断(高速三相ADC自动抓拍)Skill sb_upload_unzip_8671100062229597285

用于永磁同步电机(PMSM)磁场定向控制(FOC)控制器的实车与台架故障诊断:在固件中加入高速三相 ADC 自动抓拍功能,当转速 ≥1500 rpm 持续 0.5 s 时自动记录 400 个 PWM 周期的 U/V/W 原始电流、CC1~CC3 比较值与电角度,并通过 CAN 0x4F0~0x4F4 分帧发出,配合 Python 解码脚本与 SIL 仿真回放,验证"电流采样窗口不足"猜想是否成立,定位"Iq 指令大、实测小"的根因。文档给出了完整的分析方法论:用仅取稳定时间 ≥3 µs 的周期拟合正弦波来评估短窗口读数偏差,识别三相增益/零偏不一致、霍尔表边沿角度误差与电压矢量鼓包、抗饱和回拉,以及主循环被 FOC 中断挤占导致 1 ms 任务实际 2.5 ms 执行等问题,并列出下一步验证方向。关键词:FOC、磁场定向控制、电流采样窗口、死区时间、下管导通窗口、三相ADC抓拍、CAN报文解码、ASC日志、霍尔角度标定、电角度跳变、电压饱和、抗饱和、dq电流波动、零偏标定、增益不一致、PWM占空比、主循环任务调度、SIL仿真、AT32M412、嵌入式电机控制调试。

嵌入式软件 0 次安装 2 次浏览 更新于 11/11/2026

日期: 2026-11-04 类型: 测试记录 项目: CloseLoop_AlphaV3_2 固件版本: 59 号(1103 海林版)+ 高速三相 ADC 自动抓拍

2026-11-04 高速三相 ADC 自动抓拍(验证"电流采样窗口"猜想)

一句话结论:59 号程序加了自动抓拍。车进入高速段(前进、转速 ≥ 1500 rpm 连续 0.5 s)后,自动记录 400 个 PWM 周期(约 27 ms)的三相 ADC 原始值、CC1~CC3 和电角度,记完自动从 CAN 0x4F0~0x4F4 发出。之后每隔约 4 s 再抓一次,不需要发任何 CAN 命令。SIL 已验证整条链路能跑通。实车只要照常录 ASC,交给 Claude 解码即可。

为什么要抓

  • 猜想:高速时最大占空比相的下管导通时间很短。再扣掉死区 2.0 µs,采样时运放还没稳定,读数偏小,电流环被"骗"了。详见 [[2026-11-04_工况数据与小模型标定]] 第三步。
  • 死区设置:现在 59 号 deadtime = 205 ≈ 2.0 µs;9 月能跑 2800 rpm 的老程序 V7.6 是 192 ≈ 1.42 µs。PWM 周期、采样点(CH4 = 5989,下管窗口正中)两版相同。
  • 采样前的稳定时间 = 下管窗口的一半 − 死区。最大相占空比 90 % 时只剩 1.3 µs(老程序 1.9 µs);93 % 时只剩 0.3 µs;94 % 以上采样时下管还没导通。

固件改动(只加诊断,不改任何控制参数)

文件 改动
[pwm_capture.inc](<file:///D:/Users/12078/at32ide-workspace3/CloseLoop_AlphaV3_2/AT32M412CBT7_YC_MCU_0612/project/AT32_IDE/user/APP/app/pwm_capture.inc>)、[pwm_capture.h](<file:///D:/Users/12078/at32ide-workspace3/CloseLoop_AlphaV3_2/AT32M412CBT7_YC_MCU_0612/project/AT32_IDE/user/APP/app/pwm_capture.h>) 新增:触发、记录、分帧发送
task.c 加 include;200 µs 任务里先调 pwm_capture_service()
control_pipeline.inc FOC 计算前读本次生效的 CC1~CC3,计算后记一条
.cproject、Debug/makefile 去掉 -u _printf_float(程序里没有用 %f 打印),腾出 Flash
  • 编译:Flash 112.7 KB / 122 KB(剩约 12 KB),RAM 剩约 3 KB,无警告。
  • 烧录文件:[AT32M412CBT7_WorkBench_59_PwmCap_20261104.hex](<file:///D:/Users/12078/at32ide-workspace3/CloseLoop_AlphaV3_2/AT32M412CBT7_YC_MCU_0612/project/AT32_IDE/Debug/>)
  • 改之前的备份:📂 [bak_capture](<file:///C:/Users/12078/AppData/Local/Temp/claude/3f3d7f858c3082ff/d75ac5ba-e6a4-4f46-89cb-b0af5b4c3a30/scratchpad/bak_capture/>)(task.c、control_pipeline.inc、can.c、at32m412_416_int.c、makefile、cproject.xml)
  • 存储借用开机零偏标定的 g_calib_raw_u/v/w(6 KB)。这块缓冲区平时被起步交接诊断(0x480~0x48E)借用,抓拍时让出:本次起步的交接诊断数据会被丢弃,发完再还给交接诊断。
  • 每次发送约 940 帧,1 帧/ms,约 1 s 发完,总线负载增加约 26 %(500 kbps)。ID 0x4F0~0x4F4 优先级低,不影响其他报文。
  • 可调宏(pwm_capture.inc 开头):触发转速 PWM_CAP_TRIG_RPM 1500、持续 0.5 s、两次间隔 3 s、周期数 400。

报文格式(大端)

ID 内容
0x4F0 抓拍编号、周期数、U 零偏、V 零偏
0x4F2 抓拍编号、W 零偏、触发时转速 rpm、母线电压 ×100
0x4F4 抓拍编号、Iq 指令 ×100、Iq 实测 ×100、Id 实测 ×100
0x4F1 帧序号 + 3 个字。每周期 7 个字:U/V/W 原始值(低 12 位,高位放序号、饱和、桥臂、母线标志)、CC1~CC3、电角度
0x4F3 抓拍编号、累加和、发送失败次数、漏周期次数

实车测试步骤

  1. 烧 ..._59_PwmCap_20261104.hex。
  2. 开始录 ASC,然后照常跑:经济模式满把到平台,保持 10 s 以上;动力模式中油门、满把到平台,各保持 10 s 以上。
  3. 每到平台都会自动抓拍,约每 4 s 一次,不用做任何操作。停车前多跑几秒,让最后一次发完。
  4. 把 ASC 交给 Claude;或者自己运行:python D:\Users\12078\at32ide-workspace3\tools\pwm_cap_decode.py 记录.asc
  • 解码脚本:[pwm_cap_decode.py](<file:///D:/Users/12078/at32ide-workspace3/tools/pwm_cap_decode.py>)。每次抓拍输出一个 CSV,屏幕打印"最大占空比那一相读数 / 另外两相反推值"的分档表。

怎么判断

  • 三相电流之和理论上是 0。最大占空比相的读数如果偏小,用另外两相反推它的真实值,比值就会小于 1。
  • 比值在"稳定时间 < 约 1 µs"那几档明显小于 1 → 采样窗口猜想成立,下一步考虑:按扇区挑选下管导通时间长的两相、调采样时刻,或者和硬件确认死区能否减小。
  • 各档比值都接近 1 → 采样没问题,"指令大、实际小"另找原因(电压波动、抗饱和等)。

SIL 验证(2026-11-04)

  • 11-4 实车数据回放,固件版本含抓拍。
  • 经济满把自动抓到 6 次,动力满把自动抓到 8 次。校验全部通过,漏周期 0。动力模式有 1 帧丢失:SIL 写日志时两条报文混进了同一行,属于仿真日志的问题;解码脚本正确报出了"校验不通过"。
  • 动力满把时最大占空比 94~95 %。按 SIL 预设的 5 µs 窗口模型:稳定时间 < 0 µs 那档比值 0.73,0~0.5 µs 档 0.94,其余各档约 1.01。说明解码和判断方法能识别读数偏小。实车结果要看真实数据。
  • 回放时发现 drive_mode.inc 已改成经济 1800 / 动力 2400 rpm(11-04 14:31 修改)。所以触发转速定为 1500,两种模式都能触发。
  • 加了 SIL_CANLOG=<路径> 环境变量,sil_drive 可以把全部 CAN 报文写成 ASC。

第一份台架数据(11-04 16:19)

📂 [台架/00.asc](<file:///D:/01-英创汇智文件/01测试数据/01-我的测试数据/11-4/台架/00.asc>),空载台架,抓到 1 次(205.1 s)。

  • 工况:2173 rpm,母线 75.9 V,Iq 指令 84 A / 实测 2 A,Id −6 A,最大占空比 95.2 %,400 个周期里 66 个电压饱和。校验通过,没有丢帧、漏周期。
  • 三相电流之和的均方根 12.5 A。空载时真实相电流只有约 3.5 A 均方根,所以这个误差相对真实电流很大。
  • W 相不参与控制,只能当参考,而且本身偏差较大:三相稳定时间都 ≥ 3 µs 时,三相和平均 3.9 A、均方根 5.5 A;W 的均方根 6.4 A,比 U、V 的 3.5 A 大。这就是误差底线。
  • V 相(电流环在用):稳定时间 0~1 µs 时,平均误差 +18.3 A(10 个周期);1~3 µs 时,均方根 10~12 A;≥ 3 µs 时回到底线 5.3 A。稳定时间越短,V 相读数越不准,和采样窗口猜想一致。
  • U 相:这次很少处在短稳定时间(< 2 µs 只有 14 个周期),误差和底线差不多,还不能下结论。
  • 局限:只有 1 次抓拍,而且空载电流很小。实车带负载的数据才能看出读数是不是系统性偏小。

台架数据结论(结合同一份 ASC 的其他报文)

  1. 抓拍功能在硬件上可用:触发、记录、发送、校验都正常。
  2. 空载也复现了"指令大、实际小":动力模式满油门,目标 2400 rpm,实际停在 2170~2178 rpm;Iq 指令 84 A,实测 3.5 A;Vq 28.4 V、Vd −7 V,电压幅值约 29 V,只用了上限 39.4 V 的 73 %;锁存一直是 0。说明问题和负载、车辆无关,也不是锁存造成的:控制器还有约 27 % 的电压余量没用上。
  3. 霍尔角度每圈在固定位置跳变(可信度高):FOC 角度正常每个 PWM 周期走 4.34°,但在固定几个角度上,每圈都会修正一次:
    • 约 264°、327°、88° 处停顿,少走 4~6°;
    • 约 14°、137°、200° 处突进,多走 3.5~6.8°;
    • 每圈的修正合计约等于 0。说明霍尔表的边沿位置和电机实际霍尔边沿对不上,误差约 ±7° 电角度。
  4. 电压矢量每圈在固定位置鼓起来:转子角 60~150° 时电压幅值 0.80~0.90,其他位置约 0.70~0.75;66 个饱和周期里有 61 个落在这里。这个位置正好在 88° 停顿和 137° 突进这两个霍尔修正附近。推测:角度跳变 → 电流瞬变 → 电流环每圈短暂顶到电压上限 → 抗饱和把积分往回拉 → 平均电压上不去。可信度中等,需要带载数据确认。
  5. V 相读数在稳定时间 < 1 µs 时偏差约 +18 A,误差底线约 5 A(可信度中等:空载,只有 10 个周期)。U 相样本不够。W 不参与控制,本身偏差较大。
  6. 另一个现象,待查:经济模式目标 1800 rpm,实际只到 1630~1685,Iq 指令只有约 2 A,转速爬得很慢。

下一步

  • 带载(台架加载或实车满把)录 ASC,确认结论 4 和 5。
  • 用抓拍里的角度跳变位置重新核对霍尔表的六个边沿角度。这一项是离线分析,不改程序。

带载四组数据(11-04 17:06~17:10,LOUXIA,全部满油门)

📂 [LOUXIA](<file:///D:/01-英创汇智文件/01测试数据/01-我的测试数据/11-4/台架/LOUXIA/>):00经济模式、000经济模式、01动力模式、001动力模式。同一次上电,抓拍编号 #1~#4,每个文件 1 次。

  • 转速目标按 drive_mode.inc:经济 1800 rpm,动力 2400 rpm。SPEED_COMMAND_MAX_RPM 2300 只在开机第 1 ms 起作用。
文件 抓拍工况 结果
00经济 / 000经济 1922 / 1925 rpm,Iq 指令 23.8 / 24.5 A,实测 22.8 / 23.6 A 到达目标 1800(先冲到 1920 再回落),指令 ≈ 实测,正常
01动力 1839 rpm,松油门回收 −20 A 抓在减速段,参考意义小
001动力 2181 rpm(12 s 后爬到 2254),Iq 指令 82 A / 实测 22~25 A,Vd −11、Vq 21.7,电压利用率约 81 %,锁存 0,38 个周期饱和 和实车平台段一模一样的现象

结论 1:采样窗口猜想不成立(修正前面的判断)

  • 新方法:每相只用自己稳定时间 ≥ 3 µs 的周期拟合正弦波,再看短窗口时的读数偏离多少。不依赖其他相。
  • 001 动力模式,最大占空比 94.9 %,稳定时间一直短到 < 0 µs:
    • U 相偏差 −0.7~+1.0 A,V 相 −2.3~−3.8 A,都在拟合残差(3~4 A)以内;
    • 只有 W 相(不参与控制)短窗口时偏大 +4~+5.5 A。
  • 前面用"另外两相反推"得出的"U 偏小 15 A",是把 W 的偏差算到了 U 头上。作废。16:19 空载那次的"V 偏差 +18 A",用新方法只有 +6 A(残差 4.8 A),也不算明显。
  • 所以:U、V 两相的采样在现有死区和采样点下是够用的,"电流采样窗口不够"不是平台段的原因。小模型里的 ADC_MINLOW_US 5 没有实车依据,要重新考虑。

结论 2:三相增益、零偏不一致(可信度高,4 次抓拍一致)

抓拍 U 幅值 V 幅值 W 幅值 V 直流偏置
#1 经济 23.2 25.3 26.5 +1.7 A
#3 经济 24.5 26.5 28.1 +1.6 A
#4 动力 25.9 29.2 29.3 +2.8 A
  • U 相幅值一直比 V 小 8~11 %。电流环用的正好是 U、V,增益不一致会让 dq 电流出现 2 倍电频率的波动。
  • V 相带约 +2 A 的直流偏置,会让 dq 电流每转一圈波动一次。开机零偏 V = 2095,比理论值 2048 高 47 个计数。
  • 是采样电路的增益 / 零偏问题,还是电机三相真的不平衡,要用钳形表或示波器测一相实际电流来区分。

结论 3:电机运行时主循环被挤占,1 ms 任务实际约 2.5 ms 才执行一次(可信度高)

  • 抓拍帧按设计每 1 ms 发一帧。实测:桥臂关闭时正好 1.00 ms;桥臂打开(运行、回收)时 10~13 ms。说明 200 µs 任务实际每 2~2.5 ms 才执行一次。
  • 用目标转速斜坡交叉验证:动力模式设计每 1 ms 升 6 rpm,实测 2.4 rpm/ms;经济模式设计 4 rpm/ms,实测约 1.6 rpm/ms。两者都对应 1 ms 任务实际每 2.5 ms 执行一次。
  • 原因:0x422 显示 FOC 电流环分支每次 34.5 µs,占 PWM 周期 66.7 µs 的 52 %,再加上 ADC、霍尔、提交 PWM 等中断,留给主循环的 CPU 不多,而且是 -O0 编译。SoftTask_update 每轮主循环最多执行一次,counter %= period 会把漏掉的周期直接丢掉。
  • 影响:速度环、油门、驱动模式斜坡、保护等 1 ms 任务都只有设计速度的约 40 %。斜坡和积分都按"每次 1 ms"算,所以响应慢了约 2.5 倍。经济模式先冲过目标到 1920 rpm、动力模式平台段慢慢爬,可能都和这个有关。SIL 没有模拟这个 CPU 占用,小模型的速度环响应比实车快。
  • 抓拍也受影响:触发要求的 0.5 s 实际变成约 6 s,冷却 3 s 实际变成约 36 s,所以每次加速只抓到 1 次。

结论 4:霍尔角度每圈在固定位置修正(可信度高)

  • LOUXIA 这 4 次抓拍的规律一致:约 330° 处每圈往回拉 8~10°,30°、90° 处往前推 3~4°。
  • 16:19 那次的规律不一样(270° 处 −6°,0° 处 +7°),可能是台架和 LOUXIA 用的不是同一台电机或同一套霍尔。
  • 001 动力的电压鼓包在转子角 0~120°,也就是 330° 回拉刚过之后;38 个饱和周期里 31 个在这一段。这支持"角度跳变 → 电流环每圈短暂顶到电压上限 → 抗饱和回拉积分 → 平均电压只有约 81 %"的推测(可信度中等)。

下一步

  1. 平台段的原因,现在的嫌疑是:每圈的角度跳变和电压饱和、加上抗饱和回拉,再加上 U/V 增益和零偏不一致。不再是采样窗口。
  2. 用抓拍的角度修正量离线核对霍尔表的六个边沿,尤其是 330° 那个。
  3. 抓拍触发改成按真实时间(ms 计时)判断,而不是按任务调用次数计数。这样每次加速能抓到多次。这需要改程序,等确认后再做。
  4. 主循环被挤占的问题,要评估:Release(-O2)编译,或者 1 ms 任务按实际经过的时间计算。这个改动影响面大,要单独决定。