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):
-
ADC量化电压
:
V_PA7 = raw_volt × (3.3V / 4095)-
原理:ADC将0–3.3V线性映射为0–4095整数。
3.3/4095 ≈ 0.00080586 V/LSB是量化系数。
-
原理:ADC将0–3.3V线性映射为0–4095整数。
-
分压网络还原
:
V_BAT = V_PA7 × 11- 原理:由硬件电路决定,PA7电压仅为电池电压的1/11。
-
合并公式
:
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
:
-
ADC量化电压
:
Vout = raw_curr × (3.3V / 4095)-
此
Vout即INA199A1的输出电压,直接施加于PA7引脚。
-
此
-
电流-电压关系还原
:
I = Vout / 0.2-
原理:由INA199A1电路推导出
Vout = 0.2 × I,故I = Vout / 0.2 = Vout × 5。
-
原理:由INA199A1电路推导出
-
合并公式
:
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)与库仑计数法(对电流积分),实现更精准的剩余电量百分比估算,显示于地面站。
这些实践证明,一个看似简单的电压电流采集模块,其设计质量直接关联到飞行器的安全性、可靠性与智能化水平。它不是控制环路的旁观者,而是整个系统健康状态的守门人。

343

被折叠的 条评论
为什么被折叠?



