なぜ自作?

ファンクションとファンクションブロックはプログラムの共有が目的で、同じようなプログラムを複数の人がそれぞれで作っていたものを1つにして、同じプログラムをみんなで使いましょうというのが目的です
● 複数の人がバラバラで同じようなものを作るよりプログラムの作成工数が減ります
● 同じプログラムを使うことでプログラムの品質は一定になります

ファンクションを作るか? ファンクションブロックを作るか? どっち?

1スキャンで結果を出力できる処理内容ならファンクション

計算ならよほど大量の計算が必要でない限りファンクションで作ります

複数スキャン必要な処理ならファンクションブロック

複数スキャン必要な処理とは、通信処理、モーション、ファイル操作などがあげられます

おおまかなFUNとFBの選択基準

選択基準
処理内容推奨
四則演算Function
単位変換Function
文字列処理Function
タイマーFB
通信FB
ファイル操作FB
モーション制御FB

Execute型とEnable型の違い

Enable型
違い
項目Execute型
起動立上りエッジON中継続
Busyあり通常なし
Doneあり通常なし
用途通信・ファイル操作継続監視

ルール お作法的な

入出力

入力に何らかの値を入れれば出力にその結果を出力します
その入力と出力は以下の3つの基本形のどれかに合わせるようにします

実際はInput,Outoutは複数になるでしょうが、入力変数が10個とか多くなるようなら関係ある変数を構造体にしてまとめるのがいいでしょう

Function

ファンクション
変数名内容
Functionのグラフィック入力EN 実行
ONしているときにファンクション内部の処理を実行します
Input入力パラメータ
出力ENO
空白(Out)戻り値
BOOL以外の時にこちらに出力される

Execute型FB

ファンクションブロック(Execute型)
変数名内容
Execute型のグラフィック入力Execute 起動
常にFB内部は実行し続ています
Executeの立ち上がりで処理を開始します
ExecuteがOFFになっても完了するまで処理を続けます
処理が完了したらDoneかErrorのどちらかをONにします
Input 入力パラメータ
出力Done正常終了時にON
Busy実行中にON
Error異常終了時にON
ErrorID異常コード出力
Output 処理結果

Execute型の各フラグは以下のタイムチャートのような動作をするように作ります
Execute型のチャート


Enable型FB

ファンクションブロック(Enable型)
変数名内容
Enable型のグラフィック 入力 Enable 実行
常にFB内部は実行し続ています
EnableがONしたらEnabledをONにして処理をします
EnableがOFFになったらEnableをOFFにして処理を終了します
Input 入力パラメータ
出力 Enabled 実行中
Output 処理結果

注意したいところ

入力変数と出力変数と入出力変数

入力変数出力変数は値渡し(ByVal)です
入出力変数はポインタ渡し(ByRef)です

通常は入力変数出力変数を使います
大きな変数(例えばWORD型の配列10000個とか)を入力変数に入れたいときは入出力変数にするのがよいでしょう

その理由は・・・
入力変数は値をFBのインスタンス内の変数に値をコピーしてからFB内のプログラムを実行します
処理した結果を出力変数にコピーしてFBの外部に値を渡します(入力変数と出力変数は値渡しとして扱われるため、大きな配列ではコピーコストが発生しオーバーヘッドとなり処理に時間がかかります。)
この処理はプログラマーからは見えないところで行われているので、コピーする時間だけスキャンタイムが伸びることに注意してください

それに対して入出力変数はコピーはせずに変数の値を直接読み書きします
コピー処理は行われないので大きなサイズの変数を入出力変数にしてもスキャンタイムが伸びることはありません

外部変数

原則として使用を避けるべきです
使っていいのはシステム定義変数のみ
ここにユーザが作ったグローバル変数が入った時点で部品化できずにそのプロジェクトだけで使用できるFun/FBになってしまいします
ユーザが作った変数を使いたい場合は入力変数にすべきです

入力チェック

入力変数に想定外の値が入ってきたときのエラー処理を忘れずやりましょう
入力変数に変数を入れなかった時のために必要なところは初期値も入れましょう

ErrorIDに入れる値

ErrorIDは基本的にFB内部で使用した命令のErrorIDをそのまま出力します
ErrorExがある場合はErrorIDExも出力変数に追加します
それ以外にオリジナルのエラーIDを付ける場合はErrorIDにオリジナルのエラーであるコードを入れて(例えば#FFFFなど)、ErrorIDExに詳細なエラーIDを入れるようにすると区別しやすくなります

よくある質問

自作するならFunctionとFunction Blockのどちらを選ぶべきですか?

1スキャンで結果を返せる処理はFunction、通信処理やモーション制御など複数スキャンにまたがる処理はFunction Blockが適しています。

Execute型FBとEnable型FBの違いは何ですか?

Execute型は立上りエッジで処理を開始し、Busy・Done・Errorを使用します。Enable型はEnable信号がONの間継続して動作し、主に監視処理などで利用されます。

入力変数・出力変数と入出力変数はどのように使い分けますか?

通常の入力変数と出力変数はByValの入力変数・出力変数です。大容量配列などコピーコストが大きいデータを扱う場合はByRefの入出力変数を利用するとスキャンタイム増加を抑えられます。

FBで外部変数は使用すべきですか?

原則として使用を避け、必要なデータは入力変数として受け渡します。外部変数に依存すると再利用性が低下します。

この記事へのコメント