目次

3. I2C 応用編 (その他のセンサ)

概要

CHIRIMEN for Raspberry Pi 3(以下 「CHIRIMEN Raspi3」) を使ったプログラミングを通じて、Web I2C API の使い方を学びます。

前回は温度センサを使いながら Web I2C API の基本的な利用方法を学びました。今回は温度センサ以外のI2Cセンサの使い方を見ていきましょう。

ここでは例として光センサ、距離センサ、加速度センサの 3 つについて詳しく説明していますが、最後に「他の I2C モジュールも使ってみる」として紹介しているように、CHIRIMEN ではそれ以外にも多くの I2C デバイス (あるいは I2C の ADC を使って様々なアナログセンサ類) が簡単に扱えるようになっており、 examples ページ (オンライン版) に回路図とサンプルコードが用意されています。各自興味のあるセンサを順に試していってください。

前回までのおさらい

本チュートリアルを進める前に前回までのチュートリアルを進めておいてください。

前回までのチュートリアルで学んだことは下記のとおりです。

1.準備

複数のI2Cモジュールを接続するために

前回は Raspberry Pi と温度センサを4本のジャンパケーブルで直接接続しました。

I2Cバスには複数のモジュールが接続できますので、今回は複数の I2C モジュールを容易に追加・削除できるように Grove I2C Hub を利用することにします。

Grove I2C Hub は、4つの Grove コネクタを備えた I2C モジュールを接続するためのハブです。

4ピンの Grove 4ピン ケーブルを経由すれば、後述するGrove Digital Light SensorなどGroveコネクタを備えたI2Cモジュールを直接接続することができます。

Raspi 3 や前回のADT7410などピンヘッダを備えた(あるいは事前にスルーホールにピンヘッダをはんだ付けしてある)モジュールとの接続には、Grove 4ピン ジャンパ メスケーブル 経由で接続することができます。

用意するもの

ここでは、1つのGroveコネクタつきI2Cモジュールと1つのピンヘッダつきI2Cモジュールを接続することを想定し、下記を用意しておきましょう。

ハブとケーブル

上記に加え今回紹介するセンサが必要となりますが、センサについては各センサの説明のパートに記載します。

2. 光センサを使ってみる

光の強度に反応するセンサを使ってみましょう。

a. 部品と配線について

「1.準備」のパートに記載したものに加え、下記を用意してください。

Raspberry Pi 3との接続方法については、下記回路図を参照ください。

/home/pi/Desktop/gc/i2c/i2c-grove-light/schematic.png

回路図

このセンサモジュールはGroveコネクタを備えていますので、接続方法に応じてコネクタを選んでください。

b. 接続確認とexampleの実行

i2cdetect で接続を確認しておきましょう。

$ i2cdetect -y -r 1

SlaveAddress 0x29 が見つかれば接続OKです。

次に example を動かします。

/home/pi/Desktop/gc/i2c/i2c-grove-light/index.html

画面の回路図の下の数値が明るさの値です。

センサに当たる光を遮断してみてください。数値が小さくなるはずです。

逆にセンサに LED の光を直接当てると数値が大きくなることが確認できるでしょう。

c. コード解説

example のコードから、光センサに関係する部分を見ていきます。

今回はドライバーライブラリの中までは深入りせずに、アプリケーションの流れを追ってみましょう。

ADT7410 の時とほとんど同じであることがわかるはずです。

c-1. index.html

下記がindex.htmlの中から主要な部分を抜き出したコードです。

index.html

: 
  <script src="../../polyfill/polyfill.js"></script>
  <script src="../../drivers/i2c-grove-light.js"></script>
  <script src="./main.js"></script>
  :
  <body>
    :
    <p id="head">TEST</p>
    :
  </body>

HTML は ADT7410 の時とほとんど同じです。 ドライバーライブラリが、i2c-grove-light.js に変わりました。

c-2. main.js

次に、main.jsを見てみましょう。(重要な部分以外は削っています)

main.js

  var i2cAccess = await navigator.requestI2CAccess();
  var port = i2cAccess.ports.get(1);
  var grovelight = new GROVELIGHT(port,0x29);
  await grovelight.init();
    while(1) {
    var value = await grovelight.read();
    head.innerHTML = value ? value : head.innerHTML;
    await sleep(200);
  }

main.js も温度センサとほとんど同じです。

var grovelight = new GROVELIGHT(port,0x29)

ここで光センサ用のドライバーライブラリのインスタンス生成を行なっています。

ライブラリ名が変わっただけで ADT7410 と同様に、port オブジェクトと、SlaveAddress をパラメータで渡しています。

grovelight.init()

init() では、インスタンス生成時に指定したportオブジェクトと slaveAddress(0x29) を用いて I2CPort.open() を行ない、返却される I2CSlaveDevice を保存後に resolve() で呼び出し元に処理を返しています。

grovelight.read()

Grove Digital Light Sensor の仕様に基づくデータ読み出し処理をここで実施しています。

3. 測距センサを使ってみる

モノまでの距離を測定する測距センサ (GP2Y0E03) を使ってみましょう。

a. 部品と配線について

「1.準備」のパートに記載したものに加え、下記を用意してください。

Raspi 3 との接続方法については、下記回路図を参照ください。

/home/pi/Desktop/gc/i2c/i2c-GP2Y0E03/schematic.png

回路図2

このセンサモジュールには、細い7本のケーブルが付属していますが、このままでは Raspi3 と接続することができません。

この細いケーブルを 2.54mm のジャンパーピンにハンダづけするなどしてブレッドボード経由で Raspi3 と接続できるよう、加工しておいてください。

ピンの加工例

加工例

b. 接続確認と example の実行

i2cdetect で接続を確認しておきましょう。

$ i2cdetect -y -r 1

SlaveAddress 0x40 が見つかれば接続OKです。

次にexampleを動かします。

/home/pi/Desktop/gc/i2c/i2c-GP2Y0E03/index.html

画面の回路図の下の数値が距離の値(cm)です。 センサの前面(小さな目玉のような部品が着いた面)を障害物の方向に向けてみてください。障害物とセンサの距離に応じて数字が変化するはずです。

GP2Y0E03 が計測できる距離は 60cm くらいまでです。

測定できる範囲を超えている場合、out of range と表示されます。

c.コード解説

example のコードから、測距センサに関係する部分を見ていきます。

c-1. index.html

下記がindex.htmlの中から主要な部分を抜き出したコードです。

index.html

: 
  <script src="../../polyfill/polyfill.js"></script>
  <script src="../../drivers/i2c-GP2Y0E03.js"></script>
  <script src="./main.js"></script>
  :
  <body>
    :
    <p id="distance">init</p>
    :
  </body>

HTML は ADT7410 の時とほとんど同じです。 ドライバーライブラリが、i2c-GP2Y0E03.js に変わりました。

c-2. main.js

次に、main.js を見てみましょう。(重要な部分以外は削っています)

main.js

  var i2cAccess = await navigator.requestI2CAccess();
  var port = i2cAccess.ports.get(1);
  sensor_unit = new GP2Y0E03(port,0x40);
  await sensor_unit.init();

  while(1) {
    try {
      var distance = await sensor_unit.read();
      if(distance != null){
        valelem.innerHTML = "Distance:"+distance+"cm";
      } else {
        valelem.innerHTML = "out of range";
      }
    } catch(err) {
      console.log("READ ERROR:" + err);
    }
    await sleep(500);
  }

main.js も温度センサとほとんど同じです。

var sensor_unit = new GP2Y0E03(port,0x40)

ドライバーライブラリのインスタンス生成処理です。

sensor_unit.init()

こちらも、内部で I2CSlaveDevice インタフェースを取得する処理で、他のセンサと同様です。

sensor_unit.read()

測距センサ GP2Y0E03 の仕様に基づくデータ読み出し処理をここで実施しています。

4. 三軸加速度センサを使ってみる

傾きなどに反応するセンサを使ってみましょう。

a. 部品と配線について

「1.準備」のパートに記載したものに加え、下記を用意してください。

Raspi 3 との接続方法については、下記回路図を参照ください。

/home/pi/Desktop/gc/i2c/i2c-grove-accelerometer/schematic.png

回路図

このセンサモジュールはGroveコネクタを備えていますので、接続方法に応じてコネクタを選んでください。

b. 接続確認とexampleの実行

i2cdetect で接続を確認しておきましょう。

$ i2cdetect -y -r 1

SlaveAddress 0x53 が見つかれば接続OKです。

次に example を動かします。

/home/pi/Desktop/gc/i2c/i2c-grove-accelerometer/index.html

画面の回路図の下に表示されている3つの数値が加速度センサの値です。

画面左から、X、Y、Zの値となっています。

加速度センサの値

センサを傾けると数値が変化するはずです。

c. コード解説

exampleのコードを見てみましょう。

c-1. index.html

下記がindex.htmlの中から主要な部分を抜き出したコードです。

index.html

  : 
  <script src="../../polyfill/polyfill.js"></script>
  <script src="../../drivers/i2c-grove-accelerometer.js"></script>
  <script src="./main.js"></script>
  :
  <body>
    :
      <div id="ax" class="inner">ax</div>
      <div id="ay" class="inner">ay</div>
      <div id="az" class="inner">az</div>
    :
  </body>

ドライバーライブラリが、i2c-grove-accelerometer.js に、そしてX、Y、Z、3つの値を表示するため要素が3つに変わりましたが、それ以外は今回もこれまでとほとんど同じです。

c-2. main.js

次に、main.js を見てみましょう。(重要な部分以外は削っています)

main.js

  var i2cAccess = await navigator.requestI2CAccess();
  var port = i2cAccess.ports.get(1);
  var groveaccelerometer = new GROVEACCELEROMETER(port,0x53);
  await groveaccelerometer.init();
  while(1) {
    try {
      var values = await roveaccelerometer.read();
      ax.innerHTML = values.x ? values.x : ax.innerHTML;
      ay.innerHTML = values.y ? values.y : ay.innerHTML;
      az.innerHTML = values.z ? values.z : az.innerHTML;
    } catch ( err ){
      console.log("READ ERROR:" + err);
    }
    await sleep(1000);
  }

main.js も温度センサとほとんど同じです。

var groveaccelerometer = new GROVEACCELEROMETER(port,0x53)

ここで加速度センサ用のドライバーライブラリのインスタンス生成を行なっています。

grovelight.init()

これまでのドライバーライブラリ同様に init() では、インスタンス生成時に指定した port オブジェクトと slaveAddress(0x29) を用いて I2CPort.open() を行ない、返却される I2CSlaveDevice を保存後にresolve()で呼び出し元に処理を返しています。

groveaccelerometer.read()

read() では、加速度センサの X、Y、Zの値が一度に返却されます。

5. 演習: 複数のセンサを組み合わせて使ってみよう

せっかく Grove I2C Hub を用意しましたので、これまでの復習と応用を兼ねて下記のような組み合わせで2つのセンサを繋いで動かしてみましょう。

※この組み合わせなら、冒頭で用意したケーブルで足りるはずです。

オンライン版のドライバーライブラリは下記にあります。

まずはセンサを繋いでから、jsbinjsfiddle を使ってコードを書いてみましょう。

6. 他の I2C モジュールも使ってみる

前回からこれまでに 4 つの I2C センサを使ってみました。

CHIRIMEN Raspi3 には、他にも /home/pi/Desktop/gc/i2c/ 配下に下記のようなI2Cモジュールの examples が含まれています。それぞれの回路図、デイバスドライバ、サンプルコードもあるので、お手持ちのデバイスを使ってみてください。

また、CHIRIMEN Raspi3 のイメージ内に同梱されている example 以外にも、CHIIRMEN examples ページのオンライン版 にはこれらに加えてコミュニティによって順次いろいろなデバイス利用例が追加されています。作りたいもの、試したいものを考えながら試してみてください。

I2C デバイスを複数使う場合の注意事項

I2Cデバイスを同時に接続して使用するとき、重要な注意事項があります。それは I2C アドレスの衝突です。チュートリアル2―2の図に書かれているように I2C デバイスはアドレスを持っています。このアドレスは I2C デバイスの製品ごとに固有のアドレスが設定されています。そのためたまたま同じアドレスを持ったデバイスが販売されていることがあります。そしてアドレスが衝突しているデバイスは接続できません。このチュートリアルで使ったデバイスのアドレスを以下の表に掲載します。NativeAddr がそのデバイスのオリジナルの状態のアドレスです。すでに衝突しているものがいくつかあるのがわかると思います。

一方、I2C デバイスのによってはこのアドレスを変更でき、アドレスの衝突を回避できる場合があります。ただしアドレスの変更はデバイスの基板上でハードウェア的(電気的)に設定するジャンパによって設定します。(ジャンパはピンヘッダとして用意され、ジャンパ線などで設定できるものもありますが、多くの場合は半田を盛ってジャンパとするタイプです。詳しくは各デバイスを購入すると付属しているデータシートを参照してください。)下表の ChangedAddr はアドレス変更可能なデバイスでジャンパーを設定し、すべてのデバイスのアドレスを衝突しないようにした例です。

Device NativeAddr ChangedAddr
ADT7410 0x48 =>test brd:0x49
ADS1015 0x48
VEML6070 0x38, 0x39
S11059 0x2a
PCA9685 0x40 =>test brd:0x41
grove-touch 0x5a
grove-oledDisplay 0x3c
grove-gesture 0x73
grove-light 0x29
grove-accelerometer 0x53
GP2Y0E03 0x40

まとめ

このチュートリアルでは 下記について学びました。

このチュートリアルで書いたコードは以下のページで参照できます:

次のCHIRIMEN for Raspberry Pi 3 チュートリアルでは、『Web GPIO APIとWeb I2C APIを組み合わせたプログラミング』に挑戦します!