项目概述

这是一套可独立运行的气压高度计:ESP32 读取 Bosch BMP580 的温度与气压,用国际气压高度公式换算海拔,再把当前海拔减去上电(或手动清零)时的基准,得到厘米级相对高度。

系统同时提供三条输出通道:

通道 作用
240×240 TFT 现场主显示:相对高度、温度、气压、海拔、垂直速度、约 60 秒趋势、IP 与时钟
局域网网页 手机/电脑看实时数据、历史曲线,可清零、设 P0、下载 CSV
串口 115200 调试与命令:z 清零,p= 设海平面气压,a= 按已知海拔校准

上电后优先连已配置的 WiFi;连不上则开 SoftAP 热点 BMP580-Altimeter。历史数据每 5 秒写入 LittleFS /log.csv,内存环形缓冲约保留 30 分钟。

能测什么、不能测什么: 这是气压计,不是 IMU。左右晃动、水平平移几乎不改变相对高度;只有垂直方向气压变化才会反映到 Rel 上。使用时请先清零,再垂直举高 1~2 米或走上楼梯。


项目亮点

  1. 厘米级相对高度
    气压 16 倍过采样 + IIR 系数 7 + 软件 EMA + 0.8 cm 死区,显示按 1 cm 取整,适合做“举高 / 上楼”演示。

  2. 三端同步
    屏幕、网页、串口共用同一套滤波后的状态量。网页 500 ms 刷新,屏幕局部刷新避免整屏闪烁。

  3. 可校准、可掉电保存
    海平面气压 P0 存在 NVS(Preferences 命名空间 bmp580)。支持直接设 P0,也支持输入已知海拔反推 P0。

  4. 历史可回看、可导出
    RAM 环形缓冲 360 点 + 文件 /log.csv(上限约 80 KB,超限自动裁掉旧数据)。网页可画气压 / 相对高度历史,并下载 CSV。

  5. 联网与离线都能用
    STA 失败自动 SoftAP;NTP 用 CST-8(阿里云 / 腾讯 / pool.ntp.org);WiFi 掉线约每 15 秒重连。

  6. 现场可清零
    GPIO12 按键、串口 z、网页按钮三条路径都会把当前海拔设为相对高度零点。


项目难点及解决方案

开发过程中真正卡住过的问题,以及固件里对应的处理,如下。

1. 芯片配置后一直读数为 0

原因: BMP580 的过采样、IIR、输出速率必须在 STANDBY 下改,最后再切 NORMAL。若配置后仍停在待机,或用 dataReady() 死等 DRDY,主循环会永远拿不到有效气压。

解决: configureBmp580() 固定顺序:STANDBY → 写 OSR/IIR/ODR → NORMAL。updateSensor() 直接 performReading(),不依赖 DRDY 门闩。

2. 接上 TFT 后 I2C 丢了

原因: ST7789 走硬件 SPI。部分板上 tft.init() 之后 SDA/SCL 状态异常,BMP580 突然无应答。

解决: 每次初始化总线先 recoverI2CPins():释放引脚、必要时补时钟脉冲,再 Wire.begin(21, 22)。只探测 0x46 / 0x47,最多重试 3 次。

3. 串口“突然停了”

原因: ESP32 硬件 I2C 在 loop 里被高频轮询会卡死;扫描地址 0x7E 会踩到 I3C,同样可能挂死。

解决: 读传感器间隔至少 100 ms;Wire.setTimeOut(30);探测只扫 BMP580 两个地址。

4. 温度 127.5 ℃、气压 1305 hPa 等垃圾值

原因: 总线毛刺或芯片未真正进入测量时,寄存器可能吐出越界值。

解决: isReadingSane() 要求温度在 −20~85 ℃、气压在 300~1250 hPa。连续失败 3 次则 recoverBmp580() 重新 begin + 配置。

5. 240×240 方屏画面偏左、右侧一条白边

原因: 很多 ST7789 驱动芯片显存是 240×320。TFT_eSPI 按 320 宽报尺寸,UI 若按 0,0 画 240 宽,有效像素会落在显存左侧,屏幕上看就是偏了。

解决: UI 锁定 240×240;TFT_OFF_X/Y = -1 时自动用 (nativeW - 240) 做偏移(常见为 80,0),再用 setViewport() 把后续绘制裁在方屏里。仍偏可把 TFT_OFF_X 改成 0 或 80

6. GPIO12 清零键上电异常

原因: GPIO12 是 ESP32 的 strapping 脚。上电时若被按住拉低,可能影响启动。

解决: 按键接 GND,内部上拉;上电时不要按住。运行后再按才清零。

7. 屏幕不能显示中文

原因: TFT_eSPI 默认字体是 ASCII,没有完整 CJK 点阵。

解决: 屏幕标签用英文(Rel / T / P / ALT / Vz);中文放在网页端。

8. 网页曲线发糊

原因: Canvas 用 CSS 拉伸,未按 devicePixelRatio 设置实际像素。

解决: sizeCanvas() 按 DPR 设 canvas.width/height,再 setTransform 用 CSS 像素画线。


目录

一、硬件系统部分

1.1 硬件清单

1.2 接线方案

1.3 硬件连接图

1.4 实物连接图

二、软件架构设计

2.1 系统初始化

2.2 主循环逻辑

三、代码拆分讲解

3.1 配置与全局状态

3.2 气压 ↔ 海拔

3.3 BMP580 驱动封装

3.4 人机接口

3.6 显示

3.7 网络

四、操作过程及数据展示

4.1 操作步骤

4.2 数据展示说明

4.3 演示视频

五、技术原理

5.1 工作原理

5.2 工作模式配置

六、常见问题指引

6.1. 串口提示找不到 BMP580(0x46/0x47)

6.2. 芯片应答成功,但一直没有有效气压

6.3. 读数乱跳或出现 127 ℃ / 上千 hPa

6.4. 历史为空或下载 CSV 失败


一、硬件系统部分

1.1 硬件清单

序号 名称 规格 / 备注
1 主控 零知ESP32
2 气压传感器 BMP580 模块,必须 3.3V,走 I2C
3 彩屏 240×240 ST7789 SPI TFT
4 杜邦线 / 面包板 建议电源线稍粗,GND 共地
6 USB 线 供电 + 烧录 + 串口

可选:已知海拔的参考点(用于 a= 校准),以及 2.4 GHz WiFi。

供电注意: BMP580 不要接 5V。CSB 必须保持高电平,模块才会停在 I2C 而不是 SPI。

1.2 接线方案

BMP580(I2C)

BMP580 引脚 接到 说明
VIN / VCC ESP32 3.3V 禁止 5V
GND GND 与屏幕、按键共地
SDA / SDI GPIO21 I2C_SDA
SCL / SCK GPIO22 I2C_SCL
CS / CSB 3.3V 或模块已拉高 保持 I2C
SDO 悬空 → 地址 0x47;接地 → 0x46 固件两种都试

内部 INPUT_PULLUP,按下为低电平。上电时不要按住。

1.3 硬件连接图

实物接线时记住三件事:

  1. 所有模块共地。
  2. BMP580 与屏幕不要抢同一组数据脚: 传感器走 I2C(21/22),屏幕走 SPI(18/23/15/13/4)。
  3. 先不接屏幕也能用串口验证传感器;屏幕正常后再并上 TFT。

1.4 实物连接图


二、软件架构设计

固件以单文件草图的形式组织,整体逻辑可划分为六个层次:

2.1 系统初始化

setup() 顺序不能随便调换:屏幕会动 SPI,必须在屏幕起来之后再专门恢复 I2C,否则容易“屏亮了、气压没了”。

步骤 函数 做什么
1 Serial.begin(115200) 调试口
2 loadPrefs() 读出已保存的 P0、WiFi 账号
3 setupLittleFS() 挂载文件系统,载入 /log.csv
4 pinMode(BUTTON_PIN, INPUT_PULLUP) 清零键
5 setupDisplay() tft.init()、旋转、计算 80 像素偏移、setViewport(240,240)
6 initBmp580() 恢复总线 → 探测 0x47/0x46 → STANDBY 配置 → NORMAL → 读首帧
7 setupWiFi() 最多等 12 s;失败则 SoftAP
8 setupWeb() 注册 //api/*/log.csv
9 把 IP 写到屏幕底部 STA 用局域网 IP,AP 用 192.168.4.1

WiFi 请在源码里改这两行(不要把密码提交到公开仓库):

const char *WIFI_SSID = "你的WiFi名称";
const char *WIFI_PASS = "你的WiFi密码";

2.2 主循环逻辑

loop() 不做长 delay,只在末尾 delay(2) 让出 CPU。各任务用时间戳分流。

关键节拍:

  • 100 ms: 传感器。对应 ODR 10 Hz,再快没有意义,还会把 I2C 打挂。
  • 500 ms: 串口一行、屏幕更新、网页火花图用的 72 点环形缓冲。
  • 5 s: 落盘一条历史。360 条 × 5 s ≈ 30 分钟。
  • 15 s: STA 断开后尝试 WiFi.begin
  • 30 s: NTP 仍未同步则再 configTzTime

相对高度死区 0.8 cm:只有 |新值 − 当前 Rel| ≥ 0.008 m 才更新显示,避免最后一位乱跳。


三、代码拆分讲解

源码虽在一个 .ino 里,可按职责拆开读。

3.1 配置与全局状态

文件开头宏决定硬件脚、屏幕几何、日志容量:

  • I2C_SDA/SCLBUTTON_PIN
  • SCREEN_W/H = 240TFT_ROTATION 3TFT_OFF_X/Y = -1 自动偏移
  • LOG_INTERVAL_MS = 5000LOG_RAM_N = 360,文件最大约 80 KB
  • 运行时核心量:temperatureCpressureHpaaltitudeMrelativeMverticalMsseaLevelHpazeroAltitudeM

网页 HTML 以 PROGMEM 原始字符串嵌在固件里,ESP32 当 Web 服务器直接吐页面,不需要外置站点。

3.2 气压 ↔ 海拔

国际标准气压高度公式(温度按 ISA 近似):

[
h = 44330 \times \left(1 - \left(\frac{P}{P_0}\right)^{0.190295}\right)
]

反推海平面气压(已知当地海拔 (h)):

[
P_0 = P \big/ \left(1 - \frac{h}{44330}\right)^{5.255}
]

对应 pressureToAltitude()seaLevelFromAltitude()。相对高度:

Rel = 当前海拔 − 清零时海拔

上电第一次有效读数会自动把基准海拔设为当前值,所以开机 Rel 从 0 附近开始。

3.3 BMP580 驱动封装

函数 作用
recoverI2CPins() 释放被拉死的 SDA,补 16 个时钟
beginI2CBus() 100 kHz + 30 ms 超时
scanI2C() 只探 0x47、0x46
configureBmp580() 待机写入 OSR/IIR/ODR 后进 NORMAL
initBmp580() 最多 3 轮,成功则记下地址并留下首帧
recoverBmp580() 读失败后的软复位路径
updateSensor() 滤波、死区、垂直速度

垂直速度:(\Delta Rel / \Delta t),再做 0.25 * 新值 + 0.75 * 旧值,只作趋势参考,精度不如 Rel。

3.4 人机接口

串口

命令 效果
z 或 zero 相对高度清零
p=1013.25 设置 P0(hPa)并写入 NVS
a=50 把当前气压当作海拔 50 m,反推 P0 并保存

按键: GPIO12 低电平且已有有效样本 → zeroRelativeAltitude()

网页 API

路径 说明
GET / 看板 HTML
GET /api/data 当前 T/P/Alt/Rel/Vz/P0/时间
GET /api/zero 清零
GET /api/sealevel?hpa= 设 P0
GET /api/calibrate?alt= 按海拔校准
GET /api/history 历史 JSON
GET /api/clear 清空记录
GET /log.csv 下载文件
  • NVS bmp580 p0ssidpass
  • LittleFS /log.csv 表头 ts,t,p,alt,rel。文件过大时丢掉大约前 40%,保留后段
  • RAM logRam[360] 网页历史曲线优先读这里,重启后由 CSV 回填

未对上 NTP 时,时间戳用 millis()/1000,网页上显示 T+…s,曲线底部不会画时钟刻度。

3.6 显示

屏幕采用“静态底 + 局部刷新”:

  1. drawStaticLayout() 画卡片外壳和标签(只在需要时重画)
  2. updateDisplay() 比较上次字符串,数字没变就不擦
  3. Rel 上升绿色、下降黄色、接近 0 蓝色
  4. 底部火花图 72 点,对应约 36 秒~1 分钟的 Rel(随 500 ms 节拍)

网页主数字是相对高度厘米;温度 / 气压 / 海拔 / 垂直速度四宫格;下方实时趋势 + 历史双曲线(气压绿、Rel 蓝),并按 devicePixelRatio 锐化。

3.7 网络

STA 12 s 内连上 → 保存账号、NTP、mDNS bmp580.local
STA 失败     → SoftAP BMP580-Altimeter / 12345678,默认 http://192.168.4.1
之后         → maintainWifi() 维持 STA 与 NTP

手机连 SoftAP 后,地址以串口打印为准。Windows 上 .local 有时无效,直接用 IP 更稳。


四、操作过程及数据展示

4.1 操作步骤

  1. 改 WiFi 与确认引脚
    打开 BMP580_Altimeter.ino,填写 WIFI_SSID / WIFI_PASS。确认 I2C、按键与 TFT_eSPI User_Setup 一致。

  2. 接线检查
    BMP580 只接 3.3V;CSB 为高;SDA/SCL 没有和屏幕 MOSI/SCLK 接反。

  3. 编译烧录
    串口监视器 115200。正常时应看到类似:

    ESP32 + BMP580 气压高度计
    BMP580 芯片应答成功,地址 0x47
    首帧数据 T=xx.xx C  P=xxxx.xx hPa
    WiFi 已连接,浏览器打开 http://192.168.x.x
    也可尝试 http://bmp580.local
    就绪。
    
  4. 看屏幕
    右上角 LIVE 表示传感器在更新。中间大号为相对高度(cm)。底部左侧 IP,右侧时钟(NTP 成功为绿色,否则 --:--)。

  5. 清零再做高度实验
    按 GPIO12,或串口输入 z,或网页点「相对高度清零」。然后垂直举高模块或走上楼梯,Rel 应变大;左右晃不应有明显变化。

  6. 打开网页
    浏览器访问串口给出的 IP 或 http://bmp580.local。若页面还是旧版,强制刷新(Ctrl+F5)。

  7. 看历史与导出
    等待数分钟后点「刷新历史」。需要存档时下载 log.csv。不要的数据可「清空记录」。

4.2 数据展示说明

串口一行示例:

T=26.31 C  P=1008.452 hPa  Alt=39.12 m  Rel=+123 cm  Vz=+0.15 m/s  2026-08-25 14:12:03
字段 含义
T 滤波后温度
P 滤波后气压
Alt 相对海平面 P0 的海拔
Rel 相对清零点的高度,厘米
Vz 垂直速度估计
时间 NTP 成功为日历时间,否则为上电秒数

屏幕: 主视觉是 Rel;四宫格为 T / P / ALT / Vz;底部短曲线看最近 Rel 是否在爬升。

网页: 顶部时钟与 NTP/I2C 状态;大号 cm;历史图左侧有纵轴刻度,底部有时分。曲线发糊时刷新页面;没有时间刻度说明还没对上 NTP。

4.3 演示视频

零知ESP32--BMP580 气压高度计


五、技术原理

5.1 工作原理

BMP580 是压阻式气压传感器:膜片随外界气压形变,片上 ADC 读出原始值,再用出厂校准系数补偿得到温度(℃)和气压(hPa)。

海拔不是直接测出来的。在标准大气假设下,气压随高度近似指数下降,因此可用 (P) 和海平面参考 (P_0) 反算几何高度。本项目:

  1. 芯片以约 10 Hz 产出补偿后的 T、P。
  2. 软件对 T 做轻量平滑(新值 20%),对 P 做更重的 EMA(新值 12%),压掉通风和人手热干扰。
  3. 用公式得到绝对海拔 altitudeM
  4. 记住清零瞬间的海拔 zeroAltitudeM,差值为相对高度。
  5. 小于 0.8 cm 的跳动丢弃,显示时四舍五入到 1 cm。

误差来源(做实验时心里有数):

  • (P_0) 不准 → 绝对海拔整体偏移,但相对高度几乎不受影响(演示请用 Rel)。
  • 天气、空调、关门会造成 hPa 级慢漂,长时间 Rel 会爬。
  • 温度突变会通过气压补偿耦合进高度,所以不要把模块对着热风口。
  • 本方案没有 GPS / 超声波交叉验证,适合教学与室内相对高度,不适合做航空级高度表。

5.2 工作模式配置

Bosch BMP5xx 常见电源模式:

模式 含义 本固件
STANDBY 停测,才能改 OSR / IIR / ODR 配置阶段使用
NORMAL 按 ODR 连续测量 运行阶段使用
FORCED 测一次再睡 未使用

当前寄存器配置(configureBmp580()):

参数 取值 用意
温度过采样 温度变化慢,2 倍足够,还给气压留带宽
气压过采样 16× 压低量化噪声,换厘米级稳定性
气压使能 高度只来自气压
IIR 系数 7 片内再滤一档,抑制短时扰动
ODR 10 Hz 与 100 ms 轮询匹配,人眼跟得上,I2C 也不过载
电源模式 NORMAL 连续出数

配置时序必须是:

STANDBY → 写 OSR / IIR / ODR → NORMAL → 延时约 50 ms → 读首帧

I2C 地址由 SDO 决定:悬空常用 0x47,接地为 0x46。CSB 若被拉低,芯片会切到 SPI,I2C 初始化会失败——这是接线里最容易忽略的一点。


六、常见问题指引

6.1. 串口提示找不到 BMP580(0x46/0x47)

检查 3.3V 而不是 5V;SDA/SCL 有没有和屏幕接反;CSB 是否为高;模块杜邦线是否松。可先卸下屏幕再初始化,确认是传感器问题还是 SPI 冲突。

6.2. 芯片应答成功,但一直没有有效气压

供电是否稳定;CSB 是否在测量时仍保持高。固件会提示检查 3.3V 与 CSB。看 configureBmp580() 是否完整执行进了 NORMAL。

6.3. 读数乱跳或出现 127 ℃ / 上千 hPa

多为 I2C 被干扰。固件会丢弃非法值并在连续失败后重建总线。加短线、共地、远离电机。不要在 loop 里自行加密集扫描。

6.4. 历史为空或下载 CSV 失败

分区要带 spiffs/LittleFS。串口若打印 “LittleFS 启动失败”,历史只在内存,掉电即无。文件超过约 80 KB 会自动裁旧。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐