United Statesからアクセスのようです。言語設定をEnglishに切り替えますか?
Switch to English site
Skip to main content

PYTHON言語でオートメーション制御を: パート4

この一連の投稿も今回でパート4となった。復習が必要な場合は、パート1パート2パート3を参照してほしい。

GUIは、PIDコントローラを実行しているのと同じRevPiシステム上で実行し、任意のブラウザからアクセスできるが、まずはMQTTブローカーをインストールする必要がある。

PuTTYセッションに戻り、次のコマンドを使用して、MQTTブローカーをこのシステムにインストールする。

sudo apt-get install mosquitto mosquitto-clients

MQTTブローカーの役割は、クライアントから来る値を受け取ることだ。クライアントはそのような「メトリクス」を「トピック」(一種の名前付きコンテナ)の下で「パブリッシュ」する。他のクライアントはそのようなトピックを「サブスクライブ」できる。新しい値がブローカーに送信されると、ブローカーはこの値のトピックにサブスクライブしているすべてのクライアントに値を転送する。このデータ配信は暗号化によってセキュリティ保護できるが、このデモでは簡潔さを優先するため、暗号化は行わない。

RevPiPyLoadサービスは、「export」をマークしたプロセスイメージのすべてのIO値をMQTTブローカーにパブリッシュするように設定できる。RevPiPyControlアプリケーションに戻り、[PLC] -> [PLC options…]を開く。次のようなウィンドウが開く。

image075_51203798601db56c853b13efbb65310eb68b2ea0.jpgimage077_695f3419862047e13cfd2ef88e1225c4dffb9137.jpgimage0791_7884c79a6113376f8fec24ea537b637e5dbf2fe8.jpg

[RevPiPyLoad server services]セクションの[MQTT process image publisher]のチェックボックスをオンにして、[Settings]をクリックする。このデモ用には上の画像の設定を使用してほしい。ネットワークのどこかでMQTTブローカーを使用している場合、パブリッシュ間隔を1秒から10秒などに変更することを検討する必要がある。

[Save]を2回クリックすると、直ちにメトリクスがプロセスイメージからMosquitto MQTTブローカーへとパブリッシュされる。任意のクライアントで、以下のトピックにサブスクライブして、パブリッシュされた値を受信できる。

  • RevPiProcessImage/event/PWM_heater1
  • RevPiProcessImage/event/PWM_heater2
  • RevPiProcessImage/event/Temp10
  • RevPiProcessImage/io/PWM_heater1
  • RevPiProcessImage/io/PWM_heater2
  • RevPiProcessImage/io/Setpoint
  • RevPiProcessImage/io/Temp10

ここでは、Node-RedをMQTTクライアントとして使用し、これらの値にサブスクライブして、UIに表示する。Node-Redは優れた「ドラッグアンドドロップスタイルソフトウェア制作ツール」だ。IBMによって開発され、JS-Foundationのオープンソースプールで提供される。IDEはブラウザベースで動作するので、いわゆるメッセージの「フロー」は簡単にセットアップ可能。事前に定義された各種のノードから「ノード」部品をフローにドラッグアンドドロップするだけだ。次にマウスを使用してノード出力をノード入力に「配線」(接続)する。すべてのノードは、ノードをクリックすることで、パラメータで設定できる。

Node-Redは、すべてのRevPiにプリインストールされており、サーバーサービスを開始するだけで利用できる。次のコマンド(PuTTYセッションを使用)すると、Node-Redを恒久的に有効にして開始できる。

sudo systemctl enable nodered.service
sudo systemctl start nodered

「フロー」をプログラムして、保存(「デプロイ」)している場合、そのフローは起動後に自動的に実行される(Node-Redはすでに手動で開始されているため、今すぐ再起動する必要はない)。

新しい「ノード」をNode-Red IDEに追加する必要があるので、次のコマンドで「npm」(JavaScriptランタイムシステム「Node.js」のパケットマネージャ)をインストールする。

sudo apt-get install npm

これでほぼ完了です。後は、フローをセットアップするだけです。パソコン上からブラウザで、IPとポートアドレス「http://192.168.0.241:1880」(自分のRevPiのIPで置き換えてほしい)を使用してIDEにアクセスできる。IDEの言語はブラウザの優先言語になる。

左のサイドバーにすべての「ノード」が表示され、そこからウィンドウ中央の空のフローにドラッグアンドドロップできる。ダッシュボード(UI)ノードを追加する必要があるが、これはnpmのおかげで簡単に実行できる。まず、メニューアイコン(右上隅)をクリックし、[Manage Palette]を選択。[install]タブを選択し、検索文字列として「dashboard」と入力。しばらくすると結果が表示されるので、[node-red-dashboard]を選択して[install]をクリック。次にPalette Managerを閉じ、ブラウザを更新(F5)。これで、左サイドパレットの[dashboard]というタイトルの下に、新しくインストールしたノードが表示される。

パレットのinputセクションに移動し、mqttノードをフローエリアにドラッグアンドドロップ。ノードをダブルクリックして設定する。

 

image083_f6d5f229acad936f20cb0fd062064e40bb115e7a.jpg

トピック「RevPiProcessImage/io/Temp10」を入力し、[Done]をクリックする。温度を°Cで表示したいので、プロセスイメージのメトリクス(MQTTブローカーから受信したもの)に10を掛ける必要がある。これは「function」ノード([function]セクションの最初のノード)を使用して実行する。このノードをmqttノードの右にドラッグアンドドロップし、ダブルクリックして設定する。

image085_36a685f53c17ebfbb30ad2beecf3d19745f1a47f.jpg

[Function]エディタを使用するとJavaコードを入力できる。すべてのノードは、オブジェクト「msg」を認識する。これはノードで送受信されるメッセージだ。メッセージの内容を変更するため、「payload」(すべてのノードのプライマリコンテンツ、任意の新しいコンテンツ変数を自由に追加できる)を使用する。msg.payload = msg-payload/10で必要な処理を行える。そのあと、[Done]をクリックする。

次に2つのdashboardノードを追加し、functionノードの右にドラッグアンドドロップする。

gaugeノードとchartノードを次のように設定する。

 

image087_6ae760fcf22dee35add9d70fdea8eb74b1096a1c.jpgimage089_79746cf3cf9e5b578d914b6605386af5ca3606a6.jpg

次にノードを接続(「配線」)する。ノードの右端の小さな円(ノードの出力)をクリックして、マウスボタンを押したままノードの左端の円(入力)まで線を引く。下図のとおり、1つの円に複数の線をつなぐことができる。

image091_c0c518e5f07562e87971b7e842c633f1883eb977.jpg

青いドットは未保存(「未デプロイ」)ノードを示しているので、[Deploy]をクリックするとフローが実行される。MQTTメッセージを受信すると、その値に10が掛けられ、UI要素の入力として使用される。しかし、結果を確認するにはどうしたらよいだろうか?これは非常に簡単で、ブラウザウィンドウでhttp://192.168.0.241:1880/ui (IPは自分のRevPiのIPで置き換えてほしい)を開くだけだ。

image093_174bbbf28e98a287e2018cbfebac96c251f92ce3.jpg

右サイドメニュー[dashboard]を使用して、UIページ名(「Home」)とグループ名(「Default」)を編集し、お好みのテキストに変更する。

image0951_5f9c56a893404daf004293740f58e23ee03e4bb3.jpg

PWM値のチャートとゲージの追加は、宿題として説明せずに残しておく。MQTTトピック「RevPiProcessImage/event/PWM_heater1」を使用する必要がある。

.

image0971_4627c7ec857c1badd073fc01ea68b86a5ea59ba4.jpg

image099_a53dd48fce32689b80c68442bdb1ed041dc2b8da.jpg

引き続き私たちのデモプロジェクトに興味をお持ちの方は、セットポイントスライダーの追加にも付き合ってほしい。

スライダーをフローにドラッグアンドドロップし、「Setpoint」という名前の第3のUIグループに追加します(範囲30~50°C、0.5刻み、出力は[only on release]に設定)。このノードをmqtt出力ノードに接続する。mqtt出力ノードは、パブリッシュトピック「Setpoint」で設定される。

 

image101_bf710a32861a2575a13dc904be48797ae465a952.jpg

image103_5aa3529fd805e2580ba46b80ed9cebfaf061ca59.jpg

私たちのPythonソフトウェアを使用してこの値にサブスクライブし、それを定数値の代わりにPID関数呼び出しのセットポイントとして使用する。そのため、「paho mqtt」というPython MQTTクライアントライブラリをインストールする必要がある。PuTTYを使用して次のコマンドを入力する。

sudo pip3 install paho-mqtt

次にPythonコードを編集する。ライブラリのインポートステートメントを追加し、いわゆる「コールバック」関数を「def」ステートメントで追加する。この関数は、サブスクライブしたトピックがMQTTブローカーから新しいメッセージを受信するたびに、Paho MQTTクライアントによって呼び出される。さらに5行のコードで、MQTTクライアントを初期化して開始し、「Setpoint」にサブスクライブする。

from simple_pid import PID
import revpimodio2
import time
import paho.mqtt.client as mqtt

def on_message(client, userdata, message):
    TempController.setpoint = int(float(message.payload)*10)

client = mqtt.Client("myplc")
client.connect("localhost")
client.on_message=on_message
client.subscribe("Setpoint",2)
client.loop_start()

TempController = PID(5,0.13,10.5,sample_time=0.1, setpoint=400, output_limits=(0,100))
rpi = revpimodio2.RevPiModIO(autorefresh=True)

while True:
    Temp = rpi.io.Temp10.value
    pwm = TempController(Temp)
    rpi.io.PWM_heater1.value = int(pwm)
    rpi.io.PWM_heater2.value = int(pwm)
    time.sleep(0.05)

次にこのスクリプトをRevPiPyLoadの「自動実行フォルダ」である「/var/lib/revpipyload」に保存し、「program.py」という名前を付ける(この2つのパラメータは、私たちのプロジェクトの最初に編集した設定ファイルで変更可能)。これは、IDLEエディタの[save as …]で行うことはできない。パス「/var/」に書き込むには管理者権限が必要だからだ。そのため、PuTTYを使用して、次のLinuxコマンドを入力する。

sudo mv ~/myplc.py /var/lib/revpipyload/program.py

「sudo」はこのコマンドの実行1回だけに管理者権限を与える魔法の言葉である。

RevPiPyControlウィンドウで、[PLC restart]をクリックすると、赤いエラーメッセージは表示されなくなるはずだ。緑のバーは、Python PLCスクリプトが正常に開始されたことを示す。

image105_96e8936baa856cf84b8b9c17c4ce0fa687f4b6bb.jpg

この段階を追った説明が皆さんのお役に立てば幸いだ。沢山の設定を行う必要があるが、最終的にわずか19行のPythonコードに行き着く(デバッグ用のコメントは削除した)。ぜひIBM Watsonノードを試してみてほしい。値をクラウドにアップするのがどれだけ簡単か驚くことだろう(IBMは実験目的で無償の「クイックスタート」アクセスを許可している)。このアドレスにアクセスして、私のデバイスがオンラインかどうか、私のオフィスの温度がどうなっているかを確認するころができる。RevPi Pythonコントローラの講築中に何かトラブルが発生した場合は、英語版記事にコメントを残すか、私にメッセージを送ってほしい。RevPiModIOの作者のSven Sager氏は、このデモからプロフェッショナルバージョンを作成する方法についてシェアしたいと考えている。おそらく、コメント欄にまもなく彼のアイディアが投稿されるだろう。オートメーション用Pythonへの理解を深めたい方は、引き続きご注目していただきたい。

image107_795a02e3f1e5c467fa0c0f936ec1b185773cbbdd.jpg

 

____________________________________________________________________________

____________________________________________________________________________

RevPiModIOライブラリの作成者Sven Sagerから次のコメントが寄せられた。:

 „while True“ ループについて:

もし、Arduinoのようなマイコンを使っていれば必ず無限ループを使う。その中で、すべてのハードウェアの処理や出力を行うことになる。ここで重要なのは、その無限ループがマイコンの唯一のプロセスであるということだ。

しかし、今回使っているRevolution PiはDebianベースのLinuxカーネルを使用している。そのため、OSがプロセスを処理している方法についても理解する必要がある。

プログラムの起動は、シェル経由、ダブルクリックなどで行われる。これで、プログラムの「while True」ループが実行される。

プログラムを終了するには、Ctrl + C、RevPiPyLoadの「PLCの停止」ボタンを押すか、Revolution Piをシャットダウンするなどがある。このとき、OSのペンギンが、プログラムに「TERM」シグナルを送信している。ここで、「while True」ループを終了し、データを保存し、データベースから切断するか、その他のクリーンアップを行う必要がある。しかし、「while True」は終了することができない。プログラムを終了することはできないため、ペンギンは彼のくちばしで「KILL」シグナルを送信する。ファイルを書いたり、データベースにデータを保存したり、ネットワークパートナーと通信したりしても、もう終わってしまう!ファイルを終了する、変更をコミットする、または切断する機会はない。

なので、プログラムやサービスなどを開発している場合は、シグナルに注目してほしい(以下のリンク1)。

この例では、RevPiModIOを使用しており、そのすべての信号をライブラリに含めた。 rpiオブジェクトを作成した直後に「.handlesignalend()」を呼び出して、シグナル処理をアクティブにする必要がある(以下のリンク2)。プログラムが「SIGTERM」を取得すると、RevPiModIOは「exitevent」を設定し、これを使用して無限ループを終了できる。 「while True:」を「while not rpi.exitevent.is_set():」に変更するだけだ。
RevPiModIOには、Revolution Pi用のプロフェッショナルな制御プログラムを作成するための機能がいくつかある。例を挙げると、周期的なプログラムだ。 whileループの行は50ミリ秒ごとに呼び出されますが、プロセスイメージと同期していない!
PLCのサイクルは、プロセスイメージからすべての入力を読み取り、凍結した入力値で周期関数を実行し、すべての出力をプロセスイメージに書き込んで、最初からやり直す必要がある。

これの必要性はというと、例えば、14個の出力を1つの入力の値に設定すると、出力がすべて同じ値になることが期待される。しかし、「while True」を使用すると、10個の出力を設定した後に入力の値が変わるため、次の4つの出力の値が異なる。

RevPiModIOでは、「.cycleloop」を使用できる(以下のリンク3)。 「while True:」を「def cycle(cycletools):」に置き換え、「time.sleep(0.05)」を削除し、ファイルの最後で「rpi.cycleloop(cycle、cycletime = 50)」を呼び出すだけだ! RevPiModIOは、50ミリ秒ごとに関数を呼び出せる。もちろん、「.handlesignalend」も機能する!

したがって、これは変更されたサンプルプログラムであり、オペレーティングシステムの信号を処理し、プロセスイメージと同期してサイクル関数を処理する。さらに副作用として、関数の実行時間が監視され、cycletoolsが動作する(以下のリンク4 )!

from simple_pid import PID
import revpimodio2
import paho.mqtt.client as mqtt

def on_message(client, userdata, message):
    TempController.setpoint = int(float(message.payload)*10)

client = mqtt.Client("myplc")
client.connect("localhost")
client.on_message=on_message
client.subscribe("Setpoint",2)
client.loop_start()

TempController = PID(5,0.13,10.5,sample_time=0.1, setpoint=400, output_limits=(0,100))
rpi = revpimodio2.RevPiModIO(autorefresh=True)
rpi.handlesignalend()

def cycle(cycletools):
    Temp = rpi.io.Temp10.value
    pwm = TempController(Temp)
    rpi.io.PWM_heater1.value = int(pwm)
    rpi.io.PWM_heater2.value = int(pwm)

rpi.cycleloop(cycle, cycletime=50)
​

Links:

  1. https://docs.python.org/3/library/signal.html
  2. https://revpimodio.org/en/doc2/#handlesignalend
  3. https://revpimodio.org/en/doc2/#cycleloop
  4. https://revpimodio.org/en/doc2/cycletools/
Volker de Haas started electronics and computing with a KIM1 and machine language in the 70s. Then FORTRAN, PASCAL, BASIC, C, MUMPS. Developed complex digital circuits and analogue electronics for neuroscience labs (and his MD grade). Later: database engineering, C++, C#, industrial hard- and software developer (transport, automotive, automation). Designed and constructed the open-source PLC / IPC "Revolution Pi". Now offering advanced development and exceptional exhibits.
DesignSpark Electrical Logolinkedin