Raspberry Pi 3 Model B でI2Cデバイス(BME680)を使う(コマンドライン)

(2019/1/14 追記) 接続方法に誤りがあったため修正

# 前提条件(環境)と準備したもの
- Raspberry Pi 3 Model B
- Raspbien 9.6(Strech)
- 上記にSSH接続する端末
- CJMCU-680(BME680を搭載したブレークアウトボード)

# 自分がやりたいこと
- ラズパイでI2Cを利用するための初期設定
- コマンドラインを利用してBME680と通信
    - Cで接続する場合は、[こちら](https://qiita.com/nyoki/items/5ba799ef4d4ca0828a86)

# この記事で扱わないこと
- I2Cの説明
- SPI接続全般
- CJMCU-680を利用しない場合のBME680接続

# 手順1：Raspberry PiでI2Cを利用可能にする

## raspi-configでI2Cを有効にする
```
$ sudo raspi-config
```
5 Interfacing Options → P5 I2C から有効化

## 関連コマンドをインストール
```
$ sudo apt install pigpio i2c-tools
```

# 手順2：CJMCU-680をGPIOに接続する

| CJMCU-680 | GPIO | 補足    |
|-----------|-------------|---|
| VCC       | 3V3         |  |
| GND       | GND         |  |
| SCL       | GPIO03(SCL) |  |
| SDA       | GPIO02(SDA) |  |
| SDO       | 3V3         | BME680のアドレスを変更するために利用する。H:0x77 L:0x76 |
| CS        | 3V3         |  |
SDOは、未接続の場合Hにした場合と同等だった

接続確認
SDOの設定により、77または76が検出される

```
pi@raspberrypi:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77
```

# 手順3：BME680と通信

> ※[公式ライブラリ](https://github.com/BoschSensortec/BME680_driver)を利用するほうが確実かと思います。
> ここでは、I2Cの勉強を兼ねてコマンドラインで実行します。

## 設定値を送信する

公式のデータシート([ここからダウンロード](https://www.bosch-sensortec.com/bst/products/all_products/bme680))の3.2.1 QuickStartに沿って試してみる

以下、意訳

まず、湿度・気温・気圧の設定を行う。
それぞれのoversumplingを変更することで精度を変更可能。
気温と気圧はoversumpling設定値により16-20bit
湿度は16bitだが、oversumplingを上げることにより誤差を減らすことができる
oversumplingを0xにすると、その項目はスキップする。
1. 湿度のoversumplingを1xに設定する→osrs_h<2:0>に0b001を書き込む
2. 温度のoversumplingを2xに設定する→osrs_t<2:0>に0b010を書き込む
3. 気圧のoversumplingを16xに設定する→osrs_p<2:0>に0b101を書き込む

```
$ i2cset -y -m 0x07 1 0x77 0x72 0x01
$ i2cset -y -m 0xE0 1 0x77 0x74 0x40
$ i2cset -y -m 0x1C 1 0x77 0x74 0x14
```

次に、室内空気質(IAQ, Indoor Air Quality)の設定を行う。
設定は10種類保存できる。(設定0～9)
4. 設定0の予熱時間を100msに設定する→gas_wait_0<7:0>に0x59を書き込む
5. 設定0のヒーターの温度を設定する→res_heat_0<7:0>に Datasheetの§3.3.5で計算される値を設定する(=0x10)
6. 設定0を利用するようにする→nb_conv<3:0>に0b0000を書き込む
7. gas計測を有効にする→run_gas<0:0>に0b1を書き込む

```
$ i2cset -y 1 0x77 0x64 0x59
$ i2cset -y 1 0x77 0x5A 0x10
$ i2cset -y -m 0x0F 1 0x77 0x71 0x00
$ i2cset -y -m 0x10 1 0x77 0x71 0x10
```

準備ができたので、計測を行う
8. 計測を行う→mode<1:0>に0b01を書き込む

```
$ i2cset -y -m 0x03 1 0x77 0x74 0x01
```

## 計測結果を受信する

### 気圧
0x1Fと0x20と0x21の先頭4bitを連結
※oversumpling設定により精度は変化

```
$ i2cget -y 1 0x77 0x1F;i2cget -y 1 0x77 0x20;i2cget -y 1 0x77 0x21
0x4b
0xbd
0xb0
```
0x4d57a=316,794
分解能20bit、気圧のレンジは300～1100hPaなので、
300+800*316,794/1,048,576=541.69hPa
あれ・・・？

### 温度
0x22と0x23と0x24の先頭4bitを連結
※oversumpling設定により精度は変化

```
$ i2cget -y 1 0x77 0x22;i2cget -y 1 0x77 0x23;i2cget -y 1 0x77 0x24
0x78
0xf9
0x80
```
0x78f98=495,512
分解能20bit、温度のレンジは-40～85℃なので、
-40+125*495,512/1,048,576=19.07℃

### 湿度
0x25と0x26を連結

```
$ i2cget -y 1 0x77 0x25;i2cget -y 1 0x77 0x26
0x3d
0x75
```
0x3d75=15,733
分解能16bit、湿度のレンジは0～100%なので、
100*15,733/65,536=24.01%

### IAQ
0x2A・0x2Bの値を計算式(Datasheet §3.4.1)に従って計算
(2019/1/14 追記) 接続方法を修正することで正しい値が取れるようになった

```
$ i2cget -y 1 0x77 0x2A;i2cget -y 1 0x77 0x2B;i2cget -y 1 0x77 0x04
0x4f
0x62
0x13
```
gas_res=1097063.621
とのことだが、値の意味がわからない

# おわりに
気圧が正しく取得できていないが、ラズパイでI2C通信の基礎を学ぶことができたのでよしとする。
次は、[公式ライブラリ](https://github.com/BoschSensortec/BME680_driver)を利用してみる。