4. 六位置标定法(加速度计)

加速度计的标定,说白了就是找到它的「真实面」。

我刚开始做MEMS的时候,总觉得芯片出厂前不是已经校准过了吗?后来发现,温度、焊接应力、PCB安装角度,都会让加速度计的输出偏离理想值。你想想看,一个手机里的加速度计,如果零偏误差有50mg,那倾斜角度算出来能差好几度——这谁受得了?

六位置法,就是目前最经典、最实用的加速度计标定方法。它不需要转台,不需要高精度设备,只需要一个水平的平台,加上你的耐心。

4.1 六位置法的原理

加速度计的数学模型,其实很简单:

Ax_meas = Sx * (Ax_true + Bx)
Ay_meas = Sy * (Ay_true + By)
Az_meas = Sz * (Az_true + Bz)

其中:

  • Ax_meas:加速度计实际输出的原始值
  • Sx:X轴的灵敏度(比例因子)
  • Bx:X轴的零偏(bias)
  • Ax_true:真实的加速度值

理想情况下,Sx=1,Bx=0。但现实嘛……

六位置法的核心思想是:利用重力加速度这个已知的「标准源」。地球重力加速度g,大小是9.8 m/s²,方向永远指向地心。我们把加速度计的六个敏感轴分别对准重力方向,就能得到六个方程,解出六个未知数。

哪六个位置?

  • 位置1:X轴朝上(感受+g)
  • 位置2:X轴朝下(感受-g)
  • 位置3:Y轴朝上(感受+g)
  • 位置4:Y轴朝下(感受-g)
  • 位置5:Z轴朝上(感受+g)
  • 位置6:Z轴朝下(感受-g)

每个位置,我们记录加速度计三个轴的输出。这样就有6组数据,每组3个轴,总共18个测量值。但我们要解的只有6个参数(3个零偏 + 3个比例因子),所以这是个超定方程组——用最小二乘法来拟合最合适。

关键假设:六位置法假设加速度计的轴间非正交误差可以忽略,或者已经预先补偿。如果轴间误差较大,需要用更复杂的九位置法或十二位置法。

4.2 数据采集步骤

数据采集这块,我踩过不少坑。有一次在实验室里,我拿着加速度计模块手动翻转,结果手抖得不行,数据噪声大得离谱。后来学乖了——用夹具固定,每次翻转后等3秒再采集。

具体步骤:

  1. 准备一个水平平台:用水平仪校准,误差控制在0.1°以内。
  2. 固定传感器模块:用夹具或双面胶,确保模块不会松动。
  3. 上电预热:我一般预热5分钟,让芯片温度稳定下来。
  4. 位置1(X轴朝上):将模块按图示方向放置,等待2秒,采集100个样本取平均。
  5. 位置2(X轴朝下):翻转180°,同样等待2秒,采集100个样本取平均。
  6. 位置3~6:依次完成Y轴和Z轴的朝上/朝下位置。

我的小技巧:每个位置采集时,不要只采一次。我习惯采3次,每次间隔1秒,然后取中位数。这样可以剔除偶然的粗大误差。

数据记录格式建议如下:

位置 Ax (LSB) Ay (LSB) Az (LSB)
X朝上 16384 12 -8
X朝下 -16376 10 -5
Y朝上 15 16382 -3
Y朝下 13 -16378 -6
Z朝上 8 -5 16380
Z朝下 11 -7 -16374

注意:这里的数值是ADC原始输出,单位是LSB。如果你的加速度计量程是±2g,分辨率是16位,那么1g对应的理论值是16384 LSB。

4.3 最小二乘法拟合

好了,数据到手了。接下来怎么算?

我们以X轴为例。在位置1(X朝上),X轴感受到的真实加速度是+1g,所以:

Ax_meas1 = Sx * (1g + Bx)

在位置2(X朝下),X轴感受到的真实加速度是-1g:

Ax_meas2 = Sx * (-1g + Bx)

两个方程相减,就能消掉Bx:

Ax_meas1 - Ax_meas2 = Sx * 2g
Sx = (Ax_meas1 - Ax_meas2) / (2g)

两个方程相加,消掉Sx:

Ax_meas1 + Ax_meas2 = Sx * 2 * Bx
Bx = (Ax_meas1 + Ax_meas2) / (2 * Sx)

嗯,这是最简化的解法。但实际中,我更喜欢用最小二乘法,因为它能同时处理所有数据,而且对噪声更鲁棒。

最小二乘法的思路是这样的:我们建立一个线性方程组,把六个位置的测量数据都放进去,然后求解使得残差平方和最小的参数。

对于每个位置i,我们有:

Ax_meas_i = Sx * (Ax_true_i + Bx)
Ay_meas_i = Sy * (Ay_true_i + By)
Az_meas_i = Sz * (Az_true_i + Bz)

写成矩阵形式:

[Ax_meas_1]   [Ax_true_1  1  0  0  0  0]   [Sx]
[Ay_meas_1] = [0  0  Ay_true_1  1  0  0] * [Bx]
[Az_meas_1]   [0  0  0  0  Az_true_1  1]   [Sy]
...                                          [By]
                                             [Sz]
                                             [Bz]

用Python实现的话,代码很简洁:

import numpy as np

# 测量数据(LSB)
meas = np.array([
    [16384, 12, -8],    # X朝上
    [-16376, 10, -5],   # X朝下
    [15, 16382, -3],    # Y朝上
    [13, -16378, -6],   # Y朝下
    [8, -5, 16380],     # Z朝上
    [11, -7, -16374]    # Z朝下
])

# 真实加速度(g)
true_acc = np.array([
    [1, 0, 0],   # X朝上
    [-1, 0, 0],  # X朝下
    [0, 1, 0],   # Y朝上
    [0, -1, 0],  # Y朝下
    [0, 0, 1],   # Z朝上
    [0, 0, -1]   # Z朝下
])

# 构建设计矩阵
A = np.zeros((18, 6))
b = np.zeros(18)

for i in range(6):
    for j in range(3):
        row = i * 3 + j
        A[row, j*2] = true_acc[i, j]  # 比例因子
        A[row, j*2+1] = 1              # 零偏
        b[row] = meas[i, j]

# 最小二乘求解
params, residuals, rank, s = np.linalg.lstsq(A, b, rcond=None)

Sx, Bx, Sy, By, Sz, Bz = params
print(f"Sx={Sx:.4f}, Bx={Bx:.2f}")
print(f"Sy={Sy:.4f}, By={By:.2f}")
print(f"Sz={Sz:.4f}, Bz={Bz:.2f}")

注意:这里的真实加速度值用的是g作为单位。如果你的加速度计输出已经是m/s²,那就要把1g换成9.8。我习惯统一用g,最后再换算。

4.4 参数提取与验证

参数算出来了,怎么知道对不对?

我的做法是:用标定后的参数去补偿原始数据,然后看补偿后的模长是不是接近1g。

def calibrate(ax, ay, az, Sx, Bx, Sy, By, Sz, Bz):
    ax_cal = (ax - Bx) / Sx
    ay_cal = (ay - By) / Sy
    az_cal = (az - Bz) / Sz
    return ax_cal, ay_cal, az_cal

# 验证:用任意位置的原始数据
ax_raw, ay_raw, az_raw = 16384, 12, -8
ax_cal, ay_cal, az_cal = calibrate(ax_raw, ay_raw, az_raw, Sx, Bx, Sy, By, Sz, Bz)
norm = np.sqrt(ax_cal**2 + ay_cal**2 + az_cal**2)
print(f"补偿后模长: {norm:.4f} g")  # 应该接近1.0

如果模长偏差在±0.01g以内,说明标定效果不错。我曾经遇到过模长偏差0.05g的情况,查了半天发现是平台没放平——后来用水平仪重新校准,偏差就降到0.003g了。

经验之谈:六位置法标定后的加速度计,零偏误差可以做到5mg以内,比例因子误差0.1%以内。如果你的结果差很多,先检查数据采集过程,再检查平台水平度。

最后,我把整个六位置法的流程画了张图,方便你理解:

六位置标定法流程 步骤1:准备 水平平台 + 夹具 步骤2:预热 上电5分钟 步骤3:采集 6个位置数据 步骤4:数据预处理 去噪 + 取平均 步骤5:最小二乘法 求解6个参数 步骤6:参数提取 Sx, Bx, Sy, By, Sz, Bz 步骤7:验证 补偿后模长≈1g 合格? 标定完成 检查平台/重新采集

这张图把整个流程串起来了。你跟着走一遍,基本不会出错。

最后提醒一句:六位置法虽然简单,但精度上限取决于你的平台水平度和数据采集质量。如果追求更高精度,可以考虑用温控箱做温度补偿,或者用九位置法补偿轴间误差。不过那是后话了。