目录
[安装 I2C 工具集](#安装 I2C 工具集)
[扫描 I2C 总线](#扫描 I2C 总线)
[Shell 脚本读取传感器数据](#Shell 脚本读取传感器数据)
[16 位有符号数转换](#16 位有符号数转换)
前言
MPU6050 是常用的六轴传感器(三轴加速度计 + 三轴陀螺仪),本文详细介绍如何在 Linux 系统下通过命令行(I2C 工具)读取 MPU6050 的原始数据,并换算为物理单位(g、°/s),全程基于纯 Shell 脚本实现,无需编译代码,适合嵌入式 Linux 开发调试。
环境准备
硬件信息
传感器:MPU6050(I2C 地址默认 0x68)
ELF 2 的 40Pin 2.54mm 连接器兼容树莓派 40Pin 连接器。包含了 I2C 、 SPI 、 UART 和若干 GPIO ,其原理图如下:

在40pin中,提供了I2C4和I2C7。
按如下对应关系连接 ELF 2 开发板与 MPU-6050 模块(如果使用的不是ELF 2,请查询原理图获得正确的连接关系):
|---------------------------|---------------------------|---------------------|--------------|
| ELF 2 开发板40pin 编号 | RK3588 引脚 | MPU-6050 引脚 | 功能说明 |
| 1 | 3.3V | VCC | 供电(禁止接 5V) |
| 6 | GND | GND | 共地 |
| 3 | I2C4_SDA | SDA | 数据信号线 |
| 5 | I2C4_SCL | SCL | 时钟信号线 |
I2C 总线:本文中传感器挂载在 I2C 总线 4。
系统:Linux(本文以 Ubuntu 为例)。
安装 I2C 工具集
MPU6050 通过 I2C 总线通信,需先安装i2c-tools工具(ELF2 自带这个工具,可以跳过此步骤):
bash
apt update && apt install -y i2c-tools
确认传感器连接
扫描 I2C 总线
使用i2cdetect扫描总线 4,确认 MPU6050 的地址(默认 0x68):
bash
i2cdetect -y 4
正常输出如下(0x68 位置显示设备):
bash
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
验证传感器通信
MPU6050 的WHO_AM_I寄存器(0x75)默认值为 0x68,读取该寄存器验证通信:
bash
i2cget -y 4 0x68 0x75
返回0x68表示传感器通信正常;若返回--,需检查硬件连接或总线配置。
Shell 脚本读取传感器数据
完整脚本(readmpu.sh)
脚本功能:唤醒 MPU6050→读取加速度计 / 陀螺仪原始数据→转换为 16 位有符号数→换算为物理单位(g、°/s):
bash
#!/bin/bash
# 读取MPU6050数据(I2C总线4,地址0x68)
# 功能:读取加速度计(±2g)和陀螺仪(±250°/s)数据,转换为物理单位
# 1. 唤醒传感器(MPU6050上电默认休眠,写入电源管理寄存器0x6B)
i2cset -y 4 0x68 0x6B 0x00 > /dev/null 2>&1
# 核心函数1:读取单个寄存器并转为十进制(处理读取失败场景)
read_mpu_reg() {
local bus=$1
local addr=$2
local reg=$3
# 读取寄存器,失败时返回0
local val=$(i2cget -y $bus $addr $reg 2>/dev/null)
if [[ $val != 0x* ]]; then
echo 0
return
fi
# 去掉0x前缀,转为十进制
echo $((16#${val:2}))
}
# 核心函数2:拼接高低字节为16位有符号数(补码转换)
combine_16bit() {
local high=$1
local low=$2
# 拼接为16位无符号数
local unsigned=$(( (high << 8) | low ))
# 转换为有符号补码(处理负数)
if (( unsigned & 0x8000 )); then
echo $(( unsigned - 0x10000 ))
else
echo $unsigned
fi
}
# ========== 读取加速度计数据(±2g量程,分辨率16384 LSB/g) ==========
echo "加速度计数据:"
# 读取加速度计三轴高低字节(寄存器0x3B-0x40)
AX_H=$(read_mpu_reg 4 0x68 0x3C)
AX_L=$(read_mpu_reg 4 0x68 0x3B)
AY_H=$(read_mpu_reg 4 0x68 0x3E)
AY_L=$(read_mpu_reg 4 0x68 0x3D)
AZ_H=$(read_mpu_reg 4 0x68 0x40)
AZ_L=$(read_mpu_reg 4 0x68 0x3F)
# 拼接为16位有符号数
AX=$(combine_16bit $AX_H $AX_L)
AY=$(combine_16bit $AY_H $AY_L)
AZ=$(combine_16bit $AZ_H $AZ_L)
# 换算为物理单位(g)
AX_G=$(echo "scale=3; $AX/16384" | bc -l)
AY_G=$(echo "scale=3; $AY/16384" | bc -l)
AZ_G=$(echo "scale=3; $AZ/16384" | bc -l)
echo "X轴: $AX (≈ $AX_G g)"
echo "Y轴: $AY (≈ $AY_G g)"
echo "Z轴: $AZ (≈ $AZ_G g)"
# ========== 读取陀螺仪数据(±250°/s量程,分辨率131 LSB/(°/s)) ==========
echo -e "\n陀螺仪数据:"
# 读取陀螺仪三轴高低字节(寄存器0x43-0x48)
GX_H=$(read_mpu_reg 4 0x68 0x44)
GX_L=$(read_mpu_reg 4 0x68 0x43)
GY_H=$(read_mpu_reg 4 0x68 0x46)
GY_L=$(read_mpu_reg 4 0x68 0x45)
GZ_H=$(read_mpu_reg 4 0x68 0x48)
GZ_L=$(read_mpu_reg 4 0x68 0x47)
# 拼接为16位有符号数
GX=$(combine_16bit $GX_H $GX_L)
GY=$(combine_16bit $GY_H $GY_L)
GZ=$(combine_16bit $GZ_H $GZ_L)
# 换算为物理单位(°/s)
GX_DPS=$(echo "scale=3; $GX/131" | bc -l)
GY_DPS=$(echo "scale=3; $GY/131" | bc -l)
GZ_DPS=$(echo "scale=3; $GZ/131" | bc -l)
echo "X轴: $GX (≈ $GX_DPS °/s)"
echo "Y轴: $GY (≈ $GY_DPS °/s)"
echo "Z轴: $GZ (≈ $GZ_DPS °/s)"
脚本执行步骤
保存脚本并添加执行权限:
bash
chmod +x readmpu.sh
运行脚本:
bash
./readmpu.sh
输出结果示例
bash
加速度计数据:
X轴: 2 (≈ 0.000 g)
Y轴: 13358 (≈ 0.815 g)
Z轴: 11481 (≈ 0.700 g)
陀螺仪数据:
X轴: 8445 (≈ 64.465 °/s)
Y轴: 23295 (≈ 177.824 °/s)
Z轴: 30463 (≈ 232.541 °/s)
关键知识点说明
数据换算规则
- 加速度计 :默认量程 ±2g,分辨率
16384 LSB/g(即 16384 个数字量对应 1g 加速度),公式:加速度(g) = 16位数值 / 16384。 - 陀螺仪 :默认量程 ±250°/s,分辨率
131 LSB/(°/s),公式:角速度(°/s) = 16位数值 / 131。
16 位有符号数转换
MPU6050 输出的是 16 位补码数据,脚本中combine_16bit函数实现:
- 先拼接高低字节为无符号数;
- 若最高位为 1(负数),则减去
0x10000转换为有符号数。
容错处理
脚本中read_mpu_reg函数增加了异常处理:若i2cget读取失败(返回--或空),则返回 0,避免脚本报错中断。
总结
Linux 下通过i2c-tools可直接与 I2C 设备交互,无需编写驱动,适合快速调试。MPU6050 需先唤醒(写入 0x6B 寄存器)才能读取有效数据。传感器原始数据为 16 位补码,需转换为有符号数后再换算为物理单位,脚本已封装核心转换逻辑,可直接复用。