嵌入式人工智能(31-基于树莓派4B的气压传感器-BMP280)

1、气压传感器

气压传感器(Pressure Sensor)是一种用于测量气体压力的装置。它可以将气体压力转换为电信号输出,进而实现对气体压力的监测和控制。气压传感器广泛应用于工业自动化、气象观测、建筑监测、航空航天等领域。

气压传感器的工作原理一般分为压阻式和压电式两种。压阻式气压传感器利用气体压力使薄膜变形,进而改变电阻值,从而实现压力测量。压电式气压传感器则利用压电材料的特性,在气体压力作用下产生电荷移动,从而产生电压信号,实现压力测量。

气压传感器的特点包括精度高、响应快、体积小、重量轻、耐高温等。不同类型的气压传感器具有不同的测量范围和工作温度范围,用户可以根据具体需求选择适合的传感器。

在应用方面,气压传感器可以用于气象观测,监测大气压力变化;在工业自动化中,可以用于测量气体管道中的压力;在航空航天领域,可以用于飞机气压高度测量等。随着物联网和智能家居技术的发展,气压传感器也被广泛应用于智能手机、智能手表等便携式设备中,用于海拔测量、运动监测等功能。

2、BMP280

BMP280博世(bosch-sensortec)的一款高精度、小体积、超低能耗的气压传感器,特别适用于移动应用。其小尺寸和低功耗使其能够应用于电池供电的设备,如手机、GPS 模块或手表。它的性能卓越,绝对精度最低可以达到0.2Pa,并且耗电极低,只有2.7μA。BMP280采用强大的8-pin陶瓷无引线芯片承载(LCC)超薄封装,可以通过I2C,SPI总线直接与各种微处理器相连。

非常小,小到看不清,如果是BME280,可以测量温度。湿度、压强。我这边没有BME280,只有BMP280,BMP280不能测量湿度。

3、BMP280与树莓派连接

网上买的BMP280没有焊接排针,自己的电烙铁不好用, 焊的比较丑,有点拿不出手哈哈。以后同学们买电烙铁维修电子产品不建议买便宜的,耽误时间啊。

我们看这个传感器是采用I2C协议接线,也可以采用SPI协议,这个SPI协议我们没有介绍,也是串口协议的一种,支持全双工收发数据,但是连线比IIC复杂。这两种接线引脚我都说明下,最后采用IIC接线方式。

VCC:接3.3V供电,不要接5V

GND:接面包板GND

SCL:IIC时钟引脚;或者是SPI的Clock引脚,用于输入信号

SDA:IIC的数据引脚;或者为SPI的数据输出引脚,用于向开发板发送数据。

CSB:(SPI通信模式下用到的引脚,片选引脚,拉低后启用)

SDO:(传感器地址控制位)

IIC通讯方式:SCL --> 时钟线、SDI --> 数据线、SDO --> 片地址的LSB(最低加权位)、CSB --> Vdd 拉高
SPI通讯方式:SCL --> 时钟线、SDI --> 数据输入线(三线模式下为双向数据线)、SDO --> 数据输出线(3线模式下无用)、CSB --> 片选引脚,拉低后启用

实际上用IIC只要接4根线就可以了,其他的都不要管了。接上就找到该设备了。

4、实验代码与现象

(1)实验一:使用adafruit-circuitpython-bmp280库获取温度、压强和高度

pip install adafruit-circuitpython-bmp280

import board
import busio
import adafruit_bmp280
import time

# 初始化
i2c = busio.I2C(board.SCL, board.SDA)
bmp280 = adafruit_bmp280.Adafruit_BMP280_I2C(i2c)

# 设置本地的海平面压力
# 该传感器只能根据压力推测出海拔高度
bmp280.sea_level_pressure = 1013.25

# 打印读取到的数据
try:
    while True:
        print("\n温度: %0.1f C" % bmp280.temperature)
        print("压强: %0.1f hPa" % bmp280.pressure)
        print("高度:%0.2f meters" % bmp280.altitude)
        time.sleep(2)

except KeyboardInterrupt:
    print('程序结束!')

代码比较简单,这里有一个报错,同学们注意。在执行

bmp280 = adafruit_bmp280.Adafruit_BMP280_I2C(i2c)这句代码时,

引用的库文件代码里面写的IIC地址是0x77,但是我们的地址是0x76,改一下就行,主要是到哪改。找到adafruit_bmp280.py里面的adafruit_bmp280_I2C这个类里面的init,将0x77改为0x76即可。

温度值还是差不多的,不知道这个高度计算有什么依据吗,我只能将传感器抬高10cm,效果有那么一点点,应该是可以的,但是如果要用做无人机定高,注意误差能不能委以重任。

我这七七八八的东西实在太多,桌子实在太乱了。

这些数据仍然可以上传到远程服务器上面,我就不做了,很简单,只要几行代码。

(2)使用smbus库测量温度和压强

实际上这个传感器里面的的寄存器还是很多的,底层实现起来也比较复杂,只不过上面的adafruit-circuitpython-bmp280库里面的函数直接调用,内部细节完全不用管,Python代码写起来非常6。如果用smbus库,大家可以回想下PCF8591.有的内部功能还是要写函数实现的。

import time
import smbus

# BMP280 iic address.
BMP280_I2C_ADDRESS = 0x76        # SDO = 0

# Registers value
BMP280_ID_Value = 0x58           # BMP280 ID
BMP280_RESET_VALUE = 0xB6

# BMP280 Registers definition
BMP280_TEMP_XLSB_REG = 0xFC      # Temperature XLSB Register
BMP280_TEMP_LSB_REG = 0xFB       # Temperature LSB Register
BMP280_TEMP_MSB_REG = 0xFA       # Temperature LSB Register
BMP280_PRESS_XLSB_REG = 0xF9     # Pressure XLSB  Register
BMP280_PRESS_LSB_REG = 0xF8      # Pressure LSB Register
BMP280_PRESS_MSB_REG = 0xF7      # Pressure MSB Register
BMP280_CONFIG_REG = 0xF5         # Configuration Register
BMP280_CTRL_MEAS_REG = 0xF4      # Ctrl Measure Register
BMP280_STATUS_REG = 0xF3         # Status Register
BMP280_RESET_REG = 0xE0          # Softreset Register
BMP280_ID_REG = 0xD0             # Chip ID Register

# calibration parameters
BMP280_DIG_T1_LSB_REG = 0x88
BMP280_DIG_T1_MSB_REG = 0x89
BMP280_DIG_T2_LSB_REG = 0x8A
BMP280_DIG_T2_MSB_REG = 0x8B
BMP280_DIG_T3_LSB_REG = 0x8C
BMP280_DIG_T3_MSB_REG = 0x8D
BMP280_DIG_P1_LSB_REG = 0x8E
BMP280_DIG_P1_MSB_REG = 0x8F
BMP280_DIG_P2_LSB_REG = 0x90
BMP280_DIG_P2_MSB_REG = 0x91
BMP280_DIG_P3_LSB_REG = 0x92
BMP280_DIG_P3_MSB_REG = 0x93
BMP280_DIG_P4_LSB_REG = 0x94
BMP280_DIG_P4_MSB_REG = 0x95
BMP280_DIG_P5_LSB_REG = 0x96
BMP280_DIG_P5_MSB_REG = 0x97
BMP280_DIG_P6_LSB_REG = 0x98
BMP280_DIG_P6_MSB_REG = 0x99
BMP280_DIG_P7_LSB_REG = 0x9A
BMP280_DIG_P7_MSB_REG = 0x9B
BMP280_DIG_P8_LSB_REG = 0x9C
BMP280_DIG_P8_MSB_REG = 0x9D
BMP280_DIG_P9_LSB_REG = 0x9E
BMP280_DIG_P9_MSB_REG = 0x9F


class BMP180(object):
    def __init__(self, address=BMP280_I2C_ADDRESS):
        self._address = address
        self._bus = smbus.SMBus(1)    # 1: iic编号为1(根据自己的硬件接口选择对应的编号)
        # Load calibration values.
        if self._read_byte(BMP280_ID_REG) == BMP280_ID_Value: # read bmp280 id
            self._load_calibration()                          # load calibration data
            # BMP280_T_MODE_1 << 5 | BMP280_P_MODE_1 << 2 | BMP280_SLEEP_MODE;
            ctrlmeas = 0xFF
            # BMP280_T_SB1 << 5 | BMP280_FILTER_MODE_1 << 2;
            config = 0x14
            self._write_byte(BMP280_CTRL_MEAS_REG, ctrlmeas)  # write bmp280 config
            # sets the data acquisition options
            self._write_byte(BMP280_CONFIG_REG, config)
        else:
            print("Read BMP280 id error!rn")

    def _read_byte(self, cmd):
        return self._bus.read_byte_data(self._address, cmd)

    def _read_u16(self, cmd):
        LSB = self._bus.read_byte_data(self._address, cmd)
        MSB = self._bus.read_byte_data(self._address, cmd+1)
        return (MSB << 8) + LSB

    def _read_s16(self, cmd):
        result = self._read_u16(cmd)
        if result > 32767:
            result -= 65536
        return result

    def _write_byte(self, cmd, val):
        self._bus.write_byte_data(self._address, cmd, val)

    def _load_calibration(self):                           # load calibration data
        "load calibration"

        """ read the temperature calibration parameters """
        self.dig_T1 = self._read_u16(BMP280_DIG_T1_LSB_REG)
        self.dig_T2 = self._read_s16(BMP280_DIG_T2_LSB_REG)
        self.dig_T3 = self._read_s16(BMP280_DIG_T3_LSB_REG)
        """ read the pressure calibration parameters """
        self.dig_P1 = self._read_u16(BMP280_DIG_P1_LSB_REG)
        self.dig_P2 = self._read_s16(BMP280_DIG_P2_LSB_REG)
        self.dig_P3 = self._read_s16(BMP280_DIG_P3_LSB_REG)
        self.dig_P4 = self._read_s16(BMP280_DIG_P4_LSB_REG)
        self.dig_P5 = self._read_s16(BMP280_DIG_P5_LSB_REG)
        self.dig_P6 = self._read_s16(BMP280_DIG_P6_LSB_REG)
        self.dig_P7 = self._read_s16(BMP280_DIG_P7_LSB_REG)
        self.dig_P8 = self._read_s16(BMP280_DIG_P8_LSB_REG)
        self.dig_P9 = self._read_s16(BMP280_DIG_P9_LSB_REG)


    def compensate_temperature(self, adc_T):
        """Returns temperature in DegC, double precision. Output value of "1.23"equals 51.23 DegC."""
        var1 = ((adc_T) / 16384.0 - (self.dig_T1) / 1024.0) * (self.dig_T2)
        var2 = (((adc_T) / 131072.0 - (self.dig_T1) / 8192.0) *
                ((adc_T) / 131072.0 - (self.dig_T1) / 8192.0)) * (self.dig_T3)
        self.t_fine = var1 + var2
        temperature = (var1 + var2) / 5120.0
        return temperature

    def compensate_pressure(self, adc_P):
        """Returns pressure in Pa as double. Output value of "6386.2"equals 96386.2 Pa = 963.862 hPa."""
        var1 = (self.t_fine / 2.0) - 64000.0
        var2 = var1 * var1 * (self.dig_P6) / 32768.0
        var2 = var2 + var1 * (self.dig_P5) * 2.0
        var2 = (var2 / 4.0) + ((self.dig_P4) * 65536.0)
        var1 = ((self.dig_P3) * var1 * var1 / 524288.0 +
                (self.dig_P2) * var1) / 524288.0
        var1 = (1.0 + var1 / 32768.0) * (self.dig_P1)

        if var1 == 0.0:
            return 0  # avoid exception caused by division by zero

        pressure = 1048576.0 - adc_P
        pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1
        var1 = (self.dig_P9) * pressure * pressure / 2147483648.0
        var2 = pressure * (self.dig_P8) / 32768.0
        pressure = pressure + (var1 + var2 + (self.dig_P7)) / 16.0

        return pressure

    def get_temperature_and_pressure(self):
        """Returns pressure in Pa as double. Output value of "6386.2"equals 96386.2 Pa = 963.862 hPa."""
        xlsb = self._read_byte(BMP280_TEMP_XLSB_REG)
        lsb = self._read_byte(BMP280_TEMP_LSB_REG)
        msb = self._read_byte(BMP280_TEMP_MSB_REG)

        adc_T = (msb << 12) | (lsb << 4) | (
            xlsb >> 4)      # temperature registers data
        temperature = self.compensate_temperature(
            adc_T)    # temperature compensate

        xlsb = self._read_byte(BMP280_PRESS_XLSB_REG)
        lsb = self._read_byte(BMP280_PRESS_LSB_REG)
        msb = self._read_byte(BMP280_PRESS_MSB_REG)

        adc_P = (msb << 12) | (lsb << 4) | (
            xlsb >> 4)      # pressure registers data
        pressure = self.compensate_pressure(
            adc_P)          # pressure compensate
        return temperature, pressure


if __name__ == '__main__':

    import time

    print("BMP280 Test Program ...n")

    bmp280 = BMP180()

    while True:
        time.sleep(1)
        temperature, pressure = bmp280.get_temperature_and_pressure()
        print(' Temperature = %.2f C Pressure = %.3f kPa' %
              (temperature, pressure/1000))

你们慢慢看把,我先洗洗睡了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值