目次

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ピン ジャンパ メスケーブル 経由で接続することができます。

なお、ハブと言っても同じピン同士を繋いでいるだけなので、手持ちがない場合はブレッドボードで 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

WebI2C 版 /home/pi/Desktop/gc/i2c/i2c-detect/index.html でも確認できますが、I2C 接続をこちらを使う場合は確認後に必ずタブを閉じて

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="node_modules/@chirimen-raspi/polyfill/polyfill.js"></script>
    <script src="node_modules/@chirimen-raspi/chirimen-driver-i2c-grove-light/GROVELIGHT.js"></script>
    <script src="./main.js" defer></script>
    :
  <body>
    :
    <p id="head">TEST</p>
  </body>

HTML は ADT7410 の時とほとんど同じです。ドライバーライブラリは、GROVELIGHT.js に変わりました。リモートから最新の Polyfill とドライバを読み込みたい場合は http://r.chirimen.org/polyfill.jshttp://r.chirimen.org/grove-light.js を指定します。

c-2. main.js

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

main.js

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

main.js も温度センサとほとんど同じです。最初に I2C デバイスを操作するため I2CAccess、Port と順に取得したら SlaveAddress と一緒にドライバに渡して初期化し、あとはセンサーの値を読みたいときに read() します。詳しく見てみましょう。

var grovelight = new GROVELIGHT(port,0x29)

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

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

grovelight.init()

init()I2C ポートを開いてセンサーを初期化 します。

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

grovelight.read()

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

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

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

a. 部品と配線について

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

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

回路図

このセンサモジュールは 4 本のピンヘッダ経由で接続します。あらかじめピンヘッダをハンダ付けしておいてください。また、製品によってはチップ表面に黄色の保護フィルムがついているものがあります。剥して使用してください。

ピンの加工例 (保護フィルムが残っている状態)

加工例

b. 接続確認と example の実行

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

$ i2cdetect -y -r 1

SlaveAddress 0x52 が見つかれば接続OKです。次にexampleを動かします。

/home/pi/Desktop/gc/i2c/i2c-VL53L0X/VL53L0X.html

センサの前面 (VIN、GND、SCL、SDA等の文字が書いてある方) に手を近づけたり離したりしてみてください。距離の値が変化するはずです。

VL53L0X が計測できる距離は およそ 3〜200 cm (30-2000 mm) までです。

c.コード解説

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

c-1. index.html

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

VL53L0X.html

    :
    <script src="node_modules/@chirimen-raspi/polyfill/polyfill.js"></script>
    <script src="node_modules/@chirimen-raspi/chirimen-driver-i2c-vl53l0x/VL53L0X.js"></script>
    <script src="./main.js" defer></script>
    :
  <body>
    :
    <tr><td>Distance [mm]</td>
    <td id="dist"></td></tr>
    :
  </body>

HTML は ADT7410 の時とほとんど同じです。ドライバーライブラリは VL53L0X.js に変わりました。リモート版の URL は https://r.chirimen.org/vl53l0x.js です。

c-2. main.js

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

main.js

  var dist = document.getElementById("dist");
  var i2cAccess = await navigator.requestI2CAccess();
  var port = i2cAccess.ports.get(1);
  var vl = new VL53L0X(port, 0x29);
  await vl.init(); // for Long Range Mode (<2m) : await vl.init(true);
  for (;;) {
    var distance = await vl.getRange();
    dist.innerHTML=distance;
    await sleep(200);
  }

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

var vl = new VL53L0X(port, 0x29)

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

vl.init()

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

vl.read()

測距センサ VL53L0X の仕様に基づくデータ読み出し処理をここで実施しています。計測範囲内に遮蔽物がない場合には値が数値で得られないことに注意してください。

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つの数値が加速度センサの値 (単位は m/s^2) です。画面左から加速度ベクトルの X、Y、Z 成分の値となっており、ベクトルの長さは静止時に地球の重力加速度 (ここが地球なら約 9.8) となります。

ADXL345 は各成分 ±16g の範囲で計測が可能です。

加速度センサの値

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

c. コード解説

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

c-1. index.html

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

index.html

    :
    <script src="node_modules/@chirimen-raspi/polyfill/polyfill.js"></script>
    <script src="node_modules/@chirimen-raspi/chirimen-driver-i2c-grove-accelerometer/GROVEACCELEROMETER.js"></script>
    <script src="./main.js" defer></script>
    :
  <body>
    :
      <div id="ax" class="inner">ax</div>
      <div id="ay" class="inner">ay</div>
      <div id="az" class="inner">az</div>
    :
  </body>

今回のドライバーライブラリは、GROVEACCELEROMETER.js です。オンラインから読み込む場合は https://r.chirimen.org/grove-accelerometer.js です。そして X、Y、Z、3つの値を表示するため要素が3つに変わりましたが、それ以外は今回もこれまでとほとんど同じです。

c-2. main.js

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

main.js

  var ax = document.getElementById("ax");
  var ay = document.getElementById("ay");
  var az = document.getElementById("az");
  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 ページのオンライン版 にはこれらに加えてコミュニティによって順次いろいろなデバイス利用例が Advanced Examples として追加されています (ドライバーなどが cotrib ディレクトリ内にあるので注意)。作りたいもの、試したいものを考えながら試してみてください。

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

I2Cデバイスを同時に接続して使用するとき、重要な注意事項があります。それは I2C アドレスの衝突です。チュートリアル2-2 の図に書かれているように I2C デバイスは個々のアドレスを持っています。このアドレスは I2C デバイスの製品ごとに固有のアドレスが設定されていますが、偶然同じアドレスを持ったデバイスを手にすることもあります。

アドレスが衝突しているデバイスは同時に接続できません。 このチュートリアルで使ったデバイスのアドレスを以下の表に掲載します。NativeAddr がそのデバイスのオリジナルの状態のアドレスです。すでに衝突しているものがいくつかあるのがわかると思います。

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

下表の ChangedAddr はアドレス変更可能なデバイスでジャンパーを設定し、すべてのデバイスのアドレスを衝突しないようにする例です。

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

まとめ

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

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

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