5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (41) 距離センサ4 I2C RPR-0521RS

照度と距離がカウント値で得られるセンサ

 RPR-0521RSは、距離を測る近接センサと、環境の明るさを測るフォト・ダイオードを搭載した複合センサです。スイッチサイエンスのモジュールを入手しました。I2Cインターフェースを通して、16ビット・データでカウントを読み取ります。

  Conta 照度・近接一体型センサモジュール RPR-0521RS搭載

 このモジュールの説明によると、一つは100mmまでの範囲で赤外線を反射して距離を測る近接センサ(PS)です。データシートにはPSという用語が頻繁に出てきますが、説明はありません。データシートには反射物との距離が50mm時のカウント値が掲載されていますが、ほかの距離のデータはありません。

 もう一つ、暗がりから直射日光まで幅広い範囲の照度が得られるセンサ(ALS)が搭載されているとあります。データシートには暗がりのカウント値が最大10、明るいときのカウント値がいくらであるのかを見つけられませんでした。照度計として利用できる赤外と可視光の二つのセンサがありますが、中心波長や感度特性は不明です。取得したカウント値からlxを求める変換式は掲載されていません。したがって、カウント値を基準として、明るさや距離のスレッショルドを設定する用途のセンサといえます。

 モジュールの説明によると、電源電圧は2.8~3.6Vなので、Arduino UNOなどの5Vを使うマイコンでは直接つなげられません。また、I2Cのスレーブ・アドレスは0x38と書かれています。

BM1383AGLVのスペック

 製造元ロームのデータシートに転載不可と書かれているので、直接データシートを読んでください。

接続

 ラズパイとの接続は下記のようになります。

RPR-0521RS ラズパイ
SDA 3番ピン
SCL 5番ピン
GND 6番ピン
3.3V 1番ピン 3.3V
IO4(INT) -

 ラズパイは本体に1.8kΩのプルアップ抵抗がSDA/SCL信号に入っています。Arduinoでは入っていません。モジュール表側にチップ抵抗をはんだ付けできるパターンが用意されているので、コンパクトに実装できます。

 このモジュールは、ピンヘッダが最初からはんだ付けされています。ピンはほぼ0.4mmスクエアで、細ピンではありません。モジュールに仕様書には、ピンの太さの記述は見当たりません。

 上記のように接続が完了したら、ラズパイの電源を入れます。ターミナルから、i2cdetect -y 1 で接続を確認しました。スレーブ・アドレスは0x38でした。

レジスタ

 製造元ロームのデータシートに転載不可と書かれているので、直接データシートを読んでください。

プログラム

 パワーオン・リセット時にセンサはスリープしています。最初にモード・コントロール・レジスタ0x41へ0xfeを送って起こします。0x42のALS_PS_CONTROLレジスタでは、ALSゲインは1倍、LEDの電流100mAに初期設定されています。0x43のPS_CONTROL レジスタでは、PSゲインは1倍に初期設定されています。初期設定のまま使います。

 PSデータ(0x44)を読みます。反射強度の最初のバイトは低位、次が高位バイトです。

 ALSデータDATA0(0x46)を読みます。DATA0は可視光+赤外線の照度と思われます。最初のバイトは低位、次が高位バイトです。

 ALSデータDATA1(0x48)を読みます。DATA0は赤外線の照度と思われます。最初のバイトは低位、次が高位バイトです。

 データシートには、連続測定結果というグラフが頻繁に出てきますが、連続測定やワンショット測定モードというのはないようです。測定時間の設定はできます。LEDの電流とともに設定すれば、感度を調整できるようです。10~400msの範囲です。0xfeは100msの設定です。

 データシートには、どの命令を送ったときからLEDが発光し、新しいデータがいつレジスタに用意されるかが書かれていません。また、用意される前に読み出したデータが不定であるか、前のデータがラッチされているかも書かれていません。モード・コントロール・レジスタへ書き込んだ後余裕を見て200ms待つことにします。その後、繰り返して測定が行われ新しいデータが用意されると期待し、連続して読み出します。

#!/usr/bin/env python
import smbus
import time
i2c = smbus.SMBus(1)
addr=0x38
config = 0b11000110

#main
i2c.write_byte_data(addr,0x40,0x80) #reset
i2c.write_byte_data(addr,0x41,config)
time.sleep(0.2)
while 1:
data = i2c.read_i2c_block_data(addr,0x44,6)
PS = data[1]*256 + data[0]
ALS_DATA0 = data[3]*256 + data[2]
ALS_DATA1 = data[5]*256 + data[4]
print PS,ALS_DATA0,ALS_DATA1
time.sleep(1)

実行結果

 距離センサを測定しました。反射物体はアルミ・ブロックです。

 10~100mmの範囲で、両対数では直線関係に見えます。

 10から100mm間の値で近似曲線をエクセルに計算してもらいました。60mm以上では近似できていますが、近距離では大きく値が異なります。したがって、複数回測定し、10~100mm間を3,4等分し、それぞれの区間で近似曲線を求めて数式にすると、精度が上がると思われます。

 明るさを変えながら、照度計と照度の測定値を比較します。照度計のlux値とALSデータDATA0のカウントはほぼ同じ数値です。部屋の中は蛍光灯とLED電球の光りが入り混じっています。

  可視光センサは赤外線を分離できないので、単独の赤外線データから減じるとlux値がより正しくなると思われます。赤外線の強度の比率がわからないので、とりあえずそのまま引いてみました。

 エクセルが推定した近似曲線から、利用した照度計とこのセンサの照度は比例関係にあり、センサのカウント値を約1/2するとlux値が得られました。照度計のもつ確度、照度計の取り付け位置によって計測値は異なります。したがって、このセンサを使ってほんとうのlux値を求めるには、校正された照度計を使い、測定条件を慎重に選び、測定を複数回行ったうえで近似関数を求めて使ってください。

※執筆時点;2017-11-29版をダウンロードし、sudo apt-get update と sudo apt-get upgrade -y および sudo rpi-update で更新し、カーネルはuname -a で確認。4.9.70でした。

※プログラムを仮にrpr0521.pyという名前で/home/piに保存すると、sudo chmod 755 rpr0521.py で実行権を付け、ターミナルから、python rpr0521.pyで実行します。I2CやSPIのグループにpiユーザが属しているので、sudoは不要です。
 プログラム・リストは、表示の関係でTabキーが無視されるので、スペースに代えてあります。また、リスト中を2回クリックすると全選択になるので、CTRL-Cでコピーし、テキスト・エディタにCTRL-Vで貼り付けて利用してください。ラズパイに持っていくと、スペースやリターン・コードなどが化けていることがあるので、一度消して、ラズパイのテキスト・エディタで修正してください。

※I2Cの有効化は、こちらの説明を参照ください。SPIなどにもEnableにチェックを入れています。