OpenPLC Editorの機能として、IEC61131-3相当のPLCプログラム言語でのプログラミングが行えますが、Arduinoのスケッチも同時に実行できる機能が有ります。今回は全体的な動作をPLCプログラム言語のラダー図言語で作成して、ステッピングモータを動作させる部分をスケッチで作成して、ラダー図言語プログラムからスケッチにデータを渡して、ステッピングモータを動作させる実験を行いましたので紹介します。
1.初めに
以前、オープンソースのPLCプログラム作成ソフトウェアであるOpenPLC Editorで作成したプログラムをRaspberry Pi Pico Wで動作させてLEDのON・OFFを行う実験を行った記事を紹介しました。(OpenPLCをRaspberry Pi Pico Wで動作させる記事はこちら)
OpenPLC EditorのIEC61131-3相当のプログラム言語でステッピングモータ等の制御を行おうとすると難点がありました。最新のOpenPLC EditorではIEC61131-3のプログラム言語とArduinoのプログラムであるスケッチも同時に実行出来る機能が設けられました。
今回は全体的な動作をPLCプログラム言語のラダー図言語で作成して、ステッピングモータを動作させる部分をスケッチで作成して、ラダー図言語プログラムからスケッチにデータを渡して、ステッピングモータを動作させる実験を行ってみました。
使用したOpenPLC Editorのバージョンは3.0で、リリース:2024-11-08 です。
2.OpenPLC EditorのRaspberry Pi Pico W対応に関して
今回の実験ではOpenPLCを動作させるハードウェアとしてRaspberry Pi Pico Wを使用しました。図1にRaspberry Pi Pico Wの概要を示します。
Raspberry Pi Pico Wに関してOpenPLCはデフォルトで表1の様にI/Oが対応しています。ロケーションの欄に書いてある%IX0.0等はI/Oに直接アクセスするための直接表現変数です。OpenPLC Editorでは入出力変数の定義画面で、I/Oを直接操作する変数を定義する場合にLocation欄に、この表記で記載します。
直接表現変数は「%」で始まり、次にI(入力)、Q(出力)で、「X」以降はビットアドレス、「W」以降はワードアドレス(16bit)と言う形で表現されます。
OpenPLCのI/O | Raspberry Pi Pico WのI/O | ロケーション |
入力I/O | GP6, GP7, GP8, GP9, GP10, GP11, GP12, GP13 | %IX0.0~%IX0.7 |
出力I/O | GP14, GP15, GP16, GP17, GP18, GP19,GP20, GP21 | %QX0.0~%QX0.7 |
アナログ入力 | GP26, GP27, GP28 | %IW0~%IW2 |
アナログ出力 | GP4, GP5 | %QW0~%QW1 |
3.ステッピングモータに関して
3-1.使用ステッピングモータ概要
ステッピングモータは28BYJ-48とそのドライバーボードのセットを使用しました。このステッピングモータとドライバーボードは複数のネット通販から安価に購入することが出来ます。
今回使用したステッピングモータの主な仕様は表2の通りです。このモータは1/64のギアで減速されていて、1-2相励磁の場合にステップ角は5.625°/64なので4096ステップでモータ軸が1回転します。最大自起動周波数が500ppsなので、500パルス/sec以下で起動する必要があります。起動後は徐々に加速を行った場合に、最大で1000パルス/secまで仕様上は可能と思われます。
ただし、Arduino IDEのStepperライブラリーのstep()関数を使用した場合の励磁方式は2相励磁のようです。そのため2048ステップでモータ1回転となります。
項目 | 仕様 |
相数 | 4相 |
励磁方式 | 1-2相励磁方式 |
ステップ角 | 5.625°/64 (減速比1/64) |
電圧 | 5VDC |
相抵抗 | 22Ω ± 7% 25°C |
最大応答周波数 | 1000pps |
最大自起動周波数 | 500pps |
引き込みトルク | 800gf.cm / 5VDC 400pps |
3-2.ステッピングモータの駆動に関して
今回使用したステッピングモータ28BYJ-48は1-2相励磁の場合、1回転4096ステップとなります。ただStepperライブラリのstep()関数は2相励磁方式です。2相励磁の場合1回転2048ステップとなります。
stepper(step2, pin1, pin2, pin3, pin4)
関数でI/Oピンを割り振った場合の励磁順序は表2の様になっています。
引数 | 1ステップ | 2ステップ | 3ステップ | 4ステップ |
pin1 | HIGH | LOW | LOW | HIGH |
pin2 | LOW | HIGH | HIGH | LOW |
pin3 | HIGH | HIGH | LOW | LOW |
pin4 | LOW | LOW | HIGH | HIGH |
また、ステッピングモータ28BYJ-48の仕様書では1-2相励磁方式の励磁順序の表が載っていますが、それから推測した2相励磁の場合の励磁順序は表3の通りです。(時計方向回り時)
ドライバボード入力 | モータリード線 | 1ステップ | 2ステップ | 3ステップ | 4ステップ |
+ (5V) | リード線色 赤 | 5Vに接続 | 5Vに接続 | 5Vに接続 | 5Vに接続 |
IN1 | リード線色 青 | HIGH | LOW | LOW | HIGH |
IN2 | リード線色 桃 | HIGH | HIGH | LOW | LOW |
IN3 | リード線色 黄 | LOW | HIGH | HIGH | LOW |
IN4 | リード線色 橙 | LOW | LOW | HIGH | HIGH |
以上からpin1~pin4とドライバボードIN1~IN4の関係は次の様になります。
pin1: リード線色 青 (ドライバボード入力 IN1)
pin2: リード線色 桃 (ドライバボード入力 IN3)
pin3: リード線色 黄 (ドライバボード入力 IN2)
pin4: リード線色 橙 (ドライバボード入力 IN4)
ドライバボード入力にIN2とIN3がひっくり返っていることに注意が必要です。
4.実験回路
今回の実験回路では、2個のスイッチをRaspberry Pi Pico WのI/OのGP6とGP7に接続、3個のLEDをGP18~GP20に接続しました。
一般にFA機器の制御ではDC24Vで動作するセンサやアクチュエータが使用されますが、今回はOpenPLCの動作実験と言うことで、Raspberry Pi Pico WのDC3.3VのI/Oに直接スイッチとLEDを接続しました。
またステッピングモータを駆動するためのI/Oとして、OpenPLCのI/Oとして使用してないGP0~GP3を使用しました。
図2に実験装置の回路図、図3に実験装置の外観を示します。
5.ラダー図言語プログラムに関して
5-1.変数の定義
ラダー図言語プログラムの変数の定義表を図4に示します。
Location欄に%に続く文字列が記載されているSW1,SW2,LED1,LED2,LED3はRaspberry Pi Pico WのI/Oを直接操作する変数です。
SW1がGP6に接続されたスイッチの状態を表す変数、SW2がGP7に接続されたスイッチの状態を表す変数、LED1がGP18に接続されたLEDの状態を操作する変数、LDE2がGP19に接続されたLEDの状態を操作する変数、LED3がGP20に接続されたLEDの状態を操作する変数です。
Class欄にExternalと記載されている変数motor_start, move_steps, move_direction, move_speedがスケッチと共用の変数です。Externalと記載された変数はスケッチ内でそのままの名称で使用出来、その値はラダー図言語、スケッチの双方のプログラムから参照、変更が出来ます。表4に定義したExternal変数の内容を示します。
変数名 | タイプ | 内容 |
motor_start | BOOL | ラダー図言語プログラムでfalse→trueにすると、スケッチ側でステッピングモータの回転を開始します。 回転ステップ数は、move_steps変数で指定します。 回転スピードは、move_speed変数で指定します。 move_stepsで指定したステップ数モータが回転するとスケッチ側でmotor_startをfalseにします。 ラダー図言語プログラムはmotor_startがfalseになることでモータの回転が終了したことを知ります。 |
move_steps | DINT | ステッピングモータの回転ステップ数を指定します。 |
move_direction | BOOL | ステッピングモータの回転方向を指定します。 true:CW方向、false:CCW方向 |
move_speed | DINT | ステッピングモータの回転速度(rpm)を指定します。 |
5-2.ラダー図言語プログラム
作製したラダー図言語プログラムを以下に示します。
このラダー図言語プログラムは、SW1を押すと以下の順に動作します。
LED1点灯→0.5秒待ち→LED1消灯しLED2点灯→0.5秒待ち→LED2消灯しLED3点灯してステッピングモータが500ステップ回転→LED3消灯しLED1点灯の繰り返し
動作中にSW2押すとステッピングモータが500ステップ回転終了した時点で動作を停止します。
上記ラダー図言語プログラムの概略動作を図6の流れ図に示します。
6.スケッチに関して
6-1.スケッチの作製手順
ステッピングモータを駆動するスケッチの作製手順に関して示します。スケッチはラダー図言語プログラムでExternalで定義した変数を使用することが出来ます。
1.画面左側にあるProject欄のをクリックします。
2.表示された選択画面の「Arduino extention」をクリックします。
3.画面左欄のProjectのツリーに「0.x: arduino_ext_0」が追加されます。これがスケッチです。「0.x: arduino_ext_0」をダブルクリックすると、スケッチ作成画面が右側に表示されます。
4.「0.x: arduino_ext_0」をダブルクリックすると、以下の様なスケッチ作成画面が表示されます。空のsketch_setup()関数とsketch_loop()関数が自動的に表示されます。
5.最初にラダー図言語プログラムと共通で使用する変数の定義をします。変数定義表部にあるをクリックすると行が追加されます。
6.ラダー図言語プログラムの変数定義でExternalで定義したmotor_start、move_steps、move_speed、move_direction変数に関して記載します。最初にmotor_start変数に関して以下の様に記載します。
7.同様の手順で残りの変数に関しても以下の様に記載します。
8.画面でsketch_setup()と書いてある関数が、Arduinoスケッチのsetup()関数に相当します。sketch_loop()と書いてある関数が、Arduinoスケッチのloop()関数に相当します。
これらの関数は通常のスケッチと同じ処理を記述することが出来ます。
但し注意点としてラダー図言語プログラムとスケッチの処理はマルチタスクで実行されているわけではないようです。ラダー図言語プログラム処理が1スキャン分終了した後に、スケッチが1ループ分実行されて、その後またラダー図言語プログラムが1スキャン分実行されるような交互の処理となっているようです。
よって、sketch_loop()関数内に待ちのある処理(delay関数等)を入れてしまうと、ラダー図言語プログラムの処理がその分、遅くなってしまします。
以上よりsketch_loop()関数内に待ちのある処理を入れないようにアルゴリズムを工夫する必要があります。
9.必要に応じてラダー図言語を実行するタスクのインターバルを短く設定する必要があります。
スケッチのsketch_loop()関数が呼び出される頻度は、後述するようにラダー図言語プログラムのタスクの呼び出しインターバルに依存します。今回のようにsketch_loop()関数が呼び出される毎に、ステッピングモータを1ステップずつ駆動するような場合に、早い駆動を実現するためには、タスクの呼び出しインターバルを短く設定する必要があります。
タスクの呼び出しインターバルはデフォルトで20msecですが、今回作成したプログラムでは、ステッピングモータを10rpmで回転されていますが、タスク呼出しのインターバルを1msecに設定しないと、その回転速度は得られませんでした。
以下(6-2)にタスク処理のインターバルを変更する手順を示します。
6-2.タスク処理のインターバルの変更
本記事を書いた時点のOpenPLCのバージョンは「20241108」ですが、その時点でスケッチのタスクはラダー図言語プログラムと独立して指定できません。
スケッチのsketch_loop()関数が呼び出されるインターバルは、ラダー図言語プログラムのタスクのインターバルに依存しているようで、正確には調べていませんが、ラダー図言語プログラムの1スキャンが終了した時点でスケッチのsketch_loop()関数を呼び出し、sketch_loop()関数の処理が終了した時点で、再びラダー図言語プログラムを1スキャン実行する様な処理になっているのではないかと思われます。
本記事のスケッチでは、sketch_loop()関数が呼び出される毎にステッピングモータの1ステップの回転しか行っていないので、sketch_loop()関数が呼び出される時間間隔を短くしないと、ステッピングモータの早い回転速度は得られません。
本プログラムではステッピングモータの回転速度10rpmを得るために、タスクインターバルのデフォルトが20msecのところ1msecに変更しました。以下に変更手順を示します。
1.画面左側のProject欄のRes0をクリックします。下図の様な画面が右側に表示されます。
この画面で、ラダー図言語プログラム(program0)はtask0に割り当てられていて、task0のIntervalはT#20msとなっていて、20msecになっていることが分ります。
2.task0のIntevalをT#20msからT#1msに変更します。
6-3.スケッチの概要
ステッピングモータ駆動はArduinoのスケッチによって行っています。スケッチの動作の概要は図7の通りです。ラダー図言語プログラムがmotor_start変数をTrueにした場合に、ステッピングモータを指定された回転速度で指定されたステップ数回転します。
6-4.スケッチ全体
//////////////////////////////// sketch section ////////////////////////////////
#include <Stepper.h>
#define STEPS 2048 //Steps per rotation
long step_count = 0; //Motor step counter
unsigned long last_time = 0; //Last time
unsigned long delay_time = 0;//Move delay time
bool start_flag = false;
//One rotation 2048 steps
Stepper stepper(2048, 0, 2, 1, 3);
void sketch_setup()
{
Serial.begin(9600);
pinMode(0, OUTPUT); //Motor Wire Connection(blue)
pinMode(1, OUTPUT); //Motor Wire Connection(pink)
pinMode(2, OUTPUT); //Motor Wire Connection(yellow)
pinMode(3, OUTPUT); //Motor Wire Connection(orange)
stepper.setSpeed(500); //motor speed 500rpm
//Delay time culculation (usec)
delay_time = 60 * 1000 * 1000 / STEPS / move_speed;
}
void sketch_loop()
{
unsigned long pass_time;
//Read current time
unsigned long now_time = micros();
//Pass time culculation
if (now_time >= last_time){
pass_time = now_time - last_time;
}else{
//Overflow occurred
pass_time = now_time - (0xffffffffUL - last_time + 1);
}
if (motor_start == true){ //Motor start?
if (start_flag == false){
start_flag = true;
step_count = 0;
//Delay time culculation (usec)
delay_time = 60 * 1000 * 1000 / STEPS / move_speed;
pass_time = delay_time;
}
}
//Delay time has passed
if (pass_time >= delay_time){
last_time = now_time;
if (start_flag == true){
//Direction Judgement
if (move_direction == true){
stepper.step(1); //Move 1 step
step_count++; //Step count increment
} else {
stepper.step(-1); //Move -1 step
step_count++; //Step count increment
}
//Movement end decision
if (step_count >= move_steps){
step_count = 0;
start_flag = false; //Start flag clear
motor_start = false;
}
}
}
}
6-5.スケッチ説明
本スケッチで使用したステッピングモータ駆動関係(Stepperライブラリ)の関数を表5に示します。
作成したプログラムの説明用として記載したので、各関数のクラス部分はプログラム中で使用しているインスタンス名のまま記載しています。
関数等 | 説明 |
#include <Stepper.h> | ステッピングモータライブラリ関係のヘッダファイルのインクルード。 |
Stepper stepper(steps, pin1, pin2, pin3, pin4) | Stepperクラスのコンストラクター。 引数: steps: 1回転あたりのステップ数(int) pin1,pin2: モータに接続されているピンの番号 pin3,pin4: 4ピンのモータの場合のピン番号 |
stepper.setSpeed(rpms) | ステッピングモータの回転速度の設定。 rpms:モータの回転速度。1分間あたり何回転するかを正の数で設定。(long) step()をコールしたときのスピードをセットする。 |
stepper.step(steps) | ステッピングモータを回転させる。 steps:モータが回転する量(ステップ数)。逆回転させる場合は負の値を設定。(int) 回転が終了するまで関数を抜け出ない。 |
sketch_setup()関数とプロパティ
#include <Stepper.h>
#define STEPS 2048 //Steps per rotation
long step_count = 0; //Motor step counter
unsigned long last_time = 0; //Last time
unsigned long delay_time = 0;//Move delay time
bool start_flag = false;
//One rotation 2048 steps
Stepper stepper(2048, 0, 2, 1, 3);
void sketch_setup()
{
Serial.begin(9600);
pinMode(0, OUTPUT); //Motor Wire Connection(blue)
pinMode(1, OUTPUT); //Motor Wire Connection(pink)
pinMode(2, OUTPUT); //Motor Wire Connection(yellow)
pinMode(3, OUTPUT); //Motor Wire Connection(orange)
stepper.setSpeed(500); //motor speed 500rpm
//Delay time culculation (usec)
delay_time = 60 * 1000 * 1000 / STEPS / move_speed;
}
【説明】
1行目:
#include <Stepper.h> ステッピングモータライブラリ関係のヘッダファイルのインクルードです。ステッピングモータの回転スピードを設定するsetSpeed()関数、ステッピングモータを回転させるstep()関数等の関数を使用する場合にインクルードします。
9行目:
Stepper stepper(2048, 0, 2, 1, 3);
ステッピングモータの1回転のステップ数と、ステッピングモータ線が繋がるI/Oを指定します。
第1引数の2048は使用するステッピングモータの一回転のステップ数です。
第2引数から第3引数は、ステッピングモータ線がGP0,GP2,GP1,GP3に接続することを指定しています。GP1とGP2がひっくり返っているのは「ステッピングモータの駆動に関して」を参照して下さい。
15行目~18行目:
pinMode(0, OUTPUT);~pinMode(3, OUTPUT);
ステッピングモータ線と接続するRaspberry Pi Pico WのI/OのGP0~GP3を出力に指定しています。
20行目:
stepper.setSpeed(500);
ステッピングモータの回転速度を500rpmに設定しています。
但し、今回のプログラムではステッピングモータを駆動するstepper.step(steps)関数のstepsの値は「1」か「-1」で1ステップずつの駆動しかしていません。これは前述したようにsketch_loop()関数内に待ち処理は不可なので、stepper.step()関数から出来るだけ早く抜け出すようにするためです。
よって、stepper.setSpeed()関数で回転速度は決まりません。stepper.step()関数からは出来るだけ速く抜け出るようにstepper.setSpeed(rpms)のrpmsの値は大きめに設定しています。
23行目:
delay_time = 60 * 1000 * 1000 / STEPS / move_speed;
ステッピングモータを1ステップ駆動した後に次に1ステップ駆動するまでの時間をモータの回転速度(rpm)とモータの1回転のステップ数から計算しています。時間の単位はμsecです。
sketch_loop()関数
void sketch_loop()
{
unsigned long pass_time;
//Read current time
unsigned long now_time = micros();
//Pass time culculation
if (now_time >= last_time){
pass_time = now_time - last_time;
}else{
//Overflow occurred
pass_time = now_time - (0xffffffffUL - last_time + 1);
}
if (motor_start == true){ //Motor start?
if (start_flag == false){
start_flag = true;
step_count = 0;
//Delay time culculation (usec)
delay_time = 60 * 1000 * 1000 / STEPS / move_speed;
pass_time = delay_time;
}
}
//Delay time has passed
if (pass_time >= delay_time){
last_time = now_time;
if (start_flag == true){
//Direction Judgement
if (move_direction == true){
stepper.step(1); //Move 1 step
step_count++; //Step count increment
} else {
stepper.step(-1); //Move -1 step
step_count++; //Step count increment
}
//Movement end decision
if (step_count >= move_steps){
step_count = 0;
start_flag = false; //Start flag clear
motor_start = false;
}
}
}
}
【説明】
5行目~13行目:
今回のプログラムでは、一定時間間隔毎にステッピングモータを1ステップずつ駆動させています。
sketch_loop()関数内で待ち処理は出来ないので、このステップ駆動間の時間を取るのに、現在時間を読み込むmicros()関数を使用しています。
micros()関数はプログラム実行を開始した時から現在までの時間をマイクロ秒単位で返す関数です。sketch_loop()関数が呼び出される毎に、micros()関数で現在の時間を得て、前回処理した時の時間との差が予定した一定時間になった時にステッピングモータを1ステップ駆動することによって一定速度の回転が可能となります。
但し、注意が必要なのは、micros()関数のリターン値はunsigned longの32bitでオーバーフローすると零に戻ります。実際には0xffffffff (4294967295)を超えると零に戻ります。これは71.6分に相当します。
よって、micros()関数で得た現在時間から、前回の処理時にmicros()関数で得た時間を引いて経過時間を計算すると、前回処理した時の時間が71.6分近くの場合に、次の時間読込が0付近の値となってしまい経過時間が正しく計算出来ません。
今回作成したプログラムでは、現在時間と前回の時間を比較して、
現在時間 < 前回の時間
の場合は途中でオーバフローが発生したと判断して、次の様に経過時間を計算しています。
経過時間 = 現在時間 – (0xffffffffUL – 前回の時間 + 1)
15行目:
if (motor_start == true){
ラダー図言語プログラムによってmotor_start変数がfalse→trueに変更されたのを判断して、以降のステッピングモータ駆動処理を行っています。モータ回転スタートフラグであるstart_flag変数をtrueにしています。
20行目:
delay_time = 60 * 1000 * 1000 / STEPS / move_speed;
ステッピングモータを1ステップ駆動した後に次に1ステップ駆動するまでの時間をモータの回転速度(rpm)とモータの1回転のステップ数から計算しています。時間の単位はμsecです。
26行目:
if (pass_time >= delay_time){
経過時間が予め予定した時間以上になっているか判断します。
モータ回転スタートフラグであるstart_flag変数がtureで、経過時間が予定時間以上の場合に、ステッピングモータの駆動処理を実施します。
ステッピングモータの駆動は、stepper.step(steps)関数をしています。これはStepperライブラリの関数でステッピングモータをstepsで指定したステップ数駆動します。この関数での処理待ちを避けるために1ステップの送りとしています。
31行目:
if (move_direction == true)で、ステッピングモータの回転方向をチェックして、trueの場合は32行目のstepper.step(1)でプラス方向に1ステップ回転させています。
falseの場合は35行目のstepper.step(-1)でマイナス方向に1ステップ回転させています。
40行目:
if (step_count >= move_steps){
ステッピングモータの回転ステップ数が、変数move_stepsで指定した値以上になった場合に、motor_start変数をfalseにして回転を停止しています。
7.プログラムのコンパイルと書き込み手順
プログラムのコンパイルとRaspberry Pi Pico Wに書き込む手順に関して説明します。
1.先ずArduinoの開発環境であるArduino IDEをインストールします。(Arduino IDEのインストールに関してはこちらを参考にして下さい)
Arduino IDEをインストールする理由は、本プログラムではステッピングモータを駆動するのにArduino言語のStepperライブラリを使用しています。
プログラムをコンパイルするのに、StepperライブラリのStepper.hとStepper.cppと言うファイルを必要とします。
Stepper.hとStepper.cppファイルを得る方法は様々あると思えますが、Arduino IDEをインストールすると、そのlibフォルダ内に形成されますので、先ずArduino IDEをインストールします。
2.Arduino IDEのインストールをした後に、Arduino IDEのインストールの場所によって異なるかもしれませんが、
…\ユーザ\ユーザ名\AppData\Local\Arduino15\Libraries\Stepper\srcフォルダ内にあるStepper.hとStepper.cppをOpenPLCの以下フォルダ内にコピーします。
…\ユーザー\ユーザー名\OpenPLC_Editor\editor\arduino\src
3.OpenPLC Editorを起動して、File→Openをクリックして、該当するプログラムフォルダを指定して、プログラムを呼び出します。
4.OpenPLC Editorを起動したパソコンとRaspberry Pi Pico WをUSBケーブルで接続します。
5.OpenPLC Editorの画面上方のをクリックするとプログラムのコンパイルとRaspberry Pi Pico Wへの書き込みが行われます。
6.以下画面が表示されましたら、「Board Type」に「Raspberry Pico W」を選択し、「COM Port」にRaspberry Pi Pico Wと繋がるCOMポートを選択して、「Transfer to PLC」をクリックすると、Raspberry Pi Pico Wへのプログラムの書き込みが開始されます。
7.「Done!」が表示されると、プログラム書き込みが終了します。プログラム書き込み終了後、Raspberry Pi Pico Wはプログラムの実行を開始します。
8.動作動画
以下動画は、今回作成した実験装置を動作させる様子です。
SW1を押すとLED1点灯→0.5秒待ち→LED1消灯しLED2点灯→0.5秒待ち→LED2消灯しLED3点灯してステッピングモータが500ステップ回転→LED3消灯しLED1点灯の繰り返しを行います。
動作中にSW2押すとステッピングモータが500ステップ回転終了した時点で動作を停止します。
9.最後に
OpenPLC EditorでPLCプログラム言語のラダー図言語プログラムとArduinoスケッチを共存させ、全体的な動作をラダー図言語で作成して、ステッピングモータを動作させる部分をスケッチで作成して、ラダー図言語プログラムからスケッチにデータを渡して、ステッピングモータを動作させることが出来ました。
スケッチを併用することによって、ラダー図言語だけでは実現するのが難しい部分の制御が実現出来るので、OpenPLCの応用範囲が広がると思います。