1
0

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 1 year has passed since last update.

「AE2100」内蔵の920MHz帯無線「SmartHop」のモジュールを活用してみよう(2)  ―データ収集編―

Last updated at Posted at 2023-03-03

要約

  • この記事では、OKIのAIエッジコンピューター「AE2100」に内蔵されている920MHz帯マルチホップ無線「SmartHop」のモジュールを使用して、遠隔地にあるセンサーデータを収集、AE2100上で可視化する方法を紹介します。

  • 第2回の「データ収集編」では、AE2100にNode-REDを導入し、SmartHopモジュールの通信フォーマットでバイナリ(電文)を送受信することで、Modbus RTU対応のセンサーデータの収集・見える化を行う方法を解説します。
    ※SmartHopのユニットタイプを使用したデータ収集方法はこちら

はじめに

本記事は、「AE2100」内蔵の920MHz帯無線「SmartHop」のモジュールを活用する2つ目の記事「データ収集編」です。

AE2100内蔵の920MHz帯無線モジュールを活用してみよう(1)―無線ネットワーク構築編―
●AE2100内蔵の920MHz帯無線モジュールを活用してみよう(2)―データ収集編― (本記事)
AE2100内蔵の920MHz帯無線モジュールを活用してみよう(3)―パトランプ発報編―

前回の記事では、SmartHopの無線ネットワーク構築が完了しました。
今回は、いよいよSmartHop経由でのセンサーデータの収集・見える化です。
アプリケーションの実装は、Node-REDを使用して直観的かつ可能な限りローコードで行っていきます。

環境

実行環境は次の図のような構成を前提とします。
image.png

Windows PCからAE2100(LANポート2)へTeraTermによって接続、AE2100(LANポート1)からインターネットへ接続が可能なことを確認してください。
その他の環境は「AE2100」内蔵の920MHz帯無線「SmartHop」のモジュールを活用してみよう(1) ―無線ネットワーク構築編―をご参照ください。

AE2100へのNode-REDの導入

Node-REDの構成およびAE2100に導入する方法については、OKI AE2100 & Node-REDでローコードIoTしてみた。その2 構築編に分かりやすく記載されているので、そちらをご参照ください。
本記事では、AE2100内蔵のSmartHopモジュールのインターフェースで通信を行うため、「Dockerコンテナの実行」の章に記載されている「--device=/dev/ttyRS485:/dev/ttyRS485」のオプションを「--device=/dev/tty920M:/dev/tty920M」に変更してください。
なお、本記事ではMQTTは使用しないので、「Dockerコンテナの実行」の章に記載されている1883番ポートの設定は不要です。

root@ae2100:~#docker run -it -p 1880:1880 --device=/dev/tty920M:/dev/tty920M -v /home/root/.node-red:/data --name node-red-1 node-red_v1:appf

Node-REDをAE2100に導入したら、Webブラウザで http://192.168.100.1:1880 にアクセスします。おなじみのフローエディタが表示されるはずです。
image.png

ノードの全体構成

Node-REDのフローエディタで各種ノードをワークスペースに配置し、ノード間を線で結ぶことによってフローを作成します。
本記事では、SmartHopモジュールの通信フォーマットに従ったバイナリ(電文)をセンサーに送信する必要があるので、CO2濃度を収集するフローを以下のように作成しました。
image.png

全体的な流れとしては、1秒間隔でfunctionノードにてバイナリ(電文)を作成し、serial requestノードでAE2100から送信。serial requestノードでCO2コントローラーのデータ(CO2濃度)を受信して、2つ目のfunctionノードで必要なデータを抜き出し、ダッシュボードでCO2濃度の見える化まで行っています。
次の見出しから、実装のポイントを図の吹き出しの番号に沿って解説します。

SmartHopモジュールの通信フォーマットに従ったデータ収集の実装

まずは、②functionノードでSmartHopモジュールの通信フォーマットに従ったバイナリ(電文)を作成します。
SmartHopモジュールの通信フォーマットは、無線通信モジュール/ホスト CPU間 API仕様書に詳しく記載されているので、そちらを参照します。

以下、無線通信モジュール/ホスト CPU間 API仕様書 P.18、P.19の抜粋
image.png

■SmartHopモジュールの 通信フォーマット情報

項目 バイト数 備考
SYN 1 0x7E 固定
ProcessID 1 0x11 ホストCPU間の透過データ
Length 2 設定値 payloadサイズ
Payload 可変長 可変 CO2コントローラーのデータを収集するための
Modbus RTUの電文
SYN 1 0x7E

ここで、Payloadには、CO2コントローラーのデータを収集するためのModbus RTUの電文を入れます。
Modbus RTUの通信フォーマットは以下のようになっているようです。

CO2コントローラー RS485(Modbus-RTU)タイプ 通信マニュアルの抜粋
image.png

実際に、Modbus RTUの通信フォーマットをSmartHopモジュールの通信フォーマットに当てはめると以下の表のようになります。
image.png
なお、AI2100⇔センサー間の電文のやりとりやCRC-16の計算方法については、既に説明している記事がありますので、本記事では割愛します。


表を参考にバイナリを作成するプログラムをnode.jsで実装します。

var buf = new Buffer(13); // バイナリの配列を定義
//SmartHopのモジュールとホストCPU間APIの
//通信フォーマット(UARTインターフェースの通信フォーマット)に従って
//電文(バイナリ)を送る
buf[0]=0x7E;//SYN(0x7E固定) 1byte

buf[1]=0x11;//ProcessID:モジュールとホストCPU間の透過データ  1byte
           //API仕様書P.19の表5参照

buf[2]=0x00;//Length(payloadサイズ) 2byte
buf[3]=0x08;//ここでは、8byteを指定

//CO2コントローラーのデータ取得のためのModubus RTUの電文(8byte)を指定
//CO2コントローラーの仕様書を参照
buf[4]=0x01;//スレーブアドレス(局番) 1byte

buf[5]=0x03;//Modubus機能コード(0x03固定) 1byte

buf[6]=0x00;//データ項目 2byte
buf[7]=0x44;//ここでは、CO2濃度を指定

buf[8]=0x00;//データ数 2byte
buf[9]=0x01;//ここでは、1つのデータを指定

buf[10]=0xC4;//Modbus電文のCRC 2byte
buf[11]=0x1F;
//CO2コントローラーのデータ取得のためのModubus RTUの電文(8byte)終了

buf[12]=0x7E;//SYN(0x7E固定) 1byte

 
msg.payload = buf;
return msg;

image.png


あとは、③serial requestノードをSmartHop(UARTシリアル)の通信設定値に合わせて設定すれば、SmartHop経由で取得したCO2濃度のセンサーデータが④デバックエディターに表示されます。

image.png

■ シリアルポート(プロパティ)

項目 設定内容 備考
シリアルポート /dev/tty920M AE2100のSmartHopモジュールのインタフェース名
ボーレート 115200 SmartHopモジュールのUART(固定値)
データビット 8 SmartHopモジュールのUART(固定値)
パリティ なし SmartHopモジュールのUART(固定値)
終了ビット 1 SmartHopモジュールのUART(固定値)
分割後の配信データ バイナリバッファ
※他の項目はデフォルトでOKです。

デバックエディターには以下のように表示されます。

image.png

センサーデータの可視化

センサーデータをグラフ表示するために、CO2コントローラーから受信したバイナリからCO2濃度のデータの部分を抜き出す必要があります。具体的には、④デバックエディターで表示されているバイナリのmsg.payload[7]とmsg.payload[8]を2byteの16進数にして、16進数を10進数にするプログラムを⑤functionノードに実装します。

var dec = new Buffer(1);//新しい配列を作成
var s1=msg.payload[7].toString(16);//[7]に格納されている数値を16進数の文字型に変換
var s2=msg.payload[8].toString(16);//[8]に格納されている数値を16進数の文字型に変換
var sum=s1+s2;//[7]に格納されている文字と[8]に格納されている文字を結合(2byteの16進数にする)
dec= parseInt(sum,16);//16進数の文字列を10進数の数字に変換
msg.payload = dec;//msg.payloadに数値を格納
return msg;

image.png

デバックエディターで表示されている数値とCO2コントローラーに表示されている数値と一致していればOKです。
image.png

最後に、gaugeノードとchartノードを繋ぐと下図のようにCO2濃度のゲージグラフおよび時間推移がダッシュボードに表示できました。
なお、gaugeノードとchartノードの細かい設定やダッシュボードの開き方については、OKI AE2100 & Node-REDでローコードIoTしてみた。その3 実践編 1に分かりやすく記載されているので、そちらをご参照ください。
image.png

参考

念のため、ノードフローのjsonファイルを公開します。この内容をコピペしたjsonファイルを作成して、Node-REDのパレットにドラック&ドロップすれば、一連の動作は問題なく動くはずです。もしセンサーデータが得られない場合は、「AE2100」内蔵の920MHz帯無線「SmartHop」のモジュールを活用してみよう(1) ―無線ネットワーク構築編―を再度ご確認ください。

flows.json
[{"id":"d55d9079.29bed","type":"tab","label":"フロー 1","disabled":false,"info":""},{"id":"e80027f1.e4ba88","type":"debug","z":"d55d9079.29bed","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":240,"wires":[]},{"id":"c57639f0.91ab98","type":"debug","z":"d55d9079.29bed","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":950,"y":240,"wires":[]},{"id":"54e5e0f3.d2eb1","type":"serial request","z":"d55d9079.29bed","name":"serial request","serial":"5a7b30e9.8a0bb","x":500,"y":400,"wires":[["564d4ba0.ff0dd4","e80027f1.e4ba88"]]},{"id":"4d80c7a5.b693d8","type":"function","z":"d55d9079.29bed","name":"","func":"var buf = new Buffer(13); // バイナリの配列をつくる\n//SmartHopのモジュールとホストCPU間APIの\n//通信フォーマット(UARTインターフェースの通信フォーマット)に従って\n//電文(バイナリ)を送る\nbuf[0]=0x7E;//SYN(0x7E固定) 1byte\n\nbuf[1]=0x11;//ProcessID:モジュールとホストCPU間の透過データ  1byte\n           //仕様書P.19の表5参照\n\nbuf[2]=0x00;//Length(payloadサイズ) 2byte\nbuf[3]=0x08;//ここでは、8byteを指定\n\n//CO2コントローラーの測定データ取得コマンド(8byte)を送る\nbuf[4]=0x01;//スレーブアドレス(局番) 1byte\n\nbuf[5]=0x03;//機能コード(0x03固定) 1byte\n\nbuf[6]=0x00;//データ項目 2byte\nbuf[7]=0x44;//ここでは、CO2濃度を指定\n\nbuf[8]=0x00;//データ数 2byte\nbuf[9]=0x01;//ここでは、1つのデータを指定\n\nbuf[10]=0xC4;//エラーチェック 2byte\nbuf[11]=0x1F;\n//CO2コントローラーの測定データ取得コマンド(8byte)終了\n\nbuf[12]=0x7E;//SYN(0x7E固定) 1byte\n\n \nmsg.payload = buf;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":340,"y":400,"wires":[["54e5e0f3.d2eb1"]]},{"id":"564d4ba0.ff0dd4","type":"function","z":"d55d9079.29bed","name":"","func":"var dec = new Buffer(1);//新しい配列を作成\nvar s1=msg.payload[7].toString(16);//[7]に格納されている数値を文字型に変換\nvar s2=msg.payload[8].toString(16);//[8]に格納されている数値を文字型に変換\nvar sum=s1+s2;//[7]に格納されている文字と[8]に格納されている文字を結合する\ndec= parseInt(sum,16);//16進数の文字を10進数の数字に変換\nmsg.payload = dec;//msg.payloadに数値を格納\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":680,"y":400,"wires":[["c57639f0.91ab98","251df414.d0183c","fa263f4b.29865"]]},{"id":"251df414.d0183c","type":"ui_gauge","z":"d55d9079.29bed","name":"gauge","group":"ddfec04a.0cf5f","order":1,"width":6,"height":6,"gtype":"gage","title":"CO2濃度","label":"ppm","format":"{{value}}","min":0,"max":"2000","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":930,"y":340,"wires":[]},{"id":"fa263f4b.29865","type":"ui_chart","z":"d55d9079.29bed","name":"chart","group":"ddfec04a.0cf5f","order":4,"width":9,"height":6,"label":"CO2濃度推移","chartType":"line","legend":"false","xformat":"HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"400","ymax":"800","removeOlder":"10","removeOlderPoints":"","removeOlderUnit":"60","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"x":930,"y":440,"wires":[[]]},{"id":"cbe762b5.1dff7","type":"inject","z":"d55d9079.29bed","name":"inject","props":[{"p":"payload"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":400,"wires":[["4d80c7a5.b693d8"]]},{"id":"5a7b30e9.8a0bb","type":"serial-port","z":"","serialport":"/dev/tty920M","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"/n","bin":"bin","out":"char","addchar":"","responsetimeout":"1000"},{"id":"ddfec04a.0cf5f","type":"ui_group","z":"","name":"ダッシュボード","tab":"d2e076eb.aafbd8","order":1,"disp":true,"width":18,"collapse":false},{"id":"d2e076eb.aafbd8","type":"ui_tab","z":"","name":"Qiitaデモ","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

まとめ

今回は、AE2100内蔵の920MHz帯マルチホップ無線「SmartHop」モジュールを活用して、センサーデータの収集・見える化を行いました。Node-REDを活用することで、ローコードなプログラムの実装が実現し、直感的に実装内容をご理解いただけたのではないでしょうか。
次回は、本記事で収集したデータの閾値に合わせてパトランプの制御を行っていきたいと思います。

次回の記事:
「AE2100」内蔵の920MHz帯無線「SmartHop」のモジュールを活用してみよう(3)―パトランプ発報編―
前回の記事:
「AE2100」内蔵の920MHz帯無線「SmartHop」のモジュールを活用してみよう(1) ―無線ネットワーク構築編―

1
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?