Raspberry Pi 2 Model B でI2C 照度センサーモジュール(BH1750)を使う

## 概要
Raspberry pi 2 Model B (Raspbian)での aitendo [M1750-5P](http://www.aitendo.com/product/10240 "M1750-5P")(BH1750使用 照度センサーモジュール) 設定覚書き

---
## 参考
参考にしました、ありがとうございます。

* [ローム BH1750FVI Datasheet](http://rohmfs.rohm.com/jp/products/databook/datasheet/ic/sensor/light/bh1750fvi-j.pdf "Datasheet")←説明書
* [androciti](http://wiki.androciti.com/index.php?BH1750FVI%A5%C7%A5%B8%A5%BF%A5%EB%BE%C8%C5%D9%A5%BB%A5%F3%A5%B5%A1%BC%A5%E2%A5%B8%A5%E5%A1%BC%A5%EB "BH1750FVIデジタル照度センサーモジュール")
* [wiringPi](http://wiringpi.com)

---
## センサーモジュール接続
[ここ](http://pi.gadgetoid.com/pinout/pin1_3v3_power "Raspberry Pinout")のピンアウト表を参照しました。今回は、1,3,5,9ピンを使用し設定します。
ADDRピンに0.7VCC以上流すとI2Cアドレスが、0x23から0x5Cになります。
ADDRピンは、1Kの抵抗を通ってGNDに繋がっているようです。他のデバイスと重なってないので、接続なし(0x23)で使用します。[参照](http://www.aitendo.com/product/10240)
　ADDR = ‘H’ ( ADDR ≧ 0.7VCC ) の時 “1011100“
　ADDR = 'L' ( ADDR ≦ 0.3VCC ) の時 “0100011“

![image](https://qiita-image-store.s3.amazonaws.com/0/74786/847d1d7a-94b9-228c-d915-c60087869798.png)

## センサーモジュール設定情報
[説明書](http://rohmfs.rohm.com/jp/products/databook/datasheet/ic/sensor/light/bh1750fvi-j.pdf "Datasheet")を読んでみます。
シェルスクリプトでも簡単に使用できるRaspberryPiで使いやすいセンサーモジュールだと思います。

説明書が分かり易いので、そのままなのですが、命令一覧になります。

![image](https://qiita-image-store.s3.amazonaws.com/0/74786/afac22dd-2886-e72e-9f14-ecf968812af0.png)

1回測定でしたら、電源をオンにし測定命令を与え、測定時間を待ち、結果を取得すればよいようです。
取得した結果は、以下の計算式で計算します。

H-resolution mode 時 1count あたりの照度 = 1 / 1.2 *( 69 / X )
H-resolution mode2時 1count あたりの照度 = 1 / 1.2 *( 69 / X ) / 2
1.2 : 測定確度
69 : MTregの初期値(10進表記)
X :MTregの値

入力光減衰補正機能(感度補正機能)があり、測定時間設定レジスタ(Mtreg)の値を変更することによって利用できます。
感度をN倍にする場合、測定時間もN倍されます。

31〜254の範囲で、初期値は69です。
上の表を参照し、設定したい感度の上位3ビットを"01000"のあとに付与して8ビットを構成し、感度の下位5ビットを"011"のあとに付与して8ビットを構成し設定します。

例えば、感度2倍なら69の倍で138なので、2進表記で"1000_1010"になります。
それを、上位3ビット(100)と下位5ビット(01010)に分け、上記の構成を実施すると、"0100_0100"と"0110_1010"になります。

H-resolution mode2は、10lx 以下の照度検出に適したモードのようです。

---
## センサーモジュール設定手順

#### SPI有効

```bash:SPI有効
$ sudo raspi-config
```

「8 Advanced Options」 → 「A6 SPI」 → 「SPI enable」

#### I2C有効

```bash:I2C有効
$ sudo raspi-config
```

「8 Advanced Options」 → 「A7 SPI」 → 「I2C enable」

#### I2Cモジュール設定

```bash:I2Cモジュール読み込み設定
$ sudo nano /etc/modules
```

```
snd-bcm2835
i2c-dev
```

#### I2Cライブラリインストール

```bash:I2Cライブラリインストール
$ sudo sudo apt-get install libi2c-dev
```

#### gitインストール

```bash:gitインストール
$ sudo apt-get install git-core
```

#### アップデート

```bash:アップデート
$ sudo apt-get update
$ sudo apt-get upgrade
```

#### WiringPiインストール

```bash:WiringPiインストール
$ git clone git://git.drogon.net/wiringPi
$ cd wiringPi
$ ./build
```

#### ライブラリパス設定

```bash:ライブラリパス追加設定
$ sudo nano /etc/ld.so.conf
$ sudo ldconfig
```

```
include /etc/ld.so.conf.d/*.conf
/usr/local/lib
```

#### センサーモジュールアドレス確認
たぶん、0x23だと思います。

```bash:アドレス確認
$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --
```

#### 再起動

```bash:再起動
$ sudo reboot
```

#### サンプルコード
このサンプルコードは、1回測定のものです。
シェルスクリプトが上手くできてませんでした。修正しました。
まずは、シェルスクリプトでデータ取得できることを確認します。

```bash:bh1750_sample.sh
#!/bin/bash

sudo i2cset -y 1 0x23 0x01 c
sleep 1

sudo i2cset -y 1 0x23 0x20 c
sleep 1

TMP=$(sudo i2cget -y 1 0x23 0x00 w)
MSB="0x$(echo $TMP | cut -c 5-6)"
LSB="0x$(echo $TMP | cut -c 3-4)"
IL=$(((MSB<<8)|LSB))

printf "Illuminance: %.2f lx\n" $(echo "scale=2;$IL / 1.2" | bc)

exit 0
```

Cでのサンプルコードです。
気になるとこや間違いなどあればコメントいただけると助かります。

```c:bh1750_sample.c
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>

#define BH1750_ADDRESS 				0x23	// SECOND ADDRESS 0x53

#define BH1750_POWER_DOWN			0x00
#define BH1750_POWER_ON				0x01
#define BH1750_RESET				0x07
#define BH1750_CONTINUE_H_RESOLUTION_MODE	0x10
#define BH1750_CONTINUE_H_RESOLUTION_MOD2	0x11
#define BH1750_CONTINUE_L_RESOLUTION_MODE	0x13
#define BH1750_ONETIME_H_RESOLUTION_MODE	0x20
#define BH1750_ONETIME_H_RESOLUTION_MOD2	0x21
#define BH1750_ONETIME_L_RESOLUTION_MODE	0x23
#define BH1750_MTREG				69	// DEFAULT 69 (31 - 254)
#define BH1750_MODE_DIV				1	// MODE2 2
#define BH1750_WAIT_TIME			150	// ms

int main(void) {

	int fd;
	int ret;

	unsigned char set_value[1];
	unsigned char result[2];

	int lData;

	fd = wiringPiI2CSetup(BH1750_ADDRESS);

	// Power On
	if((wiringPiI2CWrite(fd, BH1750_POWER_ON)) < 0) {
		printf("error: power on\n");
	}

	usleep(1000);

	// Set Configuration
	set_value[0] = BH1750_ONETIME_H_RESOLUTION_MODE;
	ret = write(fd, set_value, 1);
	if (ret < 0) {
		printf("error: set configuration value\n");
		return 1;
	} 

	usleep(BH1750_WAIT_TIME * 1000);

	// Get Value
	ret = read(fd, result, 2);
	if (ret < 0) {
		printf("error: read value\n");
		return 1;
	}

	lData = result[0] << 8;
	lData |= result[1];
	printf("Illuminace: %.2f\n", lData / 1.2 * (69 / BH1750_MTREG) / BH1750_MODE_DIV);

	return 0;
}
```