一、目的
这一节我们来学习如何使用合宙ESP32 C3,连接BMP180压力传感器模块,使用ST7735屏幕进行显示。下面我们一起来学习一下吧!
前面我们学习了BMP280压力传感器模块,大家先看一下这个文章,我们在这个的基础上再来学习BMP180。
二、环境
ESP32 C3开发板(MicroPython v1.19.1 on 2022-06-18)+ BMP180压力传感器模块 + BMP280压力传感器模块 + TFT ST7735屏幕 + 几根杜邦线 + Win10商业版
ESP32 C3和各模块接线方法:
ESP32 C3连接ST7735屏幕的方法,请参考物联网开发124这个文章。
BMP180和BMP280接线如下:
模块介绍:
1百帕(hpa)=100帕斯卡(pa),h就是hundred的意思,就是100,所以1h=100,即1hpa等于100pa。百帕是一个气压单位。世界气象组织决定,今后气压单位既可用“百帕”,也可用“毫巴”,两者暂时并用,最后逐步统一使用“百帕”。简写符号hPa,即为100个帕,正好与1毫巴相等。按国际标准组织规定:1帕=1牛顿/平方米,标准大气压=760mm汞柱=76cm汞柱=1.01325×10^5Pa=10.336m水柱。
标准大气压值的规定,是随着科学技术的发展,经过几次变化的。最初规定在摄氏温度0℃、纬度45°、晴天时海平面上的大气压强为标准大气压,其值大约相当于760mm汞柱高。后来发现,在这个条件下的大气压强值并不稳定,它受风力、温度等条件的影响而变化。于是就规定760mm汞柱高为标准大气压值。但是后来又发现760mm汞柱高的压强值也是不稳定的,汞的密度大小受温度的影响而发生变化;g值也随纬度而变化,为了确保标准大气压是一个定值,1954年第十届国际计量大会决议声明,规定标准大气压值为,1标准大气压=101325 N/㎡。
三、bmp180驱动
'''
bmp180 is a micropython module for the Bosch BMP180 sensor. It measures
temperature as well as pressure, with a high enough resolution to calculate
altitude.
'''
from ustruct import unpack as unp
from machine import I2C, Pin
import math
import time
# BMP180 class
class BMP180():
#Init i2c:协议 addr:bmp地址 oversample:过采样设置0-3 Baseline:海拔基线 默认101325
def __init__(self, i2c, addr, oversample, Baseline):
# create i2c obect
self._bmp_i2c = i2c
self._bmp_addr = addr
self.oversample = oversample
self.Baseline = Baseline
self.oversample_sett = self.oversample #过采样0-3
self.baseline = self.Baseline#基线 海拔线 101325 默认
self.chip_id = self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xD0, 2)
# read calibration data from EEPROM
self._AC1 = unp('>h', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xAA, 2))[0]
self._AC2 = unp('>h', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xAC, 2))[0]
self._AC3 = unp('>h', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xAE, 2))[0]
self._AC4 = unp('>H', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xB0, 2))[0]
self._AC5 = unp('>H', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xB2, 2))[0]
self._AC6 = unp('>H', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xB4, 2))[0]
self._B1 = unp('>h', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xB6, 2))[0]
self._B2 = unp('>h', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xB8, 2))[0]
self._MB = unp('>h', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xBA, 2))[0]
self._MC = unp('>h', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xBC, 2))[0]
self._MD = unp('>h', self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xBE, 2))[0]
# settings to be adjusted by user
self.oversample_setting = 3
self.baseline = 101325.0
# output raw
self.UT_raw = None
self.B5_raw = None
self.MSB_raw = None
self.LSB_raw = None
self.XLSB_raw = None
self.gauge = self.makegauge() # Generator instance
for _ in range(128):
next(self.gauge)
time.sleep_ms(1)
def compvaldump(self):
'''
Returns a list of all compensation values
'''
return [self._AC1, self._AC2, self._AC3, self._AC4, self._AC5, self._AC6,
self._B1, self._B2, self._MB, self._MC, self._MD, self.oversample_setting]
# gauge raw
def makegauge(self):
'''
Generator refreshing the raw measurments.
'''
delays = (5, 8, 14, 25)
while True:
self._bmp_i2c.writeto_mem(self._bmp_addr, 0xF4, bytearray([0x2E]))
t_start = time.ticks_ms()
while (time.ticks_ms() - t_start) <= 5: # 5mS delay
yield None
try:
self.UT_raw = self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xF6, 2)
except:
yield None
self._bmp_i2c.writeto_mem(self._bmp_addr, 0xF4, bytearray([0x34+(self.oversample_setting << 6)]))
t_pressure_ready = delays[self.oversample_setting]
t_start = time.ticks_ms()
while (time.ticks_ms() - t_start) <= t_pressure_ready:
yield None
try:
self.MSB_raw = self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xF6, 1)
self.LSB_raw = self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xF7, 1)
self.XLSB_raw = self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xF8, 1)
except:
yield None
yield True
def blocking_read(self):
if next(self.gauge) is not None: # Discard old data
pass
while next(self.gauge) is None:
pass
@property
def oversample_sett(self):
return self.oversample_setting
@oversample_sett.setter
def oversample_sett(self, value):
if value in range(4):
self.oversample_setting = value
else:
print('oversample_sett can only be 0, 1, 2 or 3, using 3 instead')
self.oversample_setting = 3
@property
def temperature(self):
'''
Temperature in degree C.
'''
next(self.gauge)
try:
UT = unp('>H', self.UT_raw)[0]
except:
return 0.0
X1 = (UT-self._AC6)*self._AC5/2**15
X2 = self._MC*2**11/(X1+self._MD)
self.B5_raw = X1+X2
return (((X1+X2)+8)/2**4)/10
@property
def pressure(self):
'''
Pressure in mbar.
'''
next(self.gauge)
self.temperature # Populate self.B5_raw
try:
MSB = unp('B', self.MSB_raw)[0]
LSB = unp('B', self.LSB_raw)[0]
XLSB = unp('B', self.XLSB_raw)[0]
except:
return 0.0
UP = ((MSB << 16)+(LSB << 8)+XLSB) >> (8-self.oversample_setting)
B6 = self.B5_raw-4000
X1 = (self._B2*(B6**2/2**12))/2**11
X2 = self._AC2*B6/2**11
X3 = X1+X2
B3 = ((int((self._AC1*4+X3)) << self.oversample_setting)+2)/4
X1 = self._AC3*B6/2**13
X2 = (self._B1*(B6**2/2**12))/2**16
X3 = ((X1+X2)+2)/2**2
B4 = abs(self._AC4)*(X3+32768)/2**15
B7 = (abs(UP)-B3) * (50000 >> self.oversample_setting)
if B7 < 0x80000000:
pressure = (B7*2)/B4
else:
pressure = (B7/B4)*2
X1 = (pressure/2**8)**2
X1 = (X1*3038)/2**16
X2 = (-7357*pressure)/2**16
return pressure+(X1+X2+3791)/2**4
@property
def altitude(self):
'''
Altitude in m.
'''
try:
p = -7990.0*math.log(self.pressure/self.baseline)
except:
p = 0.0
return p
四、st7735屏幕驱动
和物联网开发124那篇文章是一样的。这里不再贴了,大家在文章的第一节链接进去找哈。。。
五、操作字体文件方法库
和物联网开发124那篇文章是一样的。这里不再贴了,大家在文章的第一节链接进去找哈。。。
六、BMP280驱动
from micropython import const
from machine import I2C
class BMP280():
def __init__(self, i2c,address):
self.i2c = i2c
self.address = address
self.tb = bytearray(1)
self.rb = bytearray(1)
self.dig_T1 = self.get2Reg(0x88)
self.dig_T2 = self.short(self.get2Reg(0x8A))
self.dig_T3 = self.short(self.get2Reg(0x8C))
self.dig_P1 = self.get2Reg(0x8E)
self.dig_P2 = self.short(self.get2Reg(0x90))
self.dig_P3 = self.short(self.get2Reg(0x92))
self.dig_P4 = self.short(self.get2Reg(0x94))
self.dig_P5 = self.short(self.get2Reg(0x96))
self.dig_P6 = self.short(self.get2Reg(0x98))
self.dig_P7 = self.short(self.get2Reg(0x9A))
self.dig_P8 = self.short(self.get2Reg(0x9C))
self.dig_P9 = self.short(self.get2Reg(0x9E))
self.mode = 3
self.osrs_p = 3
self.osrs_t = 1
self.setReg(0xF4, 0x2F)
self.setReg(0xF5, 0x0C)
self.filter = 3
self.T = 0
self.P = 0
self.version = '1.0'
def short(self, dat):
if dat > 32767:
return dat - 65536
else:
return dat
# set reg
def setReg(self, reg, dat):
self.tb[0] = dat
self.i2c.writeto_mem(self.address, reg, self.tb)
# get reg
def getReg(self, reg):
self.i2c.readfrom_mem_into(self.address, reg, self.rb)
return self.rb[0]
# get two reg
def get2Reg(self, reg):
return self.getReg(reg) + self.getReg(reg+1) * 256
def get(self):
adc_T = (self.getReg(0xFA)<<12) + (self.getReg(0xFB)<<4) + (self.getReg(0xFC)>>4)
var1 = (((adc_T>>3)-(self.dig_T1<<1))*self.dig_T2)>>11
var2 = (((((adc_T>>4)-self.dig_T1)*((adc_T>>4) - self.dig_T1))>>12)*self.dig_T3)>>14
t = var1+var2
self.T = ((t * 5 + 128) >> 8)/100
var1 = (t>>1) - 64000
var2 = (((var1>>2) * (var1>>2)) >> 11 ) * self.dig_P6
var2 = var2 + ((var1*self.dig_P5)<<1)
var2 = (var2>>2)+(self.dig_P4<<16)
var1 = (((self.dig_P3*((var1>>2)*(var1>>2))>>13)>>3) + (((self.dig_P2) * var1)>>1))>>18
var1 = ((32768+var1)*self.dig_P1)>>15
if var1 == 0:
return # avoid exception caused by division by zero
adc_P = (self.getReg(0xF7)<<12) + (self.getReg(0xF8)<<4) + (self.getReg(0xF9)>>4)
p=((1048576-adc_P)-(var2>>12))*3125
if p < 0x80000000:
p = (p << 1) // var1
else:
p = (p // var1) * 2
var1 = (self.dig_P9 * (((p>>3)*(p>>3))>>13))>>12
var2 = (((p>>2)) * self.dig_P8)>>13
self.P = p + ((var1 + var2 + self.dig_P7) >> 4)
return [self.T, self.P]
# get Temperature in Celsius
def getTemp(self):
self.get()
return self.T
# get Pressure in Pa
def getPress(self):
self.get()
return self.P
# Calculating absolute altitude
def getAltitude(self):
return 44330*(1-(self.getPress()/101325)**(1/5.255))
# sleep mode
def poweroff(self):
self.setReg(0xF4, 0)
# normal mode
def poweron(self):
self.setReg(0xF4, 0x2F)
七、示例代码
from machine import Pin,SPI,I2C
from st7735 import ST7735,color
from ufont import BMFont
from bmp180 import BMP180
from bmp280 import BMP280
import time
font = BMFont("fonts/unifont-14.0.04.bmf")
spi = SPI(1,baudrate = 60_000_000,polarity = 0,sck = Pin(2),mosi = Pin(3),miso = None)
tft = ST7735(spi,rst = 10,dc = 6,cs = 7,bl = 8, width = 160, height = 80,rotate = 1,rgb = True)
i2c = I2C(0,scl = Pin(5),sda = Pin(4),freq = 400_000)
bmp1 = BMP180(i2c,0x77,3,101325)
bmp2 = BMP280(i2c,0x76)
def BMP():
#180
temp1 = bmp1.temperature
pres1 = bmp1.pressure
alti1 = bmp1.altitude
#280
temp2 = bmp2.getTemp()
pres2 = bmp2.getPress()
alti2 = bmp2.getAltitude()
font.text(tft,"温度: %.2f %.2f"%(temp1,temp2),0,16,color(255,255,255),font_size = 16,reverse = False,clear = False,show = True,half_char = True,auto_wrap = False)
font.text(tft,"压力: %.2f"%(pres1),0,32,color(255,255,255),font_size = 16,reverse = False,clear = False,show = True,half_char = True,auto_wrap = False)
font.text(tft,"压力: %.2f"%(pres2),0,48,color(255,255,255),font_size = 16,reverse = False,clear = False,show = True,half_char = True,auto_wrap = False)
font.text(tft,"海拔: %.2f %.2f"%(alti1,alti2),0, 64,color(255,255,255),font_size = 16,reverse = False,clear = False,show = True,half_char = True,auto_wrap = False)
# print("温度: %.2f %.2f"%(temp1,temp2))
# print("压力: %.2f %.2f"%(pres1,pres2))
# print("海拔: %.2f %.2f"%(alti1,alti2))
# time.sleep(1)
def main():
font.text(tft,"BMP180&BMP280",24, 0,color(0,255,0),font_size = 16,reverse = False,clear = False,show = True,half_char = True,auto_wrap = False)
while True:
BMP()
if __name__ == "__main__":
main()
八,演示效果
九、模块购买
BMP180和BMP280购买链接:
BMP180资料下载链接:https://pan.baidu.com/s/1omMQgzUgw_98QXgGk3kYSQ
提取码:8888
BMP280资料下载链接:https://pan.baidu.com/s/1TyQGJQ6R30hntzGr1SaSNg
提取码:8888