Armadillo-IoTで、TMP107(双方向SMAARTワイヤI/Fの温度センサ)評価モジュール
を使って、デイジー・チェーン接続されている4つの温度センサーのデータを読み取って、クラウド(Heroku)経由で見てみました。
(ブラウザのURLの部分は、後述の手順でHerokuから割り当てられたURLになりますので、伏字(***.herokuapp.com)にしてます。)
当方で確認した手順、サンプルプログラムを下記に説明します。
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
注意)
ここでは、当方が確認した簡易的な手順を示しているに過ぎません。(エラー処理等は考慮されていません。)
本格的には、エラー処理、フェイルセーフ等のソフト設計を行う必要があります。
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
以下、 TMP107(双方向SMAARTワイヤI/Fの温度センサ)評価モジュールは、「TMP107評価モジュール(温度センサー)」 と呼称します。
今回の動作確認は下図のような構成です。
手順の概要は下記のようになります。
●1.機材、資料
●2.Armadillo-IoTとTMP107評価モジュール(温度センサー)の接続
●3.TMP107評価モジュール(温度センサー)との通信仕様の確認
●4:TMP107評価モジュール(温度センサー)からデータを取得するサンプルプログラム
●5.クラウド(Heroku)側のアプリの準備
●6.TMP107評価モジュール(温度センサー)のデータをクラウド(Heroku)で見る
●1.機材、資料
機材は下記のものを使用しました。
・Armadillo-IoT
・TMP107評価モジュール(温度センサー)
USBインタフェース経由で、4つのTMP107(温度センサー)からデイジー・チェーンでデータを読み出せます。
今回の動作確認において、下記の資料を使用しました。
・TMP107データシート
●2.Armadillo-IoTとTMP107評価モジュール(温度センサー)の接続
TMP107評価モジュール(温度センサー)を使用するに当たり、FTDI製のUSBシリアルコンバーターのドライバが必要です。
Armadillo-IoTのカーネルコンフィギュレーションで、FTDI製のUSBシリアルコンバーターのドライバを有効にします。
ATDEで、make menuconfigを実行して、カーネルコンフィギュレーションで下記のように設定を行います。
(USB FTDI Single Port Serial Driverを有効にします。)
Kernel Configuration
Device Drivers --->
[*] USB support --->
<*> USB Serial Converter support --->
<*> USB FTDI Single Port Serial Driver
上記の設定後、ビルドしたイメージをArmadillo-IoTに書き込んで、起動します。
Armadillo-IoTのUSBコネクタにTMP107評価モジュール(温度センサー)を接続します。
Armadillo-IoTにTMP107評価モジュール(温度センサー)が接続されている状態の場合、下記のように認識されているログが表示されます。
[root@armadillo-iotg (ttymxc1) ~]# usb 1-1: new full-speed USB device number 3 using ci_hdrc
ftdi_sio 1-1:1.0: FTDI USB Serial Device converter detected
usb 1-1: Detected FT232RL
usb 1-1: Number of endpoints 2
usb 1-1: Endpoint 1 MaxPacketSize 64
usb 1-1: Endpoint 2 MaxPacketSize 64
usb 1-1: Setting MaxPacketSize 64
usb 1-1: FTDI USB Serial Device converter now attached to ttyUSB0
上記のログより、USBシリアルコンバーターはttyUSB0として認識されています。
以降の説明において、TMP107評価モジュール(温度センサー)のデバイスファイルは、"/dev/ttyUSB0"の場合で説明します。
●3.TMP107評価モジュール(温度センサー)との通信仕様の確認
TMP107評価モジュール(温度センサー)はシリアル通信で制御します。
TMP107データシートより、通信手順を簡単にまとめると下記のようになります。
・0x55 0x95 0x05を送信(アドレスイニシャライズ。本例では、末尾の0x05でアドレスの開始番号を0x00に指定。)
・レスポンス(※1)温度センサーの数だけアドレスが返ってくる。)
・0x55, 0x5dを送信(リセット)
・0x55, 0x01, 0xa1, 0x00, 0xa0を送信(コンフィギュレーションの設定。本例では、末尾の0xa0でセンシング間隔を1秒に設定。)
・0x55, 0x03, 0xa0を送信(※2)全てのTMP107(温度センサー)に温度データをリード要求)
・レスポンス(※2)全てのTMP107(温度センサー)から温度データが返ってくる)
※1)アドレスイニシャライズのレスポンス
温度センサーの数だけアドレスが返ってきます。
アドレスは、USBインタフェースに近い方から、遠い方へ1ずつインクリメントしてつけられています。
各アドレスは1Byteのデータで、上位5bitがアドレス、下位3bitは"011"です。
今回使用したTMP107評価モジュール(温度センサー)は、4つのTMP107(温度センサー)が接続されており、
開始アドレスを0x00に指定した(送信データの"0x55 0x95 0x05"の末尾の0x05)ので、
0x03 0x0b 0x13 0x1b
のようなレスポンスになります。つまり、
0x03 -- 上位5ビットより、アドレスは、0x00
0x0b -- 上位5ビットより、アドレスは、0x01
0x13 -- 上位5ビットより、アドレスは、0x10
0x1b -- 上位5ビットより、アドレスは、0x11
となっています。
※2)各TMP107(温度センサー)とは、個別(Individual)、または、全て(Global)の2つの通信方法が行えます。
上記では、全て(Global)と通信する方法で、4つのTMP107(温度センサー)から温度データを取得しています。
この場合、温度センサーの数だけ温度データが返ってきます。
温度データは2Byteで、アドレスの大きい方(USBインタフェースから遠い方)から順番に返ってきます。
今回使用したTMP107評価モジュール(温度センサー)は、4つのTMP107(温度センサー)が接続されているため、
2Byte(LSB、MSBの順)×4個のデータが返ってきます。
例)
0xf0 0x14 0xb8 0x1c 0x7c 0x15 0x00 0x17
の場合、
0xf0 0x14 -- アドレス:0x03の温度データ:0x14f0
0xb8 0x1c -- アドレス:0x02の温度データ:0x1cb8
0x7c 0x15 -- アドレス:0x01の温度データ:0x157c
0x00 0x17 -- アドレス:0x00の温度データ:0x1700
補足)上記データを[℃]の単位にするには、上記データの下位14bitのみを抽出し、
2の補数を10進数に変換して、0.015625倍する必要があります。
なお、個別(Individual)に通信する方法を使うと、アドレスを指定することで特定の温度センサーのみから
温度データを取得することができます。
●4:TMP107評価モジュール(温度センサー)からデータを取得するサンプルプログラム
手順3のとおり、Armadillo-IoTとTMP107評価モジュール(温度センサー)は、シリアルで通信します。
そこで、Armadillo実践開発ガイド第2部6.5.1. シリアルエコーサーバー
をベースに、手順3で確認したシリアル通信で、4つの温度センサーの温度データを取得、算出し、
ログファイルへ出力するサンプルプログラムを作成しました。
serial_tmp107_data.tar.gz
<サンプルプログラムの用法>
添付のサンプルプログラムをATDE上に解凍して、serial_tmp107_dataディレクトリ内でmakeすると、
serial_tmp107_dataという実行ファイルができます。
この実行ファイルをArmadillo-IoTに置いて、シリアル通信のデバイスファイルを引数として実行します。
serial_tmp107_dataを実行すると、取得したデータのログ表示と、
log_tmp.txt
というファイルへ、4つの温度データを書き込みます。
serial_tmp107_data <device>
引数
device:デバイスファイル(手順2で確認した"/dev/ttyUSB0")
下記は実行例です。(USBシリアルインタフェースのデバイスファイルが"/dev/ttyUSB0"の場合)
[root@armadillo-iotg (ttymxc1) ~]# ./serial_tmp107_data /dev/ttyUSB0
****************************************************
-------- Command: 0x55 0x95 0x05
-------- Read data: 0x55 0x95 0x05 0x03 0x0b 0x13 0x1b
-------- Number of TMP107: 4
****************************************************
-------- Command: 0x55 0x5d
-------- Read data: 0x55 0x5d
****************************************************
-------- Command: 0x55 0x01 0xa1 0x00 0xa0
-------- Read data: 0x55 0x01 0xa1 0x00 0xa0
****************************************************
-------- Command: Global Read(Temperature)
-------- Start Address: 0x1b
-------- Temperature Register: 0x00
-------- Read data: 0x55 0x1b 0xa0 0xb0 0x14 0x84 0x1d 0x04 0x15 0x00 0x17
-------- Temperature
Address(0x00): 23.000[degC]
Address(0x01): 21.016[degC]
Address(0x02): 29.516[degC]
Address(0x03): 20.688[degC]
補足)上記ログのRead data:は、送信したコマンドに続いて、レスポンスの値が表示されています。
-------- Command: 0x55 0x95 0x05
-------- Read data: 0x55 0x95 0x05 0x03 0x0b 0x13 0x1b
のように、Read dataの頭には、送信したコマンド(0x55 0x1b 0xa0)が含まれます。
ログファイル log_tmp.txt には、下記のように4つの温度センサーの温度([℃]に算出したもの)が書き込まれます。
[root@armadillo-iotg (ttymxc1) ~]# cat log_tmp.txt
tmp0=23.000&tmp1=21.484&tmp2=28.719&tmp3=20.938&
補足)下記、手順5のクラウド側のアプリに合わせて、各データを&で区切っています。
<サンプルプログラムの補足>
serial_tmp107_data.c
(Armadillo実践開発ガイド第2部 6.5.1. シリアルエコーサーバーをベースに今回のサンプル特有の箇所を抜粋します。)
/**** sample: TMP107 serial setting: begin ****/
// シリアル通信のボーレートの設定
#define SERIAL_BAUDRATE B57600
/**** sample: TMP107 serial setting: end ****/
/**** sample: TMP107 command: begin ****/
// 手順3のTMP107評価モジュール(温度センサー)へのコマンドを定義したもの
// アドレスイニシャライズ
static unsigned char cmd_init[] = {0x55, 0x95, 0x05}; /* set TMP107: init */
// リセット
static unsigned char cmd_reset[] = {0x55, 0x5d}; /* set TMP107: reset */
// コンフィギュレーション(ここでは、アドレス0x00のTMP107(温度センサー)にのみ、個別(Individual)で設定)
static unsigned char cmd_conf[] = {0x55, 0x01, 0xa1, 0x00, 0xa0}; /* set TMP107: configuration */
// アドレスを指定して、個別(Individual)でTMP107(温度センサー)のレジスタをリード
// 0x02(アドレス)と、0xa0(レジスタ)は、プログラム内で再設定。
static unsigned char cmd_read_i[] = {0x55, 0x02, 0xa0}; /* set TMP107: individual read */
// 全て(Global)のTMP107(温度センサー)の指定したレジスタの値をリード
// 0x03(アドレス)で、開始アドレス0x00を指定。
// 0xa0(レジスタ)は、プログラム内で再設定。
static unsigned char cmd_read_g[] = {0x55, 0x03, 0xa0}; /* set TMP107: global read */
/**** sample: TMP107 command: end ****/
/**** sample: variable for senseor data: begin ****/
int num_tmp; // TMP107(温度センサーの数)
float tmp[32]; // 温度データ[℃]
unsigned char abs_tmp[2]; // 温度データ(2の補数計算用)
int addr, reg; // アドレス、レジスタの変数
/**** sample: for senseor data: end ****/
/**** sample: TMP107 initialize: begin ****/
// アドレスイニシャライズ
/**** sample: TMP107 initialize: end ****/
/**** sample: TMP107 reset: begin ****/
// リセット
/**** sample: TMP107 reset: end ****/
/**** sample: TMP107 configuration: begin ****/
// コンフィギュレーションの設定
/**** sample: TMP107 configuration: end ****/
/**** sample: TMP107 individual read registers: begin ****/
// 個別(Individual)にTMP107(温度センサー)のアドレスを指定して、レジスタをリード
// ※1)コメントアウトを外すことで有効になる
/**** sample: TMP107 individual read registers: end ****/
/**** sample: TMP107 global read registers: begin ****/
// 全て(Global)のTMP107(温度センサー)のレジスタをリード
// ※1)コメントアウトを外すことで有効になる
/**** sample: TMP107 global read registers: end ****/
/**** sample: TMP107 global read temperature register: begin ****/
// 全て(Global)のTMP107(温度センサー)の温度データのレジスタのみをリード
// 取得した温度データを[℃]に算出し、ログ表示と、ログファイルへ出力。
/**** sample: sensor data to log file for post to heroku: begin ****/
// 温度データをログファイルへ出力。
/**** sample: sensor data to log file for post to heroku: end ****/
補足)本プログラムでは、TMP107(温度センサー)にコマンドを送信してから、レスポンスの確認まで1秒ウェイトしています。
※1)レジスタ確認用にすべてのレジスタをリードしています。 上記補足のとおり、レスポンスの確認に1秒ウェイトしており、全てのレジスタ確認に時間がかかるため、コメントアウトしています。
●5.クラウド(Heroku)側のアプリの準備
まず、Armadillo-IoT + Heroku(Node.js)でHello World のとおり、 Armadillo側からのデータ送信と動作確認まで行ってください。 以下、この手順を実行したことをベースに説明します。 よって以下では、ATDE5の ~/temp/myapp がクラウド(Heroku)側のアプリ用のディレクトリとします。
5.2.サンプル
クラウド(Heroku)側のアプリのサンプルソースを添付します。
myapp_tmp107_20160312.tar.gz
を解凍して、myapp_tmp107_20160312ディレクトリの中身を
~/temp/myapp
ディレクトリの下にコピーしてください。
<サンプルソースの説明>
今回のサンプル特有の部分のみ説明します。
app.js
・HerokuのURL(***.herokuapp.com)にアクセスした際、index.ejsを表示するようにします。 表示の際、index.ejsに4つの温度データを与えています。
app.get('/', function(req, res){
res.render('index', {tmp0: tmp0, tmp1: tmp1, tmp2: tmp2, tmp3: tmp3});
});
・HerokuのURL(***.herokuapp.com/series)にポストされたデータ(※)をパースして、上記のindex.ejsに渡す変数に代入しています。
※)上記サンプルアプリ(serial_tmp107_data)を実行時のログファイル
log_tmp.txt
の
tmp0=23.000&tmp1=21.484&tmp2=28.719&tmp3=20.938&
という形式のデータです。"&"で4つの温度データを区切っています。
app.post('/series', function(req, res) {
console.log('post:/series');
tmp0 = req.body.tmp0;
tmp1 = req.body.tmp1;
tmp2 = req.body.tmp2;
tmp3 = req.body.tmp3;
res.send("Received\n");
});
view/index.ejs
・上記app.get('/', function(req, res)により、受け取ったTMP107評価モジュール(温度センサー)のセンサーデータを表示するhtmlです。
●6.TMP107評価モジュール(温度センサー)のデータをクラウド(Heroku)で見る
Armadillo-IoTからTMP107評価モジュール(温度センサー)のデータをクラウドに送信するスクリプト send_tmp107.sh を添付します。
このスクリプトをArmadillo-IoTの/rootディレクトリに置いて、実行権限をつけてください。 サンプルプログラムserial_tmp107_dataも Armadillo-IoTの/rootディレクトリに置いて実行します。
[root@armadillo-iotg (ttymxc1) ~]# chmod +x send_tmp107.sh
[root@armadillo-iotg (ttymxc1) ~]# ls /root
send_tmp107.sh
serial_tmp107_data
send_tmp107.shは、下記のように使用します。
send_tmp107.sh <device> <HerokuのURL>
引数
device:USBシリアルインタフェースのデバイスファイル("/dev/ttyUSB0")
HerokuのURL:手順5で確認したHerokuのURL
例)TMP107評価モジュール(温度センサー)がUSBシリアルインタフェースのデバイスファイル("/dev/ttyUSB0")と認識されている場合、 HerokuのURLが***.herokuapp.comの場合、下記のように実行します。
[root@armadillo-iotg (ttymxc1) ~]# ./send_tmp107.sh /dev/ttyUSB0 https://***.herokuapp.com/series
上記のスクリプトを実行すると、Armadillo-IoTはTMP107評価モジュール(温度センサー)から 4つの温度センサーの温度データを10秒毎に取得し、算出値を書き込んだログファイル log_tmp.txt から読みだして、クラウド(Herokuのhttps://***.herokuapp.com/series)に送信します。
Webブラウザで、https://***.herokuapp.comにアクセスすると、 Armadillo-IoTが送信したTMP107評価モジュール(温度センサー)のデータが冒頭のWebブラウザの写真のように見ることができます。
補足)
Webブラウザの表示の更新には再読み込みが必要です。
今回の設定の場合は、10秒毎にTMP107評価モジュール(温度センサー)のデータを取得しているので、Webブラウザの表示の更新間隔は10秒以上になります。
クラウド(Heroku)側のアプリがデータを受信した場合は、"Received"という文字をArmadillo-IoTに送信するので、 クラウド(Heroku)側が受け取ったかどうかを、Armadillo-IoTの標準出力で確認することができます。