第一章 传感器校准基础

做飞控这么多年,我见过太多新手上来就调PID,结果飞机怎么都稳不住。其实啊,八成问题出在传感器没校准。传感器不准,后面调参全是白费功夫。今天咱们就把加速度计、陀螺仪、磁力计、气压计这四样东西的校准原理和方法,一次性说清楚。

核心观点:传感器校准是飞控调参的基石。数据不准,算法再牛也白搭。

传感器校准 加速度计 六位置法校准 零偏 + 比例因子 陀螺仪 静止采集零偏 温漂补偿 磁力计 椭球拟合校准 硬铁/软铁补偿 气压计 静态气压校准 温度补偿 校准顺序:陀螺仪 → 加速度计 → 磁力计 → 气压计

一、加速度计校准

加速度计测的是什么?说白了就是比力。它测的是物体受到的加速度,包括重力。静止的时候,它读到的就是重力加速度g。

我刚开始做飞控时,拿了个加速度计直接读数,发现三个轴加起来不是1g。当时我还以为是传感器坏了,后来才知道——每个传感器都有零偏和比例误差。

校准原理

加速度计的误差模型其实很简单:

实际值 = 比例因子 × (原始读数 - 零偏)

我们需要求的就是零偏和比例因子这两个参数。怎么求?用六位置法。

六位置法操作步骤

  1. 把传感器平放,Z轴朝上,记录读数
  2. 翻转,Z轴朝下,记录读数
  3. 侧放,X轴朝上,记录读数
  4. 侧放,X轴朝下,记录读数
  5. 侧放,Y轴朝上,记录读数
  6. 侧放,Y轴朝下,记录读数

每个位置静止采集个几百组数据,取平均。然后就能算出零偏和比例因子了。

我的小技巧:采集数据时别用手拿着,找个水平台面或者用夹具固定。手抖会引入额外噪声,数据就不准了。

代码示例(Python)

import numpy as np

# 假设六个位置的读数(单位:m/s²)
# 顺序:Z上, Z下, X上, X下, Y上, Y下
data = {
    'z_up':   [9.78, 9.79, 9.77],
    'z_down': [-9.82, -9.81, -9.83],
    'x_up':   [9.76, 9.77, 9.75],
    'x_down': [-9.80, -9.79, -9.81],
    'y_up':   [9.79, 9.80, 9.78],
    'y_down': [-9.81, -9.82, -9.80]
}

# 计算每个位置的平均值
avg = {k: np.mean(v) for k, v in data.items()}

# 计算零偏和比例因子
bias_x = (avg['x_up'] + avg['x_down']) / 2
bias_y = (avg['y_up'] + avg['y_down']) / 2
bias_z = (avg['z_up'] + avg['z_down']) / 2

scale_x = (avg['x_up'] - avg['x_down']) / (2 * 9.81)
scale_y = (avg['y_up'] - avg['y_down']) / (2 * 9.81)
scale_z = (avg['z_up'] - avg['z_down']) / (2 * 9.81)

print(f"零偏: X={bias_x:.3f}, Y={bias_y:.3f}, Z={bias_z:.3f}")
print(f"比例因子: X={scale_x:.3f}, Y={scale_y:.3f}, Z={scale_z:.3f}")

注意:加速度计校准必须在静止状态下进行。我曾经见过有人把传感器拿在手里晃来晃去地校准,结果数据乱七八糟。记住,动起来的数据是没法用的。

二、陀螺仪校准

陀螺仪测的是角速度。它有个特点——静止时读数应该是0。但实际呢?总有零偏。

我记得有一次调试四旋翼,飞机悬停时总往一个方向慢慢偏。查了半天,发现是陀螺仪零偏没校准。校准之后,问题立马解决了。

校准原理

陀螺仪的误差模型更简单:

真实角速度 = 原始读数 - 零偏

没有比例因子?对,陀螺仪的比例因子一般出厂就标定了,我们只需要校准零偏。

校准方法

  1. 把传感器放在静止的平台上
  2. 采集至少1000组数据(大概10秒钟)
  3. 取平均值,就是零偏

就这么简单。但有个坑——陀螺仪的零偏会随温度变化。

关键点:陀螺仪零偏是温度的函数。温度变了,零偏也会变。所以很多飞控会在上电后先预热几分钟,等温度稳定了再校准。

温漂补偿

如果你对精度要求高,可以做个温漂模型:

# 不同温度下的零偏数据
temp_data = {
    25:  [0.01, 0.02, -0.01],   # 25°C时的零偏
    35:  [0.03, 0.04, 0.01],
    45:  [0.05, 0.06, 0.03],
    55:  [0.08, 0.09, 0.05]
}

# 拟合一条直线,用于实时补偿
# 实际代码中可以用最小二乘法拟合
def get_bias_at_temp(temp):
    # 假设线性关系
    bias_x = 0.001 * temp - 0.015
    bias_y = 0.0012 * temp - 0.02
    bias_z = 0.0008 * temp - 0.01
    return [bias_x, bias_y, bias_z]

我的经验:对于大多数消费级飞控,只做静态零偏校准就够了。温漂补偿一般用在工业级或军用级产品上。别为了追求完美把简单问题搞复杂了。

三、磁力计校准

磁力计测的是磁场强度。它用来找北,但也是最容易受干扰的传感器。

为什么?因为周围任何铁磁性物质都会影响它。电机、电池、螺丝刀,甚至你手机里的扬声器,都会让磁力计读数变形。

校准原理

理想情况下,磁力计在三维空间旋转时,读数应该落在一个球面上。但实际呢?由于硬铁干扰和软铁干扰,这个球会变成椭球,而且球心会偏移。

硬铁干扰:相当于加了一个固定的偏置磁场,让球心偏移。

软铁干扰:相当于磁场被扭曲,让球变成椭球。

椭球拟合法

校准过程就是采集大量数据,然后拟合出一个椭球,再把它修正回标准球。

import numpy as np
from scipy.optimize import least_squares

# 假设采集到的磁力计数据(单位:uT)
mag_data = np.array([
    [10.2, 5.1, -8.3],
    [-9.8, 6.2, 7.9],
    [8.5, -10.1, -6.8],
    # ... 更多数据点
])

# 椭球拟合函数
def ellipsoid_fit(params, data):
    a, b, c, cx, cy, cz = params
    x, y, z = data[:, 0], data[:, 1], data[:, 2]
    return ((x - cx)/a)**2 + ((y - cy)/b)**2 + ((z - cz)/c)**2 - 1

# 初始猜测
initial_guess = [10, 10, 10, 0, 0, 0]

# 最小二乘拟合
result = least_squares(ellipsoid_fit, initial_guess, args=(mag_data,))
a, b, c, cx, cy, cz = result.x

print(f"椭球参数: a={a:.2f}, b={b:.2f}, c={c:.2f}")
print(f"中心偏移: cx={cx:.2f}, cy={cy:.2f}, cz={cz:.2f}")

避坑指南:我曾经在实验室里校准磁力计,结果怎么都校不准。后来发现实验台下面有根钢筋。所以校准磁力计时,一定要远离金属物体,最好在室外空旷地方做。

校准步骤

  1. 找一个空旷的地方,远离金属和磁场源
  2. 拿着传感器在空中画"8"字,尽量覆盖所有方向
  3. 采集至少200个数据点
  4. 用椭球拟合算法算出偏移和缩放参数
  5. 把参数写入飞控参数表

四、气压计校准

气压计用来测高度。原理很简单——气压随高度变化。但实际用起来,问题不少。

最大的问题是:气压受温度影响很大。你想想看,太阳晒一会儿,气压计温度升高,读数就变了。这时候高度也跟着变,飞机就会莫名其妙地上下飘。

校准原理

气压计校准主要做两件事:

  • 静态校准:在已知高度的地方,记录气压值,建立基准
  • 温度补偿:消除温度变化对气压读数的影响

静态校准方法

# 标准大气压公式
# P = P0 * (1 - 0.0065 * h / T0)^(5.257)

def calibrate_barometer(pressure_sea_level, temp_sea_level):
    """
    在海平面高度进行校准
    pressure_sea_level: 当前海平面气压(单位:hPa)
    temp_sea_level: 当前海平面温度(单位:°C)
    """
    # 记录当前读数
    raw_pressure = read_barometer()
    
    # 计算校准偏移
    offset = pressure_sea_level - raw_pressure
    
    return offset

# 实际使用时
offset = calibrate_barometer(1013.25, 15.0)
corrected_pressure = raw_pressure + offset

温度补偿

大多数气压计芯片内部都有温度传感器。我们可以利用它来做补偿:

def temperature_compensate(raw_pressure, temp):
    """
    温度补偿函数
    raw_pressure: 原始气压读数
    temp: 芯片内部温度
    """
    # 温度系数,不同芯片不一样
    temp_coeff = 0.012  # hPa/°C
    
    # 以25°C为参考温度
    ref_temp = 25.0
    
    # 补偿
    compensated = raw_pressure - temp_coeff * (temp - ref_temp)
    
    return compensated

我的建议:气压计校准最好在飞行前做。因为天气变化会影响海平面气压。我一般会在起飞前让飞机静止10秒,采集气压数据做基准。这样能最大程度减少环境变化的影响。

校准顺序很重要

最后说一句,四个传感器的校准顺序是有讲究的:

顺序 传感器 原因
1 陀螺仪 静止校准,最简单,先搞定
2 加速度计 需要陀螺仪数据做姿态参考?其实不需要,但习惯上先做陀螺仪
3 磁力计 需要加速度计数据做倾斜补偿
4 气压计 独立校准,放最后

嗯,传感器校准这块儿就这些内容。记住一句话:校准做得好,调参没烦恼。别急着飞,先把基础打牢。


专注资料整理