四轴飞行器电压电流采集系统设计与实现

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

1. 电压与电流采集的工程目标与系统定位

在四轴飞行器控制系统中,电池电压与电机总电流是两个关键的状态反馈量。它们不参与核心控制律(如PID或LQR)的实时计算,但承担着不可替代的系统级保障职能:电压用于判断电池剩余电量、防止过放导致动力骤降甚至失控;电流则反映整机负载状态,是电机异常(如堵转、短路)、电调故障或空气动力学失衡的重要判据。因此,该采集模块的设计目标并非追求微秒级响应,而是强调 数据稳定性、长期漂移抑制与工程可解释性 ——即每次采样值必须能通过确定性公式反推出物理世界的实际电压/电流值,且在数小时连续运行中保持一致性。

这一目标决定了整个采集链路的技术选型与配置逻辑。我们采用STM32F570RB(Cortex-M33内核)作为主控,其ADC1外设具备12位精度、多通道扫描及DMA自动搬运能力,完全满足本场景对精度(电压分辨率优于0.1V,电流优于10mA)与实时性(100Hz以上更新率)的要求。采集信号来源于两路独立硬件电路:一路为飞控板上的电池电压分压网络,另一路为电调板上的高精度电流检测芯片(INA199A1)。二者均通过物理接口连接至MCU,构成一个跨板卡的分布式传感子系统。

2. 硬件电路原理与参数溯源

2.1 电池电压采集电路分析

电压采集点位于飞控板的5V电源输入路径上游,直接监测锂电池组输出端。由于标称电压为12V(满电12.6V,截止电压约10.2V),远超STM32 ADC输入耐压范围(0–3.3V),必须进行无源分压。原理图显示,该电路由R1=100kΩ与R2=10kΩ精密电阻串联构成,PA7引脚连接于R1与R2之间节点,如图1所示。

V_BAT (12V) ───┬── R1 (100kΩ) ───┬── PA7 (ADC_IN7)
               │                │
              GND             R2 (10kΩ)
                               │
                              GND

该分压比为 R2/(R1+R2) = 10k/(100k+10k) = 1/11。因此,PA7引脚实际承受电压 V_PA7 = V_BAT / 11。此关系是后续所有软件校准的物理基础。需注意:电阻精度直接影响最终电压读数误差,选用1%精度金属膜电阻可将分压误差控制在±1%以内,满足飞行器应用需求。

2.2 电机总电流采集电路分析

电流采集部署于电调板,检测对象为四路无刷电机的公共供电回路总电流。核心器件为TI INA199A1高侧电流检测放大器,其内部集成精密增益电阻与运算放大器,典型增益G=50V/V。原理图显示,电流流经一个R_SHUNT=4mΩ(0.004Ω)的锰铜分流电阻,INA199A1的VSense引脚跨接于此电阻两端,Vout引脚输出放大后的电压信号,该信号经排线送至飞控板PVE引脚(对应ADC1_IN9)。

根据INA199A1数据手册,其输出电压公式为:
Vout = G × (I × R_SHUNT) + VREF

其中VREF为参考电压。本设计中,VREF引脚(VEF)直接接地(GND),故VREF=0V。代入G=50、R_SHUNT=0.004Ω,得:
Vout = 50 × I × 0.004 = 0.2 × I

即输出电压与被测电流呈线性关系,比例系数为0.2 V/A。这意味着当电流I=1A时,Vout=0.2V;I=5A时,Vout=1.0V。该系数是电流软件解算的核心常量,其准确性取决于INA199A1的增益精度(典型±1%)与分流电阻的阻值精度(本设计选用±0.5%规格)。

3. STM32 HAL库ADC与DMA配置详解

3.1 CubeMX图形化配置逻辑

在STM32CubeMX中,ADC1配置需严格遵循以下工程原则:

  • 工作模式 :选择“Independent mode”(独立模式)。因仅使用ADC1,无需与ADC2同步。
  • 分辨率 :12位(Resolution: 12 Bits)。12位对应0–4095数字量,提供足够动态范围(3.3V/4095≈0.8mV/LSB)。
  • 数据对齐 :Right alignment(右对齐)。HAL库默认处理方式,低位为低有效位,便于后续数值运算。
  • 扫描模式 :Enabled(启用)。因需连续采集两个通道(IN7与IN9),必须开启扫描以按序轮询。
  • 连续转换 :Enabled(启用)。确保ADC在完成一次扫描后自动启动下一轮,形成稳定数据流。
  • DMA设置 :Enabled(启用),Data Width: Word(32位),Mode: Circular(循环模式)。DMA是实现零CPU干预采集的关键:循环模式使DMA指针在预设缓冲区(如80×2数组)内自动回绕,避免溢出中断;Word宽度匹配HAL_ADC_GetValue()返回的uint32_t类型,提升搬运效率。

通道配置细节:
- Channel 7 (PA7) :Rank 1,Sampling Time: 239.5 Cycles(最大值)。长采样时间提升信噪比,适用于相对缓慢变化的电池电压。
- Channel 9 (PVE) :Rank 2,Sampling Time: 239.5 Cycles。与通道7一致,保证两路信号采样条件对称,消除时序偏差。

时钟配置需确认ADCCLK ≤ 36MHz(F570最高支持),本设计中APB2时钟为64MHz,经2分频后ADCCLK=32MHz,符合要求。

3.2 生成代码的初始化流程解析

CubeMX生成的 MX_ADC1_Init() 函数完成了ADC外设的基础寄存器配置,包括时钟使能、通道映射、采样时间设定等。但关键的DMA启动与ADC使能需在用户代码中显式调用:

// 启动ADC1并开启DMA传输
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_dma_buffer, 
                       ADC_BUFFER_SIZE, ADC_DATA_ALIGN_RIGHT, 
                       HAL_ADC_MODE_CIRCULAR) != HAL_OK) {
    Error_Handler(); // 初始化失败处理
}

此处 adc_dma_buffer 为声明的二维数组 uint16_t adc_dma_buffer[ADC_BUFFER_SIZE][2] ADC_BUFFER_SIZE 定义为80。DMA配置为从ADC_DR寄存器(数据寄存器)读取16位数据,并按扫描顺序依次填入缓冲区: adc_dma_buffer[i][0] 存放通道7(电压)数据, adc_dma_buffer[i][1] 存放通道9(电流)数据。循环模式确保DMA在填满80行后自动回到首行,持续覆盖旧数据。

4. 数据采集与物理量解算的软件实现

4.1 缓冲区管理与数据获取策略

为规避单次DMA传输延迟导致的数据不一致(如读取过程中DMA正写入新值),采用双缓冲或原子读取策略。本方案采用更简洁有效的“索引快照法”:定义一个volatile全局变量 adc_read_index ,在DMA传输完成回调(HAL_ADC_ConvCpltCallback)中递增;用户任务读取时,先拷贝当前索引值,再据此访问缓冲区。核心代码如下:

volatile uint8_t adc_read_index = 0;

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
    if(hadc->Instance == ADC1) {
        adc_read_index = (adc_read_index + 1) % ADC_BUFFER_SIZE;
    }
}

// 获取指定通道的平均值(防抖)
float get_adc_average(uint8_t channel) {
    uint8_t idx = adc_read_index;
    uint32_t sum = 0;
    for(uint8_t i = 0; i < ADC_BUFFER_SIZE; i++) {
        sum += adc_dma_buffer[(idx + i) % ADC_BUFFER_SIZE][channel];
    }
    return (float)sum / (float)ADC_BUFFER_SIZE;
}

get_adc_average(0) 返回电压通道(IN7)的80点滑动平均值, get_adc_average(1) 返回电流通道(IN9)的80点滑动平均值。滑动平均有效抑制了高频噪声与瞬态干扰,使数据显示平稳。

4.2 电压物理量解算公式推导

ADC原始值 raw_volt (范围0–4095)需经三步转换为真实电池电压 V_BAT (单位:V):

  1. ADC量化电压 V_PA7 = raw_volt × (3.3V / 4095)
    • 原理:ADC将0–3.3V线性映射为0–4095整数。 3.3/4095 ≈ 0.00080586 V/LSB 是量化系数。
  2. 分压网络还原 V_BAT = V_PA7 × 11
    • 原理:由硬件电路决定,PA7电压仅为电池电压的1/11。
  3. 合并公式 V_BAT = raw_volt × (3.3 × 11 / 4095) = raw_volt × 0.0088645 V/LSB

实际代码中,为避免浮点运算开销(尤其在资源受限的M33上),可预先计算常量:

#define VOLTAGE_SCALE_FACTOR (3.3f * 11.0f / 4095.0f) // ≈ 0.0088645
float battery_voltage = get_adc_average(0) * VOLTAGE_SCALE_FACTOR;

4.3 电流物理量解算公式推导

电流解算同样分三步,但起点是通道9的原始值 raw_curr

  1. ADC量化电压 Vout = raw_curr × (3.3V / 4095)
    • Vout 即INA199A1的输出电压,直接施加于PA7引脚。
  2. 电流-电压关系还原 I = Vout / 0.2
    • 原理:由INA199A1电路推导出 Vout = 0.2 × I ,故 I = Vout / 0.2 = Vout × 5
  3. 合并公式 I = raw_curr × (3.3 / 4095) × 5 = raw_curr × (16.5 / 4095) ≈ raw_curr × 0.004029 A/LSB

代码实现:

#define CURRENT_SCALE_FACTOR (3.3f * 5.0f / 4095.0f) // ≈ 0.004029
float motor_current = get_adc_average(1) * CURRENT_SCALE_FACTOR;

5. 实时验证与工程调试方法

5.1 调试输出任务设计

为验证采集链路有效性,需构建一个轻量级调试任务,周期性打印电压与电流值。该任务应运行于FreeRTOS环境,优先级低于电机控制任务(如 osPriorityBelowNormal ),避免抢占关键控制周期。

void debug_task(void const * argument) {
    for(;;) {
        float v = battery_voltage; // 由采集任务更新的全局变量
        float i = motor_current;
        printf("BAT: %.2fV | CURR: %.3fA\r\n", v, i);
        osDelay(500); // 2Hz刷新率,兼顾可观测性与串口负载
    }
}

5.2 静态与动态工况验证

  • 静态验证(电机停转) :连接12V电池,观察串口输出。理论值: V_BAT ≈ 12.0V I ≈ 0.000A 。实测若显示 10.8V ,表明电池已放电至约85%容量(12.6V满电,10.2V截止),符合预期。此时电流读数应稳定在 0.05–0.06A ,此残余电流源于飞控自身功耗(MCU、传感器、LED等),属正常现象。

  • 动态验证(电机启停与油门调节) :解除电机控制代码注释,逐步增加油门。观察电流值变化:

  • 油门10%:电流升至 ~0.11A ,反映电机空载启动电流。
  • 油门50%:电流应显著上升(如 ~0.8A ),体现负载增加。
  • 油门100%:电流达峰值(如 ~2.5A ),验证系统带载能力。
    同时,电压值在大电流下应有轻微跌落(如 10.8V → 10.5V ),这是电池内阻压降的体现,进一步佐证数据真实性。

5.3 常见问题排查指南

现象 可能原因 排查步骤
电压读数恒为0或4095 PA7引脚未正确连接;分压电阻虚焊;ADC通道未使能 万用表测量PA7对地电压;检查CubeMX中ADC1_IN7是否勾选;确认 hadc1.Init.ScanConvMode = ENABLE
电流读数恒为0 PVE引脚断路;INA199A1供电缺失(Vs=5V);分流电阻开路 测量PVE引脚电压(空载应≈2.5V,负载随电流变化);检查电调板5V供电;确认分流电阻两端导通
电压/电流值跳变剧烈 DMA缓冲区未正确声明为 __attribute__((aligned(4))) ;未使用 volatile 修饰 adc_read_index ;采样时间过短 检查缓冲区内存对齐;确认索引变量属性;增大Sampling Time至239.5 Cycles
数值偏高/偏低系统性偏差 分压电阻实际阻值偏差;INA199A1增益误差;ADC参考电压(VREF+)未稳定 用高精度万用表实测分压比;查阅INA199A1数据手册增益容差;确认VREF+引脚焊接良好且无噪声

6. 工程实践中的关键经验与优化建议

6.1 硬件层面的经验沉淀

在多个飞行器项目迭代中,发现以下硬件细节对采集精度影响显著:
- 分压电阻布局 :100kΩ与10kΩ电阻应紧邻PA7引脚放置,避免长走线引入分布电容与噪声。曾有项目因电阻远离MCU,导致高频开关噪声耦合进PA7,使电压读数在电机运行时波动±0.3V。解决方案是将分压点直接做在MCU焊盘附近。
- 电流检测PCB走线 :分流电阻的Kelvin连接(四线制)至关重要。必须使用独立的电流检测走线(Sense+与Sense-)连接INA199A1,而非共用功率走线。否则大电流产生的磁场与压降会污染检测信号。我们曾因未严格执行Kelvin布线,导致电流读数在5A时误差高达±15%。
- 模拟地(AGND)分割 :ADC的AGND引脚必须与INA199A1的AGND、分压网络的GND单点连接,并与数字地(DGND)通过0Ω电阻或磁珠隔离。混用地平面是引入共模噪声的主因。

6.2 软件层面的鲁棒性增强

  • 启动时序保护 :ADC初始化后,首次转换结果可能不稳定。应在 HAL_ADC_Start_DMA() 后,执行10–20ms延时或等待2–3次DMA传输完成,再开始读取有效数据。否则上电瞬间可能读到全0或随机值。
  • 数值范围钳位 :添加物理合理性检查。例如,电压值若超出 8.0–13.0V 范围,或电流值若为负数/超过 10A (依据电调规格),则标记为“无效数据”,并沿用上一有效值。这能防止传感器故障或瞬态干扰导致飞控误判。
  • 低功耗优化 :若飞行器进入待机模式,可动态关闭ADC时钟( __HAL_RCC_ADC1_CLK_DISABLE() )并进入Stop模式。唤醒后重新初始化ADC与DMA,比维持运行更省电。

6.3 与上层控制系统的集成

采集到的电压/电流数据不应仅用于监控。在实际项目中,我们将其深度融入控制系统:
- 电压自适应PID参数 :当 V_BAT < 11.0V 时,自动降低PID控制器的比例增益Kp,补偿因电压下降导致的电机响应变慢,维持姿态控制性能稳定。
- 电流异常熔断 :若 motor_current > 3.0A 持续500ms,触发安全停机(禁用所有电机PWM输出),防止电调过热损坏。此功能在螺旋桨被异物卡住时成功避免了多次硬件事故。
- 电量估算(SOC) :结合电压查表法(LUT)与库仑计数法(对电流积分),实现更精准的剩余电量百分比估算,显示于地面站。

这些实践证明,一个看似简单的电压电流采集模块,其设计质量直接关联到飞行器的安全性、可靠性与智能化水平。它不是控制环路的旁观者,而是整个系统健康状态的守门人。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值