零知派ESP32–基于BMI160的IMU姿态监测系统
项目概述
本系统以零知派 ESP32 为主控,读取 Bosch BMI160 六轴惯性传感器(三轴加速度计 + 三轴陀螺仪),在 MCU 上用 Madgwick 算法融合成横滚角(Roll)、俯仰角(Pitch)、偏航角(Yaw)。
结果同时送到三路:
- ST7789 1.54 寸 240×240 屏幕:本地仪表,含角度、水平气泡和状态灯
- WiFi 热点网页:3D 正方体、实时数据、开始/停止记录、一键导出 CSV
- USB 串口(可选):FireWater 协议对接 VOFA+,在电脑上看 3D
数据可写入 ESP32 内部 Flash(LittleFS),文件名为 log_01.csv、log_02.csv 等。网页「导出 CSV」即可下载到手机或电脑,无需拆机、无需 SD 卡读卡器。
适用场景:水平校准、短时姿态记录、IMU 教学演示。BMI160 没有磁力计,偏航角会随时间缓慢漂移,属六轴系统固有限制。
项目亮点
- 采集—解算—显示—记录—导出闭环,不是只打印原始加速度。
- 双界面:不连电脑时看屏幕;连热点后用浏览器看 3D 正方体并导出数据。
- 网页 3D 不依赖外网:正方体用 CSS 3D 绘制,连 ESP32 热点也能转。
- 陀螺零偏校准:上电静止约 2.5 秒采集零偏,网页可再次校准。
- I2C 掉线恢复:杜邦线接触不良时自动恢复总线并重新初始化传感器。
- 状态一目了然:绿=正常,黄=校准中,红=I2C 故障。
项目难点及解决方案
| 难点 | 现象 | 解决 |
|---|---|---|
| BMI160 初始化失败 | 角度全 0 | 检查 3.3V、I2C 地址 0x68/0x69;驱动探测两个地址 |
| 开机立刻校准 | 静止时偏航仍快速漂 | 等陀螺进入 Normal 后再延时,丢掉前 0.4 s 样本 |
| 热点下 Three.js 拉不下来 | 3D 卡住很久 | 网页改用内置 CSS 立方体 |
| 读 I2C 失败仍推旧姿态 | 画面停在一个角度 | 连续失败则恢复总线;屏幕 I2C 灯变红 |
| 记录占满程序分区 | 无法写 CSV | 使用 partitions.csv 划分 LittleFS,不要选 huge_app |
| 同步 WebServer 占用 | 界面卡顿 | 屏幕 5 Hz、网页轮询约 3 Hz,串口 50 Hz |
目录
一、硬件系统部分
1.1 硬件清单
| 名称 | 规格 | 数量 | 说明 |
|---|---|---|---|
| 零知派 ESP32 | ESP32,4MB Flash | 1 | 主控 |
| BMI160 模块 | I2C,3.3V | 1 | 六轴 IMU |
| ST7789 屏幕 | 240×240,SPI | 1 | TFT_eSPI 驱动 |
| 杜邦线 / 排线 | — | 若干 | 建议尽量短 |
| USB 线 | 供电与烧录 | 1 | 可选接电脑 VOFA+ |
电源:BMI160 与屏幕均用 3.3V,禁止给 BMI160 接 5V。
1.2 接线方案
BMI160(I2C)
| BMI160 | ESP32 |
|---|---|
| VCC | 3.3V |
| GND | GND |
| SDA | GPIO 21 |
| SCL | GPIO 22 |
| SDO/SA0 | GND → 地址 0x68(接 3.3V 则为 0x69,固件会自动尝试另一地址) |
ST7789(SPI,引脚在 TFT_eSPI 的 User_Setup.h 中配置)
| ST7789 | ESP32 |
|---|---|
| MOSI / SDA | GPIO 23 |
| SCLK / SCL | GPIO 18 |
| CS | GPIO 15 |
| DC | GPIO 13 |
| RST | GPIO 4 |
| VCC | 3.3V |
| GND | GND |
I2C 与 SPI 分开,不要把屏幕的 SDA 接到 GPIO 21。屏幕方向在固件里为 tft.setRotation(3)(旋转 3)。
打开零知派;开发板选零知派 ESP32;分区选带 SPIFFS 的方案(工程内已有 partitions.csv)。库:Wire、WiFi、WebServer、LittleFS 随 ESP32 核心提供。
1.3 硬件连接图


1.4 实物连接图

二、软件架构设计
工程按功能拆文件,主程序只负责调度。
| 文件 | 职责 |
|---|---|
BMI160.ino |
setup / loop,串口命令 |
config.h |
引脚、热点名、采样率 |
bmi160.h/.cpp |
传感器初始化、读数、总线恢复 |
fusion.h/.cpp |
零偏、Madgwick、欧拉角 |
display.h/.cpp |
ST7789 界面 |
logger.h/.cpp |
LittleFS 写/列/导出 CSV |
web.h/.cpp |
SoftAP + HTTP |
webpage.h |
网页 HTML(含 CSS 3D 正方体) |
partitions.csv |
程序区 + LittleFS |
2.1 系统初始化
setup() 顺序:
- 可选点亮 GPIO2 LED
- 串口 115200(VOFA+ 与
dump共用,运行时不要开串口监视器抢口) imu.begin(21, 22, 0x68, 100kHz):软复位、加速度/陀螺 Normal、等 PMU 就绪、再稳定 500 msfusion.beginloggerBegin:挂载 LittleFS(失败则无法记录)displayBegin:tft.init(),setRotation(3),画状态栏webBegin:SoftAPBMI160-LOG/12345678,HTTP 80- 若 IMU 成功,开始约 2.5 s 陀螺校准(前 0.4 s 丢弃)
2.2 主循环逻辑
loop() 每一圈:
pollVofaCommands():处理start/stop/calibrate/reset_yaw/dumpwebLoop():处理网页请求- 100 Hz:读 BMI160,融合;连续失败则
imu.recover() - 50 Hz:串口输出
roll,pitch,yaw;若正在记录则写入 CSV 缓冲 - 5 Hz:刷新屏幕,并向网页模块更新 Live JSON
网页每约 300 ms 请求 /api/live 更新数字和正方体,不使用 WebSocket,热点下更稳。
三、代码拆分讲解
3.1 配置 config.h
I2C 21/22、热点 SSID/密码、IMU_SAMPLE_HZ=100、VOFA_HZ=50、DISPLAY_HZ=5、GYRO_CAL_MS=2500。改接线只动这里和 TFT_eSPI 的 User_Setup.h。
3.2 驱动 bmi160.cpp
Chip ID 0xD1。加速度 ±4 g(8192 LSB/g),陀螺 ±500 dps(65.6 LSB/°/s),ODR 100 Hz。从寄存器 0x0C 连续读 12 字节(先陀螺后加速度)。recoverBus() 在 SDA 被拉死时补时钟并重新 Wire.begin。
3.3 融合 fusion.cpp
校准阶段只累加陀螺均值。运行时减去零偏,Madgwick 输出四元数,再转欧拉角给屏幕和网页。静止一段时间会缓慢跟踪剩余零偏。无磁力计时偏航只能靠陀螺积分。
3.4 屏幕 display.cpp
顶部 I2C / CAL / REC 圆点,中部三个角度,左下气泡(roll/pitch 映射到圆内),底部提示 192.168.4.1。角度变化小于 0.05° 不重绘,减少闪烁。
3.5 记录 logger.cpp
start 创建 /log_XX.csv,表头:
t_ms,roll,pitch,yaw,ax,ay,az,gx,gy,gz
t_ms 从本次记录开始计。内存攒 32 行再写盘。最多 99 个文件。
3.6 网页 web.cpp + webpage.h
| 路径 | 作用 |
|---|---|
GET / |
主页面 |
GET /api/live |
实时 JSON |
GET /api/logs |
文件列表 |
POST /api/start stop calibrate |
记录与校准 |
GET /api/export |
下载最近一份 CSV |
GET /download?f=log_01.csv |
下载指定文件 |
正方体用六个面拼成板状,JavaScript 按rotateY(yaw) rotateX(pitch) rotateZ(-roll) 更新。
四、操作过程及数据展示
4.1 操作步骤
- 按 1.2 接线,确认 BMI160 为 3.3V。
- 打开
BMI160.ino,选零知派 ESP32,分区带 SPIFFS,编译上传。 - 上电后将模块放平静止约 3 秒,屏幕 CAL 由黄变绿。
- 手机连接 WiFi BMI160-LOG,密码 12345678。
- 浏览器打开 http://192.168.4.1(屏幕底部也有该地址)。
- 转动模块:网页正方体与 ROLL/PITCH/YAW 应同步变化。
- 点 开始记录,REC 变绿;点 停止 保存。
- 点 导出 CSV,浏览器下载
log_xx.csv。用 Excel 或 Python 打开。 - 需要重新校准:点 校准,保持静止直到 CAL 变绿。
CSV 示例
t_ms,roll,pitch,yaw,ax,ay,az,gx,gy,gz
0,1.02,4.10,-0.12,-0.076,0.019,1.064,0.02,-0.01,0.00
20,1.05,4.08,-0.10,-0.077,0.018,1.063,0.01,-0.02,0.01
平放时 az 约 1 g,ax/ay 接近 0,roll/pitch 为小角度。
可选 VOFA+:协议 FireWater,115200,I0/I1/I2 绑定 3D。不要同时开串口监视器。
4.2 演示视频
零知派ESP32–基于BMI160的IMU姿态监测系统
五、技术原理
5.1 工作原理
加速度计测比力,静止时主要是重力,可得到 roll、pitch,但对偏航不敏感,动态时受运动加速度干扰。陀螺仪测角速度,积分得到相对转角,但有零偏,积分会漂。
本工程:
- 静止时估计陀螺零偏并减去。
- Madgwick 用陀螺预报四元数,用加速度作重力方向校正(主要稳住 roll/pitch)。
- 偏航没有地磁参考,长期会漂,可网页或串口
reset_yaw把当前航向当作 0。
屏幕气泡只用 roll、pitch,不依赖航向。
5.2 工作模式配置
BMI160
- 加速度、陀螺:Normal
- 加速度:±4 g,100 Hz
- 陀螺:±500 °/s,100 Hz
- I2C:100 kHz(杜邦线比 400 kHz 更稳)
系统任务频率
| 任务 | 频率 |
|---|---|
| IMU 采样与融合 | 100 Hz |
| 串口 / 写 CSV | 50 Hz |
| 屏幕 | 5 Hz |
| 网页轮询 | 约 3 Hz |
存储partitions.csv:应用约 1.75 MB,LittleFS 约 2.2 MB。50 Hz 记录大约可记十余分钟量级(视行长而定),不是长时间黑匣子。需要更久请改 SD 卡。
网络
仅 SoftAP,STA 不连路由器。IP 固定 192.168.4.1。
六、常见问题指引
Q1:点开始记录 REC 仍灰
分区没有 LittleFS(不要 huge_app),或已有 99 个 log 文件。
Q2:导出是空的或 404
先成功记录并停止一次。导出最近一份;历史列表可下旧文件。
Q3:VOFA+ 打不开串口
关掉串口监视器后再连。
更多推荐


所有评论(0)