电机驱动开发学习6. 三相电流采集与过流保护

电机驱动开发学习6. 三相电流采集与过流保护

    • [1. 为什么需要电流采集与过流保护](#1. 为什么需要电流采集与过流保护)
    • [2. 电流采样电路原理](#2. 电流采样电路原理)
      • [2.1 U 相电流检测原理图](#2.1 U 相电流检测原理图)
    • [3. 硬件过流保护电路](#3. 硬件过流保护电路)
      • [3.1 过流保护原理图](#3.1 过流保护原理图)
      • [3.2 工作原理](#3.2 工作原理)
      • [3.3 硬件保护与软件保护的分工](#3.3 硬件保护与软件保护的分工)
    • [4. 软件实现](#4. 软件实现)
      • [4.1 关键宏定义](#4.1 关键宏定义)
      • [4.2 ADC 多通道 + DMA 配置](#4.2 ADC 多通道 + DMA 配置)
      • [4.3 DMA 完成回调:分离各通道并累加](#4.3 DMA 完成回调:分离各通道并累加)
      • [4.4 偏置电压校准](#4.4 偏置电压校准)
      • [4.5 主函数:电压、温度、三相电流同一帧输出](#4.5 主函数:电压、温度、三相电流同一帧输出)
      • [4.6 软件过流保护](#4.6 软件过流保护)
    • [5. 实验操作](#5. 实验操作)
      • [5.1 接线](#5.1 接线)
      • [5.2 串口指令](#5.2 串口指令)
      • [5.3 现象观察](#5.3 现象观察)
      • [5.4 注意事项](#5.4 注意事项)

本系列教程学习资源来自野火官方电机教程,部分代码及博客内容摘自官方教程。

本系列教程使用野火骄阳 F407 开发板及野火有刷/无刷驱动板。

本篇代码按本人实际驱动板配置 :采样电阻 0.02 Ω (原理图 R48 等,Current_U/V/W),电流 ADC 偏置 1.65 V(上电校准)。野火文档中另有 0.01 Ω 改版,以板上丝印/原理图为准。

上一篇 中,我们完成了电源电压 VBUS 与 NTC 温度的 ADC 采集。本篇在此基础上,继续学习驱动板上三相电流的采样原理硬件过流保护电路,以及如何在 STM32 中通过 ADC + DMA 读取 U/V/W 三相电流。


1. 为什么需要电流采集与过流保护

电机驱动系统中,电流是最核心的反馈量之一:

  • 监测运行状态:空载、带载、堵转时电流差异明显,可用于保护判断。
  • 闭环控制基础:为后面FOC作准备,因为FOC 等高级算法需要实时相电流;即使当前用六步换相开环驱动,也应具备电流观测能力。
  • 安全保护:短路、堵转、异常负载会导致电流急剧上升,必须在毫秒级内切断功率输出,否则 MOS 管、电机绕组都有烧毁风险,这比通过NTC保护更快。

保护手段通常分两层:

方式 响应速度 实现位置 典型用途
硬件过流保护 极快(μs 级) 比较器 + 锁存 + SD 关断 瞬时过流、短路
软件过流/堵转保护 较慢(ms 级) ADC 采样 + 程序判断 堵转检测、限流、统计

野火无刷驱动板两种都做了 :比较器硬件直接拉低 Motor_SD_B 关断驱动;MCU 侧则通过 ADC 周期性读取三相电流,供显示、调试及后续算法使用。本文讲的是软件上的实现。


2. 电流采样电路原理

野火无刷驱动板对控制信号和 ADC 采样电路均做了隔离(光耦 + AMC1200 隔离运放),可有效抑制功率地的开关噪声。

U 相为例,三相(U/V/W)电路结构相同,仅采样电阻串接位置不同。

2.1 U 相电流检测原理图

信号链路如下:

复制代码
相电流 → 采样电阻(0.02Ω) → 隔离运放(×8) → 差分转单端运放(+1.65V偏置) → Motor_IU_ADC → STM32 ADC

① 采样电阻

在 U 相下桥臂回路串入 0.02 Ω、2 W、1% 采样电阻(原理图如 R48,Current_W;U/V 相各有一颗),利用欧姆定律将电流转为毫伏级电压:

V i = I × R s h u n t = I × 0.02 V_i = I \times R_{shunt} = I \times 0.02 Vi=I×Rshunt=I×0.02

② 隔离运放放大

信号经 AMC1200 隔离运放放大 8 倍 后差分输出,再经普通运放转为单端信号,并叠加 1.65 V 偏置电压 (零电流时 ADC 输入约为 1.65 V,而非 0 V,便于测量正负电流;更早期板子为 1.24 V)。

根据原理图与实测,ADC 端电压与相电流的关系为:

V c u r r e n t _ a d c = 8 × V i + 1.65 = 0.16 × I + 1.65 V_{current\_adc} = 8 \times V_i + 1.65 = 0.16 \times I + 1.65 Vcurrent_adc=8×Vi+1.65=0.16×I+1.65

因此软件中需先减去上电校准得到的偏置(零电流时约 1.65 V),再除以 8 倍放大与 0.02 Ω 采样电阻,反算电流。

③ 引脚连接(驱动板接口 2)

信号 开发板引脚 ADC 通道
Motor_IU_ADC PF6 ADC3_IN4
Motor_IV_ADC PF7 ADC3_IN5
Motor_IW_ADC PF8 ADC3_IN6
VBUS PF9 ADC3_IN7
TEMP PF10 ADC3_IN8

3. 硬件过流保护电路

3.1 过流保护原理图

该电路对 U/V/W 三相共用一套保护逻辑,任意一相过流均可触发关断。

3.2 工作原理

比较器(LMV331)

  • 每相 ADC 电压 Motor_IU/V/W_ADC 送入比较器反相端 IN-。
  • IN+ 接电阻分压基准 2V84_IN (板上硬件过流比较阈值,标称约 10 A)。
  • 比较器规则:IN+ > IN- 输出高电平,反之输出低电平。

正常状态

三相 ADC 电压均低于 2V84_IN → 比较器输出高电平 3.3 V → 后级比较器 U33 输出低电平 → Q8 截止 → Motor_SD_B = 3.3 V → 驱动正常工作,过流指示灯不亮。

过流触发

任一相 ADC 电压超过 2V84_IN → 该相比较器输出低电平 → 经 R133/R134/C33 的 RC 网络,U33 反相端电压被拉低 → U33 输出高电平 → Q8 导通 → Motor_SD_B 被迅速拉至 0 V → 驱动芯片 SD 引脚关断 ,功率输出切断,过流指示灯点亮。

恢复过程

电流恢复正常后,比较器重新输出高电平,但保护不会立刻解除:R145/C99 的 RC 充电需达到一定电压后,U34 才重新输出高电平,使 Motor_SD_B 恢复 3.3 V。这段延时避免电流在阈值附近抖动时频繁启停。

迟滞(R144)

R144 为 U33 提供施密特迟滞:触发电压约 1.571 V,恢复电压约 1.729 V,防止临界状态反复触发。

3.3 硬件保护与软件保护的分工

项目 硬件过流 软件(ADC)
响应 极快,不依赖 CPU 受采样周期限制(约 ms 级)
阈值 约 10 A(2V84_IN) 8 A(MOTOR_OVERCURRENT_MA,可调)
触发后 直接关断 SD 串口打印三相电流 + 程序关断
恢复 需等 RC 充电 + 重新使能 程序可主动判断

实验时用手堵转电机或快速加载,可观察到驱动板过流灯亮、Motor_SD_B 变低,电机立即停止------这是硬件保护在起作用,与程序是否运行无关。


4. 软件实现

在 lesson5 的 ADC 框架上,扩展为 5 通道扫描采集:温度、VBUS、IU、IV、IW。

4.1 关键宏定义

c 复制代码
#define VREF                            3.3f
#define ADC_NUM_MAX                     320

#define CURR_SHUNT_OHM                  0.02f    /* 原理图 R48 等,0.02 Ω / 2 W */
#define CURR_ADC_BIAS_V                 1.65f    /* 零电流时 ADC 端典型偏置(由校准实测) */

#define GET_ADC_VDC_VAL(val)            ((float)(val) / 4096.0f * VREF)
#define GET_ADC_CURR_VAL(val)           (((float)(val) / 8.0f / CURR_SHUNT_OHM) * 1000.0f)  // mA
#define GET_VBUS_VAL(val)               (((float)(val) - 1.24f) * 37.0f)

#define MOTOR_OVERCURRENT_MA            8000   // 软件过流阈值(mA)

#define ADC_WAVE_HEADER0                0xAAU
#define ADC_WAVE_HEADER1                0x55U
#define ADC_WAVE_FRAME_LEN              12U

GET_ADC_CURR_VAL 的含义:ADC 电压 val(已去偏置)→ 除以放大倍数 8 → 除以采样电阻 0.02 Ω → 乘 1000 转为 mA。

CURR_ADC_BIAS_V 仅作说明;实际上电后电机未启动时通过 17 次采样 得到各相 adc_offset,运行时减去该偏置,无需在公式里写死 1.65 V。

与 lesson5 相同,采样数据通过串口以二进制帧 输出,而非 printf 文本。lesson6 在 lesson5 的 6 字节帧(VBUS + 温度)基础上扩展为 12 字节同一帧,将 U/V/W 三相电流与电压、温度合并输出。

4.2 ADC 多通道 + DMA 配置

使用 ADC3 + DMA2 Stream0 Channel2,开启扫描模式,连续转换 5 个通道:

  1. Rank 1:TEMP(PF10)
  2. Rank 2:VBUS(PF9)
  3. Rank 3:IU(PF6)
  4. Rank 4:IV(PF7)
  5. Rank 5:IW(PF8)

DMA 循环搬运 320 个半字到 adc_buff[]。缓冲区按 [T, VBUS, IU, IV, IW, T, VBUS, ...] 交错排列,步长为 5。

4.3 DMA 完成回调:分离各通道并累加

c 复制代码
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    HAL_ADC_Stop_DMA(hadc);

    /* 温度、VBUS:直接求本轮均值 */
    for (uint32_t count = 0; count < ADC_NUM_MAX; count += 5)
        adc_mean += adc_buff[count];
    // ...

    /* 三相电流:累加到 sum,由 get_curr_val_x 再做平均 */
    for (uint32_t count = 2; count < ADC_NUM_MAX; count += 5)
        adc_mean += adc_buff[count];
    adc_mean_sum_u += adc_mean / (ADC_NUM_MAX / 5);
    adc_mean_count_u++;

    HAL_ADC_Start_DMA(&ADC_Handle, (uint32_t *)&adc_buff, ADC_NUM_MAX);
}

电流通道采用多次 DMA 回调累加再求平均,比单次采样更平滑;可根据实际需求调整累加次数。

4.4 偏置电压校准

硬件零电流时 ADC 输入约 1.65 V (新版),不能当作 0 A。上电后电机未启动时,各相独立采集 17 次 平均值作为 adc_offset(实测偏置会接近 1.65 V):

c 复制代码
int32_t get_curr_val_u(void)
{
    static uint8_t flag = 0;
    static uint32_t adc_offset = 0;

    curr_adc_mean = adc_mean_sum_u / adc_mean_count_u;
    adc_mean_count_u = 0;
    adc_mean_sum_u = 0;

    if (flag < 17) {
        adc_offset = curr_adc_mean;
        flag++;
    }
    if (curr_adc_mean >= adc_offset)
        curr_adc_mean -= adc_offset;
    else
        curr_adc_mean = 0;

    float vdc = GET_ADC_VDC_VAL(curr_adc_mean);
    return GET_ADC_CURR_VAL(vdc);
}

V、W 相逻辑相同(get_curr_val_vget_curr_val_w)。

4.5 主函数:电压、温度、三相电流同一帧输出

在 lesson5 的 AA 55 帧头上,把 U/V/W 三相电流与 VBUS、温度打包进同一帧 (12 字节),每 50 ms 发送一次。串口助手需切换到 HEX 显示

c 复制代码
if (HAL_GetTick() % 50 == 0 && print_flag == 0) {
    print_flag = 1;
    adc_send_waveform_frame();   /* 一帧内含 VBUS + 温度 + IU + IV + IW */
}

同一帧格式(12 字节,小端 uint16):

偏移 长度 内容 换算
0~1 2 帧头 AA 55 固定
2~3 2 VBUS 实际电压(V) × 100
4~5 2 温度 实际温度(℃) × 10
6~7 2 U 相电流 mA
8~9 2 V 相电流 mA
10~11 2 W 相电流 mA

示例:24.5 V、25.3 ℃、U=120 mA、V=130 mA、W=110 mA →

AA 55 92 09 FD 00 78 00 82 00 6E 00

adc_send_waveform_frame() 先调用 adc_fill_wave_snapshot() 在同一时刻读取全部 5 路量,再一次性组帧发送:

c 复制代码
static void adc_fill_wave_snapshot(uint16_t *vbus_x100, uint16_t *temp_x10,
                                   int32_t *iu_ma, int32_t *iv_ma, int32_t *iw_ma)
{
    *vbus_x100 = float_to_u16_scaled(get_vbus_val(), 100.0f);
    *temp_x10  = float_to_u16_scaled(get_ntc_t_val(), 10.0f);
    *iu_ma     = get_curr_val_u();
    *iv_ma     = get_curr_val_v();
    *iw_ma     = get_curr_val_w();
}

void adc_send_waveform_frame(void)
{
    uint8_t frame[ADC_WAVE_FRAME_LEN];
    /* 快照后写入 frame[0..11],一次 Usart_SendBytes 发出 */
}

按键/串口控制电机的方式与 lesson4、lesson5 相同。

4.6 软件过流保护

除驱动板硬件比较器(约 10 A)外,程序在 motor_overcurrent_poll() 中周期性检测三相电流;任一相超过 MOTOR_OVERCURRENT_MA(8 A)时关断电机并打印提示:

c 复制代码
static void motor_overcurrent_poll(void)
{
    int32_t iu, iv, iw;

    if (!motor_hall_is_active())
        return;

    if (!adc_is_overcurrent(&iu, &iv, &iw))
        return;

    printf("Overcurrent: U=%ldmA V=%ldmA W=%ldmA\r\n", (long)iu, (long)iv, (long)iw);
    set_bldcm_disable();
}

主循环中同时保留 lesson4 的 Hall 堵转检测(motor_stall_poll()),形成堵转 + 软件过流 + 硬件过流三层保护。


5. 实验操作

5.1 接线

与 lesson5 相同,驱动板排线接开发板直流有/无刷电机驱动接口 2

驱动板 开发板
5V_IN / GND 5V / GND
U+ / V+ / W+ PI5 / PI6 / PI7
U- / V- / W- PH13 / PH14 / PH15
SD / GND PE6 / GND
HU / HV / HW / GND PH10 / PH11 / PH12 / GND
TEMP / VBUS PF10 / PF9
IU / IV / IW PF6 / PF7 / PF8

三相绕组线序(以电机说明为准):黄 U、绿 V、蓝 W。

编码器:黄 HU、绿 HV、蓝 HW、黑 H-、红 H+。

5.2 串口指令

复制代码
d 0 \n      电机正转
d 1 \n      电机反转
v 1000 \n    速度设为 1000
v 0  \n      停转

5.3 现象观察

  1. 空载运行 :串口每 50 ms 输出一帧 AA 55 开头的 12 字节 HEX 数据,三相电流字段(偏移 6~11)数值较小。
  • 三相峰值 错开(红/蓝/绿不同时到顶)
  • 尖峰之间 经常掉到 0
  • 幅值在 几百 mA
  1. 手捏堵转 :电流字段明显增大;超过软件阈值(4 A)时串口打印 Overcurrent: ... 并关断;若超过硬件阈值(约 10 A),驱动板过流灯亮,电机立刻停止。

  2. 恢复:等待 RC 充电延时后,重新发送使能指令方可再次启动。

5.4 注意事项

  • 测量精度受 VREF 影响,可用万用表实测 VDDA 后修正 bsp_adc.h 中的 VREF 宏。
  • 软件过流阈值可在 bsp_adc.h 中修改 MOTOR_OVERCURRENT_MA(默认 4000 mA)。
  • 电机运行中不要直接按 RESET 复位,应先停转再复位,避免反电动势损坏硬件。
  • 采样电阻以原理图/板上丝印 为准(本板 R48 = 0.02 Ω );bsp_adc.hCURR_SHUNT_OHM 须与之一致。野火另有 0.01 Ω 改版,勿照搬文档。
  • 偏置电压若实测接近 1.24 V 而非 1.65 V,说明是更早期板型,仍可依赖上电 17 次 adc_offset 校准,一般无需改代码。