跳转至

exs_bmi270 扩展库

作者:江访 | 最后修改:2026-08-05

一、概述

exs_bmi270 是 Bosch(博世)BMI270 六轴惯性传感器的 LuatOS 扩展库。BMI270 集成 3 轴加速度计 + 3 轴陀螺仪 + 温度传感器,采用 16 位 ADC,内置可配置低功耗模式,是智能穿戴、姿态跟踪、运动检测等场景常用的 MEMS 传感器。本库支持 I2C 与 SPI 两种通信接口,内置 Mahony 互补滤波姿态解算,可直接输出 roll/pitch/yaw 姿态角。

1.1 主要特性

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

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

  • 内置温度传感器:分辨率 512 LSB/°C,输出范围 -40.0~+85.0 °C

  • 支持 I2C 与 SPI 两种通信接口:I2C 可选硬件外设或软件模拟,SPI 使用 4 线制(主模式)

  • 支持加速度采样率 25~1600 Hz、陀螺仪采样率 25~3200 Hz 配置,默认均为 200 Hz

  • 内置 Mahony 互补滤波姿态解算:get_attitude() 输出 roll/pitch/yaw,yaw 角连续叠加无 ±180° 跳变

  • 支持陀螺零偏标定:calibrate_gyro() 静止采样后自动扣除三轴零偏,减少姿态漂移

  • 支持中断功能:data_ready(数据就绪)开箱即用,any_motion/no_motion/sig_motion/step(特征中断)自动使能并映射到 INT1/INT2 引脚,setup()config.int1/config.int2 即可注册 GPIO 中断回调,中断回调只发消息不读数据(避免打断软件 I2C 时序)

  • 特征中断参数可调:any_motion/no_motion 支持阈值(mg)与持续时间(ms),sig_motion 支持触发时长,step 支持步数计数(get_step_count() 读取步数)

  • 内置 I2C 总线自动恢复:检测到从机锁死总线时自动发送 9 个时钟脉冲解锁

1.2 注意事项

  • 首次使用必须加载微程序:BMI270 上电后需写入 Bosch 出厂微程序(8192 字节)才能正常测量,本库已内置配置,setup() 时自动完成加载,无需用户干预

  • 姿态解算需连续调用get_attitude() 依赖陀螺仪积分,必须在一个循环中以固定频率(建议 10~50 ms 间隔)持续调用,中断后陀螺积分会重置,姿态将从当前加速度推算值重新收敛

  • 无磁力计时 yaw 会缓慢漂移:本库未接入磁力计,yaw 角无法绝对校正,长时间使用会有缓慢漂移,仅适合短时相对姿态测量

  • 静止放置时加速度读数:水平静止时 Z 轴为 +1.0g,X/Y 轴为 0g(受放置角度影响存在微小偏差);运动时合加速度会偏离 1g 属于正常现象

  • sys.wait() 的接口必须在协程中调用setup()reset()wakeup() 内部含延时,只能在 sys.taskInit 创建的协程中使用

  • 中断回调内禁止读传感器:GPIO 中断回调运行在中断上下文,cb 回调只做通知(或通过 topic 发消息),数据读取与中断状态清除由主任务协程完成(get_int_status()/get_data())。在回调内直接读 I2C 会打断软件 I2C 位时序,导致数据错乱

  • 特征中断开箱即用any_motion/no_motion/sig_motion/step 属于特征中断,本库在 setup()/int_config() 配置时会自动使能对应功能并映射到中断引脚,无需用户额外操作;data_ready 数据中断同样开箱即用

  • I2C 上拉电阻:SCL 和 SDA 需外接 4.7kΩ~10kΩ 上拉电阻到 VCC(常见 BMI270 模块已内置)

1.3 中断方式选择速查

BMI270 提供 5 种中断触发方式,按你的应用场景对号入座即可:

中断方式 什么时候触发 适合场景 配置写法
data_ready 每个采样周期都触发(默认 200Hz 下每 5ms 一次,触发频率很高) 持续读取数据流、姿态解算 data_ready = true
any_motion 检测到任意运动(加速度变化超过阈值) 运动唤醒、震动报警、有人移动 any_motion = true
no_motion 设备静止超过设定时长 静止监测、设备防拆、停车检测 no_motion = true
sig_motion 持续剧烈运动超过设定时长 跌倒报警、剧烈运动监测、防丢 sig_motion = true
step 检测到一步(配合 step_counter 计步) 计步器、健身追踪、步数统计 step = true + step_counter = true

选择要点: - 只需要"不停拿数据"→ 选 data_ready - 需要"检测到动作/事件"→ 在 any_motion/no_motion/sig_motion/step 里按触发条件选 - 5 种中断可同时开启,映射到 INT1/INT2 引脚各自独立,互不干扰 - 触发后主任务用 get_int_status() 查询具体是哪个事件触发(读后自动清除)

⚠️ data_ready 触发频率很高,请注意: - 默认采样率 200Hz,data_ready 每 5ms 触发一次(若将 acc_odr/gyro_odr 调低到 100Hz 则为每 10ms 一次) - 若在中断回调里做 get_int_status() 或读数据,需评估是否跟得上触发频率;高频场景建议降低采样率(如设 acc_odr = 50)或不追求每周期都处理(丢弃部分触发) - 若仅需"检测到事件"而非连续数据流,优先选 any_motion/no_motion/sig_motion/step 等事件型中断,避免被 data_ready 高频中断淹没

中断后如何获取结果(两种回调方式)

方式 用法 适合场景
topic 消息(推荐) 配置 topic = "消息名",中断时回调自动发布消息,主任务 sys.waitUntil("消息名") 等待后读数据 绝大多数场景,尤其是需要读取传感器数据或做多步处理
cb 回调 配置 cb = 函数名,中断时回调被调用(无参数),在回调里只做标记/计数,主任务另行读取 只需知道"中断发生了"、不需要立即读数据的轻量场景

为什么推荐 topic:中断回调运行在中断上下文,不能在里面读传感器(会打乱时序),而 sys.waitUntil + 主任务读数据是更自然的写法。两种方式二选一,同时配置时 topic 优先生效。

1.4 硬件连接

BMI270 支持 I2C 与 SPI 两种接法,按需选择其中一种。

I2C 接线表(推荐,接线最省)

BMI270 模块 Air780EXX 系列 / Air8101 核心板
VCC VDD_EXT(3.3V)
GND GND
SCL I2Cx_SCL(如 GPIO31)
SDA I2Cx_SDA(如 GPIO30)
SDO GND(地址 0x68)或 VCC(地址 0x69)
BMI270 模块                Air780EXX 系列核心板
┌──────────┐              ┌──────────────────┐
│ VCC      ├─────────────┤ VDD_EXT (3.3V)    │
│ GND      ├─────────────┤ GND               │
│ SCL      ├─────────────┤ GPIO31 (I2Cx_SCL) │
│ SDA      ├─────────────┤ GPIO30 (I2Cx_SDA) │
│ SDO      ├───GND───┐   │                   │
│ INT1     ├─────────┼───┤ GPIO(可选,中断用)│
└──────────┘         │   └──────────────────┘
                     └─ 接 GND:地址 0x68 / 接 VCC:地址 0x69

SPI 接线表(高速场景)

BMI270 模块 Air780E 系列 / Air8101 核心板
VCC VDD_EXT(3.3V)
GND GND
CS GPIO(片选,可任意 GPIO)
SCK SPIx_SCK
SDI SPIx_MOSI
SDO SPIx_MISO

BMI270 六轴惯性传感器接线示意图

1.5 加载方式

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

二、核心示例

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

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

2.1 按使用接口划分

2.1.1 软件 I2C 模式读取数据

使用 GPIO 模拟 I2C 时序,任意 GPIO 均可,接线灵活,适合大多数场景。

local exs_bmi270 = require "exs_bmi270"

-- 初始化函数:软件 I2C 模式,SCL=GPIO31,SDA=GPIO30
local function init_func()
    local result = exs_bmi270.setup("I2C", {scl = 31, sda = 30})
    if not result then
        log.error("demo", "BMI270 初始化失败,请检查接线")
        return false
    end
    log.info("demo", "BMI270 初始化成功,版本:", exs_bmi270.version())
    return true
end

-- 读取并打印加速度、角速度、温度
local function read_data_func()
    local acc = exs_bmi270.get_accel()
    local gyro = exs_bmi270.get_gyro()
    local temp = exs_bmi270.get_temp()
    if not acc or not gyro or not temp then
        log.error("demo", "读取数据失败")
        return
    end
    log.info("demo", 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))
end

-- 主任务:初始化后每 500ms 读取一次
local function demo_task_func()
    sys.wait(100)  -- 等待系统启动稳定,100ms
    if not init_func() then return end
    while true do
        read_data_func()
        sys.wait(500)  -- 每 500ms 读取一次
    end
end

sys.taskInit(demo_task_func)

2.1.2 硬件 I2C 模式

使用芯片内置 I2C 外设,占用更少 CPU,适合对实时性要求高的场景。

local exs_bmi270 = require "exs_bmi270"

-- 初始化函数:硬件 I2C 模式,使用 I2C0 总线,设备地址 0x68
local function init_func()
    local result = exs_bmi270.setup("I2C", {i2c_id = 0, addr = 0x68})
    if not result then
        log.error("demo", "BMI270 初始化失败,请检查接线")
        return false
    end
    log.info("demo", "BMI270 初始化成功")
    return true
end

-- 主任务
local function demo_task_func()
    sys.wait(100)  -- 等待系统启动稳定,100ms
    if not init_func() then return end
    while true do
        local data = exs_bmi270.get_data()
        if data then
            log.info("demo", string.format("acc:(%.3f,%.3f,%.3f)g gyro:(%.1f,%.1f,%.1f)°/s temp:%.1f°C",
                data.x, data.y, data.z, data.gx, data.gy, data.gz, data.temp))
        end
        sys.wait(500)  -- 每 500ms 读取一次
    end
end

sys.taskInit(demo_task_func)

2.1.3 SPI 模式

使用 SPI 外设通信,速率最高可达 1 MHz 以上,适合高速采样场景。

local exs_bmi270 = require "exs_bmi270"

-- 初始化函数:SPI 模式,SPI0 总线,片选 GPIO12
local function init_func()
    local result = exs_bmi270.setup("SPI", {spi_id = 0, cs = 12, speed = 1000000})
    if not result then
        log.error("demo", "BMI270 初始化失败,请检查接线")
        return false
    end
    log.info("demo", "BMI270 初始化成功")
    return true
end

-- 主任务
local function demo_task_func()
    sys.wait(100)  -- 等待系统启动稳定,100ms
    if not init_func() then return end
    while true do
        local acc = exs_bmi270.get_accel()
        if acc then
            log.info("demo", string.format("acc:(%.3f,%.3f,%.3f)g", acc.x, acc.y, acc.z))
        end
        sys.wait(100)  -- 每 100ms 读取一次
    end
end

sys.taskInit(demo_task_func)

2.2 按使用场景划分

2.2.1 姿态角测量(Mahony 互补滤波)

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

local exs_bmi270 = require "exs_bmi270"

-- 初始化函数:软件 I2C 模式,使用默认量程(acc ±4g / gyro ±500°/s,200Hz)
local function init_func()
    local result = exs_bmi270.setup("I2C", {scl = 31, sda = 30})
    if not result then
        log.error("demo", "BMI270 初始化失败")
        return false
    end
    log.info("demo", "BMI270 初始化成功")
    return true
end

-- 姿态任务:固定 20ms 间隔调用 get_attitude 保持积分连续
local function attitude_task_func()
    sys.wait(100)  -- 等待系统启动稳定,100ms
    if not init_func() then return end
    while true do
        local roll, pitch, yaw = exs_bmi270.get_attitude()
        if roll then
            log.info("demo", string.format("roll:%.1f pitch:%.1f yaw:%.1f", roll, pitch, yaw))
        end
        sys.wait(20)  -- 20ms 调用一次(50Hz),间隔过大会影响姿态平滑度
    end
end

sys.taskInit(attitude_task_func)

2.2.2 运动检测(加速度合矢量监测)

适用场景:跌倒检测、设备振动检测、静止/运动状态识别等。

local exs_bmi270 = require "exs_bmi270"

-- 初始化函数:软件 I2C 模式,加速度量程 ±16g(运动幅度大时防止溢出)
local function init_func()
    local result = exs_bmi270.setup("I2C", {scl = 31, sda = 30, acc_range = "16g"})
    if not result then
        log.error("demo", "BMI270 初始化失败")
        return false
    end
    log.info("demo", "BMI270 初始化成功")
    return true
end

-- 运动检测任务:计算三轴合加速度,超过阈值判定为运动
local function motion_task_func()
    sys.wait(100)  -- 等待系统启动稳定,100ms
    if not init_func() then return end
    while true do
        local acc = exs_bmi270.get_accel()
        if acc then
            local mag = math.sqrt(acc.x * acc.x + acc.y * acc.y + acc.z * acc.z)
            if mag > 1.5 then
                log.info("demo", string.format("检测到运动,合加速度=%.2fg", mag))
            end
        end
        sys.wait(200)  -- 每 200ms 检测一次
    end
end

sys.taskInit(motion_task_func)

2.2.3 中断方式读取数据(data_ready)

适用场景:需要及时响应新数据、避免高频轮询占用 CPU 的场景。推荐使用 topic 模式:中断回调只发布消息,主任务 sys.waitUntil 收到消息后再读取数据,回调内不做任何 I2C 操作。

⚠️ 注意触发频率:默认采样率 200Hz,data_ready 每 5ms 触发一次,频率很高。若你的应用不需要这么高的数据速率,建议在 setup() 里把 acc_odr/gyro_odr 调低(如 50Hz 时每 20ms 一次),否则主任务可能被中断消息频繁唤醒。

local exs_bmi270 = require "exs_bmi270"

-- 初始化函数:软件 I2C 模式 + INT1 注册 data_ready 中断
-- int_gpio 是 BMI270 的 INT1 引脚所接的 GPIO 编号
local function init_func()
    local result = exs_bmi270.setup("I2C", {
        scl = 31, sda = 30,
        int1 = {
            int_gpio = 12,          -- BMI270 INT1 引脚接的 GPIO
            data_ready = true,      -- 开启数据就绪中断
            topic = "BMI270_DRDY",  -- 中断回调发布该消息,主任务等待
        },
    })
    if not result then
        log.error("demo", "BMI270 初始化失败")
        return false
    end
    log.info("demo", "BMI270 初始化成功")
    return true
end

-- 主任务:等待中断消息后读取数据
local function int_task_func()
    sys.wait(100)  -- 等待系统启动稳定,100ms
    if not init_func() then return end
    while true do
        sys.waitUntil("BMI270_DRDY", 1000)  -- 等待数据就绪中断消息,超时 1000ms
        local data = exs_bmi270.get_data()  -- 中断发生后读取数据(读后自动清除中断标志)
        if data then
            log.info("demo", string.format("acc:(%.3f,%.3f,%.3f)g", data.x, data.y, data.z))
        end
    end
end

sys.taskInit(int_task_func)

2.2.4 中断方式读取特征事件(any_motion)

适用场景:运动唤醒、震动报警等需要检测"发生了运动"的场合。特征中断开箱即用,setup() 时配置 int1any_motion = true 即可自动使能特征并映射到 INT 引脚,无需额外操作。本例还演示了自定义阈值(灵敏度)与持续时间。

local exs_bmi270 = require "exs_bmi270"

-- 初始化函数:软件 I2C 模式 + INT1 注册 any_motion 中断
local function init_func()
    local result = exs_bmi270.setup("I2C", {
        scl = 31, sda = 30,
        int1 = {
            int_gpio = 12,                    -- BMI270 INT1 引脚接的 GPIO
            any_motion = true,                -- 开启任意运动检测中断
            any_motion_thresh_mg = 100,       -- 自定义阈值 100mg(默认 83mg,越小越灵敏)
            any_motion_duration_ms = 100,     -- 自定义持续时间 100ms(默认 100ms)
            topic = "BMI270_MOTION",
        },
    })
    if not result then
        log.error("demo", "BMI270 初始化失败")
        return false
    end
    log.info("demo", "BMI270 初始化成功")
    return true
end

-- 主任务:等待中断消息后读取中断状态
local function motion_int_task_func()
    sys.wait(100)  -- 等待系统启动稳定,100ms
    if not init_func() then return end
    while true do
        sys.waitUntil("BMI270_MOTION", 5000)  -- 等待运动中断消息,超时 5000ms
        local events = exs_bmi270.get_int_status()  -- 读取中断状态(读后清除)
        if events and #events > 0 then
            log.info("demo", "检测到事件:", table.concat(events, ","))
        end
    end
end

sys.taskInit(motion_int_task_func)

2.2.5 计步器(step 步进中断 + 步数统计)

适用场景:计步器、健身追踪、步数统计。开启 step 中断 + step_counter 计数,检测到步伐时触发中断,主任务读取累计步数。

local exs_bmi270 = require "exs_bmi270"

-- 初始化函数:软件 I2C 模式 + INT1 注册步进中断与步数计数
local function init_func()
    local result = exs_bmi270.setup("I2C", {
        scl = 31, sda = 30,
        int1 = {
            int_gpio = 12,               -- BMI270 INT1 引脚接的 GPIO
            step = true,                 -- 开启步进检测中断(每检测到一步触发一次)
            step_counter = true,         -- 同时使能步数计数,可用 get_step_count() 读取
            step_watermark_steps = 20,   -- 每累计 20 步刷新一次步数读数(默认值,可按需调)
            topic = "BMI270_STEP",
        },
    })
    if not result then
        log.error("demo", "BMI270 初始化失败")
        return false
    end
    log.info("demo", "BMI270 初始化成功")
    return true
end

-- 主任务:等待步进中断,读取累计步数
local function step_task_func()
    sys.wait(100)  -- 等待系统启动稳定,100ms
    if not init_func() then return end
    -- 开始计步前清零,本次从 0 累计
    exs_bmi270.reset_step_count()
    while true do
        sys.waitUntil("BMI270_STEP", 5000)  -- 等待步进中断消息,超时 5000ms
        local steps = exs_bmi270.get_step_count()  -- 读取累计步数(步数每 20 步刷新一次)
        if steps then
            log.info("demo", "累计步数:", steps)
        end
    end
end

sys.taskInit(step_task_func)

2.2.6 静止检测(no_motion)

适用场景:设备防拆、停车检测、长时间静止告警。开启 no_motion 中断,设备静止超过设定时长后触发,可搭配 no_motion_duration_ms 调整判定时长。

local exs_bmi270 = require "exs_bmi270"

-- 初始化函数:软件 I2C 模式 + INT1 注册静止检测中断
local function init_func()
    local result = exs_bmi270.setup("I2C", {
        scl = 31, sda = 30,
        int1 = {
            int_gpio = 12,                -- BMI270 INT1 引脚接的 GPIO
            no_motion = true,             -- 开启静止检测中断
            no_motion_duration_ms = 1000, -- 静止 1 秒判定为无运动(默认 100ms,用于防拆建议调大)
            no_motion_thresh_mg = 70,     -- 阈值 70mg,低于此值视为静止
            topic = "BMI270_NOMOTION",
        },
    })
    if not result then
        log.error("demo", "BMI270 初始化失败")
        return false
    end
    log.info("demo", "BMI270 初始化成功")
    return true
end

-- 主任务:等待静止中断
local function nomotion_task_func()
    sys.wait(100)  -- 等待系统启动稳定,100ms
    if not init_func() then return end
    while true do
        sys.waitUntil("BMI270_NOMOTION", 60000)  -- 等待静止中断消息,超时 60 秒
        log.info("demo", "检测到设备已静止")
    end
end

sys.taskInit(nomotion_task_func)

三、常量解释

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


四、函数详解

4.1 初始化

4.1.1 exs_bmi270.setup(model, config)

功能

初始化 BMI270 六轴惯性传感器。支持 I2C 与 SPI 两种通信接口,初始化时自动完成芯片 ID 校验、微程序加载(8192 字节)、量程与采样率配置。初始化成功后即可读取数据。

⚠️ 协程限制:必须在 sys.taskInit 创建的协程中调用 原因:初始化流程内部含延时等待(软复位等待 50ms、微程序加载等待 100ms、配置生效等待 50ms),需要 sys.wait 让步 最长等待:单次初始化约 250ms(含最多 3 次重试)

参数

model

参数含义:通信接口模式
数据类型:string
取值范围:"I2C"(I2C 总线通信,接线 2 根,推荐大多数场景)/"SPI"(SPI 总线通信,接线 4 根,适合高速采样场景)
是否必选:是
参数示例:"I2C"

config

参数含义:配置参数表
数据类型:table
取值范围:
{
    参数含义:软件 I2C 的 SCL 引脚(传 scl+sda 时自动使用软件 I2C,任意 GPIO 均可)
    数据类型:number
    取值范围:根据芯片 GPIO 引脚定义,如 31
    是否必选:否
    注意事项:与 config.sda 需同时传入;传了 scl/sda 时 config.i2c_id 会被忽略(若同时传了 i2c_id 则使用硬件 I2C 的对应 id)
    参数示例:31
    config.scl ,

    参数含义:软件 I2C 的 SDA 引脚(与 config.scl 配合使用)
    数据类型:number
    取值范围:根据芯片 GPIO 引脚定义,如 30
    是否必选:否
    注意事项:与 config.scl 需同时传入
    参数示例:30
    config.sda ,

    参数含义:硬件 I2C 总线 ID(单独传 i2c_id 时使用硬件 I2C 外设)
    数据类型:number
    取值范围:0 ~ 1,具体取决于芯片支持的 I2C 外设数量
    是否必选:否
    注意事项:仅传 i2c_id 时不具备总线自动恢复能力;建议同时传 scl/sda 以获得 I2C 卡死自动恢复能力
    参数示例:0
    config.i2c_id ,

    参数含义:I2C 设备地址(SDO 引脚决定)
    数据类型:number
    取值范围:0x68(SDO 接 GND)/ 0x69(SDO 接 VCC)
    是否必选:否
    注意事项:默认 0x68;常见 BMI270 模块 SDO 默认接地,若读取不到数据可尝试 0x69
    参数示例:0x68
    config.addr ,

    参数含义:SPI 总线 ID(SPI 模式必填)
    数据类型:number
    取值范围:0 ~ 1,具体取决于芯片支持的 SPI 外设数量
    是否必选:否
    注意事项:仅 SPI 模式使用
    参数示例:0
    config.spi_id ,

    参数含义:SPI 片选引脚
    数据类型:number
    取值范围:根据芯片 GPIO 引脚定义
    是否必选:否
    注意事项:仅 SPI 模式使用,可接任意空闲 GPIO
    参数示例:12
    config.cs ,

    参数含义:SPI 通信速率
    数据类型:number
    取值范围:100000 ~ 10000000,单位 Hz
    是否必选:否
    注意事项:默认 1000000(1 MHz);连线较长或环境干扰大时建议降低速率
    参数示例:1000000
    config.speed ,

    参数含义:加速度计量程
    数据类型:string
    取值范围:"2g"(±2g,分辨率最高 16384 LSB/g,适合小幅振动/倾角测量)/"4g"(±4g,默认,分辨率 8192 LSB/g,适合日常运动)/"8g"(±8g,分辨率 4096 LSB/g,适合较大冲击)/ "16g"(±16g,分辨率 2048 LSB/g,适合剧烈运动/跌倒检测)
    是否必选:否
    注意事项:量程越大可测量的加速度上限越高,但分辨率越低;不确认时建议使用默认值 "4g"
    参数示例:"4g"
    config.acc_range ,

    参数含义:陀螺仪量程
    数据类型:string
    取值范围:"125"(±125 °/s,分辨率最高 262.4 LSB/(°/s),适合缓慢转动)/ "250"(±250 °/s)/ "500"(±500 °/s,默认,适合日常姿态测量)/ "1000"(±1000 °/s)/ "2000"(±2000 °/s,分辨率最低,适合快速旋转)
    是否必选:否
    注意事项:量程越大可测量的角速度上限越高,但分辨率越低;不确认时建议使用默认值 "500"
    参数示例:"500"
    config.gyro_range ,

    参数含义:加速度采样率
    数据类型:number
    取值范围:25 / 50 / 100 / 200(默认)/ 400 / 800 / 1600,单位 Hz
    是否必选:否
    注意事项:采样率越高数据越实时但功耗越高;小于所选值会向下取最近的档位;姿态解算建议 100~200 Hz
    参数示例:200
    config.acc_odr ,

    参数含义:陀螺仪采样率
    数据类型:number
    取值范围:25 / 50 / 100 / 200(默认)/ 400 / 800 / 1600 / 3200,单位 Hz
    是否必选:否
    注意事项:采样率越高数据越实时但功耗越高;小于所选值会向下取最近的档位;姿态解算建议 100~200 Hz
    参数示例:200
    config.gyro_odr ,

    参数含义:INT1 中断配置表
    数据类型:table
    是否必选:否
    取值范围:包含以下参数:

    {
        参数含义:BMI270 INT1 引脚所接的 GPIO 编号
        数据类型:number
        取值范围:有效的 GPIO 编号
        是否必选:是
        参数示例:12
        int1.int_gpio ,

        参数含义:数据就绪中断,每次新数据准备好时触发,触发频率很高,默认200Hz 每 5ms 一次
        数据类型:boolean
        取值范围:true 或 false(不传入则不开启)
        是否必选:否
        注意事项:默认采样率 200Hz 时每 5ms 触发一次,若不需要这么高的频率,可通过 setup 的 acc_odr/gyro_odr 调低采样率(如 50Hz 时每 20ms 一次)
        参数示例:true
        int1.data_ready ,

        参数含义:任意运动检测中断,检测到任意运动时触发
        数据类型:boolean
        取值范围:true 或 false(不传入则不开启)
        是否必选:否
        注意事项:开箱即用,本库自动使能特征并映射到 INT 引脚
        参数示例:true
        int1.any_motion ,

        参数含义:任意运动检测阈值(灵敏度)
        数据类型:number
        取值范围:0 ~ 1000,单位 mg(毫g),分辨率约 0.488 mg
        是否必选:否
        注意事项:仅当 int1.any_motion 开启时生效;默认 83 mg(约 0.083g)。场景建议:室内轻微走动/放置桌面检测建议 50~100 mg;明显晃动/拍打建议 150~300 mg;剧烈运动(跑步、车载)建议 300 mg 以上,避免误触发
        参数示例:100
        int1.any_motion_thresh_mg ,

        参数含义:任意运动检测持续时间(判定为运动需连续超过阈值多久)
        数据类型:number
        取值范围:0 ~ 163000,单位 ms,分辨率 20 ms
        是否必选:否
        注意事项:仅当 int1.any_motion 开启时生效;默认 100 ms。场景建议:只需捕捉瞬时动作(如敲击、短促移动)用默认 100 ms 即可;需过滤短暂抖动的场景(如放在洗衣机上)建议 500~1000 ms
        参数示例:100
        int1.any_motion_duration_ms ,

        参数含义:无运动检测中断,静止超过阈值时间后触发
        数据类型:boolean
        取值范围:true 或 false(不传入则不开启)
        是否必选:否
        注意事项:开箱即用,本库自动使能特征并映射到 INT 引脚
        参数示例:true
        int1.no_motion ,

        参数含义:无运动检测阈值
        数据类型:number
        取值范围:0 ~ 1000,单位 mg,分辨率约 0.488 mg
        是否必选:否
        注意事项:仅当 int1.no_motion 开启时生效;默认 70 mg。场景建议:桌面/地面静止检测用默认 70 mg;设备本身有微小震动(如电机旁)建议调大到 150~300 mg,避免误判为静止
        参数示例:70
        int1.no_motion_thresh_mg ,

        参数含义:无运动检测持续时间(判定为静止需连续低于阈值多久)
        数据类型:number
        取值范围:0 ~ 163000,单位 ms,分辨率 20 ms
        是否必选:否
        注意事项:仅当 int1.no_motion 开启时生效;默认 100 ms。场景建议:需要快速识别静止(如拿起来又放下)用默认 100 ms;设备防拆/停车检测建议 3000~10000 ms,避免被短暂触碰误触发
        参数示例:100
        int1.no_motion_duration_ms ,

        参数含义:显著运动检测中断,检测到剧烈/显著运动时触发
        数据类型:boolean
        取值范围:true 或 false(不传入则不开启)
        是否必选:否
        注意事项:开箱即用,本库自动使能特征并映射到 INT 引脚
        参数示例:true
        int1.sig_motion ,

        参数含义:显著运动检测时长(需持续剧烈运动多久才触发)
        数据类型:number
        取值范围:20 ~ 1310700,单位 ms,分辨率 20 ms
        是否必选:否
        注意事项:仅当 int1.sig_motion 开启时生效;默认 5000 ms(5 秒)。场景建议:跌倒/剧烈运动报警用默认 5 秒;需要更快响应可设为 2000~3000 ms,但短暂晃动也可能触发
        参数示例:3000
        int1.sig_motion_block_ms ,

        参数含义:步进检测中断,检测到步伐时触发
        数据类型:boolean
        取值范围:true 或 false(不传入则不开启)
        是否必选:否
        注意事项:默认使能 step detector(中断),配合 step_counter 可读取步数
        参数示例:true
        int1.step ,

        参数含义:步数计数器开关(配合 step 使用,读取累计步数)
        数据类型:boolean
        取值范围:true 或 false(不传入则不开启)
        是否必选:否
        注意事项:仅当 int1.step 开启时生效;开启后可用 exs_bmi270.get_step_count() 读取步数;务必同时设置 step_watermark_steps(或使用默认值),否则计步器输出被禁用、步数恒为 0
        参数示例:true
        int1.step_counter ,

        参数含义:步数更新间隔(多少步更新一次)
        数据类型:number
        取值范围:1 ~ 20460,单位 步(内部以 20 步为粒度,不足 20 步按 20 步计)
        是否必选:否
        注意事项:仅当 int1.step_counter 开启时生效;默认 20 步更新一次。含义:每累计该数量的步数,get_step_count() 读数才刷新一次。需要更频繁看到步数变化设小值(如 20),只需要定期统计设大值(如 100/1000)
        参数示例:20
        int1.step_watermark_steps ,

        参数含义:中断有效电平(BMI270 默认低有效)
        数据类型:number
        取值范围:0(低有效,FALLING 沿触发,默认)/ 1(高有效,RISING 沿触发)
        是否必选:否
        注意事项:默认 0 即可满足绝大多数应用;仅当你的外接电路要求高有效触发时才改为 1
        参数示例:0
        int1.lvl ,

        参数含义:中断消息 topic(推荐)
        数据类型:string
        取值范围:任意合法的 sys.publish 消息名
        是否必选:否
        注意事项:传入后中断回调通过 sys.publish(topic) 发消息,主任务 sys.waitUntil(topic) 等待后读数据;回调内不做任何 I2C 操作
        参数示例:"BMI270_DRDY"
        int1.topic ,

        参数含义:中断回调函数(无参)
        数据类型:function
        取值范围:用户自定义的局部函数
        是否必选:否
        注意事项:回调运行在中断上下文,仅做"中断发生"通知,绝不能在其中读 I2C(会打断软件 I2C 位时序导致数据错乱);数据读取应在主任务协程完成。与 int1.topic 二选一
        int1.cb ,
    },

    参数含义:INT2 中断配置表
    数据类型:table
    是否必选:否
    注意事项:字段与 config.int1 完全一致(int_gpio/data_ready/any_motion/no_motion/sig_motion/step/lvl/topic/cb),对应 BMI270 的 INT2 引脚
}
是否必选:是
参数示例:
    -- 软件 I2C 模式(推荐)
    exs_bmi270.setup("I2C", {scl = 31, sda = 30})

    -- 硬件 I2C 模式
    exs_bmi270.setup("I2C", {i2c_id = 0, addr = 0x68})

    -- SPI 模式
    exs_bmi270.setup("SPI", {spi_id = 0, cs = 12})

    -- 软件 I2C + INT1 数据就绪中断(topic 模式)
    exs_bmi270.setup("I2C", {scl = 31, sda = 30, int1 = {int_gpio = 12, data_ready = true, topic = "BMI270_DRDY"}})

返回值

local result = exs_bmi270.setup(model, config)

result

含义说明:初始化是否成功
数据类型:boolean
取值范围:true(成功),false(失败)
注意事项:失败原因按概率依次为接线错误、芯片未上电、芯片损坏(微程序加载失败);失败后传感器处于未初始化状态,需修复问题后重新调用
返回示例:true

示例

-- 软件 I2C 模式初始化
local result = exs_bmi270.setup("I2C", {scl = 31, sda = 30})
if not result then return end

4.2 数据读取

4.2.1 exs_bmi270.get_data()

功能

一次读取加速度、角速度与温度三种数据,减少总线交互次数,适合周期轮询场景。

参数

返回值

local data = exs_bmi270.get_data()

data

含义说明:传感器组合测量数据;未初始化或读取失败时返回 nil
数据类型:table 或 nil
取值范围:
    data.x/y/z  - 三轴加速度,单位 g,范围受量程限制(默认 ±4g)
    data.gx/gy/gz - 三轴角速度,单位 °/s,范围受量程限制(默认 ±500 °/s)
    data.temp   - 芯片温度,单位 °C,范围 -40.0~+85.0,精确度 ±2.0 °C
注意事项:加速度/角速度数据有效位取决于所选量程;温度数据随芯片发热会高于环境温度,属正常现象
返回示例:{x = 0.012, y = -0.005, z = 0.998, gx = 0.5, gy = -0.3, gz = 0.1, temp = 32.6}

示例

-- 读取组合数据
local data = exs_bmi270.get_data()
if data then
    log.info("exs_bmi270", string.format("acc:(%.3f,%.3f,%.3f)g temp:%.1f°C",
        data.x, data.y, data.z, data.temp))
end

4.2.2 exs_bmi270.get_raw()

功能

读取传感器原始 ADC 值(未换算物理量),供高级用户实现自定义滤波或标定算法。

参数

返回值

local raw = exs_bmi270.get_raw()

raw

含义说明:原始 ADC 测量值;未初始化或读取失败时返回 nil
数据类型:table 或 nil
取值范围:
    raw.ax/ay/az - 三轴加速度原始值,16 位有符号整数,范围 -32768 ~ 32767
    raw.gx/gy/gz - 三轴陀螺仪原始值,16 位有符号整数,范围 -32768 ~ 32767
    raw.temp     - 温度原始值,16 位有符号整数,换算温度需乘 512 并加 23.0(℃)
注意事项:原始值未经量程换算,直接对比需保证两次读取时量程一致
返回示例:{ax = 125, ay = -32, az = 16000, gx = 12, gy = -8, gz = 3, temp = 49}

示例

-- 读取原始数据
local raw = exs_bmi270.get_raw()
if raw then
    log.info("exs_bmi270", string.format("raw ax=%d ay=%d az=%d", raw.ax, raw.ay, raw.az))
end

4.2.3 exs_bmi270.get_accel()

功能

读取三轴加速度。水平静止放置时 Z 轴为 +1.0g,X/Y 轴为 0g。

参数

返回值

local acc = exs_bmi270.get_accel()

acc

含义说明:三轴加速度数据;未初始化或读取失败时返回 nil
数据类型:table 或 nil
取值范围:
    acc.x/y/z - 三轴加速度,单位 g,范围受量程限制(默认 ±4g,分辨率 1/8192 g)
注意事项:设备运动时读数受自身运动加速度影响,静止时读数等于重力分量
返回示例:{x = 0.012, y = -0.005, z = 0.998}

示例

-- 读取三轴加速度
local acc = exs_bmi270.get_accel()
if acc then
    log.info("exs_bmi270", string.format("acc:(%.3f,%.3f,%.3f)g", acc.x, acc.y, acc.z))
end

4.2.4 exs_bmi270.get_gyro()

功能

读取三轴角速度。静止时三轴读数接近 0 °/s,转动时为正/负角速度。

参数

返回值

local gyro = exs_bmi270.get_gyro()

gyro

含义说明:三轴角速度数据;未初始化或读取失败时返回 nil
数据类型:table 或 nil
取值范围:
    gyro.x/y/z - 三轴角速度,单位 °/s,范围受量程限制(默认 ±500 °/s,分辨率 1/65.6 °/s)
注意事项:角速度积分为角度,长时间积分会累积漂移;静止时读数在 0 附近小幅波动属正常现象
返回示例:{x = 0.5, y = -0.3, z = 0.1}

示例

-- 读取三轴角速度
local gyro = exs_bmi270.get_gyro()
if gyro then
    log.info("exs_bmi270", string.format("gyro:(%.1f,%.1f,%.1f)°/s", gyro.x, gyro.y, gyro.z))
end

4.2.5 exs_bmi270.get_temp()

功能

读取芯片内部温度。适用于环境温度粗略监测或传感器发热判断。

参数

返回值

local temp = exs_bmi270.get_temp()

temp

含义说明:芯片温度;未初始化或读取失败时返回 nil
数据类型:number 或 nil
取值范围:-40.0 ~ +85.0,单位 °C,精确度 ±2.0 °C
注意事项:长时间工作后芯片自发热会导致读数高于环境温度,偏差可达 5~10 °C;需要精确环境温度请使用专用温度传感器
返回示例:32.6

示例

-- 读取芯片温度
local temp = exs_bmi270.get_temp()
if temp then
    log.info("exs_bmi270", string.format("temp:%.1f°C", temp))
end

4.2.6 exs_bmi270.get_attitude()

功能

Mahony 互补滤波姿态解算,融合陀螺仪积分(动态响应快)与加速度计修正(长期稳定),输出平滑姿态角。yaw 角做连续叠加展开,可累计多圈(无 ±180° 跳变)。

参数

返回值

local roll, pitch, yaw = exs_bmi270.get_attitude()

roll

含义说明:横滚角,绕 X 轴旋转,右倾为正
数据类型:number
取值范围:-180.0 ~ +180.0,单位 °
返回示例:12.5

pitch

含义说明:俯仰角,绕 Y 轴旋转,前倾为正
数据类型:number
取值范围:-90.0 ~ +90.0,单位 °
注意事项:接近 ±90° 时姿态估计会变敏感(欧拉角万向锁),请结合应用场景设计倾角限幅
返回示例:-3.2

yaw

含义说明:偏航角,绕 Z 轴旋转,连续叠加值(可超过 ±180°,无跳变)
数据类型:number
取值范围:无上限(多圈累计),单位 °
注意事项:无磁力计辅助,yaw 会随时间缓慢漂移;需要绝对航向请外接磁力计(本库不提供融合接口)
返回示例:45.8

示例

-- 在固定间隔循环中调用,保持陀螺积分连续
while true do
    local roll, pitch, yaw = exs_bmi270.get_attitude()
    if roll then
        log.info("exs_bmi270", string.format("roll:%.1f pitch:%.1f yaw:%.1f", roll, pitch, yaw))
    end
    sys.wait(20)  -- 20ms 调用一次(50Hz),间隔过大会影响姿态平滑度
end

4.3 参数配置

4.3.1 exs_bmi270.set_acc_range(range)

功能

运行时切换加速度量程。适合同一设备在不同工况下需要不同测量范围的应用。

参数

range

参数含义:加速度量程
数据类型:string
取值范围:"2g"(±2g,分辨率最高,适合小幅振动/倾角测量)/"4g"(±4g,分辨率 8192 LSB/g,适合日常运动)/"8g"(±8g,适合较大冲击)/"16g"(±16g,适合剧烈运动/跌倒检测)
是否必选:是
注意事项:量程越大可测上限越高但分辨率越低;切换后 get_accel()/get_data() 自动按新量程换算
参数示例:"8g"

返回值

local result = exs_bmi270.set_acc_range(range)

result

含义说明:切换是否成功
数据类型:boolean
取值范围:true(成功),false(失败)
返回示例:true

示例

-- 切换到 ±8g 量程
local result = exs_bmi270.set_acc_range("8g")
if result then
    log.info("exs_bmi270", "加速度量程已切换为 ±8g")
end

4.3.2 exs_bmi270.set_gyro_range(range)

功能

运行时切换陀螺仪量程。适合同一设备在不同旋转速度工况下需要不同测量范围的应用。

参数

range

参数含义:陀螺仪量程
数据类型:string
取值范围:"125"(±125 °/s,分辨率最高,适合缓慢转动)/"250"(±250 °/s)/"500"(±500 °/s,适合日常姿态测量)/"1000"(±1000 °/s)/"2000"(±2000 °/s,分辨率最低,适合快速旋转)
是否必选:是
注意事项:量程越大可测上限越高但分辨率越低;切换后 get_gyro()/get_data()/get_attitude() 自动按新量程换算
参数示例:"1000"

返回值

local result = exs_bmi270.set_gyro_range(range)

result

含义说明:切换是否成功
数据类型:boolean
取值范围:true(成功),false(失败)
返回示例:true

示例

-- 切换到 ±1000 °/s 量程
local result = exs_bmi270.set_gyro_range("1000")
if result then
    log.info("exs_bmi270", "陀螺仪量程已切换为 ±1000°/s")
end

4.3.3 exs_bmi270.calibrate_gyro(samples)

功能

陀螺零偏标定。设备静止放置时采样陀螺仪原始值并取平均,得到三轴零偏并缓存,后续 get_attitude() 姿态积分前自动扣除,可显著减小静止漂移。适合开机后固定设备做一次标定。

⚠️ 使用前提:设备必须静止放置,采样期间不要触碰或移动设备。

参数

samples

参数含义:采样次数
数据类型:number
取值范围:任意正整数,默认 50
是否必选:否
注意事项:次数越多零偏越准但耗时越长(每次采样含一次完整数据读取,50 次约耗时 100ms 以内);不传使用默认值 50
参数示例:100

返回值

local bias = exs_bmi270.calibrate_gyro(samples)

bias

含义说明:三轴零偏;未初始化或采样失败时返回 nil
数据类型:table 或 nil
取值范围:
    bias.x/y/z - 三轴零偏,单位 °/s
返回示例:{x = 0.02, y = -0.01, z = 0.03}

示例

-- 静止放置时标定陀螺零偏
local bias = exs_bmi270.calibrate_gyro(50)
if bias then
    log.info("exs_bmi270", string.format("零偏:(%.3f,%.3f,%.3f)°/s", bias.x, bias.y, bias.z))
end

4.4 中断控制

4.4.1 exs_bmi270.int_config(int, cfg)

功能

setup() 之后动态配置中断事件,作用与 setup()config.int1/config.int2 相同,适合运行时需要切换中断场景(如不同工况使用不同中断)的情况。

参数

int

参数含义:中断引脚名称
数据类型:string
取值范围:"int1"(BMI270 INT1 引脚)/"int2"(BMI270 INT2 引脚)
是否必选:是
参数示例:"int1"

cfg

参数含义:事件配置表,字段与 setup 的 config.int1/int2 完全一致
数据类型:table
取值范围:包含以下参数:

{
    参数含义:BMI270 中断引脚所接的 GPIO 编号
    数据类型:number
    取值范围:有效的 GPIO 编号
    是否必选:是
    参数示例:12
    cfg.int_gpio ,

    参数含义:中断有效电平
    数据类型:number
    取值范围:0(低有效,FALLING 沿,默认)/ 1(高有效,RISING 沿)
    是否必选:否
    注意事项:不传默认 0(低有效)
    参数示例:0
    cfg.lvl ,

    参数含义:数据就绪中断,每次新数据准备好时触发,触发频率很高,默认 200Hz 每 5ms 一次
    数据类型:boolean
    取值范围:true 或 false(不传入则不开启)
    是否必选:否
    注意事项:默认 200Hz 时每 5ms 触发一次,可用 setup 的 acc_odr/gyro_odr 调低采样率降低触发频率
    参数示例:true
    cfg.data_ready ,

    参数含义:任意运动检测中断
    数据类型:boolean
    取值范围:true 或 false(不传入则不开启)
    是否必选:否
    注意事项:开箱即用,本库自动使能特征并映射到 INT 引脚
    参数示例:true
    cfg.any_motion ,

    参数含义:任意运动检测阈值(灵敏度)
    数据类型:number
    取值范围:0 ~ 1000,单位 mg,分辨率约 0.488 mg
    是否必选:否
    注意事项:仅当 cfg.any_motion 开启时生效;默认 83 mg;场景建议值与 setup 的 int1.any_motion_thresh_mg 相同
    参数示例:100
    cfg.any_motion_thresh_mg ,

    参数含义:任意运动检测持续时间
    数据类型:number
    取值范围:0 ~ 163000,单位 ms,分辨率 20 ms
    是否必选:否
    注意事项:仅当 cfg.any_motion 开启时生效;默认 100 ms;场景建议值与 setup 的 int1.any_motion_duration_ms 相同
    参数示例:100
    cfg.any_motion_duration_ms ,

    参数含义:无运动检测中断
    数据类型:boolean
    取值范围:true 或 false(不传入则不开启)
    是否必选:否
    注意事项:开箱即用,本库自动使能特征并映射到 INT 引脚
    参数示例:true
    cfg.no_motion ,

    参数含义:无运动检测阈值
    数据类型:number
    取值范围:0 ~ 1000,单位 mg,分辨率约 0.488 mg
    是否必选:否
    注意事项:仅当 cfg.no_motion 开启时生效;默认 70 mg;场景建议值与 setup 的 int1.no_motion_thresh_mg 相同
    参数示例:70
    cfg.no_motion_thresh_mg ,

    参数含义:无运动检测持续时间
    数据类型:number
    取值范围:0 ~ 163000,单位 ms,分辨率 20 ms
    是否必选:否
    注意事项:仅当 cfg.no_motion 开启时生效;默认 100 ms;场景建议值与 setup 的 int1.no_motion_duration_ms 相同
    参数示例:100
    cfg.no_motion_duration_ms ,

    参数含义:显著运动检测中断
    数据类型:boolean
    取值范围:true 或 false(不传入则不开启)
    是否必选:否
    注意事项:开箱即用,本库自动使能特征并映射到 INT 引脚
    参数示例:true
    cfg.sig_motion ,

    参数含义:显著运动检测时长
    数据类型:number
    取值范围:20 ~ 1310700,单位 ms,分辨率 20 ms
    是否必选:否
    注意事项:仅当 cfg.sig_motion 开启时生效;默认 5000 ms(5 秒);场景建议值与 setup 的 int1.sig_motion_block_ms 相同
    参数示例:3000
    cfg.sig_motion_block_ms ,

    参数含义:步进检测中断
    数据类型:boolean
    取值范围:true 或 false(不传入则不开启)
    是否必选:否
    注意事项:开箱即用,本库自动使能特征并映射到 INT 引脚
    参数示例:true
    cfg.step ,

    参数含义:步数计数器开关(配合 step 使用)
    数据类型:boolean
    取值范围:true 或 false(不传入则不开启)
    是否必选:否
    注意事项:仅当 cfg.step 开启时生效;开启后可用 exs_bmi270.get_step_count() 读取步数;务必设置 step_watermark_steps(或使用默认值),否则步数恒为 0
    参数示例:true
    cfg.step_counter ,

    参数含义:步数更新间隔(多少步更新一次)
    数据类型:number
    取值范围:1 ~ 20460,单位 步(内部以 20 步为粒度)
    是否必选:否
    注意事项:仅当 cfg.step_counter 开启时生效;默认 20 步更新一次;含义与 setup 的 int1.step_watermark_steps 相同
    参数示例:20
    cfg.step_watermark_steps ,

    参数含义:中断消息 topic(推荐)
    数据类型:string
    取值范围:任意合法的 sys.publish 消息名
    是否必选:否
    注意事项:传入后中断回调通过 sys.publish(topic) 发消息,主任务 sys.waitUntil(topic) 等待后读数据
    参数示例:"BMI270_DRDY"
    cfg.topic ,

    参数含义:中断回调函数(无参)
    数据类型:function
    取值范围:用户自定义的局部函数
    是否必选:否
    注意事项:回调运行在中断上下文,仅做通知,绝不能在其中读 I2C;数据读取应在主任务协程完成。与 cfg.topic 二选一
    cfg.cb ,
}

返回值

local result = exs_bmi270.int_config(int, cfg)

result

含义说明:配置是否成功
数据类型:boolean
取值范围:true(成功),false(失败)
注意事项:未 setup() 或参数类型错误时返回 false
返回示例:true

示例

-- setup 之后动态开启 INT1 数据就绪中断(topic 模式)
local result = exs_bmi270.int_config("int1", {
    int_gpio = 12,
    data_ready = true,
    topic = "BMI270_DRDY",
})
if not result then
    log.error("exs_bmi270", "中断配置失败")
end

4.4.2 exs_bmi270.get_int_status()

功能

返回当前已触发的中断事件名数组,读取后自动清除中断标志。与 GPIO 中断回调配合,在主任务协程中确认具体是哪个事件触发(如 data_readyany_motionstep)。

参数

返回值

local events = exs_bmi270.get_int_status()

events

含义说明:已触发的中断事件名数组;未初始化时返回 nil
数据类型:table 或 nil
取值范围:
    数据类事件:"data_ready" "fifo_wm" "fifo_ffull" "error"
    特征类事件:"any_motion" "no_motion" "sig_motion" "step"
注意事项:读取后自动清除中断标志(GPIO 引脚在触发条件消失后自动复位);无中断触发时返回空表 {}
返回示例:{"data_ready"}

示例

-- 读取中断状态(读后清除)
local events = exs_bmi270.get_int_status()
if events and #events > 0 then
    log.info("exs_bmi270", "中断事件:", table.concat(events, ","))
end

4.4.3 exs_bmi270.get_step_count()

功能

读取步数计数器累计值(完整 32 位)。需要先通过 int1/int2step = true + step_counter = true 使能步数计数器(setup()int_config() 均可)。

参数

返回值

local count = exs_bmi270.get_step_count()

count

含义说明:累计步数;未初始化或未使能步数计数器时返回 nil
数据类型:number 或 nil
取值范围:0 ~ 4294967295(32 位无符号整数)
注意事项:
  1. 需先使能 step_counter(int1.step + int1.step_counter = true)
  2. 步数按 step_watermark_steps 的间隔更新(默认每 20 步更新一次),不是每步都变
  3. 步数寄存器为 32 位,日常使用几乎不会达到上限;若连续累积超过 4294967295 步会自然回绕
返回示例:1024

示例

-- 使能步数计数器后读取步数
local count = exs_bmi270.get_step_count()
if count then
    log.info("exs_bmi270", "累计步数:", count)
end

4.4.4 exs_bmi270.reset_step_count()

功能

清零步数计数器,计数重新从 0 开始。适合开始计步前清零,或按天/按次分段统计。

参数

返回值

local result = exs_bmi270.reset_step_count()

result

含义说明:清零是否成功
数据类型:boolean
取值范围:true(成功),false(失败)
注意事项:需先使能 step 相关功能(step 或 step_counter);清零后步数从 0 重新累计
返回示例:true

示例

-- 开始计步前清零,然后读取
exs_bmi270.reset_step_count()
sys.wait(1000)  -- 等待 1 秒
local count = exs_bmi270.get_step_count()
if count then
    log.info("exs_bmi270", "本次计步:", count)
end

4.5 电源管理

4.5.1 exs_bmi270.sleep()

功能

进入休眠模式,关闭加速度计、陀螺仪和温度传感器电源,功耗最低。内部配置(量程、采样率)保留,调用 wakeup() 可快速恢复工作,无需重新 setup()。

参数

返回值

示例

-- 进入休眠模式
exs_bmi270.sleep()

4.5.2 exs_bmi270.wakeup()

功能

从休眠模式唤醒,重新上电使能加速度计、陀螺仪和温度传感器。唤醒后自动等待数据就绪(最多 70ms),返回即可读取有效数据。

⚠️ 协程限制:必须在 sys.taskInit 创建的协程中调用 原因:唤醒后需等待传感器上电并数据就绪(最多 70ms),需要 sys.wait 让步 最长等待:70ms

参数

返回值

示例

-- 从休眠模式唤醒
exs_bmi270.wakeup()

4.5.3 exs_bmi270.reset()

功能

软复位传感器并重新执行完整初始化流程(微程序重新加载、量程采样率恢复为 setup 时的配置)。适合传感器工作异常时恢复。

⚠️ 协程限制:必须在 sys.taskInit 创建的协程中调用 原因:复位后需等待微程序重新加载(100ms)与配置生效(50ms),需要 sys.wait 让步 最长等待:约 200ms

参数

返回值

local result = exs_bmi270.reset()

result

含义说明:复位并重新初始化是否成功
数据类型:boolean
取值范围:true(成功),false(失败)
返回示例:true

示例

-- 复位并重新初始化传感器
local result = exs_bmi270.reset()
if result then
    log.info("exs_bmi270", "传感器复位完成")
end

4.6 资源释放

4.6.1 exs_bmi270.close()

功能

关闭传感器并释放通信资源。传感器进入休眠,硬件 I2C 总线与 SPI 设备被释放。close() 后需重新调用 setup() 才能再次使用。

参数

返回值

示例

-- 关闭传感器并释放资源
exs_bmi270.close()

4.7 版本信息

4.7.1 exs_bmi270.version()

功能

获取扩展库版本号。

参数

返回值

local version = exs_bmi270.version()

version

含义说明:扩展库版本号
数据类型:string
取值范围:格式 yyyymmddhhmm(年/月/日/时/分)
返回示例:"202608051200"

示例

-- 打印版本号
log.info("exs_bmi270", "version:", exs_bmi270.version())

五、版本更新说明

版本号:202608051200

  1. 更新时间:2026-08-05

  2. 更新内容:第一版发布,实现功能如下:

    • 支持 I2C(软件/硬件)与 SPI 两种通信接口初始化,自动完成芯片 ID 校验、微程序加载、量程/采样率配置

    • 数据读取:三轴加速度(g)、三轴角速度(°/s)、温度(°C)、原始 ADC 值、组合数据 get_data()

    • Mahony 互补滤波姿态解算 get_attitude(),输出 roll/pitch/yaw;陀螺零偏标定 calibrate_gyro()

    • 运行时量程/采样率切换 set_acc_range()/set_gyro_range()、软复位 reset()、休眠/唤醒 sleep()/wakeup()、关闭 close()

    • 中断功能:data_ready 数据就绪 + any_motion/no_motion/sig_motion/step 特征中断,支持阈值/时长/计步间隔参数可调,topiccb 两种回调方式,get_int_status() 查询触发事件

    • 计步功能:get_step_count() 读取 32 位累计步数、reset_step_count() 清零、step_watermark_steps 控制刷新间隔

    • I2C 总线卡死自动恢复、软复位后中断配置自动重应用


六、产品支持说明

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

搜索
AirMaster 实时解答