python-peripheryを使ってみる

SPI温度計(BMP280)

ディジタル温度計はいくつかありますが、BMP280は i2c/SPI の両方で使えるちょっと変わったディジタル温度計です。
そこで、この温度計を i2c/SPI の両方で使ってみます。
前回、i2c での使い方を紹介しましたが、今回は SPI での使い方を紹介します。
BMP280は4ピン仕様(i2c専用)と6ピン仕様(i2c/SPI兼用)のモジュールが有りますが、
SPIで使うときは6ピン仕様のモジュールを使う必要が有ります。

左からBMP085(i2c専用) BMP280(i2c専用) BMP280(i2c/SPI兼用)


こ ちらで公開されているC言語のコードを移植しただけです。
BMP280のサンプルは圧倒的にi2cを使ったサンプルが多いのですが、
BitBang-SPI(ソフトウェアSPI)での使い方を紹介している貴重なページです。
C言語をPythonに移植する場合、Pythonには符号付整数の考え方が無いので、少し注意が必要です。
下のコードではint16()関数を使って符号なし整数値を16ビット符号付整数値に変換しています。
#!/usr/bin/python
#-*- encoding: utf-8 -*-
from periphery import GPIO
import sys
import time

DEBUG = 0

mosi = 4 # Pin#19
miso = 3 # Pin#21
sclk = 2 # Pin#23
cs = 5   # Pin#24

dig_T1 = 0
dig_T2 = 0
dig_T3 = 0
dig_P1 = 0
dig_P2 = 0
dig_P3 = 0
dig_P4 = 0
dig_P5 = 0
dig_P6 = 0
dig_P7 = 0
dig_P8 = 0
dig_P9 = 0

hum_raw = 0
temp_raw = 0
pres_raw = 0
t_fine = 0

gpio_mosi = GPIO(mosi, "out")
gpio_miso = GPIO(miso, "in")
gpio_sclk = GPIO(sclk, "out")
gpio_cs = GPIO(cs, "out")

def readTrim():
    global dig_T1
    global dig_T2
    global dig_T3
    dig_T1 = read16bit(0x88)
    dig_T2 = int16(read16bit(0x8A))
    dig_T3 = int16(read16bit(0x8C))
    if(DEBUG == 1):
      print("dig_T1 = %d" % dig_T1),
      print("dig_T2 = %d" % dig_T2),
      print("dig_T3 = %d" % dig_T3)

    global dig_P1
    global dig_P2
    global dig_P3
    global dig_P4
    global dig_P5
    global dig_P6
    global dig_P7
    global dig_P8
    global dig_P9
    dig_P1 = read16bit(0x8E)
    dig_P2 = int16(read16bit(0x90))
    dig_P3 = int16(read16bit(0x92))
    dig_P4 = int16(read16bit(0x94))
    dig_P5 = int16(read16bit(0x96))
    dig_P6 = int16(read16bit(0x98))
    dig_P7 = int16(read16bit(0x9A))
    dig_P8 = int16(read16bit(0x9C))
    dig_P9 = int16(read16bit(0x9E))
    if(DEBUG == 1):
      print("dig_P1 = %d" % dig_P1),
      print("dig_P2 = %d" % dig_P2),
      print("dig_P3 = %d" % dig_P3)
      print("dig_P4 = %d" % dig_P4),
      print("dig_P5 = %d" % dig_P5),
      print("dig_P6 = %d" % dig_P6)
      print("dig_P7 = %d" % dig_P7),
      print("dig_P8 = %d" % dig_P8),
      print("dig_P9 = %d" % dig_P9)

def readChipId():
  ChipId = read8bit(0xD0)
#  print("ChipId = 0x%x " % ChipId)
  return ChipId

def readData():
  global pres_raw
  global temp_raw
  global hum_raw

  gpio_cs.write(False)
  SpiWrite(0xF7 | 0x80)  #0xF7 pressure msb read, bit 7 high
  data = []
  for x in range(8):
    data.append(SpiRead())
  gpio_cs.write(True)
  pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)  #0xF7, msb+lsb+xlsb=19bit
  if(DEBUG == 1):print("pres_raw = %d " % pres_raw)
  temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)  #0xFA, msb+lsb+xlsb=19bit
  if(DEBUG == 1):print("temp_raw = %d " % temp_raw)
  hum_raw  = (data[6] << 8) | data[7];  #0xFD, msb+lsb=19bit(16:0)
  if(DEBUG == 1):print("hum_raw = %d " % hum_raw)

def int16(x):
  if x>0xFFFF:
    raise OverflowError
  if x>0x7FFF:
    x=int(0x10000-x)
    return -x
  return x

def int32(x):
  if x>0xFFFFFFFF:
    raise OverflowError
  if x>0x7FFFFFFF:
    x=int(0x100000000-x)
    return -x
  return x

def calibration_T(adc_T):
  global t_fine
  var1 = ((((adc_T >> 3) - (dig_T1<<1))) * (dig_T2)) >> 11
  var2 = (((((adc_T >> 4) - (dig_T1)) * ((adc_T>>4) - (dig_T1))) >> 12) * (dig_T3)) >> 14

  t_fine = var1 + var2
  t_fine = int32(t_fine)
  T = (t_fine * 5 + 128) >> 8
  return T

def calibration_P(adc_P):
  var1 = ((t_fine)>>1) - 64000
  if (DEBUG == 1):print("var1(1) = %d " % var1)
  var2 = (((var1>>2) * (var1>>2)) >> 11) * (dig_P6)
  if(DEBUG == 1):print("var2(2) = %d " % var2)
  var2 = var2 + ((var1*(dig_P5))<<1)
  if(DEBUG == 1):print("var2(3) = %d " % var2)
  var2 = (var2>>2)+((dig_P4)<<16)
  if(DEBUG == 1):print("var2(4) = %d " % var2)
  var1 = (((dig_P3 * (((var1>>2)*(var1>>2)) >> 13)) >>3) + (((dig_P2) * var1)>>1))>>18
  if(DEBUG == 1):print("var1(5) = %d " % var1)
  var1 = ((((32768+var1))*(dig_P1))>>15)
  if(DEBUG == 1):print("var1(6) = %d " % var1)
  if (var1 == 0):
    return 0
  P = ((((1048576)-adc_P)-(var2>>12)))*3125
  if(P<0x80000000):
    P = (P << 1) / (var1)
  if(P>=0x80000000):
    P = (P / var1) * 2;
  var1 = ((dig_P9) * ((((P>>3) * (P>>3))>>13)))>>12
  var2 = (((P>>2)) * (dig_P8))>>13
  if(DEBUG == 1):
    print("var1 = %d" % var1),
    print("var2 = %d" % var2)
  P = (P + ((var1 + var2 + dig_P7) >> 4))
  return P

def writeReg(reg_address, data):
  gpio_cs.write(False)
  SpiWrite(reg_address & 0x7F)  # write, bit 7 low
  SpiWrite(data)
  gpio_cs.write(True)

def read16bit(reg):
  gpio_cs.write(False)
  SpiWrite(reg | 0x80)  # read, bit 7 high
  d1 = SpiRead()
  d2 = SpiRead()
  data = (d2 << 8) | d1
  gpio_cs.write(True)
  return data

def read8bit(reg):
  gpio_cs.write(False)
  SpiWrite(reg | 0x80)  # read, bit 7 high
  data = SpiRead();
  gpio_cs.write(True)
  return data;

def SpiWrite(data):
  mask = 0x80
  for x in range(8):
    gpio_sclk.write(False)
    bit = data & mask
    if (bit != 0):
      gpio_mosi.write(True)
    if (bit == 0):
      gpio_mosi.write(False)
    gpio_sclk.write(True)
    mask = mask >> 1

def SpiRead():
  r_data = 0;
  mask = 0x80
  gpio_mosi.write(False)
  for x in range(8):
    r_data = r_data << 1
    gpio_sclk.write(False)
    gpio_sclk.write(True)
    bit = gpio_miso.read()
    if (bit == True):
      r_data = r_data + 1
  return r_data;

def main():
  t_sb = 5    #stanby 1000ms
  filter = 0  #filter O = off
  spi3or4 = 0 #SPI 3wire or 4wire, 0=4wire, 1=3wire
  osrs_t = 4  #OverSampling Temperature x4
  osrs_p = 4  #OverSampling Pressure x4
  Mode = 3    #Normal mode

  ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | Mode
  config_reg    = (t_sb << 5) | (filter << 2) | spi3or4

  if(DEBUG == 1):print("ctrl_meas_reg = %x" % ctrl_meas_reg)
  writeReg(0xF4,ctrl_meas_reg)
  if(DEBUG == 1):print("config_reg = %x " % config_reg)
  writeReg(0xF5,config_reg)
  time.sleep(1)

  while True:
    readTrim()
    ChipId = readChipId()
    readData()

    temp_cal = calibration_T(temp_raw)
    if(DEBUG == 1):print("temp_cal = %d " % temp_cal)
    press_cal = calibration_P(pres_raw)
    if(DEBUG == 1):print("press_cal = %d " % press_cal)
    temp_act = temp_cal / 100.0
    press_act = press_cal / 100.0

    print("-----------------------");
    print "Chip ID     : 0x%x " % ChipId
    print "Temperature : {:.2f} C".format(temp_act)
    print "Pressure    : {:.2f} hPa".format(press_act)
    time.sleep(2)

if __name__=="__main__":
  try:
    main()
  except KeyboardInterrupt:
    pass



おしまい