Raspberry Piで取得したセンサーデータをリアルタイムに可視化する(センサー編)
前回に引き続き、Raspberry Piでセンサーデータを取得して、Milkcocoaを使ってリアルタイムにブラウザ上にグラフ化する方法を紹介していきます。
今回は以下の流れで、センサーデータの取得と保存について説明していきます。
- 回路を組む
- シリアル通信の準備
- ADコンバーターからデータを取得
- データの確認と保存
なお、センサーは以下のキットのものを使用します。同じように開発したい場合はご購入ください。
ハック ラズベリーパイ Raspberry Pi 電子工作入門キット。
回路を組む
こちらの記事の図の通りに回路を組んで下さい。以下、私が実際に組んだ回路です。フォトトランジスタ(センサー)によって変化するアナログ信号を、ADコンバーターでデジタル信号に変換してRaspberry Piに入力している、という回路になります。
フォトトランジスター、ADコンバーターには向きがあるので注意してください。また使用する7.5kΩの抵抗の色は「紫・緑・赤・金」です。
回路を組むときは、Raspberry Piの電源をOFFにした状態で行って、回路を組み終わったら電源を入れるようにします。
シリアル通信の準備
回路を組んだら、データの取得に用いるシリアル(SPI)通信の準備をします。シリアル通信用のnpmモジュール(pi-spi)があるので、インストールします。
前回と同じディレクトリ(work/milkgraph)で以下のコマンドを実行します。
$ npm install pi-spiRaspberry Piでは、デフォルトでシリアル通信が使えない設定になっているので、使えるようにしてあげます。
$ sudo vi /etc/modprobe.d/raspi-blacklist.conf#blacklist spi-bcm2708
blacklist i2c-bcm2708blacklist spi-bcm2708の部分を#でコメントアウトしたら保存して、sudo rebootで再起動します。
再起動したら、以下のコマンドでデバイスが認識されているか確認して下さい。
$ ls -la /dev/spi*
crw------- 1 root root 153, 0 Jan 1 1970 /dev/spidev0.0
crw------- 1 root root 153, 1 Jan 1 1970 /dev/spidev0.1ADコンバーターからデータを取得
準備ができたので、以下のコードで照度を取得してコンソールに表示します(こちらの記事を参考にしています)。
// lux.js
var SPI = require('pi-spi');
var spi = SPI.initialize("/dev/spidev0.0"),
MCP3002 = Buffer([0x68, 0]);
setInterval(function() {
spi.transfer(MCP3002, MCP3002.length, function (e,d) {
if (e) console.error(e);
else {
var v = ((d[0]<<8) + d[1]) & 0x03FF
console.log(v, "Got \""+v.toString()+"\" back.");
}
});
}, 5000);これを見て一発で理解できる人はそういないと思うので、ひとつひとつ説明します。
Raspberry Pi側から送るデータの作成
MCP3002 = Buffer([0x68, 0]);このADコンバーターは、先に「どういうデータを取得するか」という信号を送ったあとに、データを取得するようになっています。その信号が上記の式になります。
これは、参考記事の以下の部分を、pi-spi用に変換したものです。pi-spiでは通信のデータをBufferクラスで扱うことになっていて、「0x68」は「0b01101000(2進数)」を16進数に変換したものです。
例えば、今回のコードで以下のデータを送っていますが、1bitは0、2bit目はスタートビットとして必ず1、SGL/DIFFビットでは1、次のビットでは今回はCH0を使っているので0,MSBFでは受け取るデータをMSBFにするため1としています。それ以降はDon't careのため0です。
raw = spi.write [0b01101000,0]
ちゃんと理解したい方は、MCP3002のデータシートを見て下さい。一番関係あるであろう図と表を以下に貼っておきます。
データの送受信
spi.transfer(MCP3002, MCP3002.length, function (e,d) {これは、pi-spiのドキュメントを見ればわかると思いますが、ざっくり説明すると以下です。
- transferメソッドは、データの送受信の両方を行うもの
- 第一引数は送信したいデータ、第二引数はそのデータの長さ
- コールバックの第二引数(d)にデータを受信。第一引数(e)はエラー。
実データの取り出し
var v = ((d[0]<<8) + d[1]) & 0x03FFこれは結構ややこしいですが説明します。
まず、ADコンバータから返ってくるデータは16bitです。
そして、dはBufferクラスのデータです。Bufferクラスは、データが8bit区切りの配列になっています。
つまり、d[0]とd[1]に分かれてデータが入っているということになります。
また、先ほど貼ったデータシートの図の「MCU Recieved Data」を見るとわかるように、最初の6bitはセンサーの値に関係のないデータです。
なので、「d[0]とd[1]を足して、最初の6bitを削る」という操作が必要です。
この操作を実現するのが先ほどの((d[0]<<8) + d[1]) & 0x03FFになります(シフト演算(<<)とAND演算(&)の説明はこちらをご覧下さい)。わかりにくいので以下に図解します。
細かく説明しましたが、このACコンバータ(MCP3002)を使うときはすべてこのやり方なので、理解せずにコピペでも全然問題ないです。
データの確認と保存
上記のコードを実行すると、5秒ごとに数字が出力されるかと思います。
$ node lux.jsセンサーを手で覆ったりして値が変わるか試してみて下さい。
ちなみに、得られた値を照度の単位であるルクスに変換したい場合は、先ほどの参考記事のグラフで確認して下さい。
Milkcocoaに保存する
センサーのデータがちゃんと取れていることがわかったら、保存をしましょう。
// lux.js
var SPI = require('pi-spi');
var MilkCocoa = require('milkcocoa');
var spi = SPI.initialize("/dev/spidev0.0"),
MCP3002 = Buffer([0x68, 0]);
// {your-app-id}の部分は、Milkcocoaに(無料)登録してアプリを作成した際に生成されるアプリ固有の文字列です。
var milkcocoa = new MilkCocoa("{your-app-id}.mlkcca.com");
var old = 0;
setInterval(function() {
spi.transfer(MCP3002, MCP3002.length, function (e,d) {
if (e) console.error(e);
else {
var v = ((d[0]<<8) + d[1]) & 0x03FF
console.log(v, "Got \""+v.toString()+"\" back.");
if(old != v) milkcocoa.dataStore('light').push({v : v});
old = v;
}
});
}, 5000);上記の例ではデータストアを節約するために、前と同じ値だったらpushしないようにしています。保存されたかどうか確認するには、Milkcocoaの管理画面のデータストアで、lightデータストアを選択して「グラフ表示」をクリックしてみて下さい。
プログラムを実行したままにする
プログラムを実行したままにしたいときは、pm2というモジュールを使ってデーモン化します。
$ npm install pm2 -gインストールしたら、以下のコマンドでデーモン化できて、ssh接続を切っても実行されたままになります。
$ pm2 start lux.js次回はリアルタイムなグラフを作ります
今回は、センサーデータの取得方法を説明しました。
ひとつひとつ理解しようとすると大変ですが、同じコンバーターを使っている限り同じコードを使い回せるので、大丈夫かと思います。
次回は、保存されたデータを使ってリアルタイムなグラフをD3.jsで実装していきます。
※Raspberry PiやTesselでMilkcocoaを使うハンズオンが7月6日に開催されます。マイコンボードを持っていない方も会場で購入できるので、興味を持たれた方は是非参加してみて下さい!