exs_mpu6050 扩展库
作者:王城钧 | 最后修改:2026-08-25
一、概述
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)数字运动处理器,直接输出四元数与欧拉角
-
支持手动零偏校准(calibrate()),校准数据持久化到 /mpu6050_calib.txt,后续启动自动加载
-
支持互补滤波姿态解算
get_attitude():陀螺积分(96% 权重)+ 加速度修正(4% 权重) -
支持碰撞/敲击检测
detect_tap():三轴合加速度超过阈值触发 -
支持自由落体/失重检测
detect_freefall():三轴合加速度低于阈值触发 -
低通滤波器可配置(默认 5Hz),抑制高频振动噪声
1.2 注意事项
-
仅支持硬件 I2C 模式:本库使用
i2c.setup()+setup()模式,调用前需先通过i2c.setup(hwid, i2c.FAST)初始化 I2C 总线 -
芯片地址自动检测:
setup()不传 addr 时会依次探测 0x68 和 0x69 地址,GY-521 等常见模块 AD0 默认接地(地址 0x68) -
首次使用需手动校准:
setup()只加载已有校准数据,不会自动触发校准。 首次使用时调用calibrate()完成零偏校准,设备必须水平静止放置。 校准采集 200 个样本,需至少 50 个有效静止样本(连续静止 0.2s 以上)。 校准通过后数据保存到/mpu6050_calib.txt,后续启动自动加载,无需重复校准 -
DMP 固件已内置:DMP 固件(InvenSense MotionApps v20)已内置在库文件中,使用
dmp_init()无需额外准备dmp_firmware.lua -
互补滤波需连续调用:
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.setup({ i2c_id = 1 }) then return end
while true do
local d = exs_mpu6050.get_data()
log.info("mpu6050", string.format(
"acc:(%.3f,%.3f,%.3f)g gyro:(%.1f,%.1f,%.1f)°/s temp:%.1f°C",
d.accel.x, d.accel.y, d.accel.z, d.gyro.x, d.gyro.y, d.gyro.z, d.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.setup({ i2c_id = 1, addr = 0x69 }) then return end
2.2 按使用场景划分
2.2.1 静态倾角仪
适用场景:水平仪、倾斜开关、天线姿态检测等静态倾角测量。
local exs_mpu6050 = require "exs_mpu6050"
i2c.setup(1, i2c.FAST)
exs_mpu6050.setup({ i2c_id = 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.setup({ i2c_id = 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.setup({ i2c_id = 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.setup({ i2c_id = 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 固件已内置在库文件中(MotionApps v20),无需额外准备
dmp_firmware.lua
local exs_mpu6050 = require "exs_mpu6050"
i2c.setup(1, i2c.FAST)
exs_mpu6050.setup({ i2c_id = 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.setup(config)
功能
初始化 MPU6050 六轴传感器。自动检测芯片 I2C 地址(先试 0x68,再试 0x69), 读取并验证 WHO_AM_I 寄存器(期望值 0x68),对芯片执行复位, 配置量程与采样参数,并自动加载已保存的校准数据。
参数
config
参数含义:初始化配置表
数据类型:table
是否必选:是
注意事项:包含 i2c_id / addr / gyro_range / accel_range 等键,详见下表
config.i2c_id
参数含义:硬件 I2C 总线 ID
数据类型:number
取值范围:平台有效的 I2C 总线编号(如 0 或 1)
是否必选:是
注意事项:调用前必须先用 i2c.setup(i2c_id, i2c.FAST) 初始化该总线
参数示例:1
config.addr
参数含义:芯片 I2C 地址
数据类型:number
取值范围:0x68(AD0 接地)或 0x69(AD0 接 VCC)
是否必选:否
注意事项:不传时自动检测,先试 0x68 再试 0x69。GY-521 模块默认 AD0 接地,地址 0x68
参数示例:0x69
config.gyro_range
参数含义:陀螺仪量程(°/s)
数据类型:number
取值范围:250 / 500 / 1000 / 2000
是否必选:否
注意事项:默认 250(±250°/s)。dmp_init() 会强制切换为 ±2000°/s
参数示例:2000
config.accel_range
参数含义:加速度计量程(g)
数据类型:number
取值范围:2 / 4 / 8 / 16
是否必选:否
注意事项:默认 2(±2g)。dmp_init() 会强制切换为 ±2g
参数示例:16
返回值
local setup_result = exs_mpu6050.setup(config)
setup_result
含义说明:初始化是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:失败原因包括未检测到设备、WHO_AM_I 不匹配等,请检查接线和供电
返回示例:true
示例
-- 方式一:自动检测地址(AD0 接地,地址 0x68)
i2c.setup(1, i2c.FAST)
local result = exs_mpu6050.setup({ i2c_id = 1 })
-- 方式二:手动指定地址(AD0 接 VCC,地址 0x69)
i2c.setup(1, i2c.FAST)
local result = exs_mpu6050.setup({ i2c_id = 1, addr = 0x69 })
-- 方式三:指定地址 + 量程
i2c.setup(1, i2c.FAST)
local result = exs_mpu6050.setup({ i2c_id = 1, addr = 0x68, gyro_range = 2000, accel_range = 2 })
4.2 数据读取
4.2.1 exs_mpu6050.get_data()
功能
一次读取三轴加速度、三轴角速度和芯片温度(均已应用校准数据)。
静止水平放置时:Z≈+1.0g,X≈0g,Y≈0g,陀螺三轴均接近 0°/s
参数
无
返回值
local data = exs_mpu6050.get_data()
data
含义说明:传感器数据表
数据类型:table 或 nil
取值范围:包含 accel、gyro、temp 三个键;未初始化(未调用 setup)时返回 nil
返回示例:{ accel = {x = 0.012, y = -0.005, z = 1.003}, gyro = {x = 0.2, y = -0.1, z = 0.0}, temp = 32.5 }
data.accel
含义说明:三轴加速度
数据类型:table {x, y, z},值类型 number,单位 g(1g ≈ 9.8m/s²)
注意事项:已校准(自动去除零偏),默认量程 ±2g
data.gyro
含义说明:三轴角速度
数据类型:table {x, y, z},值类型 number,单位 °/s(度每秒)
注意事项:已校准(自动去除零偏),默认量程 ±250°/s。x:绕X轴(pitch), y:绕Y轴(roll), z:绕Z轴(yaw)
data.temp
含义说明:芯片温度
数据类型:number,单位 °C
注意事项:正常工作时芯片微发热,温度约 30~45°C。此温度读数为芯片内部温度,非环境温度
示例
local d = exs_mpu6050.get_data()
if d then
log.info("mpu6050", string.format(
"accel X=%.3f Y=%.3f Z=%.3f g | gyro X=%.1f Y=%.1f Z=%.1f °/s | temp %.1f°C",
d.accel.x, d.accel.y, d.accel.z, d.gyro.x, d.gyro.y, d.gyro.z, d.temp))
end
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持久化存储。首次使用建议调用一次
calibrate()完成零偏校准;setup()不会自动触发校准。
参数
无
返回值
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_data() 返回的加速度/角速度可能偏差较大
返回示例: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 负载更低。固件已内置:DMP 固件(InvenSense MotionApps v20,1929 字节)已内置在库文件中, 无需额外准备
dmp_firmware.lua,只需 require "exs_mpu6050" 即可。 固件来源:GitHub jrowberg/i2cdevlib → MPU6050_6Axis_MotionApps20.cpp 的 dmpMemory 数组。DMP 初始化会自动将传感器量程配置为 ±2000°/s + ±2g(适配 DMP 算法要求),采样率 200Hz。
参数
无
返回值
local dmp_result = exs_mpu6050.dmp_init()
dmp_result
含义说明:DMP 初始化是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:失败通常是 I2C 通信异常或固件写入失败,请检查接线
返回示例:true
示例
if exs_mpu6050.dmp_init() then
log.info("mpu6050", "DMP 就绪")
else
log.error("mpu6050", "DMP 初始化失败,请检查接线")
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
4.7 其它
4.7.1 exs_mpu6050.close()
功能
关闭传感器(进入待机模式)。关闭后需重新调用 setup() 才能继续使用。
参数
无
返回值
无
示例
exs_mpu6050.close()
4.7.2 exs_mpu6050.version()
功能
获取库版本号。
参数
无
返回值
local ver = exs_mpu6050.version()
ver
含义说明:版本号字符串,格式 yyyymmddhhmm
数据类型:string
返回示例:"202608251030"
示例
local ver = exs_mpu6050.version()
log.info("mpu6050", "version -> " .. ver)
五、版本更新说明
版本号:202608251030
- 更新时间:2026-08-25
-
更新内容:
-
将 DMP 固件数据表(原 dmp_firmware.lua)内置到库文件,使用 DMP 功能不再需要额外文件
- 现在只需 require "exs_mpu6050" 即可使用全部功能(含 DMP)
版本号:202607231800
- 更新时间:2026-07-23
-
更新内容:
-
接口改版:
init(i2c_id, addr?)调整为setup(config)表参数方式 - 数据读取统一为
get_data(),替代get_accel()/get_gyro()/get_temp() - 新增
close()关闭接口和version()版本查询接口 - 支持 DMP 硬件姿态解算(当时需额外 dmp_firmware.lua)
版本号:202607080900
- 更新时间:2026-07-08
-
更新内容:
-
初版,实现 MPU6050 驱动所有基础功能
- 支持硬件 I2C 初始化
init(),自动检测芯片地址(0x68 / 0x69) - 首次上电自动校准加速度计与陀螺仪零偏,校准数据持久化到
/mpu6050_calib.txt - 支持手动校准
calibrate()和校准状态查询is_calibrated() - 支持三轴加速度
get_accel()和三轴角速度get_gyro()数据读取 - 支持芯片温度读取
get_temp() - 支持静态倾角解算
get_tilt()(纯加速度推算) - 支持互补滤波姿态解算
get_attitude()(α=0.96) - 支持碰撞/敲击检测
detect_tap()和自由落体检测detect_freefall() - 支持 DMP 数字运动处理器:
dmp_init()/dmp_get_quaternion()/dmp_get_euler()
六、产品支持说明
所有支持 LuatOS 二次开发的模块,具体可以查看选型手册。