ARDUINO で気圧と温度をSPIバスで読む[2]

## 目的と概要

- 前回はpolling でデータを読むことができた。今回は、センサーがデータを読んだタイミングを知らせてくれる時のみデータを読むことにする。

### 内容

- 行ったこと
 - センサーのDataReadyピンの情報を調べ、配線する
 - Arduino SDKで割り込み処理を実装し、動作確認した

- はまったところ
 - （その１）Arduinoでは、すべてのピンが割り込みに使えるわけではない。仕様確認が大切。
 -  （その２）最初にデータを読まないとDataReadyが来ない。最初に一度、センサーデータを読む処理を加えて所望の動作を確認したが、それが正しい処理かは不明。

## 配線

Arduino SDKで割り込み処理は [attachInterrupt()](https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/)という関数で実装できる。
ArduinoMicroの DIGITAL PINS USABLE FOR INTERRUPTS　を確認したら、0, 1, 2, 3, 7 であることが分かる。

LPS331APの仕様書を読むと、２つおINTピンがあることが分かる。これはそれぞれ圧力と気温のDataReadyの状態を知らせるピンとして利用できる。センサの設定はCTRL_REG3　でできることが読める。

ArduinoMicroのD2はSPIのCSに利用していたので、D3とD7を二つのINTピンに接続することにした。

以上から以下のように配線した。この表は横つながりが電気的に線でつながっているという意味。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/294040/47cfea1e-f91d-a43c-44d9-5904d2c1cbc5.png)

## 実装

-  [attachInterrupt()](https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/)の仕様に従う。ピンと関数を設定する。
- とりあえず動いたので。

```
#include <SPI.h>
// Test program of ArduinoMicro for reading sensor data from SPI bus 
// at interrupted timing of data ready pin.

/// ArduinoMicro Pin asignment
const int LPS331AP_CS = 2; // D2 is used as chip select pin
const int LPS331AP_INT1 = 3;// D3 
const int LPS331AP_INT2 = 7;// D7

/// Sensor register map
const byte LPS331AP_ADDR = B1011100;  // SA0 = GND
const byte LPS331AP_WHOAMI = 0x0f;
const byte LPS331AP_CTRL1 = 0x20;
const byte LPS331AP_CTRL2 = 0x21;
const byte LPS331AP_CTRL3 = 0x22;
const byte LPS331AP_P_LL = 0x28;
const byte LPS331AP_P_L  = 0x29;
const byte LPS331AP_P_H  = 0x2A;
const byte LPS331AP_T_L  = 0x2B;
const byte LPS331AP_T_H  = 0x2C;
const byte SPI_RW = 0x80;

void spi_write(byte reg, byte val)
{
  digitalWrite(LPS331AP_CS, LOW);
  SPI.transfer(reg);
  SPI.transfer(val);
  digitalWrite(LPS331AP_CS, HIGH);
}

byte spi_read(byte reg)
{
  byte ret = 0;
  digitalWrite(LPS331AP_CS, LOW);
  SPI.transfer(reg | SPI_RW);
  ret = SPI.transfer(0);
  digitalWrite(LPS331AP_CS, HIGH);
  return ret;
}

void read_pressure(void)
{
  long P = spi_read(LPS331AP_P_H);
  P = (P << 8) | spi_read(LPS331AP_P_L);
  P = (P << 8) | spi_read(LPS331AP_P_LL);
  Serial.print("P=");
  Serial.println(P);  
}

void read_temperature(void)
{
    short T = spi_read(LPS331AP_T_H);
  T = (T << 8) | spi_read(LPS331AP_T_L);  
  Serial.print("T=");
  Serial.println(T);
}
void cb_int1(void)
{
  Serial.print("int1\n");
  read_pressure();  
}

void cb_int2(void)
{
  Serial.print("int2\n");
  read_temperature();  
}
void setup() {
  Serial.begin(9600);  
  while (!Serial) {}
  SPI.begin();
  pinMode(LPS331AP_CS, OUTPUT);// Chip select pin
  delay(100);  

  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV4); // 8MHz/8 = 1MHz; (max 10MHz)


  Serial.println(spi_read(LPS331AP_WHOAMI), HEX); // should show BB
  spi_write(LPS331AP_CTRL1, B11100000);
                       //   |||||||+ SPI Mode selection
                       //   ||||||+- DELTA_EN
                       //   |||||+-- BDU: block data update
                       //   ||||+--- DIFF_EN: interrupt circuit enable
                       //   |+++---- ODR2, ODR1, ODR0 (1Hz)
                       //   +------- PD: 0: power down, 1: active
  spi_write(LPS331AP_CTRL2, B01100000);
                       //   |||||||+ One shot enable. (default 0) 
                       //   ||||||+- Autozero enablet. (Default 0)
                       //   |||||+-- Software reset (Default 0)
                       //   +------- BOOT (Default 0) 0: normal mode; 1:reboot memory content
  spi_write(LPS331AP_CTRL3, B00100100);
                        //   |||||+++ INT1_S3, INT1_S2, INT1_S1 (default 0) 
                        //   ||+++--- INT2_S3, INT2_S2, INT2_S1 (Default 0)
                        //   |+------ PP_OD (Push-pull/open drain selection on interrupt pads)  
                        //   +------- INT_H_L: Interrupt active high/low (Default 0)

   //// setup interrupt pin configuration
   pinMode(LPS331AP_INT1, INPUT);
   pinMode(LPS331AP_INT2, INPUT);
   digitalWrite(LPS331AP_INT1, LOW);
   digitalWrite(LPS331AP_INT2, LOW);
   attachInterrupt(digitalPinToInterrupt(LPS331AP_INT1), cb_int1, RISING);
   attachInterrupt(digitalPinToInterrupt(LPS331AP_INT2), cb_int2, RISING); 
   delay(1000);
   read_pressure();
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(10);  
}
```

おまけ。
![IMG_20181024_001420.jpg](https://qiita-image-store.s3.amazonaws.com/0/294040/bab891a0-0e17-e9dd-e10c-b2088fd7fb1a.jpeg)