跳转至

exs_mpu6050 扩展库

作者:王城钧 | 最后修改:2026-07-24

一、概述

exs_mpu6050 是 InvenSense(TDK) MPU6050 六轴姿态传感器(3 轴加速度计 + 3 轴陀螺仪)的 LuatOS 扩展库。MPU6050 是全球使用最广泛的 MEMS 六轴 IMU 之一,内部集成 DMP(Digital Motion Processor)数字运动处理器,可直接输出姿态四元数和欧拉角。

1.1 主要特性

  • 三轴加速度计:16 位 ADC,默认量程 ±2g(±4/8/16g 可选),分辨率 16384 LSB/g(±2g 量程)

  • 三轴陀螺仪:16 位 ADC,默认量程 ±250°/s(±500/1000/2000°/s 可选),分辨率 131 LSB/(°/s)(±250°/s 量程)

  • 内置温度传感器:分辨率 340 LSB/°C,用于内部温度补偿

  • I2C 接口通信,可选 7 位地址 0x68(AD0 接地)或 0x69(AD0 接 VCC)

  • 内置 DMP(Digital Motion Processor)数字运动处理器,直接输出四元数与欧拉角

  • 首次上电自动校准加速度计与陀螺仪零偏,校准数据持久化到文件

  • 支持互补滤波姿态解算 get_attitude():陀螺积分(96% 权重)+ 加速度修正(4% 权重)

  • 支持碰撞/敲击检测 detect_tap():三轴合加速度超过阈值触发

  • 支持自由落体/失重检测 detect_freefall():三轴合加速度低于阈值触发

  • 低通滤波器可配置(默认 5Hz),抑制高频振动噪声

1.2 注意事项

  • 仅支持硬件 I2C 模式:本库使用 i2c.setup() + init() 模式,调用前需先通过 i2c.setup(hwid, i2c.FAST) 初始化 I2C 总线

  • 芯片地址自动检测init() 会依次探测 0x68 和 0x69 地址,GY-521 等常见模块 AD0 默认接地(地址 0x68)

  • 首次自动校准:首次上电时 init() 会触发自动校准,设备必须水平静止放置。校准采集 200 个样本,需至少 50 个有效静止样本(连续静止 0.2s 以上)。校准通过后数据保存到 /mpu6050_calib.txt,后续启动自动加载,无需重复校准

  • DMP 需要额外固件:使用 DMP 功能需准备 dmp_firmware.lua 文件(将 DMP 固件数组转为 Lua table),固件来源见 4.6 节说明

  • 互补滤波需连续调用get_attitude() 依赖陀螺积分,必须在一个循环中以固定频率(建议 10~50ms 间隔)持续调用才能正常工作,中断后积分会丢失

  • SCL 和 SDA 需外接 4.7kΩ~10kΩ 上拉电阻到 VCC(GY-521 模块已内置)

  • 所有 API 因使用了 sys.wait(),必须在协程(task)中调用

1.3 加载方式

-- 扩展库需要 require 加载后才能调用
local exs_mpu6050 = require "exs_mpu6050"

1.4 硬件连接

MPU6050 通过 I2C 接口与主控连接。以 GY-521 模块为例,模块已内置 3.3V 稳压器和 I2C 上拉电阻。

接线表

Air8000/780EXX/8101核心板 AirETH_1000配件板
VDD_EXT VCC
GND GND
I2Cx_SCL SCL
I2Cx_SDA SDA

二、核心示例

核心示例是使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码,帮助开发者快速理解如何使用本库。

更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/sensor/mpu6050

2.1 按使用接口划分

2.1.1 硬件 I2C 模式(基础用法)

使用芯片内置的硬件 I2C 外设,需先 i2c.setup() 初始化总线。

主动轮询读取加速度、角速度和温度:

local exs_mpu6050 = require "exs_mpu6050"
i2c.setup(1, i2c.FAST)
if not exs_mpu6050.init(1) then return end

while true do
    local acc  = exs_mpu6050.get_accel()
    local gyro = exs_mpu6050.get_gyro()
    local temp = exs_mpu6050.get_temp()
    log.info("mpu6050", string.format(
        "acc:(%.3f,%.3f,%.3f)g gyro:(%.1f,%.1f,%.1f)°/s temp:%.1f°C",
        acc.x, acc.y, acc.z, gyro.x, gyro.y, gyro.z, temp))
    sys.wait(100)
end

2.1.2 指定芯片地址

当模块 AD0 引脚接 VCC 时,芯片地址为 0x69,需手动指定。

local exs_mpu6050 = require "exs_mpu6050"
i2c.setup(1, i2c.FAST)
if not exs_mpu6050.init(1, 0x69) then return end

2.2 按使用场景划分

2.2.1 静态倾角仪

适用场景:水平仪、倾斜开关、天线姿态检测等静态倾角测量。

local exs_mpu6050 = require "exs_mpu6050"
i2c.setup(1, i2c.FAST)
exs_mpu6050.init(1)

while true do
    local pitch, roll = exs_mpu6050.get_tilt()
    log.info("tilt", string.format("俯仰=%.1f° 横滚=%.1f°", pitch, roll))
    sys.wait(500)
end

2.2.2 动态姿态跟踪(互补滤波)

适用场景:云台稳定器、自平衡小车、体感遥控器等需要平滑跟踪动态姿态的场景。

互补滤波融合陀螺仪高频响应和加速度计低频修正,需在循环中持续调用以保持陀螺积分连续性。

local exs_mpu6050 = require "exs_mpu6050"
i2c.setup(1, i2c.FAST)
exs_mpu6050.init(1)

while true do
    local pitch, roll = exs_mpu6050.get_attitude()
    log.info("att", string.format("俯仰=%.1f° 横滚=%.1f°", pitch, roll))
    sys.wait(10)  -- 建议 10~50ms 间隔
end

2.2.3 碰撞/敲击检测

适用场景:单击/双击控制、碰撞报警、运动触发等。

local exs_mpu6050 = require "exs_mpu6050"
i2c.setup(1, i2c.FAST)
exs_mpu6050.init(1)

while true do
    if exs_mpu6050.detect_tap(2.0, 500) then
        log.info("tap", "检测到敲击!")
        -- 执行敲击响应动作
    end
    sys.wait(50)
end

2.2.4 自由落体/失重检测

适用场景:跌落保护、投掷检测、抛物线飞行判断等。

local exs_mpu6050 = require "exs_mpu6050"
i2c.setup(1, i2c.FAST)
exs_mpu6050.init(1)

while true do
    if exs_mpu6050.detect_freefall(0.3) then
        log.warn("freefall", "检测到失重/自由落体!")
    end
    sys.wait(100)
end

2.2.5 手动重新校准

适用场景:运行过程中发现姿态漂移时触发手动校准。

-- 请先将设备水平静止放置,再调用
local ok = exs_mpu6050.calibrate()
if ok then
    log.info("mpu6050", "重新校准成功")
else
    log.error("mpu6050", "校准失败,请保持设备静止重试")
end

2.2.6 DMP 姿态输出(高精度)

适用场景:需要获得精确稳定欧拉角(偏航角 yaw 无磁力计修正会逐渐漂移)的场合,如四轴飞行器、3D 云台等。

前提:需要准备 dmp_firmware.lua 固件文件(详见 4.6 节)

local exs_mpu6050 = require "exs_mpu6050"
i2c.setup(1, i2c.FAST)
exs_mpu6050.init(1)

if exs_mpu6050.dmp_init() then
    log.info("dmp", "DMP 就绪")
    while true do
        local r, p, y = exs_mpu6050.dmp_get_euler()
        if r then
            log.info("dmp", string.format("R:%.1f P:%.1f Y:%.1f", r, p, y))
        end
        sys.wait(100)
    end
end

三、常量解释

扩展库常量,顾名思义是由合宙 LuatOS 扩展库中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用,本扩展库没有常量。


四、函数详解

4.1 初始化

4.1.1 exs_mpu6050.init(i2c_id, addr?)

功能

初始化 MPU6050 六轴传感器。自动检测芯片 I2C 地址(先试 0x68,再试 0x69),读取并验证 WHO_AM_I 寄存器(期望值 0x68),对芯片执行复位,配置默认参数(±2g / ±250°/s / 125Hz 采样率 / 5Hz 低通滤波),并自动加载或执行校准。

参数

i2c_id

参数含义:硬件 I2C 总线 ID
数据类型:number
取值范围:平台有效的 I2C 总线编号(如 0 或 1)
是否必选:是
注意事项:调用前必须先用 i2c.setup(i2c_id, i2c.FAST) 初始化该总线
参数示例:1

addr

参数含义:芯片 I2C 地址
数据类型:number
取值范围:0x68(AD0 接地)或 0x69(AD0 接 VCC)
是否必选:否
注意事项:不传时自动检测,先试 0x68 再试 0x69。GY-521 模块默认 AD0 接地,地址 0x68
参数示例:0x69

返回值

local init_result = exs_mpu6050.init(i2c_id, addr?)

init_result

含义说明:初始化是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:失败原因包括未检测到设备、WHO_AM_I 不匹配等,请检查接线和供电
返回示例:true

示例

-- 方式一:自动检测地址(AD0 接地,地址 0x68)
i2c.setup(1, i2c.FAST)
local result = exs_mpu6050.init(1)

-- 方式二:手动指定地址(AD0 接 VCC,地址 0x69)
i2c.setup(1, i2c.FAST)
local result = exs_mpu6050.init(1, 0x69)

4.2 数据读取

4.2.1 exs_mpu6050.get_accel()

功能

读取三轴加速度数据(已校准),返回加速度计测量值。

静止水平放置时:Z≈+1.0g,X≈0g,Y≈0g

参数

返回值

local acc = exs_mpu6050.get_accel()

acc

含义说明:三轴加速度数据表
数据类型:table
取值范围:包含 x、y、z 三个键,值类型 number,单位 g(1g ≈ 9.8m/s²)
注意事项:已校准(自动去除零偏),默认量程 ±2g
返回示例:{x = 0.012, y = -0.005, z = 1.003}

示例

local acc = exs_mpu6050.get_accel()
log.info("mpu6050", string.format("accel  X=%.3f Y=%.3f Z=%.3f g", acc.x, acc.y, acc.z))

4.2.2 exs_mpu6050.get_gyro()

功能

读取三轴角速度数据(已校准),返回陀螺仪测量值。

静止时三轴均接近 0°/s

参数

返回值

local gyro = exs_mpu6050.get_gyro()

gyro

含义说明:三轴角速度数据表
数据类型:table
取值范围:包含 x、y、z 三个键,值类型 number,单位 °/s(度每秒)
注意事项:已校准(自动去除零偏),默认量程 ±250°/s。x:绕X轴(pitch), y:绕Y轴(roll), z:绕Z轴(yaw)
返回示例:{x = 0.2, y = -0.1, z = 0.0}

示例

local gyro = exs_mpu6050.get_gyro()
log.info("mpu6050", string.format("gyro   X=%.1f Y=%.1f Z=%.1f °/s", gyro.x, gyro.y, gyro.z))

4.2.3 exs_mpu6050.get_temp()

功能

读取芯片内部温度传感器数据。

参数

返回值

local temp = exs_mpu6050.get_temp()

temp

含义说明:芯片温度
数据类型:number
取值范围:芯片工作温度范围 -40°C ~ +85°C
注意事项:正常工作时芯片微发热,温度约 30~45°C。此温度读数为芯片内部温度,非环境温度
返回示例:32.5

示例

local temp = exs_mpu6050.get_temp()
log.info("mpu6050", string.format("芯片温度: %.1f°C", temp))

4.3 姿态解算

4.3.1 exs_mpu6050.get_tilt()

功能

通过加速度计直接推算静态倾角(俯仰角和横滚角)。

纯加速度推算,静态精度高,但动态时有运动加速度干扰,噪声较大。适合静态或缓慢变化场景。

参数

返回值

local pitch, roll = exs_mpu6050.get_tilt()

pitch

含义说明:俯仰角
数据类型:number
取值范围:约 -90° ~ +90°
注意事项:设备前倾为正(+),后倾为负(-)。过 ±90° 时精度下降

roll

含义说明:横滚角
数据类型:number
取值范围:约 -90° ~ +90°
注意事项:设备右倾为正(+),左倾为负(-)。过 ±90° 时精度下降

示例

local pitch, roll = exs_mpu6050.get_tilt()
log.info("mpu6050", string.format("俯仰=%.1f° 横滚=%.1f°", pitch, roll))

4.3.2 exs_mpu6050.get_attitude()

功能

通过互补滤波融合陀螺仪和加速度计数据,输出平滑的动态姿态角。

互补滤波系数 α = 0.96: - 陀螺仪积分贡献 96% 权重(高频动态响应好,但会随时间漂移) - 加速度计贡献 4% 权重(长期稳定,修正陀螺漂移)

必须在一个循环中以固定频率(建议 10~50ms 间隔)持续调用,中断后陀螺积分会重置。

参数

返回值

local pitch, roll = exs_mpu6050.get_attitude()

pitch

含义说明:俯仰角(互补滤波后)
数据类型:number
取值范围:约 -180° ~ +180°
注意事项:设备前倾为正(+),后倾为负(-)。动态响应平滑,无高频噪声

roll

含义说明:横滚角(互补滤波后)
数据类型:number
取值范围:约 -180° ~ +180°
注意事项:设备右倾为正(+),左倾为负(-)。动态响应平滑,无高频噪声

示例

-- 需在循环中持续调用以保持陀螺积分
while true do
    local pitch, roll = exs_mpu6050.get_attitude()
    log.info("mpu6050", string.format("俯仰=%.1f° 横滚=%.1f°", pitch, roll))
    sys.wait(10)
end

4.4 事件检测

4.4.1 exs_mpu6050.detect_tap(threshold?, debounce_ms?)

功能

检测碰撞/敲击事件。通过计算三轴合加速度模长 √(x²+y²+z²),当超过阈值时触发。

参数

threshold

参数含义:加速度合矢量阈值(g)
数据类型:number
取值范围:0 ~ 任意正数
是否必选:否
注意事项:默认 2.0g。静止时模长约 1.0g,轻敲约 2~3g,大力敲击可达 5g 以上
参数示例:1.5

debounce_ms

参数含义:去抖时间(ms)
数据类型:number
取值范围:0 ~ 任意正数
是否必选:否
注意事项:默认 500ms。单次敲击约持续 50~100ms,设置去抖可避免一次敲击被多次检测
参数示例:300

返回值

local tap_result = exs_mpu6050.detect_tap(threshold?, debounce_ms?)

tap_result

含义说明:是否检测到敲击
数据类型:boolean
取值范围:true(检测到敲击), false(未检测到)
注意事项:有去抖机制,同一次敲击在 debounce_ms 内不会重复触发
返回示例:true

示例

-- 使用默认参数:阈值 2.0g,去抖 500ms
if exs_mpu6050.detect_tap() then
    log.info("mpu6050", "检测到敲击!")
end

-- 灵敏模式:阈值 1.5g,去抖 300ms
if exs_mpu6050.detect_tap(1.5, 300) then
    log.info("mpu6050", "轻敲检测!")
end

4.4.2 exs_mpu6050.detect_freefall(threshold?)

功能

检测自由落体/失重状态。当三轴合加速度模长 √(x²+y²+z²) 低于阈值时判定为失重/自由落体。

自由落体时加速度趋近于 0,正常静止时为 1.0g。

参数

threshold

参数含义:加速度合矢量阈值(g)
数据类型:number
取值范围:0 ~ 2.0
是否必选:否
注意事项:默认 0.3g。阈值越低抗干扰越强(需更接近真正自由落体才会触发)
参数示例:0.5

返回值

local ff_result = exs_mpu6050.detect_freefall(threshold?)

ff_result

含义说明:是否处于失重/自由落体状态
数据类型:boolean
取值范围:true(疑似失重), false(正常)
注意事项:持续低于阈值时会一直返回 true,需在循环中监控
返回示例:false

示例

-- 使用默认阈值 0.3g
if exs_mpu6050.detect_freefall() then
    log.warn("mpu6050", "自由落体!")
end

-- 提高阈值到 0.5g 灵敏度更高
if exs_mpu6050.detect_freefall(0.5) then
    log.warn("mpu6050", "失重状态!")
end

4.5 校准

4.5.1 exs_mpu6050.calibrate()

功能

手动触发 MPU6050 零偏校准。

校准采集 200 个加速度和陀螺样本,取静止样本的平均值作为零偏。 校准前必须将设备水平静止放置,连续静止超过 0.2s 的样本才被认定为有效。 需要至少 50 个有效静止样本,否则校准失败。 校准成功后将 6 个零偏值(gx, gy, gz, ax, ay, az)写入 /mpu6050_calib.txt 持久化存储。

通常无需手动调用,init() 在首次上电时会自动执行校准。

参数

返回值

local cal_result = exs_mpu6050.calibrate()

cal_result

含义说明:校准是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:失败原因通常是有效静止采样不足(<50),请确保设备水平静止重试
返回示例:true

示例

-- 运行过程中发现漂移,重新校准
local ok = exs_mpu6050.calibrate()
if ok then
    log.info("mpu6050", "校准成功")
else
    log.error("mpu6050", "校准失败,请保持设备静止重试")
end

4.5.2 exs_mpu6050.is_calibrated()

功能

查询校准状态,判断零偏校准数据是否已就绪。

参数

返回值

local cal_status = exs_mpu6050.is_calibrated()

cal_status

含义说明:是否已校准
数据类型:boolean
取值范围:true(已校准,零偏数据就绪), false(未校准,数据为原始值)
注意事项:未校准情况下 get_accel() 和 get_gyro() 可能偏差较大
返回示例:true

示例

if exs_mpu6050.is_calibrated() then
    log.info("mpu6050", "校准已就绪")
else
    log.warn("mpu6050", "尚未校准,精度有限")
end

4.6 DMP 数字运动处理器

4.6.1 exs_mpu6050.dmp_init()

功能

初始化 MPU6050 内置的 DMP(Digital Motion Processor)数字运动处理器。

DMP 将固件写入 MPU6050 内部 RAM,利用芯片内部运动处理引擎直接输出姿态四元数,无需 CPU 参与姿态融合计算。相比互补滤波 get_attitude(),DMP 输出精度更高、更新率更稳定(200Hz),且 CPU 负载更低。

前提条件: 1. 需要预先准备 dmp_firmware.lua 文件,放置在 lib/ 目录下 2. 固件来源:GitHub jrowberg/i2cdevlib → Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h 3. 将其中 dmpMemory[3062] 数组内容转为 Lua table:return {0x00, 0x01, ...} 4. 保存为 lib/dmp_firmware.lua

DMP 初始化会自动将传感器量程配置为 ±2000°/s + ±4g(适配 DMP 算法要求),采样率 200Hz。

参数

返回值

local dmp_result = exs_mpu6050.dmp_init()

dmp_result

含义说明:DMP 初始化是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:失败通常是因为缺少 dmp_firmware.lua 文件或文件格式错误
返回示例:true

示例

if exs_mpu6050.dmp_init() then
    log.info("mpu6050", "DMP 就绪")
else
    log.error("mpu6050", "DMP 初始化失败,请检查 dmp_firmware.lua")
end

4.6.2 exs_mpu6050.dmp_get_quaternion()

功能

从 DMP FIFO 读取姿态四元数。

四元数 (w, x, y, z) 是姿态的无奇异表示,可直接用于 3D 旋转计算。w 为实部,(x, y, z) 为虚部,满足 w²+x²+y²+z²=1。

参数

返回值

local q = exs_mpu6050.dmp_get_quaternion()

q

含义说明:姿态四元数
数据类型:table 或 nil
取值范围:成功返回 {w, x, y, z},值类型 number,范围 [-1, 1];FIFO 无数据返回 nil
注意事项:必须在 dmp_init() 成功后调用。DMP 刷新率约 200Hz
返回示例:{w = 0.999, x = 0.012, y = -0.005, z = 0.001}

示例

local q = exs_mpu6050.dmp_get_quaternion()
if q then
    log.info("dmp", string.format("w:%.4f x:%.4f y:%.4f z:%.4f", q.w, q.x, q.y, q.z))
end

4.6.3 exs_mpu6050.dmp_get_euler()

功能

从 DMP 读取姿态欧拉角(Roll 横滚、Pitch 俯仰、Yaw 偏航)。

欧拉角由四元数转换得到,更直观易懂。

注意:Yaw(偏航角)基于陀螺仪积分,无磁力计校正,会随时间缓慢漂移(约 ±5°/min)。 初始 Yaw 角为 0°,每次重新 dmp_init() 后 Yaw 重置为 0。

参数

返回值

local roll, pitch, yaw = exs_mpu6050.dmp_get_euler()

roll

含义说明:横滚角
数据类型:number 或 nil
取值范围:约 -180° ~ +180°

pitch

含义说明:俯仰角
数据类型:number 或 nil
取值范围:约 -90° ~ +90°

yaw

含义说明:偏航角(航向角)
数据类型:number 或 nil
取值范围:约 -180° ~ +180°
注意事项:基于陀螺积分,无磁力计校正,会缓慢漂移。初始值为 0°

示例

local r, p, y = exs_mpu6050.dmp_get_euler()
if r then
    log.info("dmp", string.format("R:%.1f° P:%.1f° Y:%.1f°", r, p, y))
end

五、版本更新说明

版本号:202607080900

  1. 更新时间:2026-07-08
  2. 更新内容:

  3. 初版,实现 MPU6050 驱动所有基础功能

  4. 支持硬件 I2C 初始化 init(),自动检测芯片地址(0x68 / 0x69)
  5. 首次上电自动校准加速度计与陀螺仪零偏,校准数据持久化到 /mpu6050_calib.txt
  6. 支持手动校准 calibrate() 和校准状态查询 is_calibrated()
  7. 支持三轴加速度 get_accel() 和三轴角速度 get_gyro() 数据读取
  8. 支持芯片温度读取 get_temp()
  9. 支持静态倾角解算 get_tilt()(纯加速度推算)
  10. 支持互补滤波姿态解算 get_attitude()(α=0.96)
  11. 支持碰撞/敲击检测 detect_tap() 和自由落体检测 detect_freefall()
  12. 支持 DMP 数字运动处理器:dmp_init() / dmp_get_quaternion() / dmp_get_euler()

六、产品支持说明

所有支持 LuatOS 二次开发的模块,具体可以查看选型手册

搜索
AI问答