【ELF2学习开发板】Linux 命令行读取 MPU6050 传感器数据(I2C 总线)实战

目录

前言

环境准备

硬件信息

[安装 I2C 工具集](#安装 I2C 工具集)

确认传感器连接

[扫描 I2C 总线](#扫描 I2C 总线)

验证传感器通信

[Shell 脚本读取传感器数据](#Shell 脚本读取传感器数据)

完整脚本(readmpu.sh)

脚本执行步骤

输出结果示例

关键知识点说明

数据换算规则

[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 位补码,需转换为有符号数后再换算为物理单位,脚本已封装核心转换逻辑,可直接复用。

相关推荐
2501_901147832 小时前
学习笔记:基于摩尔投票法的高性能实现与工程实践
笔记·学习·算法·性能优化
郝学胜-神的一滴2 小时前
Linux网络编程中的connect函数:深入探索网络连接的基石
linux·服务器·网络·c++·websocket·程序人生
春日见2 小时前
window wsl环境: autoware有日志,没有rviz界面/ autoware起不来
linux·人工智能·算法·机器学习·自动驾驶
jmxwzy2 小时前
Linux常用命令
linux
不做无法实现的梦~2 小时前
思翼mk32遥控器配置图传和数传教程
linux·嵌入式硬件·机器人·自动驾驶
馨谙2 小时前
Ansible 多 Play 编写与模块使用全解析
运维·ansible
上海合宙LuatOS2 小时前
LuatOS ——Modbus RTU 通信模式
java·linux·服务器·开发语言·网络·嵌入式硬件·物联网
铁蛋AI编程实战2 小时前
最新 豆包4.0 实操手册:混合架构部署 + 实时交互 + 动态学习
学习·架构·交互
新时代牛马2 小时前
CANopen 协议详解
linux·微信