こちらの記事について、内容・翻訳・視点・長さなど、皆様のご意見をお送りください。今後の記事製作の参考にしたいと思います。
Thank you! Your feedback has been received.
There was a problem submitting your feedback, please try again later.
こちらの記事の感想をお聞かせください。
RevPi Core 3でST言語(PLC)プログラムを実行して信号機を制御する。
前回の記事では、RevPi Core 3とDIOをDINレール上に取り付けて、起動・実行するまでを説明した。今回の投稿では、何か有益なことができないかを見ていこう。概念実証として、シンプルな信号機のシミュレーションができるかどうかを確認したいと思う。
構造化テキスト(ST言語)
PLCに対応する制御プログラムの作成に使用する主な標準言語は、構造化テキスト言語(ST言語)、ラダーロジック、ファンクションブロックダイヤグラム(FBD)の3つだ。ラダーロジックとFBDはグラフィック言語だが、ST言語ほど柔軟性は高くない。また、RevPiを搭載するlogi.CAD 3の無料版は、ラダーロジックとFBDに対応していない。こうした理由により、ST言語を使用する必要があった。
ST言語はIEC61131-3の規格に準拠して標準化された言語だが、どのPLCベンダにも独自のバリエーションと追加要素がある。ST言語を使うにあたり便利な入門者用チュートリアルをオンラインで見つけた。ST言語はPASCALから派生した言語であり、書いていると、かなり昔にZX80でピンポンゲームをプログラムするのに使用したBASICを思い出す。
logi.CAD 3
新しい言語に慣れるのと並行して、初めて使うソフトウェアでの作業にも慣れる必要があった。logi.CAD 3用語集は、用語を理解するのに役立った。必要に応じて後で参照するのにも便利だ。ここでは、2つの用語を挙げておく。
- オブジェクト - logi.CAD 3のプロジェクトエクスプローラにあるオブジェクトはフォルダ内に置かれており、オブジェクトはフォルダの子といえる。オブジェクトはファイルシステム上のフォルダに相当する。
- プロジェクト - プロジェクトは、logi.CAD 3のプロジェクトエクスプローラにある特別なタイプのフォルダだ。デフォルトでは、プロジェクトはプロジェクトエクスプローラのルートである。
すべてを包括したものをアプリケーションと呼ぶ。アプリケーションには、自分で記述したコードを含むSTLファイルだけでなく、設定ファイルとして動作するファイル、グローバル変数、使用しているPLCに固有のライブラリも含まれる。
構文などに何の問題がないにも関わらず、logi.CAD 3がアプリケーションのビルドに失敗したことが何度かある。こうした場合は、[Project]メニュー下で[Clean]をクリックすることでプロジェクトを「クリーン」にした後、Logi.CAD 3が自ら動作するままに任せると、正常にアプリケーションがビルドされる。
ライトの点滅
1つのライトが点滅するシンプルなアプリケーションを作成した。前回の記事で使用したRevPiクイックスタートガイドに記載されているサンプルをベースにした。
PROGRAM RevolutionPiCounterProgram
VAR
value : BOOL;
END_VAR
VAR_EXTERNAL
Red_1 : BOOL;
Amber_2 : BOOL;
Green_3 : BOOL;
END_VAR
IF value THEN
Red_1 := False;
value := False;
ELSE
Red_1 := True;
value := True;
END_IF;
END_PROGRAM
このサンプルでは、LEDが点滅し続ける。これは、PLCアプリケーションは自動的に繰り返されるためだ。「End_Program」は、実際には「最初に戻り、再び開始する」を意味している。
チュートリアルにも次のように書かれている。「PLCがEND_PROGRAMに達すると、PLCスキャンサイクルが再び開始され、プログラムが繰り返し実行されます」
信号機
ここで私は、「赤→赤と黄色→緑→黄色→赤に戻る」という標準的な信号機のシーケンスでLEDを点滅させる方法を考えた。
ライトが点滅する速度は、設定ファイルで値を編集するだけで簡単に変更できる。しかしそれではスキャンサイクル全体の速度が変わってしまい、アプリケーション自体の速度が単に遅くなるだけだ。これではお粗末だと考えた私は、それぞれのライトの速度を個別に変更できるようにしたいと考えた。これは当初考えていた以上に難しい作業だった。
TON機能(タイマ遅延)によって遅延させることはできたが、自分のコードでは望んでいた効果が得られなかった。またLEDを一定の期間点灯させてから消灯することもできたが、再度点灯することができなかった。そして点滅させる方法では、消灯している時間を指定できませんでした。
私は堂々巡りに陥りそうになり、自分の手には負えないのではと思ったが、インターネットでヒントを探しているとき、Codesysフォーラムの役立つ投稿にCASEステートメントの記述があるのを見つけた。Codesysはlogi.CADと同じソフトウェアPLCだ。使用されているST構文に多少の違いはあるものの、サンプルを改変して私のニーズに適応させることができた。
最終的なコードは以下のとおり。
PROGRAM RevolutionPiProgram
VAR
wait : TON;
count : INT;
END_VAR
VAR_EXTERNAL
Red_1 : BOOL;
Amber_2 : BOOL;
Green_3 : BOOL;
END_VAR
CASE count OF
0: //init
count := count + 1;
1: // Red
Red_1 := True;
Amber_2 := False;
Green_3 := False;
wait(IN:=TRUE, PT:=T#5s);
IF wait.Q THEN
wait(IN:=FALSE);
count := count + 1;
END_IF;
2: // Red and Amber
Red_1 := True;
Amber_2 := True;
Green_3 := False;
wait(IN:=TRUE, PT:=T#5s);
IF wait.Q THEN
wait(IN:=FALSE);
count := count + 1;
END_IF;
3: // Green
Red_1 := False;
Amber_2 := False;
Green_3 := True;
wait(IN:=TRUE, PT:=T#5s);
IF wait.Q THEN
wait(IN:=FALSE);
count := count + 1;
END_IF;
4: // Amber
Red_1 := False;
Amber_2 := True;
Green_3 := False;
wait(IN:=TRUE, PT:=T#5s);
IF wait.Q THEN
wait(IN:=FALSE);
count := count + 1;
END_IF;
ELSE
count := 0;
END_CASE;
END_PROGRAM
CASEは、特定の整数値が発生した場合にステートメントの実行に使用される。このサンプルでは、ELSEがゼロに戻ると、整数値「count」が各PLCスキャンごとに1ずつ増加する。TONは、各ステートメントを5秒間実行するのに使用されている。この実行時間は、下記の行の「5s」を編集すれば簡単に変更できる。
wait(IN:=TRUE, PT:=T#5s);
必要に応じて、ライトの各シーケンスに異なる時間を設定できる(下の動画では、すべての値を2秒に変更している)。さらに、簡単にコードを拡張してライトを増やすことも可能だ。
まとめ
新しいコンピュータ言語と不慣れなソフトウェアに取り組むことは大変だったが、最終目標は達成できたのでうれしく思っている。出来あがった信号灯は必ずしも「道路での使用に適したもの」ではないかもしれないが、イベント内で使用する程度のシンプルな交通制御機能であれば、ほんの少しの手間で開発できることが分かった。