2022年7月30日 星期六

壓力感測器實作 – BMP280數位式氣壓感測器

壓力感測器實作 – BMP280數位式氣壓感測器

電路圖 




程式列表

Python - BMP280_const.py

 

# Default device I2C address

BMP280_ADDR = 0x76

 

# BMP280 Temperature Registers

BMP280_REGISTER_DIG_T1 = 0x88

BMP280_REGISTER_DIG_T2 = 0x8A

BMP280_REGISTER_DIG_T3 = 0x8C

# BMP280 Pressure Registers

BMP280_REGISTER_DIG_P1 = 0x8E

BMP280_REGISTER_DIG_P2 = 0x90

BMP280_REGISTER_DIG_P3 = 0x92

BMP280_REGISTER_DIG_P4 = 0x94

BMP280_REGISTER_DIG_P5 = 0x96

BMP280_REGISTER_DIG_P6 = 0x98

BMP280_REGISTER_DIG_P7 = 0x9A

BMP280_REGISTER_DIG_P8 = 0x9C

BMP280_REGISTER_DIG_P9 = 0x9E

 

BMP280_REGISTER_ID     = 0xD0

BMP280_REGISTER_RESET  = 0xE0

BMP280_REGISTER_STATUS = 0xF3

BMP280_REGISTER_CONTROL = 0xF4

BMP280_REGISTER_CONFIG = 0xF5

 

#Pressure measurments

BMP280_REGISTER_PRESSUREDATA_MSB = 0xF7

BMP280_REGISTER_PRESSUREDATA_LSB = 0xF8

BMP280_REGISTER_PRESSUREDATA_XLSB = 0xF9

#Temperature measurments

BMP280_REGISTER_TEMPDATA_MSB = 0xFA

BMP280_REGISTER_TEMPDATA_LSB = 0xFB

BMP280_REGISTER_TEMPDATA_XLSB = 0xFC

 

# Commands

BMP280_READCMD = 0x3F

 

Python - BMP280.py

"""

 

  Reference:

    https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/bme280.py

"""

 

from machine import I2C

import utime

 

from BMP280_const import *

 

class BMP280(object):

  def __init__(self, i2c, address=0x76):

    self._i2c = i2c

    self._address = address

 

  def getShort(self, data, index):

    # return two bytes from data as a signed 16-bit value

    result = (data[index+1] << 8) + data[index]

    if (result>32767) :

      result -= 32768

    return result

 

  def getUShort(self, data, index):

    # return two bytes from data as an unsigned 16-bit value

    return (data[index+1] << 8) + data[index]

 

  def getChar(self, data,index):

    # return one byte from data as a signed char

    result = data[index]

    if result > 127:

      result -= 256

    return result

 

  def getUChar(self, data,index):

    # return one byte from data as an unsigned char

    result =  data[index] & 0xFF

    return result

 

  def write_byte_data(self, reg_addr, data):

    self._i2c.send(bytearray([reg_addr,data]),self._address)

 

  def read_i2c_block_data(self, reg_addr, size=1):

    data = bytearray(size)

    self._i2c.send(bytearray([reg_addr]),self._address)

    self._i2c.recv(data,self._address)

    return data

 

  def readBMP280ID(self):

    # Chip ID Register Address

    result = self.read_i2c_block_data(BMP280_REGISTER_ID, 1)

    chip_id =result[0]

    return (chip_id)

 

  def readBMP280All(self):

    # Oversample setting - page 27

    OVERSAMPLE_TEMP = 2

    OVERSAMPLE_PRES = 2

    MODE = 1

 

    control = OVERSAMPLE_TEMP<<5 | OVERSAMPLE_PRES<<2 | MODE

    self.write_byte_data(BMP280_REGISTER_CONTROL, control)

 

    # Read blocks of calibration data from EEPROM

    # See Page 22 data sheet

    cal1 = bytearray(24)

    cal1 = self.read_i2c_block_data(BMP280_REGISTER_DIG_T1, 24)

 

    # Convert byte data to word values

    dig_T1 = self.getUShort(cal1, 0)

    dig_T2 = self.getShort(cal1, 2)

    dig_T3 = self.getShort(cal1, 4)

 

    dig_P1 = self.getUShort(cal1, 6)

    dig_P2 = self.getShort(cal1, 8)

    dig_P3 = self.getShort(cal1, 10)

    dig_P4 = self.getShort(cal1, 12)

    dig_P5 = self.getShort(cal1, 14)

    dig_P6 = self.getShort(cal1, 16)

    dig_P7 = self.getShort(cal1, 18)

    dig_P8 = self.getShort(cal1, 20)

    dig_P9 = self.getShort(cal1, 22)

 

    # Wait in ms (Datasheet Appendix B: Measurement time and current calculation)

    wait_time = 1.25 + (2.3 * OVERSAMPLE_TEMP) + ((2.3 * OVERSAMPLE_PRES) + 0.575)

    utime.sleep(wait_time/1000)  # Wait the required time 

 

    # Read temperature/pressure

    data = self.read_i2c_block_data(BMP280_REGISTER_PRESSUREDATA_MSB, 8)

    pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)

    temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)

 

    #Refine temperature

    var1 = ((((temp_raw>>3)-(dig_T1<<1)))*(dig_T2)) >> 11

    var2 = (((((temp_raw>>4) - (dig_T1)) * ((temp_raw>>4) - (dig_T1))) >> 12) * (dig_T3)) >> 14

    t_fine = var1+var2

    temperature = float(((t_fine * 5) + 128) >> 8);

 

    # Refine pressure and adjust for temperature

    var1 = t_fine / 2.0 - 64000.0

    var2 = var1 * var1 * dig_P6 / 32768.0

    var2 = var2 + var1 * dig_P5 * 2.0

    var2 = var2 / 4.0 + dig_P4 * 65536.0

    var1 = (dig_P3 * var1 * var1 / 524288.0 + dig_P2 * var1) / 524288.0

    var1 = (1.0 + var1 / 32768.0) * dig_P1

    if var1 == 0:

      pressure=0

    else:

      pressure = 1048576.0 - pres_raw

      pressure = ((pressure - var2 / 4096.0) * 6250.0) / var1

      var1 = dig_P9 * pressure * pressure / 2147483648.0

      var2 = pressure * dig_P8 / 32768.0

      pressure = pressure + (var1 + var2 + dig_P7) / 16.0

 

    return temperature/100.0,pressure/100.0

 

Python - ePy-Lite_BMP280.py

"""

  ePy-Lite_BMP280.py

  Read data from a digital pressure sensor.

 

   ePy-Lite   BMP280

  -----------+------

   3V3       | Pin1  VCC (For powering up the module)

   GND       | Pin2  GND (Ground)

   P17_SCL0  | Pin3  SCK/SCL (I2C clock)

   P16_SDA0  | Pin4  SDI/SDA (I2C data)

             | Pin5  CSB

             | Pin6  SDO

             +--------

"""

 

from machine import Switch  #Get button KEY library

from machine import Timer, I2C,UART, LED

import utime

import BMP280

 

BLEOUT = True

 

def tick3(timer):

  global TimerDone,Timer5s,Timer5sDone

  TimerDone = True

  Timer5s += 1

  if Timer5s>=50 :

    Timer5s=0

    Timer5sDone = True

 

def key_int():

  global KeyADone

  KeyADone = True

 

# Start Function

if __name__ == '__main__':

  ledY = LED('ledy')

  ledY.off()

 

  KeyA = Switch('keya')    #Create button A

  KeyA.callback(key_int)

  KeyADone = False

 

  timer = Timer(3,freq=10)

  timer.callback(tick3)

  Timer5s = 0

  Timer5sDone = False

  TimerDone = False

 

  # Declaration I2C

  i2c = I2C(0,I2C.MASTER,baudrate=100000)  #Create I2C0 Master Mode, Baudrate=100kHz

 

  pressure_sensor=BMP280.BMP280(i2c)

  (chip_id) = pressure_sensor.readBMP280ID()

  print ("Chip ID     : {:x}H".format(chip_id))

  utime.sleep_ms(50)

 

  if(BLEOUT):

    ble = UART(1,115200)

    ble.write('AT+MODE_DATA\r\n')

 

  print("--- Start ---")

  while True:

    if Timer5sDone == True:

      ledY.on()

 

      Temp,Press = pressure_sensor.readBMP280All()

      print ('Temperature={:.2f}*C, Pressure={:.2f}hPa'.format(Temp,Press))

      if(BLEOUT):

        ble.write('T = {:.2f}*C, P = {:.2f}hPa\r\n'.format (Temp,Press))

      ledY.off()

      Timer5sDone = False

 

    if KeyADone == True:      #Press A Key

      break

 

  if(BLEOUT):

    ble.deinit()

  i2c.deinit()

  KeyA.callback(None)

  print("--- End ---")

 

執行結果