在这里插入图片描述

一、电流环是什么

lesson11/12 分别以 转速(RPM)霍尔累计位置 为被控量。本章把控制目标换成 相电流(mA):给定 目标电流,PID 自动调节 PWM 占空比,使采样电流逼近目标——在理想情况下电机输出 近似恒定转矩

这就是 单环电流闭环:被控量是 ADC 采样的相电流,执行量仍是 PWM 占空比,反馈来自 lesson6 已在 bsp_adc.c 中实现的三相电流采集与零偏校准。

1.1 与其它单环的区别

被控量 SP/ACT 典型现象 适用场景
速度环(lesson11) RPM 恒速运行,负载变化时自动加力 风扇、输送带
位置环(lesson12) 霍尔计数 转到指定位置后停下 定点定位
电流环(本章) 相电流 (mA) 恒流/恒力矩倾向,响应快 力控、串级内环

三者 PID 公式相同(位置式,lesson8/9),差别在于 反馈量纲整定思路

  • 速度环:误差单位是 RPM,输出对应「需要多快」;
  • 位置环:误差单位是计数,输出对应「需要转多远」;
  • 电流环:误差单位是 mA,输出对应「需要多大驱动电压/占空比」;方向由用户单独设定(按键 K3/K4 或串口 d),PID 只调节电流幅值。

1.2 电流反馈:三相 ADC 与 get_curr_val_max()

lesson6 已在 ADC3 + DMA 中轮询采集 U/V/W 三相电流(PF6/PF7/PF8)。本章在 lesson6 基础上 改进了零偏校准(见 §1.6),静止时 ACT 应接近 0,否则电流环无法启动。

int32_t get_curr_val_u(void);   /* U 相电流,单位 mA */
int32_t get_curr_val_v(void);
int32_t get_curr_val_w(void);
int32_t get_curr_val_max(void); /* 三相最大值,作为电流环反馈 ACT */

void adc_curr_recalibrate(void);   /* 重新做零偏校准(s 0 / cal 时调用) */
uint8_t adc_curr_is_calibrated(void); /* 1=校准完成,电流环才输出 PWM */

六步换相下 同一时刻只有两相导通,未导通相采样可能接近 0。本章取 三相最大值 作为反馈,实现简单、便于观察;精度不如 FOC 的 d/q 轴电流分解,但对 学习单环 PID 结构 足够。

项目 说明
采样电阻 0.02 Ω(本板 R48 等)
零偏 上电 静止 时自动校准,偏置电压约 1.65 V
正常运行 空载约 0.3~1 A,带载 3~5 A
软件过流 8000 mA,连续 200 ms 关断(lesson6)

1.3 六步换相下的说明

野火官方文档指出:六步换相转矩不够平稳,纯电流环力矩控制效果有限;完整力矩控制需 FOC/SVPWM(lesson16 及以后)。本章仍用六步换相 + 单环电流 PID,目的是:

  1. 理解 电流作为反馈量 的 PID 闭环结构;
  2. 为 后面的 电流→速度→位置串级 打基础(电流环作最内环);
  3. 配合 VOFA+ / FreeMASTER 观察 SP、ACT、PWM 的跟随关系。

1.4 控制周期

野火有刷电流环官方例程使用 25 ms 周期。本章沿用 25 msHAL_GetTick() 节拍,与 lesson11/12 的 50 ms 不同)。改周期后 Kp/Ki/Kd 须重调,且 dt 必须与周期严格一致(CURR_PID_DT = 0.025f)。

1.5 电流环特有问题

问题 说明 本章处理思路
零偏未校好 停转 ACT≈7000 mA,ERR 为负,OUT=0 §1.6s 0cal → 等 2s
采样噪声 电流 ADC 波动大,ACT 曲线不够平滑 官方偏 Ki 主导;看均值趋势
换相脉动 运行中 ACT 在几百 mA 范围跳动 §1.6.3 属正常;用 max(U,V,W) 近似
方向与电流 电流采样无符号 方向由 d/K3/K4 设定,PID 输出 ≥0
SP=0 停转 目标电流为 0 应关断 CURR_PID_STOP_MA 阈值停 PWM
与过流保护冲突 闭环目标过高触发保护 SP 上限 6000 mA,低于过流 8000 mA

1.6 电流零偏校准

电流采样是 差分测量:零电流时 ADC 仍有约 1.65 V 偏置,须先测出偏置再减掉,否则会把偏置当成电流。

1.6.1 本章校准策略

项目 说明
ADC_CURR_CAL_SETTLE_MS 800 ms 上电后先等模拟/front-end 稳定,再开始累计偏置
ADC_CURR_CAL_SAMPLES 64 次 对每相 ADC 原始均值 取平均 作为 adc_offset
校准期间 ACT 强制为 0 避免未校完就参与 PID
校准完成标志 adc_curr_is_calibrated()==1 串口 pid 显示 cal=1

s 0 停环 或串口 cal 会调用 adc_curr_recalibrate(),重新计时并累计 64 次;校准完成前电流环 不算 PWM 输出

1.6.2 典型故障:停转 ACT 却显示 7000+ mA

旧版 lesson6 逻辑在上电后 很快用单次采样锁零偏,模拟未稳定时偏置偏低 → 静止也显示约 7~8 A → 后果:

ACT 虚高 → ERR = SP − ACT 为负 → OUT 被钳在 0 → 电机不转(开环/闭环都不行)

处理:

s 0  →  cal  →  等约 2 s  →  pid

确认 cal=1,且 g_fm_iu/iv/iw_ma 与 ACT 均接近 0(几百 mA 以内),再 v 800s 1

1.6.3 运行中 ACT 在 100~600 mA 跳动正常吗?

正常。 六步换相 + max(U,V,W) + ADC 与 PWM 不同步,ACT 会有 脉动和毛刺

  • 趋势和均值,不要盯单点;
  • g_fm_iu/iv/iw一相高、其余低,随换相交替——这是六步特征;
  • ACT 均值长期明显低于 SP 时,可略加大 Ki 或少量 Kp
  • 需要平滑恒流见 FOC 章节,非本章六步方案所能完全达到。

二、实验简介

2.1 本章目标

在 lesson12 工程基础上,将位置环改为 电流环 PID

  • 反馈:get_curr_val_max() → 三相最大电流 (mA)
  • 给定:g_fm_target_curr(目标电流 mA,默认 1500 = 1.5 A)
  • 输出:位置式 PID → 非负 PWM(方向独立设定)
  • 复用 lesson9 bsp_pid.c/h、lesson10 FreeMASTER(PID 参数)、VOFA+ 三通道波形(SP/ACT/PWM)
  • 保留 lesson6/7 过流、堵转保护
  • 串口命令:c [mA] 设目标、s 1/0 启停闭环、cal 零偏重校准、kp/ki/kd 调参

2.2 硬件说明

与 lesson4 / lesson6 / lesson11 完全相同:野火骄阳 F407 + 无刷驱动板 + 带霍尔 BLDC,推荐 「无刷电机驱动接口 2」 牛角排线。电流采样在驱动板完成,经排线到 MCU ADC3。


三、程序设计

3.1 目录与模块划分

在 lesson12 基础上,位置环应用层 改为电流环

User/
├── adc/
│   └── bsp_adc.c/h          # 三相电流、零偏校准、get_curr_val_max()
├── pid/
│   ├── bsp_pid.c/h          # 复用 lesson9
│   └── bsp_pid_app.c/h      # 电流环:读电流、调 PWM、串口/FreeMASTER
├── freemaster/
│   └── bsp_fm_vars.h        # g_fm_target_curr、g_fm_curr_loop_en 等
└── main.c

3.2 电流环数据流

每 25 ms(curr_pid_poll):
  1. actual_ma = get_curr_val_max()        /* 校准未完成时 ACT 为 0 */
  2. error = target_ma - actual_ma
  3. 若 target_ma < CURR_PID_STOP_MA:停 PWM、清积分,return
  4. 若 !adc_curr_is_calibrated():不输出 PWM
  5. out = pid_update(&g_fm_pid, target_ma, actual_ma)
  6. 大误差起转 + 限幅 + 斜坡 → set_bldcm_speed(duty)

g_fm_target_curr mA

位置式 PID

get_curr_val_max

非负 PWM 量

限幅 + 斜坡

六步换相 + TIM8 PWM

用户设定方向 K3/K4 或 d

与野火有刷电流环一致:PID 输出只映射占空比,不通过 PID 符号换向。

3.3 核心代码示例

3.3.1 头文件常量

/* bsp_pid_app.h — 电流环 */

#define CURR_PID_TARGET_INIT        1500.0f   /* 默认 1.5 A */
#define CURR_PID_LOOP_MS            25U
#define CURR_PID_DT                 0.025f
#define CURR_PID_STOP_MA            50.0f
#define CURR_PID_BOOT_ERR_MA        300.0f    /* 误差大时起转最小占空比 */
#define CURR_PID_BOOT_MIN_DUTY      800U
#define CURR_PID_PWM_MAX_STEP       250U
#define CURR_PID_KP_INIT            0.0f      /* 参考野火有刷电流环 */
#define CURR_PID_KI_INIT            3.5f
#define CURR_PID_KD_INIT            0.0f

3.3.2 单次电流环计算

static void curr_pid_control(void)
{
    float cont_val;

    curr_pid_refresh_current();   /* 更新 g_fm_actual_curr / U/V/W */

    if (g_fm_target_curr < CURR_PID_STOP_MA)
    {
        set_bldcm_speed(0U);
        set_bldcm_disable();
        pid_reset(&g_fm_pid);
        return;
    }

    cont_val = pid_update(&g_fm_pid, g_fm_target_curr, g_fm_actual_curr);

    if (!adc_curr_is_calibrated())
        return;                         /* 零偏未校完,不输出 */

    curr_pid_apply_output(cont_val);

3.3.3 输出执行

static void curr_pid_apply_output(float cont_val)
{
    /* out ≥ 0;大误差时 duty 不低于 CURR_PID_BOOT_MIN_DUTY(克服静摩擦) */
    /* 闭环运行期间勿每周期 bldcm_apply_state(0) 关驱动,与 lesson11 一致 */
    set_bldcm_speed(duty);
}

3.3.4 零偏校准(bsp_adc.c

#define ADC_CURR_CAL_SETTLE_MS   800U   /* 上电稳定等待 */
#define ADC_CURR_CAL_SAMPLES     64U    /* 64 次均值锁偏置 */

void adc_curr_recalibrate(void);       /* s 0 / cal 时调用 */
uint8_t adc_curr_is_calibrated(void);  /* 三相均 cal_done 才为 1 */

3.4 PID 参数与限幅建议

项目 建议初值 说明
目标 SP 1500 mA(1.5 A) 空载起步;可试 800~2500 mA
out_min / out_max 0 / ~5500 与 lesson4 一致
integral_max 5500 与 PWM 满量程同量级
dt 0.025f 与 25 ms 周期一致
Kp / Ki / Kd 0 / 3.5 / 0(野火有刷官方) 不能照搬 lesson11/12 参数
SP 上限 6000 mA 低于软件过流 8000 mA

电流环与速度/位置环调参差异

  • 官方电流环常 Kp=0、靠 Ki 消除静差;
  • 电流响应快,周期宜 25 ms(比速度环 50 ms 更短);
  • ACT 噪声较大,波形不必追求完全平滑,看 趋势跟随 即可。

3.5 与 lesson11/12 的接口对照

lesson11 速度环 lesson12 位置环 lesson13 电流环
g_fm_target_rpm g_fm_target_pos g_fm_target_curr
motor_hall_get_rpm() motor_hall_get_position() get_curr_val_max()
speed_pid_control() pos_pid_control() curr_pid_control()
g_fm_speed_loop_en g_fm_pos_loop_en g_fm_curr_loop_en
串口 t [rpm] 串口 p [pos] 串口 c [mA]
PID 输出带符号(正反转) PID 输出带符号 PID 输出仅 PWM 幅值

四、FreeMASTER 与串口调参

4.1 FreeMASTER 监视变量

符号 类型 含义
g_fm_target_curr float 目标电流 SP(mA)
g_fm_actual_curr float 反馈电流 ACT(三相 max,mA)
g_fm_iu_ma / iv / iw float 三相电流分量
g_fm_error float SP − ACT
g_fm_pid.output float PID 总输出
g_fm_pid.p_term / i_term / d_term float P / I / D 分项
g_fm_pwm_out float 实际 PWM 占空比
g_fm_vbus_v float 母线电压 (V)
g_fm_curr_loop_en float 1.0=闭环开,0.0=关
g_fm_protect_en float 过流+堵转保护开关
g_fm_fault_code float 0/1/2 故障码

Scope 建议:g_fm_target_currg_fm_actual_currg_fm_pwm_out 三曲线同屏。

4.2 VOFA+ FireWater

VOFA+ 只输出过程量波形,便于观察电流跟随;PID 输出分项(OUT/P/I/D)及 Kp/Ki/Kd 请用 FreeMASTER,避免串口带宽被占满。

通道 含义
ch0 目标电流 SP(g_fm_target_curr,mA)
ch1 反馈电流 ACT(g_fm_actual_curr,mA)
ch2 实际 PWM(g_fm_pwm_out

115200、协议 FireWater3 通道

4.3 串口命令

命令 作用 示例
c [mA] 设置目标电流 c 1500
c +200 / c -200 相对当前目标 ±200 mA c +200
kp / ki / kd 修改 PID ki 3.5
s 1 / s 0 启 / 停电流闭环 s 1
pid 打印 SP/ACT/PWM/cal/fault pid
r 清积分 r
cal 电流零偏重新校准(须 s 0、电机停转) cal
? 帮助 ?
v [pwm] 开环 PWM(须 s 0 v 500
d [0|1] 开环方向(须 s 0 d 0

cal 说明:电机 必须停转s 0),否则零偏会按「有电流」去校,ACT 仍虚高。cal 后约 2 spid 应显示 cal=1,ACT/U/V/W≈0。

启闭环:须 s 1g_fm_curr_loop_en=1.0;只改 g_fm_target_curr 不会自动启电机。

闭环中:K3/K4 目标电流 ±200 mA;开环中:K1/K2 调 PWM,K3/K4 换向。


五、主程序流程

5.1 初始化

  1. 时钟、LED、串口、ADC(ADC_Initadc_curr_recalibrate()
  2. bldcm_init():TIM8 PWM、TIM5 霍尔
  3. curr_pid_init():默认 SP=1500 mA、Kp=0 Ki=3.5 Kd=0、闭环关
  4. 上电后 约 2 s 内勿启电机,等零偏 cal=1
  5. 默认 不使能电机,等待 s 1

5.2 主循环

while (1)
{
    deal_curr_pid_serial_data();
    deal_key_input();
    motor_protect_sync();
    curr_pid_poll();             /* 25 ms 电流环 */
    motor_stall_poll();
    motor_hall_speed_poll();
    motor_overcurrent_poll();
    curr_pid_vofa_poll();
}

六、建议操作与 PID 整定

安全提示:首次闭环请 空载、小目标(如 800~1500 mA),手勿靠近转子;过流或振动大时立即 s 0

6.1 推荐操作流程(含零偏)

① 烧录 → ② 上电等 3 s(零偏自动校准)→ ③ pid 看 cal=1、ACT≈0
④ s 0 → v 800 确认开环能转 → ⑤ r → ⑥ c 1500 → ⑦ d 0 → ⑧ s 1
⑨ 看 ACT 趋势逼近 SP → ⑩ 调 Ki

停转 ACT 仍 7000+

s 0 → cal → 等 2 s → pid(须 cal=1、ACT≈0)→ 再 v 800 或 s 1
步骤 操作 目的
1 烧录 lesson13,FreeMASTER 加载 .axf 确认变量符号
2 上电 等 3 spid 或 Watch g_fm_* cal=1,ACT/U/V/W≈0
3 s 0v 800 开环慢转 确认硬件能转、运行时有电流
4 s 0cal → 等 2 s(若步骤 2 未通过) 零偏重校准
5 r 清积分
6 c 1000c 1500 小目标起步
7 d 0 确认转向
8 s 1 启电流闭环
9 VOFA+ / FreeMASTER 看 SP、ACT、PWM ACT 有纹波正常,看 均值趋势
10 ki 见下文

6.2 FreeMASTER 读数速查

读数 含义 处理
ACT≈7000,SP=2000,ERR 负,OUT=0 零偏错误,以为电流已过大 cal,见 §1.6.2
cal=0 仍在校准 等 ~2 s,勿 s 1
ACT 0~几百跳动,SP=1500 六步纹波 + I 环爬升 正常,见 §1.6.3
fault=1 堵转 s 0r → 降 SP 再试
fault=2 过流 降 SP/Ki;查 ACT 是否虚高

6.3 阶跃响应现象

理想波形:

  1. 启环瞬间:ACT 低于 SP → PWM 上升,电流增大;
  2. 接近目标:误差减小 → PWM 稳定在某个占空比;
  3. 改 SP:K3/K4 或 c 命令阶跃,ACT 先冲再稳(可能略有 overshoot)。

ACT 长期低于 SP:Ki 偏小 → 加大 Ki。
ACT 振荡:Ki 过大 → 减小 Ki 或略加 Kp/Kd。
波形毛刺多、ACT 在 100~600 mA 跳:六步换相 正常现象(§1.6.3);看 均值趋势 即可。

6.4 推荐起步参数

参数 起步值 说明
Kp 0 野火有刷电流环官方
Ki 2.8~3.5 消除静差主力
Kd 0 一般不加
目标 SP 1000~1500 mA 空载 1~1.5 A
周期 25 ms CURR_PID_DT 一致

6.5 分步调参

只加 I: rkp 0kd 0ki 1.0c 1200s 1,逐步加大 Ki 直到 ACT 能跟上 SP 且不过冲严重。

可选 P: 若 Ki 已较大仍响应慢,可小 Kp(如 0.5~2.0)试加快。

6.6 常见现象

现象 可能原因 处理
停转 ACT≈7000,电机不转 零偏过早/错误锁定 s 0cal → 等 2spidcal=1、ACT≈0
s 1 打印成功但不转,OUT=0 ACT 虚高 → ERR 为负 同上;或 g_fm_protect_en、fault
v 800 也不转 未使能/霍尔/过流;或 ACT 虚高近 8A cal;再查开环与接线
能转,ACT 100~600 跳动 六步换相脉动 正常(§1.6.3);均值低于 SP 可略加 Ki
ACT 均值长期远低于 SP Ki 偏小 ki 46 试,或略加 Kp
启环后电流上冲过流 SP 过大或 Ki 过大 降低 SP;s 0r
换向后电流不对 方向与 SP 未重配 s 0d 换向后 s 1
FreeMASTER 启环无效 g_fm_curr_loop_en 用了 uint8 必须为 float 4 字节

6.7 运行效果

在这里插入图片描述

七、本章小结

  • 电流环 = 以 ADC 相电流(mA) 为反馈、PWM 幅值 为输出的单环 PID;方向 独立设定
  • 反馈取 get_curr_val_max();须先完成 零偏校准cal=1),停转 ACT 应≈0,否则 ERR 为负、电机不转。
  • cal / s 0 可触发 adc_curr_recalibrate();上电或校准后 约 2 s 再启环。
  • 运行中 ACT 几百 mA 脉动 属六步换相正常现象,看 趋势 不调波形毛刺。
  • 电流环宜 Kp=0、Ki≈3.5 起步;与 lesson11/12 参数完全不能互换
  • 启闭环g_fm_curr_loop_en=1.0s 1;SP 建议不超过 6000 mA

参考:野火《电机应用开发实战指南》「直流电机电流环控制」、BLDC 双环/串级说明;
源码: https://gitee.com/xundh/learn-motor-stm32

Logo

免费领 200 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐