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 = 0x9Fclass BMP180(object):def __init__(self, address=BMP280_I2C_ADDRESS):self._address = addressself._bus = smbus.SMBus(1) # 1: iic编号为1(根据自己的硬件接口选择对应的编号)# Load calibration values.if self._read_byte(BMP280_ID_REG) == BMP280_ID_Value: # read bmp280 idself._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 = 0x14self._write_byte(BMP280_CTRL_MEAS_REG, ctrlmeas) # write bmp280 config# sets the data acquisition optionsself._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) + LSBdef _read_s16(self, cmd):result = self._read_u16(cmd)if result > 32767:result -= 65536return resultdef _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 + var2temperature = (var1 + var2) / 5120.0return temperaturedef 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.0var2 = var1 * var1 * (self.dig_P6) / 32768.0var2 = var2 + var1 * (self.dig_P5) * 2.0var2 = (var2 / 4.0) + ((self.dig_P4) * 65536.0)var1 = ((self.dig_P3) * var1 * var1 / 524288.0 +(self.dig_P2) * var1) / 524288.0var1 = (1.0 + var1 / 32768.0) * (self.dig_P1)if var1 == 0.0:return 0 # avoid exception caused by division by zeropressure = 1048576.0 - adc_Ppressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1var1 = (self.dig_P9) * pressure * pressure / 2147483648.0var2 = pressure * (self.dig_P8) / 32768.0pressure = pressure + (var1 + var2 + (self.dig_P7)) / 16.0return pressuredef 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 datatemperature = self.compensate_temperature(adc_T) # temperature compensatexlsb = 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 datapressure = self.compensate_pressure(adc_P) # pressure compensatereturn temperature, pressureif __name__ == '__main__':import timeprint("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))
你们慢慢看把,我先洗洗睡了!