利用AE-BME280和Raspberry Pi读取温度、湿度和压力值

这篇文章来源于DevicePlus.com英语网站的翻译稿。bme280

在本教程中,我们将使用一个多功能模块,协助Raspberry Pi同时测量温度、湿度和气压三种参数。

该项目需要焊接!如上图所示,该部件带有一个单独的排针,因此我们需要将其焊接到面包板上。

AE-BME280

bme280

图1:AE-BME280 / © Akizuki Denshi

使用BME280的温度/湿度/压力传感器模块套件BME280(日语)
凭借搭载Bosch Sensortec BMP280的传感器模块,您可以同时测量温度、湿度和气压。该模块还可以通过I2C或SPI与微控制器通信。

我们将在本教程中使用这款超紧凑型AE-BME280压力传感器(尺寸:16x10mm)。该模块采购于日本零件供应商Akizuki Denshi,您也可以使用具有相同芯片的Adafruit BME280模块。请注意,Adafruit的引脚布局略有不同,因此连线时请务必参考其技术规格书。

Adafruit BME280 技术规格书

BME280——一块位于元件中心的微小银芯片——承担了大部分工作。该模块表面上还有一个非常小的开口,其作用是读取数值,因此切勿遮盖这个开口。

AE-BME280板和排针本来就是分开的。连接Raspberry Pi的最简单方法就是将两者组装在一起,如图1所示。这需要焊接。我购买的排针有10个引脚,但是连接AE-BME280只需6个引脚,所以应剪掉第6个引脚后面的排针。

技术规格请参见AE-BME280的日语手册

您可以用I2C或SPI进行通信。由于我之前已经用过SPI,所以这次我将尝试使用I2C。

I2C – 维基百科
I2C(集成电路总线)是一种由Philips Semiconductor(现为NXP Semiconductors)发明的串行总线。I2C代表I-平方-C。由于纯文本环境中的字符限制,我们将其称为I2C或IIC。该协议通常用于将低速外围IC连至主板、嵌入式系统和移动电话等设备。

bme280

图2:引脚编号和功能–摘自AE-BME280技术规格书

连接I2C或SPI是不同的,所以我们必须注意引脚接法。请参阅AE-BME280 技术规格书 (日语)或Adafruit BME280 技术规格书(英语)

如图2所示,使用I2C时,我们需要焊接 J3 跳线。我们必须在此跳线处填充焊锡。请注意,这仅适用于AE-BME280芯片。Adafruit芯片不需要设置此跳线。

焊接!

bme280

图3:焊接设备

现在,是时候焊接了!首先应加热烙铁。

焊锡 – 维基百科
焊锡是一种主要由铅和锡组成的合金,与电烙铁配合使用。主要用于连接金属元件,以及将电气元件焊接到电路板上。根据其成分,焊锡会在4-10度时变成超导体。

我在这个项目中用的是这种焊锡。这种焊锡非常柔韧,容易泄漏,因此只能一点一点地送锡。我们还应准备一个吸锡器,以防万一。如果送锡过多,可以用吸锡器吸掉多余的焊锡,所以要小心!

bme280

图4:焊接J3

首先,我们应焊接图4所示的J3跳线。J3与相邻引脚靠的很近,所以要小心不要焊接在一起。送锡时要小心仔细!

 

bme280

图5:焊接排针

下一步是连接排针。我从电路板背面焊接排针。引脚之间的间隙非常小,因此很难将电烙铁塞入。电路板两端引脚的焊锡结块示例如图5所示。

焊接技巧是先用烙铁头稍稍加热引脚,然后再送锡。如果烙铁尖过热,焊锡会燃烧并形成结块。因此,我建议焊完一个引脚后,从电源插座上拔下电烙铁并冷却后再焊接下一个引脚。不必着急。小心不要将引脚焊接在一起。慢慢来!

bme280

图6:连至面包板的AE-BME280

完成!排针焊接完毕,现在电路板垂直插在面包板上。

焊接时,我不小心碰到了排针末端并稍微烫了一下,但幸运的是这并没有影响读数。

接线

现在,让我们将Raspberry Pi连接到AE-BME280。连接示意图如图7所示,因为我们使用的是I2C通信。

bme280

图7:I2C连接方法–摘自AE-BME280技术规格书

在Raspberry Pi上,“SDA”连至GPIO2(引脚3),“SCL”连到GPIO3(引脚5)。VDD连接到引脚1,这样前3个GPIO引脚按顺序排列(参见图8)。接线时容易记忆。

 

bme280

图8:接线示意图

我将AE-BME280上的引脚5(SDO)连至GND,您也可以将其连至VDD。(请注意,如果这样做,数据收集地址会发生变化)。

设置 Raspberry Pi

Raspberry Pi默认禁用I2C。启用I2C的方法与启用SPI的方法相同,请参阅上一个教程:Raspberry Pi WebIOPi物联网,模拟输入编程。在菜单中选择[Preferences] – [Raspberry Pi Configuration],然后打开“Settings ”屏幕。

bme280

点击[Interfaces]选项卡,将[I2C]设为[Enable]

必须重新启动系统该设置才能生效,因此请在弹出窗口中单击“Yes”。重启后,I2C传输已启用。

bme280

(OS: 2015年11月21日发布的Raspbian Jessie版本)

接下来,我们安装使用I2C所需的软件包。我们需要在命令行中使用[i2c-tools],在Python中使用[python-smbus]。

安装命令
sudo apt-get install i2c-tools
sudo apt-get python-smbus

如果运行命令“i2cdetect”,系统会检测通过I2C方式连接的所有设备。

sudo i2cdetect -y 1

bme280

76是十六进制数;代表0x76。

注:选择I2C地址时,如果电路板(SDO)上的引脚5连至GND,那么默认为[0x76];如果连至VDD,则默认为[0x77]。

我将SDO连接到GND,因此显示0x76,但如果连至VDD,则会显示0x77。

此外,i2Cdetect命令中的最后一个参数取决于Raspberry Pi的版本。Revision 1(2012年10月14日之前发货的Raspberry Pi Model B)使用0,而Revision 2指定使用1。我用的是Raspberry Pi 2 Model B,因此参数值为1。

我运行程序时发生了以下错误:

bme280

发生错误后,我查看了dev目录,看到有一个名为[i2c-1]而不是[i2c-0]的文件。我无法打开这个文件,但我认为该文件包含记录的测量值。

sudo i2cdump -y 1 0x76

bme280

上图是我用i2Cdump命令输出寄存器值的结果。看起来设备读取了很多数值,但是我无法分辨哪些值来自哪里以及为什么是这样子的。

我很难对这些值进行转换/计算,所以我从Switch Science库中借用了一些Python源代码:

SWITCHSCIENCE/BME280

单击右上角的“Download ZIP”链接,将Python27文件夹中的“bme_280_sample.py”文件放在Raspberry Pi的相应位置。注意:此程序需要“python-smbus”软件包才能运行。

python /home/pi/bme280_sample.py

准备工作完成后,运行程序!成功运行之后,您会看到三行输出:温度、压力和湿度。

bme280

注意:您必须具有root权限才能运行smbus软件包。和往常一样,我尝试用PHP运行,但是出现错误,所以我放弃了。bme_280_sample.py 源代码中有很多复杂的计算,虽然我Python经验很少,但是我仍然设法修改了输出部分。我的部分定制代码如下:

/home/pi/bme280_custom.py

#coding: utf-8

import smbus
import time

bus_number  = 1
i2c_address = 0x76

bus = smbus.SMBus(bus_number)

digT = []
digP = []
digH = []

t_fine = 0.0

def writeReg(reg_address, data):
    bus.write_byte_data(i2c_address,reg_address,data)

def get_calib_param():
    calib = []

    for i in range (0x88,0x88+24):
        calib.append(bus.read_byte_data(i2c_address,i))
    calib.append(bus.read_byte_data(i2c_address,0xA1))
    for i in range (0xE1,0xE1+7):
        calib.append(bus.read_byte_data(i2c_address,i))

    digT.append((calib[1] << 8) | calib[0])
    digT.append((calib[3] << 8) | calib[2])
    digT.append((calib[5] << 8) | calib[4])
    digP.append((calib[7] << 8) | calib[6])
    digP.append((calib[9] << 8) | calib[8])
    digP.append((calib[11]<< 8) | calib[10])
    digP.append((calib[13]<< 8) | calib[12])
    digP.append((calib[15]<< 8) | calib[14])
    digP.append((calib[17]<< 8) | calib[16])
    digP.append((calib[19]<< 8) | calib[18])
    digP.append((calib[21]<< 8) | calib[20])
    digP.append((calib[23]<< 8) | calib[22])
    digH.append( calib[24] )
    digH.append((calib[26]<< 8) | calib[25])
    digH.append( calib[27] )
    digH.append((calib[28]<< 4) | (0x0F & calib[29]))
    digH.append((calib[30]<< 4) | ((calib[29] >> 4) & 0x0F))
    digH.append( calib[31] )

    for i in range(1,2):
        if digT[i] & 0x8000:
            digT[i] = (-digT[i] ^ 0xFFFF) + 1

    for i in range(1,8):
        if digP[i] & 0x8000:
            digP[i] = (-digP[i] ^ 0xFFFF) + 1

    for i in range(0,6):
        if digH[i] & 0x8000:
            digH[i] = (-digH[i] ^ 0xFFFF) + 1 

def readData():
    data = []
    for i in range (0xF7, 0xF7+8):
        data.append(bus.read_byte_data(i2c_address,i))
    pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
    temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
    hum_raw  = (data[6] << 8)  |  data[7]

    #compensate_T(temp_raw)
    #compensate_P(pres_raw)
    #compensate_H(hum_raw)
    t = compensate_T(temp_raw)
    p = compensate_P(pres_raw)
    h = compensate_H(hum_raw)
    return p + "," + t + "," + h

def compensate_P(adc_P):
    global  t_fine
    pressure = 0.0

    v1 = (t_fine / 2.0) - 64000.0
    v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * digP[5]
    v2 = v2 + ((v1 * digP[4]) * 2.0)
    v2 = (v2 / 4.0) + (digP[3] * 65536.0)
    v1 = (((digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8)  + ((digP[1] * v1) / 2.0)) / 262144
    v1 = ((32768 + v1) * digP[0]) / 32768

    if v1 == 0:
        return 0
    pressure = ((1048576 - adc_P) - (v2 / 4096)) * 3125
    if pressure < 0x80000000:         pressure = (pressure * 2.0) / v1     else:         pressure = (pressure / v1) * 2     v1 = (digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096     v2 = ((pressure / 4.0) * digP[7]) / 8192.0     pressure = pressure + ((v1 + v2 + digP[6]) / 16.0)        #print "pressure : %7.2f hPa" % (pressure/100)     return "%7.2f" % (pressure/100)     def compensate_T(adc_T):     global t_fine     v1 = (adc_T / 16384.0 - digT[0] / 1024.0) * digT[1]     v2 = (adc_T / 131072.0 - digT[0] / 8192.0) * (adc_T / 131072.0 - digT[0] / 8192.0) * digT[2]     t_fine = v1 + v2     temperature = t_fine / 5120.0     #print "temp : %-6.2f ℃" % (temperature)     return "%.2f" % (temperature)   def compensate_H(adc_H):     global t_fine     var_h = t_fine - 76800.0     if var_h != 0:         var_h = (adc_H - (digH[3] * 64.0 + digH[4]/16384.0 * var_h)) * (digH[1] / 65536.0 * (1.0 + digH[5] / 67108864.0 * var_h * (1.0 + digH[2] / 67108864.0 * var_h)))     else:         return 0     var_h = var_h * (1.0 - digH[0] * var_h / 524288.0)     if var_h > 100.0:
        var_h = 100.0
    elif var_h < 0.0:
        var_h = 0.0
    #print "hum : %6.2f %" % (var_h)
    return "%.2f" % (var_h)

def setup():
    osrs_t = 1            #Temperature oversampling x 1
    osrs_p = 1            #Pressure oversampling x 1
    osrs_h = 1            #Humidity oversampling x 1
    mode   = 3            #Normal mode
    t_sb   = 5            #Tstandby 1000ms
    filter = 0            #Filter off
    spi3w_en = 0            #3-wire SPI Disable

    ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode
    config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en
    ctrl_hum_reg  = osrs_h

    writeReg(0xF2,ctrl_hum_reg)
    writeReg(0xF4,ctrl_meas_reg)
    writeReg(0xF5,config_reg)

setup()
get_calib_param()

if __name__ == '__main__':
    try:
        readData()
    except KeyboardInterrupt:
        pass

 

我并没有修改太多代码,只是对主要的“处理”部分进行了一些小的调整。我将“print”改为“return”并进行了相关编辑,使得程序以CSV格式返回数值(带逗号)。

/home/pi/bme280.py

#coding: utf-8

 

import bme280_custom

import datetime

import os

 

dir_path = '/home/pi/bme280-data'

 

now = datetime.datetime.now()

filename = now.strftime('%Y%m%d')

label = now.strftime('%H:%M')

csv = bme280_custom.readData()

 

if not os.path.exists('/home/pi/bme280-data'):

    os.makedirs('/home/pi/bme280-data')

f = open('/home/pi/bme280-data/'+filename+'.csv','a')

f.write("'"+label+"',"+csv+"\n")

f.close()

 

我创建了另一个py,从之前修改过的“bme280_custom.py”中调用readData()函数。这会将读取的数值保存在CSV文件中。文件的设置如下:记录一整天的数据,以日期作为文件名保存。

我用cron登记了这个程序并进行了设置,让它定期运行。现在完成了!
sudo crontab -e

0-59/10 * * * * /home/pi/bme280.py

注:我将其设置为每10分钟运行一次。

接下来,我将创建一个PHP文件来显示数据。我用 DS18B20 温度传感器制作温度计时做过类似事情。


/var/www/html/bme280.php

 

<?php

$today  = date("Ymd");

$csv_dir  = '/home/pi/bme280-data/';

$csv_file = $today.'.csv';

$grapgh   = '';

if (($handle = fopen($csv_dir.$csv_file, "r")) !== false) {

    while (($line = fgets($handle)) !== false) {

    $grapgh .= '['.rtrim($line).'],'.PHP_EOL;

    }

    fclose($handle);

}else{

    echo 'no data';

}

?>

<html>

<head>

<script type="text/javascript" src="https://www.google.com/jsapi"></script>

<script type="text/javascript">

    google.load("visualization", "1", {packages:["table"]});

    google.setOnLoadCallback(drawTable);

 

    function drawTable() {

    var data = new google.visualization.DataTable();

    data.addColumn('string', 'Time');

    data.addColumn('number', 'Pressure');

    data.addColumn('number', 'Temperature');

    data.addColumn('number', 'Humidity');

    data.addRows([

 

<?php echo $grapgh; ?>

 

    ]);

 

      var table = new google.visualization.Table(document.getElementById('table_div'));

      table.draw(data, {showRowNumber: true});

    }

</script>

</head>

<body>

 

<div id="table_div"></div>

 

</body>

</html>

 

我创建了一个简单的PHP文件,在表中显示相关数据(您必须安装“php5”软件包才能使用PHP)。

bme280

通过这种方式,我可以用浏览器——导航至 https://localhost/bme280.php ——查看CSV文件的内容。即使每隔10分钟,压力也会发生巨大变化!

Raspbian最新版本预装了一个名为“LibreOffice”的办公套件。如果您只是想查看数据,那么可以使用“LibreOffice Calc”(双击CSV文件),然后您会看到如下内容:

总结

今天,我们用AE-BME280传感器构建了一个简单模块来测量多个数值(压力、湿度和温度)。这么小的传感器可以测量多达三个不同的参数,真是太神奇了。传感器非常微小,但非常强大!

这个项目还让我提高了焊接技巧。AE-BME280上的引脚非常小,彼此非常靠近,我当时还担心可能会把多个引脚焊接在一起。最后,成品的引脚焊接得很好,我很高兴。需要焊接的项目可能比较困难,但是值得!

DevicePlus 编辑团队
DevicePlus 编辑团队

设备升级版适用于所有热爱电子和机电一体化的人。

Related post

  1. raspberry pi projects

    寻找实用的Raspberry Pi项目? 制作一个智能伞架!

  2. DIY Raspberry Pi 无人机:机械构造–第一部分(续)

  3. 使用Node-RED和Raspberry Pi实现按下按钮即可发布天气信息

  4. 使用Crystal Signal Pi第3部分:使用Raspberry Pi创建警示灯解决方案—创建…

  5. raspberry pi motion control lamp

    如何用Raspberry Pi制作动作控制感应灯

  6. raspberry pi

    如何将Raspberry Pi用作Web服务器?

  7. raspberry pi

    如何将Raspberry Pi用作DNS服务器?

  8. arduino code raspberry pi

    如何在Raspberry Pi运行Arduino程序

  9. Crystal Signal Pi middleware

    使用Crystal Signal Pi第2部分: 使用Raspberry Pi创建警示灯解决方案 —…

TECH INFO

  • 重点必看
  • 技术分享
  • Arduino入门指南

基础知识

  • SiC功率元器件
  • Si功率元器件
  • 热设计
  • 仿真
  • 开关噪声-EMC
  • AC/DC
  • DC/DC
  • 电机
  • 传递函数

工程技巧


PICK UP!

  1. 模块配置
  2. ROHM开发出业界先进的第4代低导通电阻SiC MOSFET:支持xEV/EV主机逆变器和电池提高电压
  3. 刘铭
  4. 以纳米级输出电容实现稳定控制的Nano Cap™技术:无需输出电容器的线性稳压器
  5. “第三代 行驶中无线供电轮毂电机”开发成功:超小型SiC模块 助力实现无需担心充电的EV
  6. arduino explorer rover
  7. 作为车载用二次电源而开发的同步整流降压型DC/DC转换器 : 车载设备中二次电源的优点
PAGE TOP