OKI AE2100 & Node-REDでローコードIoTしてみた。その1 準備編


PythonでRS-485圧力センサーシミュレータ作成

はじめに

OKIが販売するAE2100というゲートウェイは「AIエッジコンピューター」として大注目の製品なのですが、RS-232C、RS-485といったレガシーインターフェースを備える、信頼性の高いインダストリアル向けの製品でもあります。

先日RS-485出力の圧力センサーをAE2100で評価した際に、ついでに使い慣れた Node-RED をインストールして AE2100 をローコードIoT開発のプラットフォームにしてみた内容を記事にまとめました。

まとめてみたら、長文になってしまったので4編に分けます。
本記事はその準備編になり、Pythonで圧力センサーのシミュレータを作ります。

その1 準備編「PythonでRS-485圧力センサーシミュレータ作成」 (本記事)
その2 構築編「DockerでローコードIoTプラットフォーム構築」
その3 実践編 1「Node-REDでダッシュボード作成」
その4 実践編 2「Node-REDでMQTT Pub/Sub」

前提

ソフトとしては、Linux と Docker コマンドの経験が必要です。
Node-RED は初心者向けの内容です。プログラミングは行わず、直感的にできる簡単な設定しか行わないため、経験のない方はこれを機会にトライしてみてください。
プログラミングとしてはPythonが出てきますが、Windows PC側で動かすシミュレータとして使うだけなので、Python自体を知っている必要はありません。

ハードはWindows 10 PCとUSB-RS485変換アダプター、そして AE2100 が必要です。

ネットワークに関してはMQTTを使います。
Qiitaに限らず、WebにはMQTTに関する良記事がたくさんあるので、MQTT初心者の方々はご参照ください。

AE2100

AE2100 自体に関してはOKIの製品ページを見ていただくとして、ここではこの記事に関係するポイントだけ記載します。
ハードウェアの基本スペックは以下の通り。

  • CPU : Intel Atom E3950 (4コア@1.6GHz)
  • RAM 4GB
  • ストレージ : 32GB (eMMC)
  • 1Gb Ethernet x 2

ソフトウェアとしては、OS は Yocto Linux です。 Debian 系で動いている他のゲートウェイ製品と比べてアプリの追加に難あり、と思いきや、Docker CEが組み込まれていて、アプリはDockerコンテナにして追加するようになっています。
上記のハードウェア・スペックはけっこう絶妙で、発熱も少なく、4つや5つのコンテナを同時実行しても全く問題なく動作します。(もちろん、どんなコンテナを実行するかに依存するわけですが、コンテナ技術ってホントにすごいですね。)

以降ではOKIのプロプライエタリな情報にはなるべく触れず、一般によく使われているオープンソースだけを使って作業を進めます。
初心者向けの内容でつまずくことはないと思うのですが、以下の作業は筆者の見解と経験に基づくものであり、動作の保証やサポート等に関してOKIは何も関知しないことをご了承ください。

こんなことやりました

圧力センサーからの出力をNode-REDでReadしてダッシュボードに出力するとともに、MQTTブローカーにパブリッシュします。

この図のデモアプリは40MBぐらいのコンテナに20行ぐらいのPythonスクリプトを追加してできてしまったのですが、ここではあえてDocker HubにあるNode-REDコンテナを利用して、AE2100をローコードIoT開発のプラットフォームにしてみました。

こんなふうにやりました

圧力センサー(シミュレータ)

本記事では圧力センサーは実機ではなく、Window 10 PC + USB-RS485変換アダプターを圧力センサーと見立て、Pythonで出力をシミュレーションします。

USB-RS485変換アダプター

AE2100のRS485端子台(上)とUSB-RS485変換アダプター(下)です。

AE2100 が対応するRS-485は半二重の2線式です。
今回は余興でGND付きの3端子で最安値のUSB-RS485変換アダプターを買ってみました。
このアダプターはAmazonでほとんど最安値の323円(配送料69円)の代物ですが、FTDIのチップ(FT232RL。たぶん本物)が使われていて、Windows 10 ではドライバーの追加なし使えます。
FT232RLを上下に挟んでLEDが付いていて、実際に TX, RX があると点滅してくれるので、デバッグの初期に何気に便利です。写真はちょうど TX が出ている瞬間です(よく写ったな)。

PCと接続するコネクタが USB 2.0 Standard Type B レセプタクルなのもうれしいポイントで、A to B ケーブルを久しぶりに使うことができます。捨てないで良かった!
端子台も大きくしっかりしていて、マットブラックの基盤にUSBコネクタのシルバーがキラリと光る、カッコ良い一品です(裏の半田面は秘密です)。
中国発送で到着まで2週間ぐらいかかりましたが、非常に満足度の高い買い物でした!

シミュレーターでも AE2100 とは実機と同様に接続します。
AE2100側の端子台のD+をアダプタのA端子に、D-をB端子に接続します。
GND同士もしっかり接続しました。
AE2100 のD+,D-間には AE2100 付属のターミネーター(太いやつ)を接続して、これでぬかりはないはずです。
接続に使用したワイヤーは40本で120円のオス-オスのジャンパー線ですが、10cm くらいの距離なので問題ないでしょう!

Pythonによるシミュレータ実装

シミュレータの開発言語には Python を選択しました。
簡単な事をやるには Python が一番簡単にできるのではないでしょうか。
処理は確かに遅いですが、1秒以上の応答で良ければ十分です。

今回 Windows 10ホストで実行したPythonのバージョンは3.6.9でしたが、最新のものでOKでしょう。
シリアル通信ライブラリ pyserial のインストールが必要です。

  • pip3 install pyserial

COMポートの番号はデバイスマネージャで確認する必要があります。

今回は COM11 でした。
ビットレートは、圧力センサーと同じ 9600 に設定します。
この圧力センサーは、計測した圧力値を1秒ごとに kPa で出力する設定になっていて、デリミターは'\r\n'です。
Pythonにより、low_pressとmax_pressの間を1秒に0.05kPa単位でインクリメント、デクリメントして出力をシミュレートします。

send_press.py
import serial
from time import sleep

PORT = 'COM11'  # 番号は環境依存です!
BITRATE = 9600
TIMEOUT_SEC = 10.0
min_press = cur_press = 98.0
max_press = 102.0
interval = 0.05
SLEEP_SEC = 1

ser = serial.Serial(PORT, BITRATE, timeout=TIMEOUT_SEC)

def send_press(cur_pres):
    data = f'{cur_press:.1f}'+" kPa\r\n"
    msg = bytes(data, 'utf-8')
    ser.write(msg)
    print(msg)

while True:
    while cur_press < max_press:
        cur_press += interval
        send_press(cur_press)
    while cur_press > min_press:
        cur_press -= interval
        send_press(cur_press)
    sleep(SLEEP_SEC)

TIMEOUT_SEC 経ってもシリアルポートに接続できない場合、終了します。
BITRATEはデフォルトで9600bpsなので、今回はシリアル通信をほとんど意識せず、1バイト毎に1ビットのスタートビット 0、1ビットのストップビット 1 を挟んで1秒間に9600ビット送信できるプログラムができました。
(このシミュレータは1秒ごとに20バイトぐらい送信します。)

実は pySerial ライブラリには RS-485 に特化したサブクラスが用意されているのですが、RS-485 特有の機能(マルチドロップ時のRTS制御)を使わない場合、serial.Serial クラスを使った方が安定していて処理も早いそうです。
今回は1対1通信なので、そのまま serial.Serial クラスを使っています。

シミュレータ実行

コマンドプロンプトでシミュレータを実行します。
このような出力が1秒ごとに出ればシミュレーションOKです。

Ctrl+C で終了します。

さいごに

RS-485で出力する圧力センサーのシミュレータができました。
つまらないプログラミングの話はこれで終了です。

次回はいよいよ AE2100 で Node-RED を動かします!