電子工作 > 気圧計到着 > MPL115A2(I2C接続) / ユニバーサル基板実装

屋外高度測定をするために気圧計を購入。本日届いた。
http://akizukidenshi.com/catalog/g/gI-04596/

関連 http://qiita.com/7of9/items/02433dfcda8c840b878f


## 資料
[DataSheet](http://cache.freescale.com/files/sensors/doc/data_sheet/MPL115A2.pdf)

[【きむ茶工房ガレージハウス】](
http://www.geocities.jp/zattouka/GarageHouse/micon/Arduino/Pressure/Pressure2.htm) : 旧モジュールの情報?


## 回路

AQM0802接続に使ったユニーバサル基板を流用。
http://qiita.com/7of9/items/bf5a653d1925cbb38569

以下のように接続した。

- ESP8266:SDA (IO4) <-> MPL115A2: SDA(Pin7)
- ESP8266:SCL (IO5) <-> MPL115A2: SCL(Pin8)
- EPS8266:VCC <-> MPL115A2: VDD(Pin1)
- EPS8266:VCC <-> MPL115A2: SHDN(Pin4)
- EPS8266:VCC <-> MPL115A2: RST(Pin5)
- ESP8266:VSS <-> MPL115A2: GND(Pin3)
- ESP8266:GND <-> 1uF <-> MPL115A2: CAP(Pin2)

SDAとSCLは4.7kでプルアップとデータシートにあるが、今回は基板の流用で10kプルアップで動作。

[回路図 @ upverter](https://upverter.com/7of9/b5e95a0eab20fddc/160529_ESP8266_MPL115A2/)



ブレッドボードで実装。
黄色: SCL
黄色と交差するオレンジ: SDA
緑色: GND
赤色: VCC

![DSC_0168.JPG](https://qiita-image-store.s3.amazonaws.com/0/32870/3495361e-c653-2698-75c6-08465fb4b413.jpeg)


## code v0.1

[【きむ茶工房ガレージハウス】](
http://www.geocities.jp/zattouka/GarageHouse/micon/Arduino/Pressure/Pressure2.htm)
のコードを参考にデータシートを見ながら変更した。
平均化処理は未実装。

```esp8266_160528_MPL115A2.ino
#include <Wire.h>

/*
 * v0.1 2016 May 28
 *   - add PrintPressure()
 *   - add ReadPressureAndTemperature()
 *   - add ReadCofficient()
 */

#define MPL_ADDR (0x60)

static float s_a0, s_b1, s_b2, s_c12; // 係数データ
unsigned long iPress, iTemp;

void setup() {
  Serial.begin(115200);
  Serial.println("");

  Wire.begin();
  delay(3000); // msec
  ReadCoefficient();
}

bool ReadCoefficient()
{
  int len;
  unsigned int hi, lw;

  Wire.beginTransmission(MPL_ADDR);
  Wire.write(0x04);
  len = Wire.endTransmission();
  if (len == 0) {
    len = Wire.requestFrom(MPL_ADDR, 8);
    if (len == 8) {
      hi = Wire.read();
      lw = Wire.read();
      s_a0 = (hi << 5) + (lw >> 3) + (lw & 0x07) / 8.0;
      hi = Wire.read();
      lw = Wire.read();
      s_b1 = ( hi & 0x1F) * 0x100 + lw;
      s_b1 = s_b1 / 8192.0 - 3.0;
      hi = Wire.read();
      lw = Wire.read();
      s_b2 = (hi & 0x80) << 8 + lw;
      s_b2 = s_b2 / 16384.0 - 2.0;
      hi = Wire.read();
      lw = Wire.read();
      s_c12 = (hi * 0x100) + lw;
      s_c12 = s_c12 / 16777216.0;

      Serial.println(s_a0);
      Serial.println(s_b1);
      Serial.println(s_b2);
      Serial.println(s_c12);      
      return true;
    }
  }
  return false;
}

bool ReadPressureAndTemperature()
{
  int len;
  unsigned int hi, lw;

  // 1. start conversion
  Wire.beginTransmission(MPL_ADDR);
  Wire.write(0x12);
  Wire.write(0x01);
  len = Wire.endTransmission();
  if (len != 0) return false;
  delay(3); // msec

  // 2. get values
  Wire.beginTransmission(MPL_ADDR);
  Wire.write(0x00);
  len = Wire.endTransmission();
  if (len == 0) {
    len = Wire.requestFrom(MPL_ADDR, 4);
    if (len == 4) {
      hi = Wire.read();
      lw = Wire.read();
      iPress = (hi * 256 + lw) / 64;
      hi = Wire.read();
      lw = Wire.read();
      iTemp = ( hi * 256 + lw) / 64;
      return true;      
    }
  }
  return false;
}

void PrintPressure()
{
  float prs, f0;
  f0 = s_a0 + ( s_b1 + s_c12 * iTemp) * iPress + s_b2 * iTemp;
  prs = f0 * ( (115.0 - 50.0) / 1023.0 ) + 50.0;
  Serial.print("Pressure=");
  Serial.println(prs);
}

void loop() {
  if (ReadPressureAndTemperature()) {
    PrintPressure();
  }
  delay(1000); // msec
}
```



## 結果 (v0.1) > 係数間違い

4つの係数と圧力(kPa)。

正しいのかは未確認。とりあえず通信はできている、という程度。
係数の計算式については要確認。

```
1905.00
-2.24
-2.00
0.00
Pressure=66.94
Pressure=66.83
Pressure=66.72
Pressure=66.83
Pressure=66.94
Pressure=66.72
Pressure=66.94
Pressure=66.94
Pressure=66.95
Pressure=66.71
```

## code v0.2

係数がどうもおかしいようだった。

以下で係数の計算が詳しい。
http://seppina.cocolog-nifty.com/blog/2014/09/pici2c---mpl115.html


```esp8266_160528_MPL115A2.ino
#include <Wire.h>

/*
 * v0.2 2016 May 29
 *   - fix bug > coefficients calculation
 * v0.1 2016 May 28
 *   - add PrintPressure()
 *   - add ReadPressureAndTemperature()
 *   - add ReadCoefficient()
 */

#define MPL_ADDR (0x60)

static float s_a0, s_b1, s_b2, s_c12; // 係数データ
unsigned long iPress, iTemp;

void setup() {
  Serial.begin(115200);
  Serial.println("");

  Wire.begin();
  delay(3000); // msec
  ReadCoefficient();
}

bool ReadCoefficient()
{
  int len;
  unsigned int hi, lw;

  Wire.beginTransmission(MPL_ADDR);
  Wire.write(0x04);
  len = Wire.endTransmission();
  if (len == 0) {
    len = Wire.requestFrom(MPL_ADDR, 8);
    if (len == 8) {
      hi = Wire.read();
      lw = Wire.read();
      s_a0 = (hi << 8) + lw;
      s_a0 /= 8.0;
      if (hi & 0x80) s_a0 -= 8192.0;
      hi = Wire.read();
      lw = Wire.read();
      s_b1 = (hi << 8) + lw;
      s_b1 /= 8192.0;
      if (hi & 0x80) s_b1 -= 8.0;
      hi = Wire.read();
      lw = Wire.read();
      s_b2 = (hi << 8) + lw;
      s_b2 /= 16384.0;
      if (hi & 0x80) s_b2 -= 4.0;
      hi = Wire.read();
      lw = Wire.read();
      s_c12 = (hi << 8) + lw;
      s_c12 /= 32768.0;
      if (hi & 0x80) s_c12 -= 2.0;
      s_c12 /= 512.0;

      Serial.println(s_a0);
      Serial.println(s_b1);
      Serial.println(s_b2);
      Serial.println(s_c12);      
      return true;
    }
  }
  return false;
}

bool ReadPressureAndTemperature()
{
  int len;
  unsigned int hi, lw;

  // 1. start conversion
  Wire.beginTransmission(MPL_ADDR);
  Wire.write(0x12);
  Wire.write(0x01);
  len = Wire.endTransmission();
  if (len != 0) return false;
  delay(3); // msec

  // 2. get values
  Wire.beginTransmission(MPL_ADDR);
  Wire.write(0x00);
  len = Wire.endTransmission();
  if (len == 0) {
    len = Wire.requestFrom(MPL_ADDR, 4);
    if (len == 4) {
      hi = Wire.read();
      lw = Wire.read();
      iPress = (hi * 256 + lw) / 64;
      hi = Wire.read();
      lw = Wire.read();
      iTemp = ( hi * 256 + lw) / 64;
      return true;      
    }
  }
  return false;
}

void PrintPressure()
{
  float prs, f0;
  f0 = s_a0 + ( s_b1 + s_c12 * iTemp) * iPress + s_b2 * iTemp;
  prs = f0 * ( (115.0 - 50.0) / 1023.0 ) + 50.0;
  Serial.print("Pressure=");
  Serial.println(prs);
}

void loop() {
  if (ReadPressureAndTemperature()) {
    PrintPressure();
  }
  delay(1000); // msec
}
```

## 結果(v0.2)

```txt:結果
1905.00
-2.24
-0.94
0.00
Pressure=100.48
Pressure=100.68
Pressure=100.60
Pressure=100.48
Pressure=100.60
Pressure=100.40
Pressure=100.60
```

気圧が100.48kPa = 1004.8hPa。
だいたいよく聞く気圧(1013hPa)のオーダーにはなった。

係数の4つ目は表示桁が少数2桁になってしまっている。

シリアル出力を続けていると途中で出力が止まってしまう。コードが悪いのか基板、電池が悪いのか要調査。


## ユニーバサル基板実装

ユニバーサル基板実装した。

左はmicroSDで保存するための基板。
右が気圧計を実装した基板。

それぞれ、XHPコネクタから電源供給できるが、屋外使用のためにCR-123Aを直挿しできるようにした。
気圧計のプルアップ抵抗は4.7kにしている。

![DSC_0170.JPG](https://qiita-image-store.s3.amazonaws.com/0/32870/722eeed3-3790-4656-c12b-9dccd9ef5a1e.jpeg)