4、读取原始数据:编写第一个 Python 脚本,读取 BMP280 的温度与压力原始值

好,到了这一步,咱们的 BMP280 传感器已经焊好、接好线了。I2C 地址也确认过了。接下来要干嘛?当然是让它开口说话——读取原始数据。

说实话,我第一次调 BMP280 的时候,心里还挺没底的。毕竟 datasheet 里那些寄存器地址看着就头大。但后来我发现,其实没那么复杂。你只要按部就班,把几个关键寄存器读出来,数据就到手了。

4.1 准备工作:安装必要的库

在写脚本之前,得先确认你的树莓派(或者 Jetson Nano、香橙派都行)上装了 smbus2 这个库。它是用来跟 I2C 设备打交道的。

安装命令:

sudo pip3 install smbus2

我个人习惯用 smbus2 而不是老的 smbus。为什么?因为 smbus2 更稳定,而且支持 Python 3。我在一个项目里遇到过 smbus 莫名其妙报错,换成 smbus2 就再也没出过问题。

4.2 BMP280 的原始数据长什么样?

BMP280 内部有温度传感器和压力传感器。它们输出的原始值,说白了就是两个 20 位的二进制数。但注意,它不是直接给你 20 位,而是分成了三个 8 位寄存器来存。

具体来说:

  • 温度原始值:存放在寄存器 0xFA(高8位)、0xFB(中8位)、0xFC(低8位)
  • 压力原始值:存放在寄存器 0xF7(高8位)、0xF8(中8位)、0xF9(低8位)

你想想看,这三个 8 位拼起来,就是一个 24 位的数。但 BMP280 只用了高 20 位,低 4 位是 0。所以读出来之后,要右移 4 位才是真正的原始值。

小技巧: 我建议你一次性读 6 个字节(从 0xF7 开始),而不是分两次读。这样能保证温度和压力数据是同一时刻采样的,不会出现时间差。

4.3 第一个脚本:读取原始值

好,咱们直接上代码。这个脚本很简单,就是读寄存器、拼数据、打印出来。

import smbus2
import time

# BMP280 的 I2C 地址(默认是 0x76,也可能是 0x77)
BMP280_ADDR = 0x76

# 寄存器地址
BMP280_REG_PRESS_MSB = 0xF7   # 压力高8位
BMP280_REG_TEMP_MSB  = 0xFA   # 温度高8位

# 初始化 I2C 总线(树莓派一般是 1)
bus = smbus2.SMBus(1)

def read_raw_data():
    """
    读取 BMP280 的温度和压力原始值
    返回: (temp_raw, press_raw)
    """
    # 一次性读取 6 个字节,从压力寄存器开始
    # 顺序:press_msb, press_lsb, press_xlsb, temp_msb, temp_lsb, temp_xlsb
    data = bus.read_i2c_block_data(BMP280_ADDR, BMP280_REG_PRESS_MSB, 6)

    # 拼出压力原始值(24位,取高20位)
    press_raw = (data[0] << 16) | (data[1] << 8) | data[2]
    press_raw = press_raw >> 4  # 右移4位,得到20位原始值

    # 拼出温度原始值(24位,取高20位)
    temp_raw = (data[3] << 16) | (data[4] << 8) | data[5]
    temp_raw = temp_raw >> 4    # 右移4位,得到20位原始值

    return temp_raw, press_raw

# 主循环:每秒读一次
try:
    while True:
        temp_raw, press_raw = read_raw_data()
        print(f"温度原始值: {temp_raw:6d}    压力原始值: {press_raw:8d}")
        time.sleep(1)
except KeyboardInterrupt:
    print("\n程序已停止")
    bus.close()

注意: 如果你用的是 0x77 地址,记得把 BMP280_ADDR = 0x76 改成 0x77。我曾经在一个项目里忘了改,折腾了半小时才发现是地址不对。

4.4 运行脚本,看看结果

把上面的代码保存成 read_bmp280_raw.py,然后在终端里运行:

python3 read_bmp280_raw.py

你应该会看到类似这样的输出:

温度原始值:  52340    压力原始值:  412345
温度原始值:  52341    压力原始值:  412346
温度原始值:  52340    压力原始值:  412344
...

嗯,这里要注意:这些数字看着很大,对吧?别急,它们还不是真正的温度和压力值。原始值需要经过校准公式换算,才能变成摄氏度和帕斯卡。下一章咱们就讲这个。

4.5 常见问题与避坑指南

我遇到过不少新手在这步卡住,总结几个常见问题:

问题 可能原因 解决办法
读出来全是 0 I2C 地址不对,或者传感器没上电 i2cdetect -y 1 确认地址
读出来数值不变 传感器处于休眠模式,没启动测量 检查是否写了控制寄存器(下一章会讲)
数值跳变很大 电源不稳定,或者接线太长 加一个 100nF 电容在 VCC 和 GND 之间

我的经验: 如果你发现数值一直不变,先别急着怀疑代码。用手捏一下传感器,温度原始值应该会变化。如果没变化,那八成是传感器没启动测量。我曾经被这个坑过,后来发现是忘了设置 ctrl_meas 寄存器。

4.6 小结

这一章咱们干了三件事:

  1. 理解了 BMP280 原始数据的存储方式(三个寄存器拼一个 20 位数)
  2. 写了一个完整的 Python 脚本,用 smbus2 读取原始值
  3. 学会了怎么排查常见问题

下一章,咱们就要把这些原始值转换成真正的温度和压力了。到时候你会看到,BMP280 的校准公式其实挺巧妙的——它用了一组出厂时烧录的校准系数,来修正传感器的非线性误差。

嗯,今天就到这儿。代码跑通了的话,记得在终端里按 Ctrl+C 停止程序。咱们下章见。