第13号(2024年05月20日)
Raspberry PiとNode-RedでPLC通信
はじめに
近年注目が集まっているIoTアプリですが、Raspberry PiとNode-Redを用いることで低コスト、省スペースで実現することができます。
Node-Redとは、「ハードウェアデバイス」「API」「オンラインサービス」を相互接続するためのフローベースのプログラミングツールです。
最近のRaspberry Piには標準で搭載されています。
今回はNode-Redの基本的な使い方、開発方法は省いて説明します。興味があればぜひ調べてみてください。
PLC通信
では、Node-Redを使ってRaspberry PiとPLC(三菱MELSEC)の通信を行います。
システム構成図です。Raspberry PiとPLCをLANで接続しています。
今回使用したのはRaspberry Pi 4、PLCはMELSEC-Qシリーズ です。
必要なノードを追加
このノードはNode-Red起動時に自動でPLCに接続します。
※Node-Redに標準でインストールされているノード「tcp request」でもPLC通信を実装できますが、高速の定周期通信には向きません。
「tcp request」は、実行するタイミングで毎回PLCとの接続・切断を行います。
今回は300ミリ秒毎にPLCと定周期通信する仕様であったため、しばらくすると勝手にPLCとの通信が切断されてしまう現象が発生しました。
高速で定周期通信を行う場合は、「node-red-contrib-mcprotocol」のようにNode-Red起動時にPLCに接続する方が適しています。
他にも多々PLCと通信ができるノードがありますので、仕様に沿って適切なノードを選ぶ必要があります。
●接続情報設定●
まず接続情報を設定します。MC ReadノードかMC WriteノードのConnectionから接続情報を編集できます。
Host、Portは任意で変更できるようにするため、環境変数にして外出しにしています。
これで、もしPLCの設定が変わった際でもNode-Redのエディタ画面を開く必要なく接続先を変更することができます。
●Node-Redでの環境変数の使用方法●
ここで、Node-Redでの環境変数の設定方法を紹介します。
Raspberry Piの /lib/systemd/system/nodered.service ファイルに下記のように環境変数を設定します。
Environment="(環境変数名)=(値)"
今回は、PLCのIPとポートを環境変数に設定しているので、下記の2行をファイルに追加します。※このファイルを編集するにはroot権限が必要です。
Environment="ENV_PLC_IP=XXX.XXX.XXX.XXX(PLCのIPアドレス)"
Environment="ENV_PLC_PORT=XXXX(PLCのポート)"
これで、Node-Red上で環境変数を使用できるようになります。Node-Red上で使用するときは「${(環境変数名)}」と表記します。
環境変数はNode-Redが起動したタイミングでのみ読み込まれるので、変更した後はNode-Redを再起動する必要があります。
PLC読み取り
追加したノードを使用し、Node-RedでPLCの値を読み取ります。読み取りに使用するのは「MC Read」です。
[ { "id": "2c82d58736dd51a9", "type": "MC Read", "z": "cf8f6f2a6b5cda12", "name": "", "topic": "", "connection": "5c545c4d9fc6e317", "address": "W1F03", "addressType": "str", "outputFormat": 0, "errorHandling": "throw", "outputs": 1, "x": 280, "y": 2840, "wires": [[ "35c6a066141bc191"] ] }, { "id": "35c6a066141bc191", "type": "debug", "z": "cf8f6f2a6b5cda12", "name": "debug 4", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 420, "y": 2840, "wires": [] }, { "id": "31f845f426be82ba", "type": "inject", "z": "cf8f6f2a6b5cda12", "name": "", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 150, "y": 2840, "wires": [[ "2c82d58736dd51a9"] ] }, { "id": "9457263d28e19c45", "type": "comment", "z": "cf8f6f2a6b5cda12", "name": "Read", "info": "", "x": 130, "y": 2800, "wires": [] }, { "id": "5c545c4d9fc6e317", "type": "MC Protocol Connection", "name": "melsec", "host": "${ENV_PLC_IP}", "port": "${ENV_PLC_PORT}", "protocol": "TCP", "frame": "3E", "plcType": "Q", "ascii": false, "PLCStation": "", "PCStation": "", "PLCModuleNo": "", "network": "", "octalInputOutput": false, "timeout": "30000" }]
作成したフローです。アドレス「W1F03」の値を取得します。
Addressに取得したいアドレスを入れます。ここは変数を代入してもできます。
フローを実行し、成功するとmsg.payloadに値が入ります。デバッグノードで確認すると、正常に値が取得できているのがわかります。
PLC書き込み
追加したノードを使用し、Node-RedでPLCの値を書き込みます。書き込みに使用するのは「MC Write」です。
[ { "id": "10cc912b668cde96", "type": "debug", "z": "cf8f6f2a6b5cda12", "name": "debug 5", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 420, "y": 2960, "wires": [] }, { "id": "963810959eb6eb89", "type": "inject", "z": "cf8f6f2a6b5cda12", "name": "", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 150, "y": 2960, "wires": [[ "dc2c28e1f6b950a1"] ] }, { "id": "f4720bf0d388d86b", "type": "comment", "z": "cf8f6f2a6b5cda12", "name": "Write", "info": "", "x": 130, "y": 2920, "wires": [] }, { "id": "dc2c28e1f6b950a1", "type": "MC Write", "z": "cf8f6f2a6b5cda12", "name": "", "topic": "", "connection": "5c545c4d9fc6e317", "data": "11", "address": "W1F03", "addressType": "str", "dataType": "str", "errorHandling": "throw", "outputs": 1, "x": 280, "y": 2960, "wires": [[ "10cc912b668cde96"] ] }, { "id": "5c545c4d9fc6e317", "type": "MC Protocol Connection", "name": "melsec", "host": "${ENV_PLC_IP}", "port": "${ENV_PLC_PORT}", "protocol": "TCP", "frame": "3E", "plcType": "Q", "ascii": false, "PLCStation": "", "PCStation": "", "PLCModuleNo": "", "network": "", "octalInputOutput": false, "timeout": "30000" }]
作成したフローです。アドレス「W1F03」に任意の値を書き込みます。
Addressに書き込みたいアドレス、Dataに書き込み値を入れます。ここは変数を代入してもできます。
フローを実行し、書き込みに成功するとmsg.payloadがtrueになります。
まとめ
Node-Redを使うと、コードの記述をすることなく非常に簡単にRaspberry PiとPLCの通信ができました。
このようにNode-Redは他の開発言語に比べてプログラムがシンプルで可読性の高いものになっています。
Raspberry PiとNode-Redは相性が良く、他にも様々なシステムを製作しているので、順次紹介していきます。