BME280 Environmental Sensor
来自Waveshare Wiki
| |||||||||||||||||||||
| |||||||||||||||||||||
说明
产品概述
这是一款环境传感器,可感知环境温度、湿度和大气压强,支持I2C和SPI接口,兼容3.3V/5V电平,小尺寸,低功耗,高精度和稳定性,适用于环境监测、天气预测、海拔高度监测和物联网应用场景。
特点
- 支持I2C接口通信,可设置从机地址
- 支持SPI接口通信,默认为I2C接口,可通过I/O口设置为SPI
- 板载电平转换电路,可兼容3.3V/5V的工作电平
- 提供完善的配套资料手册(Raspberry/Arduino/STM32示例程序和用户手册等)
产品参数
工作电压: | 5V/3.3V |
通信接口: | I2C/SPI |
温度范围: | -40~85°C (分辨率0.01°C,误差±1°C) |
湿度范围: | 0~100%RH (分辨率0.008%RH,±3% RH) |
压力范围: | 300~1100 hPa (分辨率0.18Pa,误差±1 hPa) |
产品尺寸: | 27mmx20mm |
过孔直径: | 2.0mm |
接口定义
I2C接口 | ||||
功能引脚 | Arduino 接口 | STM32接口 | Raspberry | 描述 |
VCC | 3.3V/5V | 3.3V /5V | 3.3V /5V | 电源正 |
GND | GND | GND | GND | 电源地 |
SDA | A4 | PB7 | SDA | I2C数据线 |
SCL | A5 | PB6 | SCL | I2C时钟线 |
ADDR | NC/GND | NC/GND | NC/GND | 地址片选(默认为高电平): 为高电平时,地址为:0x77 为低电平时,地址为:0x76 |
CS | NC | NC | NC | NC |
SPI接口 | ||||
功能引脚 | Arduino 接口 | STM32接口 | Raspberry | 描述 |
VCC | 3.3V /5V | 3.3V /5V | 3.3V /5V | 3.3V电源正 |
GND | GND | GND | GND | 电源地 |
MOSI | D11 | PA7 | MOSI | SPI数据输入 |
SCK | D13 | PA5 | SCK | SPI时钟输入 |
MISO | D12 | PA6 | MISO | SPI数据输出 |
CS | D10 | PB6 | 27 | SPI片选,低电平有效 |
用于树莓派
安装必要的函数库
- 需要安装必要的函数库,否则以下的示例程序可能无法正常工作。安装方法详见:
https://www.waveshare.net/wiki/Pioneer600_Datasheets
- 在官网上找到对应产品,在产品资料打开下载路径,在wiki中下载示例程序:
- 得到解压包,解压得到如下:
- 将Raspberry文件夹拷至树莓派。
前置工作及演示
前置工作
- 执行如下命令进行树莓派配置:
sudo raspi-config
- 选择Interfacing Options -> I2C -> yes 启动I2C内核驱动
- 选择Interfacing Options -> SPI -> yes启动SPI内核驱动
- 保存退出后,重启树莓派:
sudo reboot
- 重启后,运行命令查看,I2C,SPI模块是否已启动:
lsmod
- 将会有如下的打印信息:
- 如果显示i2c_bcm2835和spi_bcm2835则表示I2C,SPI模块已启动。
- 将BME280模块按照前述I2C总线接口说明连接至树莓派。
- BME280模块的默认I2C器件地址是0x77,若将ADDR接地则器件地址更变为0x76。
- 安装i2c-tools工具进行确认:
sudo apt-get install i2c-tools
- 查询已连接的I2C设备
i2cdetect -y 1
- 将会有如下打印信息:
- 若显示77则表示BME280模块成功连接至树莓派成功。
- 若将ADDR连接至GND则打印出76:
注意:以上测试确保I2C总线上没有其它地址和该器件地址重合的设备。如果以上测试成功则I2C模块加载成功,同时BME280模块成功连接至树莓派。
同时,BME280模块支持SPI驱动,可参考SPI接口说明部分将BME280连接至树莓派。
演示
- 成功将BME280模块连接至树莓派后:
- 如果采用I2C驱动:则先确定I2C器件地址,BME280模块默认I2C器件地址为0X77,若将ADDR接地(或用0欧姆电阻将焊桥连接),则其I2C器件地址变更为0X76。
- 打开main.c文件:
- 进入到BME280-Environmental-Sensor-Demo-Code路径下:
cd BME280-Environmental-Sensor-Demo-Code
- 打开main.c文件:
vim main.c
- 确保main.c中的USEIIC的宏定义为1,以采用I2C驱动。
- 同时检查main.c中的I2C器件地址,确保和当前BME280模块器件地址一致(默认I2C器件地址为0x77,若将ADDR接地则其器件地址为0x76):
- 如果采用SPI驱动:则将BME280模块按照接口说明中的SPI总线接线方式进行接线,并将main.c文件中的USEIIC宏定义改为0。
- 保存并退出编辑,然后重新编译:
sudo make clean sudo make
- 运行:
sudo ./bme280
- 将显示如下数据:
- 从左至右分别显示了BME280测得的温度(摄氏度),大气压(百帕斯卡),相对湿(%RH)。若未成功显示数据,或数据显示不正常请检查连线,通信方式,以及器件地址是否有误。
用于Arduino
- 将下载的示例程序的压缩包解压后,将Arduino文件夹下的BME280-Arduino-Library拷贝至Arduino第三方库目录下.之后重启ArduinoIDE,进入并打开文件->实例->BME280_Libreay->bme280test
- 按照接口说明中Arduino接口部分接线。
- 默认采用I2C驱动BME280模块,默认I2C器件地址为0X77。
- 如需采用SPI驱动BME280模块,请将bme280test.ino中的宏定义USEIIC改为0:
- 如需更改I2C器件的地址为0X76,则将ADDR引脚接至GND(或用0欧姆电阻将焊桥连接),同时将Adafruit.h中的BME280_ADDRESS器件地址改为0X76:
- 如需获取准测量的准确海拔,还需测得当地海平面的大气压,并修改SEALEVELPRESSURE_HPA宏定义:
- 在正确接线,确定通信方式以及器件地址之后,编译,下载到Arduino。
- 打开:工具 -> 串口监视器,选择波特率为115200,可得如下信息
- 其中从左至右分别显示了BME280传感器测得的温度(摄氏度),大气压(百帕斯卡),相对湿度(%RH),海拔(m)。
- 若未成功显示数据,或数据显示不正常请检查连线,通信方式,以及器件地址是否有误。
用于STM32
- 将下载的示例程序的压缩包解压后,打开STM32文件夹下的STM32-STM32_BME280->USR路径下的工程文件:按照接口说明中STM32接口部分接线。默认采用I2C驱动BME280模块,默认I2C器件地址为0X77。
- 如需采用SPI驱动BME280模块,请将main.c中的宏定义USEIIC改为0:
- 如需更改I2C器件的地址为0X76,则将ADDR引脚接至GND(或用0欧姆电阻将焊桥连接),并将dev.dev_id = BME280_I2C_ADDR_SEC;注释:
- 编译,下载,本次采用的芯片是STM32F103RBT6,采用USART2输出获得的传感器数据。
- 打开串口调试助手,选择对应的COM口,设置波特率为115200,数据位8位,停止位1位,无奇偶校验位,可得如下数据:
- 其中从左至右分别显示了BME280传感器测得的温度(摄氏度),大气压(百帕斯卡),相对湿度(%RH)。
- 若未成功显示数据,或数据显示不正常请检查连线,通信方式,以及器件地址是否有误。
代码分析
- 例程主要采用了官方(Bosch Sensortec)提供的库:https://github.com/BoschSensortec/BME280_driver
针对不同平台实现其底层函数,供上层调用。
- 采用SPI驱动BME280的初始化部分为:
struct bme280_dev dev; int8_t rslt = BME280_OK; /* Sensor_0 interface over SPI with native chip select line */ dev.dev_id = 0; dev.intf = BME280_SPI_INTF; dev.read = user_spi_read; dev.write = user_spi_write; dev.delay_ms = user_delay_ms; rslt = bme280_init(&dev);
- 采用I2C驱动BME280初始化部分:
struct bme280_dev dev; int8_t rslt = BME280_OK; dev.dev_id = BME280_I2C_ADDR_PRIM; dev.intf = BME280_I2C_INTF; dev.read = user_i2c_read; dev.write = user_i2c_write; dev.delay_ms = user_delay_ms; rslt = bme280_init(&dev);
- 其中bme280_dev为官方库中给定的BME280设备结构体,用于初始化以及获取数据用,需要针对不同的平台实现以下函数:
user_i2c_read() user_i2c_write() user_spi_read() user_spi_write() user_delay_ms()
- 并将该函数的函数指针传递给结构体bme280_dev。
读取BME280数据的函数为:
int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) int8_t stream_sensor_data_normal_mode(struct bme280_dev *dev)
- 并且以上函数均调用了打印函数:
void print_sensor_data(struct bme280_data *comp_data)
- 不同平台的延时函数,I2C读,I2C写,SPI读,SPI写的实现思路为:
void user_delay_ms(uint32_t period) { /* * Return control or wait, * for a period amount of milliseconds */ } int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) { int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ /* * The parameter dev_id can be used as a variable to select which Chip Select pin has * to be set low to activate the relevant device on the SPI bus */ /* * Data on the bus should be like * |----------------+---------------------+-------------| * | MOSI | MISO | Chip Select | * |----------------+---------------------|-------------| * | (don't care) | (don't care) | HIGH | * | (reg_addr) | (don't care) | LOW | * | (don't care) | (reg_data[0]) | LOW | * | (....) | (....) | LOW | * | (don't care) | (reg_data[len - 1]) | LOW | * | (don't care) | (don't care) | HIGH | * |----------------+---------------------|-------------| */ return rslt; } int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) { int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ /* * The parameter dev_id can be used as a variable to select which Chip Select pin has * to be set low to activate the relevant device on the SPI bus */ /* * Data on the bus should be like * |---------------------+--------------+-------------| * | MOSI | MISO | Chip Select | * |---------------------+--------------|-------------| * | (don't care) | (don't care) | HIGH | * | (reg_addr) | (don't care) | LOW | * | (reg_data[0]) | (don't care) | LOW | * | (....) | (....) | LOW | * | (reg_data[len - 1]) | (don't care) | LOW | * | (don't care) | (don't care) | HIGH | * |---------------------+--------------|-------------| */ return rslt; } int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) { int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ /* * The parameter dev_id can be used as a variable to store the I2C address of the device */ /* * Data on the bus should be like * |------------+---------------------| * | I2C action | Data | * |------------+---------------------| * | Start | - | * | Write | (reg_addr) | * | Stop | - | * | Start | - | * | Read | (reg_data[0]) | * | Read | (....) | * | Read | (reg_data[len - 1]) | * | Stop | - | * |------------+---------------------| */ return rslt; } int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) { int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ /* * The parameter dev_id can be used as a variable to store the I2C address of the device */ /* * Data on the bus should be like * |------------+---------------------| * | I2C action | Data | * |------------+---------------------| * | Start | - | * | Write | (reg_addr) | * | Write | (reg_data[0]) | * | Write | (....) | * | Write | (reg_data[len - 1]) | * | Stop | - | * |------------+---------------------| */ return rslt; }
综上,基于官方库,针对不同平台,获取BME280数据的基本流程为:
- 第一步:不同平台的系统及外设初始化。
- 第二步:实现不同平台的I2C读,I2C写,SPI读,SPI写,延时函数,并将函数指针赋值给bme280_dev结构体成员变量,将该结构体指针传递给初始*化函数int8_t bme280_init(struct bme280_dev *dev),初始化BME280设备。
- 第三步:调用int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev)或
int8_t stream_sensor_data_normal_mode(struct bme280_dev *dev)函数获取BME280传感器数据并打印到上位机或控制台。
FAQ
气压传感器计算得到的高度一般用在短周期内的相对值。比如坐垂直电梯,电梯启动前记录一个高度,电梯上升到3层,记录一个高度,两个高度的高度差是准确的。
如果需要用在绝对场合,可以输入当前位置的高度作为计算的初始值,然后运动观察高度变化就是准确的。不过如果时间长了,也会容易出现高度漂移的问题。
如果项目要求长时间获取准确高度值且频率要求高,就需要融合其他传感器进行处理,比如GPS。