MPU6050校准:如何在校准后保留加速度计全量程?
解决MPU6050加速度计偏移校准并保留全量程的方法
你的问题核心是当前软件偏移补偿会占用量程空间——比如0.96g的正向偏移会让实际可测的正向最大加速度从2g降到1.04g。要解决这个问题,直接利用MPU6050的硬件偏移校准寄存器是最优方案:通过将偏移量写入传感器内置的寄存器,让硬件自动扣除偏移,原始输出数据就已经是校准后的结果,不会占用量程,从而保留±2g的全范围。
具体步骤:
计算偏移的LSB值
MPU6050在±2g量程下,加速度灵敏度为16384 LSB/g。校准后得到的静止加速度值与理想值的差值,就是需要补偿的偏移量:- x/y轴静止时理想值为0(水平放置),偏移量 = 校准得到的
a_x/a_y(单位g) - z轴静止时理想值为1g(垂直向上),偏移量 = 校准得到的
a_z- 1.0(单位g)
把偏移量转换为16位补码的LSB值:
# 计算各轴偏移的LSB值(16位补码) offset_x = int(a_x * 16384) offset_y = int(a_y * 16384) offset_z = int((a_z - 1.0) * 16384)- x/y轴静止时理想值为0(水平放置),偏移量 = 校准得到的
写入MPU6050的偏移寄存器
MPU6050的加速度偏移寄存器对应地址如下,需将16位偏移值拆分为高8位和低8位写入:- ACCEL_XOFFS_H (0x06)、ACCEL_XOFFS_L (0x07)
- ACCEL_YOFFS_H (0x08)、ACCEL_YOFFS_L (0x09)
- ACCEL_ZOFFS_H (0x0A)、ACCEL_ZOFFS_L (0x0B)
写入代码示例:
def write_offset(i2c, reg, value): # 写入16位值到寄存器对(高8位+低8位) high_byte = (value >> 8) & 0xFF low_byte = value & 0xFF i2c.writeto_mem(0x68, reg, bytes([high_byte])) i2c.writeto_mem(0x68, reg+1, bytes([low_byte])) # 写入各轴偏移 write_offset(i2c, 0x06, offset_x) write_offset(i2c, 0x08, offset_y) write_offset(i2c, 0x0A, offset_z)验证校准效果
写入偏移后重新读取加速度数据,静止状态下x/y轴应接近0g,z轴接近1g。此时测试正向加速度,就能达到±2g的全量程,不会因偏移损失量程空间。
注意事项:
- 校准前务必保证传感器完全静止,水平放置(x/y轴不受重力影响),z轴垂直向上。
- MPU6050的偏移寄存器是易失性的,断电后会丢失。可将校准得到的偏移值保存到Raspberry Pi Pico的Flash中,每次上电后自动读取并写入传感器寄存器。
- 原校准代码中读取y轴加速度的地址
ACCEL_XOUT_H + 2是正确的(X轴地址0x3B,Y轴0x3D),但建议直接写对应寄存器地址,避免混淆。
修改后的完整校准函数示例:
def calibrate(i2c): temp=0 accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z=0,0,0,0,0,0 # 采样10000次求平均 for i in range(10000): temp += read_raw_data(i2c, 0x41) / 340.0 + 36.53 # TEMP_OUT_H地址0x41 accel_x += read_raw_data(i2c, 0x3B) / 16384.0 # ACCEL_XOUT_H地址0x3B accel_y += read_raw_data(i2c, 0x3D) / 16384.0 # ACCEL_YOUT_H地址0x3D accel_z += read_raw_data(i2c, 0x3F) / 16384.0 # ACCEL_ZOUT_H地址0x3F gyro_x += read_raw_data(i2c, 0x43) / 131.0 # GYRO_XOUT_H地址0x43 gyro_y += read_raw_data(i2c, 0x45) / 131.0 # GYRO_YOUT_H地址0x45 gyro_z += read_raw_data(i2c, 0x47) / 131.0 # GYRO_ZOUT_H地址0x47 # 计算平均值 t = temp / 10000 a_x = accel_x / 10000 a_y = accel_y / 10000 a_z = accel_z / 10000 g_x = gyro_x / 10000 g_y = gyro_y / 10000 g_z = gyro_z / 10000 print(f"校准结果:temp={t:.2f}°C, a_x={a_x:.4f}g, a_y={a_y:.4f}g, a_z={a_z:.4f}g") # 计算加速度偏移的LSB值(16位补码) offset_x = int(a_x * 16384) offset_y = int(a_y * 16384) offset_z = int((a_z - 1.0) * 16384) # 写入偏移寄存器的辅助函数 def write_offset(reg, value): high_byte = (value >> 8) & 0xFF low_byte = value & 0xFF i2c.writeto_mem(0x68, reg, bytes([high_byte])) i2c.writeto_mem(0x68, reg + 1, bytes([low_byte])) # 写入加速度偏移 write_offset(0x06, offset_x) # ACCEL_XOFFS_H/L write_offset(0x08, offset_y) # ACCEL_YOFFS_H/L write_offset(0x0A, offset_z) # ACCEL_ZOFFS_H/L print("硬件偏移校准已写入MPU6050") return t, a_x, a_y, a_z, g_x, g_y, g_z
内容的提问来源于stack exchange,提问作者Anmol Goel
相关产品推荐
相关产品推荐

