1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Grove の I2C 静電容量タッチセンサのデータを Node.js + johnny-five で得る

Last updated at Posted at 2017-01-08

やりたいこと

Groveシステムの I2C静電容量タッチセンサのデータを、Node.js + johnny-five で得ることで、遠隔地にある何かに誰かが触れたことを検出できるようにする。

きっかけは、書籍「二足歩行ロボット 工作&プログラミング(リックテレコム)」で、このタッチセンサを2足歩行ロボットRapiroに組み込んでいるのを見たことです。書籍では、センサ開発元(Seeed Studio)が提供しているライブラリとサンプルコードを使って Arduino IDE でセンシングを実装していました。ここで、もし Node.js + johnny-five で実装できれば、ネットワーク越しに遠隔監視できると考えました。

I2C(アイ・スクエア・シー)のこともよく分かっていない私ですが、上述のArduino用ライブラリとサンプルコードを解読して、johnny-five でセンサのデータを取得することができましたので、報告です。

方法

機材

以下が接続の様子です。
C1nkP8VVQAA-5X8.jpg

実装したコード

例として C:\Users\username\touch\app.js として作成

app.js
'use strict';

const five = require('johnny-five');    // johnny-fiveモジュールを使う
const arduino = new five.Board({        // arduinoを接続
    port: 'COM5'                        // COMポート番号(環境による)
});
const MPR121ADDR = 0x5A;    // MPR121静電容量タッチセンサコントローラのアドレス

// MPR121静電容量タッチセンサコントローラの初期化関数
function mpr121Config(device) {
    // Section A: dataがベースラインより大きい時のフィルタリング
    device.i2cWrite(MPR121ADDR, 0x2B, 0x01);    // MHD_R
    device.i2cWrite(MPR121ADDR, 0x2C, 0x01);    // NHD_R
    device.i2cWrite(MPR121ADDR, 0x2D, 0x00);    // NCL_R
    device.i2cWrite(MPR121ADDR, 0x2E, 0x00);    // FDL_R
    // Section B: dataがベースラインより小さい時のフィルタリング
    device.i2cWrite(MPR121ADDR, 0x2F, 0x01);    // MHD_F
    device.i2cWrite(MPR121ADDR, 0x30, 0x01);    // NHD_F
    device.i2cWrite(MPR121ADDR, 0x31, 0xFF);    // NCL_L
    device.i2cWrite(MPR121ADDR, 0x32, 0x02);    // FDL_L
    // Section C: 各電極(ELE0-11)の閾値(T:Touch,R:Release)の設定
    device.i2cWrite(MPR121ADDR, 0x41, 0x0F);    // ELE0_T
    device.i2cWrite(MPR121ADDR, 0x42, 0x0A);    // ELE0_R
    device.i2cWrite(MPR121ADDR, 0x43, 0x0F);    // ELE1_T
    device.i2cWrite(MPR121ADDR, 0x44, 0x0A);    // ELE1_R
    device.i2cWrite(MPR121ADDR, 0x45, 0x0F);    // ELE2_T
    device.i2cWrite(MPR121ADDR, 0x46, 0x0A);    // ELE2_R
    device.i2cWrite(MPR121ADDR, 0x47, 0x0F);    // ELE3_T
    device.i2cWrite(MPR121ADDR, 0x48, 0x0A);    // ELE3_R
    // device.i2cWrite(MPR121ADDR, 0x49, 0x0F);    // ELE4_T    // 電極4以降も使う場合
    // device.i2cWrite(MPR121ADDR, 0x4A, 0x0A);    // ELE4_R
    // device.i2cWrite(MPR121ADDR, 0x4B, 0x0F);    // ELE5_T
    // device.i2cWrite(MPR121ADDR, 0x4C, 0x0A);    // ELE5_R
    // device.i2cWrite(MPR121ADDR, 0x4D, 0x0F);    // ELE6_T
    // device.i2cWrite(MPR121ADDR, 0x4E, 0x0A);    // ELE6_R
    // device.i2cWrite(MPR121ADDR, 0x4F, 0x0F);    // ELE7_T
    // device.i2cWrite(MPR121ADDR, 0x50, 0x0A);    // ELE7_R
    // device.i2cWrite(MPR121ADDR, 0x51, 0x0F);    // ELE8_T
    // device.i2cWrite(MPR121ADDR, 0x52, 0x0A);    // ELE8_R
    // device.i2cWrite(MPR121ADDR, 0x53, 0x0F);    // ELE9_T
    // device.i2cWrite(MPR121ADDR, 0x54, 0x0A);    // ELE9_R
    // device.i2cWrite(MPR121ADDR, 0x55, 0x0F);    // ELE10_T
    // device.i2cWrite(MPR121ADDR, 0x56, 0x0A);    // ELE10_R
    // device.i2cWrite(MPR121ADDR, 0x57, 0x0F);    // ELE11_T
    // device.i2cWrite(MPR121ADDR, 0x58, 0x0A);    // ELE11_R
    // Section D: フィルタの設定
    device.i2cWrite(MPR121ADDR, 0x5D, 0x04);    // よく分かりません
    // Section E: 電極の設定
    device.i2cWrite(MPR121ADDR, 0x5E, 0x0C);    // 12個全ての電極を利用
}

// arduinoの準備ができたら
arduino.on('ready', function() {
    this.i2cConfig();       // I2Cを使うためのjohnny-fiveのおまじない
    mpr121Config(this);     // MPR121静電容量タッチセンサコントローラを初期設定
    // センサの状態の読み込みとタッチの判定
    this.i2cRead(MPR121ADDR, 1, function(bytes){    // センサを4個以上使う場合は2バイト読む?
        if((bytes & 0x01) == 0x01) {        // ch0を判定
            console.log('ch0 is touched');
        }
        if((bytes & 0x02) == 0x02) {        // ch1を判定
            console.log('ch1 is touched');
        }
        if((bytes & 0x04) == 0x04) {        // ch2を判定
            console.log('ch2 is touched');
        }
        if((bytes & 0x08) == 0x08) {        // ch3を判定
            console.log('ch3 is touched');
        }
    });
});

実行と動作確認

  • Node.js コマンドプロンプト にて johnny-five をインストール
C:\Users\username> npm install johnny-five
  • Node.js コマンドプロンプト で以下を実行
C:\Users\username\touch> node app.js
  • タッチセンサに触れた時に 'ch x is touched'( x はch番号)とコンソールに表示されればOK
  • 同時に複数のセンサに触れても大丈夫です

解説

  • このセンサには、MPR121というコントローラが使われており、そのI2Cアドレスは 0x5A だそうで、データの読み書き(i2cRead( )i2cWrite( ))にはそのアドレスを用います(コード中の MPR121ADDR
  • 初期設定の関数(mpr121Config( ) { })の中身は、開発元のサンプルコードを参考にしており、内容については私は理解できていません
  • なお、センサ電極(feeler)を5個以上使う場合は、コメントアウトした部分も使います

 

  • i2cRead(address, bytesToRead, handler(arrayOfBytes)) は、繰り返し、指定addressの値をbytesToReadぶん読み、データarrayOfBytesを伴ってhandlerをコールします
  • 各チャンネルのセンサに個別に触れると以下のデータ(bytes)が得られます
ch bytes ビット列
0 0x01 □□□■
1 0x02 □□■□
2 0x04 □■□□
3 0x08 ■□□□
(□=0, ■=1 以下同様)
  • 複数同時に触れると、それぞれの bytes が足し合わされた(OR された)値が返ってきます
chの組み合わせ bytes ビット列
0, 1 0x03 □□■■
0, 2 0x05 □■□■
0, 3 0x09 ■□□■
1, 2 0x06 □■■□
1, 3 0x0A ■□■□
2, 3 0x0C ■■□□
0, 1, 2 0x07 □■■■
0, 1, 3 0x0B ■□■■
0, 2, 3 0x0D ■■□■
1, 2, 3 0x0E ■■■□
0, 1, 2, 3 0x0F ■■■■

 

  • 各chに触れているか否かの判定は、戻り値 bytes と所望のchの値との AND が、所望のchの値になるかどうかを見ればよいことになります
  • 例えば、0x0F(■■■■) & 0x01(□□□■) は 0x01(□□□■) となり、ch0に触れられて__いる__ことがわかる
  • 同様に、0x0E(■■■□) & 0x01(□□□■) は 0x00(□□□□) となり、ch0に触れられて__いない__ことがわかる
        if((bytes & 0x01) == 0x01) {        // ch0を判定
            console.log('ch0 is touched');
        }
        if((bytes & 0x02) == 0x02) {        // ch1を判定
            console.log('ch1 is touched');
        }
        if((bytes & 0x04) == 0x04) {        // ch2を判定
            console.log('ch2 is touched');
        }
        if((bytes & 0x08) == 0x08) {        // ch3を判定
            console.log('ch3 is touched');
        }

 

  • 今回のコードでは、4つのセンサ分(1バイト)しかデータを取っていません
  • センサ電極(feeler)を追加購入してもっとたくさんつなげますが、その際は、以下の i2cRead(address, bytesToRead, handler(arrayOfBytes)) で複数バイト読んできて…(あとはご自身でご想像・お試しください)
    // センサの状態の読み込みとタッチの判定
    this.i2cRead(MPR121ADDR, 1, function(bytes){ ... }

所感や今後

よく分からないことだらけでしたが、サンプルコード(C++)を頑張って解読して、試行錯誤の末、なんとか JavaScript(johnny-five)に移植することができました。
これで、書籍「二足歩行ロボット 工作&プログラミング(リックテレコム)」の内容をほぼすべて JavaScript(Node.js)に書き換えられそうな気がしてきました。さらに、socket.io と組み合わせることで、遠隔でのセンシングが可能になります。

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?