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単位でインクリメント、デクリメントして出力をシミュレートします。
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 を動かします!