LinkIt Smart 7688を使ってみる

SPI入出力

LinkItには1組のSPIポートが有ります。
P22=MOSI P23=MISO P24=SCK P25=CSとしてアサインされています。

そこで、BMP280を使ってSPIの入出力を試してみました。
BMP280は4ピン仕様(i2c専用)と6ピン仕様(i2c/SPI兼用)のモジュールが有りますが、
SPIで使うときは6ピン仕様のモジュールを使う必要が有ります。

6ピン仕様のモジュールのピンマーキングは向って左から
SDO CSB SDA SCL Gnd Vcc
となっていますが、SPIで使う場合
MISO CS MOSI CLK Gnd Vcc
となります。

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


BMP280をLinkItのSPIピンに接続したらLinkItを再起動します。
これでSPIモジュールを認識します。
以下のコードでBMP280から温度と気圧を読み取ることができます。
バイトデータを書き込む場合、上位バイトと下位バイトを反転する必要が有りました。
レジスターに値を設定する場合、write()を使いますが、[0]が値、[1]がレジスターアドレスとなります。

BMP280の0xF4と0xF5のレジスターを設定しますが、SPIの通信仕様では、
書き込み時のレジスターアドレスは7ビット(0x00〜0x7F)に規定されているので、
0xF4と0xF5のレジスターを設定するときは、0x74と0x75のアドレスを指定します。
#!/usr/bin/python
#-*- encoding: utf-8 -*-
import mraa
import time

DEBUG = 0

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 int16(x):
  if x>0xFFFF:
    raise OverflowError
  if x>0x7FFF:
    x=int(0x10000-x)
    if x<2147483648:
      return -x
    else:
      return -2147483648
  return x

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


if __name__=="__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 x8
  osrs_p = 4  #OverSampling Pressure x8
  Mode = 3    #Normal mode

  # initialise spi
  spi = mraa.Spi(0)

  print('Read the contents of the ID register')
  ChipId = spi.writeByte(0xD0)
  if(DEBUG == 1):print('0x{:x}'.format(ChipId))
  if (ChipId == 0x58): print("BMP280")
  if (ChipId == 0x60): print("BME280")

#  spi.writeByte(0xD0)
#  chip_id = spi.readByte()
#  print chip_id

  # Send a command to the control register[0xF4]
  ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | Mode
  if(DEBUG == 1):print("ctrl_meas_reg = %x" % ctrl_meas_reg)
  txbuf = bytearray(2)
  txbuf[1] = 0x74 # Register Address
  txbuf[0] = ctrl_meas_reg # Register Data
  spi.write(txbuf)

  # Send a command to the config register[0xF5]
  config_reg    = (t_sb << 5) | (filter << 2) | spi3or4
  if(DEBUG == 1):print("config_reg = %x " % config_reg)
  txbuf[1] = 0x75 # Register Address
  txbuf[0] = config_reg # Register Data
  spi.write(txbuf)

  # Check control[0xF4] & config register[0xF5]
  print('Check Register')
  resp = spi.writeByte(0xF4)
  if(DEBUG == 1):
    print resp
    print("ctrl_meas_reg = %x" % resp)
  if(resp != ctrl_meas_reg):
    print("INVALID control register %x" % resp)
    exit()
  resp = spi.writeByte(0xF5)
  if(DEBUG == 1):
    print resp
    print("config_reg    = %x" % resp)
  if(resp != config_reg):
    print("INVALID config  register %x" % resp)
    exit()

  print('Read calibration data')
  resp = []
  for reg in range(0x88, 0xA0):
    data = spi.writeByte(reg)
    if(DEBUG == 1):print('{:d}'.format(data)),
    resp.append(data)
  if(DEBUG == 1):print

  dig_T1 = resp[1] * 256 + resp[0]
  dig_T2 = int16(resp[3] * 256 + resp[2])
  dig_T3 = int16(resp[5] * 256 + resp[4])
  if(DEBUG == 1):
    print("dig_T1 = %d" % dig_T1),
    print("dig_T2 = %d" % dig_T2),
    print("dig_T3 = %d" % dig_T3)

  dig_P1 = resp[7] * 256 + resp[6]
  dig_P2 = int16(resp[9] * 256 + resp[8])
  dig_P3 = int16(resp[11] * 256 + resp[10])
  dig_P4 = int16(resp[13] * 256 + resp[12])
  dig_P5 = int16(resp[15] * 256 + resp[14])
  dig_P6 = int16(resp[17] * 256 + resp[16])
  dig_P7 = int16(resp[19] * 256 + resp[18])
  dig_P8 = int16(resp[21] * 256 + resp[20])
  dig_P9 = int16(resp[23] * 256 + resp[22])
  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)

  print('Read temp and pressure')
  while(1):
    resp = []
    for reg in range(0xF7, 0xFD):
      data = spi.writeByte(reg)
      if(DEBUG == 1):print('{:d}'.format(data)),
      resp.append(data)
    if(DEBUG == 1):print
    # Check valid data
    if (resp[1] != 0 or resp[2] != 0):break
    time.sleep(1)

  pres_raw = (resp[0] << 12) | (resp[1] << 4) | (resp[2] >> 4)  #0xF7, msb+lsb+xlsb=19bit
  if(DEBUG == 1):print("pres_raw = %d " % pres_raw)
  temp_raw = (resp[3] << 12) | (resp[4] << 4) | (resp[5] >> 4)  #0xFA, msb+lsb+xlsb=19bit
  if(DEBUG == 1):print("temp_raw = %d " % temp_raw)

  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("Temperature = %f *C" % temp_act)
  print("Pressure = %f hPa" % press_act)

結果は以下のようになります。
root@mylinkit:~# python ./bmp280-spi.py
Read the contents of the ID register
BMP280
Check Register
Read calibration data
Read temp and pressure
-----------------------
Temperature = 18.180000 *C
Pressure = 1015.270000 hPa

続く....