この記事で扱っていること
- 順番を指定した処理の実行の方法
を紹介しています。
注意:すべてのエラーを確認しているわけではないので、記事の内容を実装する際には自己責任でお願いします。また、エラー配線は適当な部分があるので適宜修正してください。
LabVIEWのデザインパターンに、ステートマシンというものがあり、これはプログラムにおけるそれぞれの処理をステートとして定義し、条件によってそれら各ステートを移って一連の処理を行わせるといった手法になっています。
このデザインパターンで、「こうなったら次はこうする」という処理の流れが決まったプログラムの実装が可能になり、比較的習得するのに難易度は低いですが強力な方法になっています。
基本のステートマシンをベースに、イベントストラクチャと組み合わせたイベント駆動型ステートマシンと呼ばれる派生形もありますが、今回の記事の方法もベースはステートマシンとしつつ、処理の流れを一度に決めて、それを一気に順番に実行するために配列でステートを管理するといった派生形のプログラムを使用しています。
処理の流れをプログラム実行中に自由に決められ、決定ボタンを押すことでその通りの順番で実行したいときに便利です。
どんな結果になるか
フロントパネルには順番を決めるべき処理がブールボタンでまとまっていて、プログラム実行時にそれらを好きな順番で実行することができます。
実行時に好きな順番にボタンを押し、決定ボタンを押すと、今何番目のどの処理を実行中かの表示が出て現在何をやっているかをユーザーに知らせてくれます。
それぞれの指定項目で何かしらの処理をさせ(このサンプルでは特定の処理はせずただ現在の状況を表示するだけですが)、その間は余計な操作ができないようにプログラム停止以外のボタンがグレーアウトするようにしています。
そして指定した順番で全ての処理を終えたら、また選択ができる状態に戻り、これをプログラム停止ボタンが押されるまで繰り返します。
プログラムの構造
プログラムはステートマシンをベースにしていますが、指定の順番を守らせるために配列を使用してステートを分けています。
ケースストラクチャは10、イベントは5個定義しています。
ただし、この記事のサンプルでは選択項目リストに全部で7個の項目があったためケースの数が10となっていますが、項目数が変わるとケースの数も当然変動します。
この記事と同じようにプログラムを組んだ場合、ケースの数は「項目の数+3」になります。
この記事のサンプルでは、各ケースにおける処理(アルゴリズムの実行)をメインループに行わせて、それと並行しユーザーインタフェース(UI)の操作は別ループで行わせています。
そのため、各ケースにおいてUIを制御するためにUI制御ループへキューを使用してデータを渡しています。
ここでいうデータとは、各ボタンの無効プロパティをどう制御するかのブールと、フロントパネルの実行表示の文字列表示器に何を表示させるかの文字列を含んだクラスタになります。
UIループで使用しているサブVIは以下のようになっており、メインVIの方でクラスタやブールのリファレンスを渡されることでコンパクトにすべての無効プロパティを操作できるようにしました。
ではメインのWhileループを見ていきます。
このサンプルの肝になる部分は、ステートマシンの各ステートを配列で管理し、毎ループごとにその配列の要素番号0のステートを実行、そしてこの要素は削除してしまうという構造です。
もう一つ重要なのは、ステートを指定するタイプ定義された列挙体では、「フロントパネルに設置した各ボタンに対応するステート」を項目の後半に置いていることです。
今回のプログラムではステートとして、(ステートマシン全体の)初期化を行うinitステート、イベント待機をするevent_waitステート、そしてプログラムそのものを終了するためのfinishステート以外は、フロントパネルの選択項目リストの各ボタンに対応したステートとしています。これら各ボタンに対応したステートを必ず列挙体の項目の後半にもってきます。
それでは、まずはinitステートです。このステートは、プログラムを初めて一番最初に行われます。今回のプログラムでは特別何かをしているわけではありませんが、多くの場合何かしら初期化を行うためにこういったステートを必要とするので用意してみました。
次にevent_waitのステートですが、このステートの全体像は既に上で示しているので、計5つのイベントの中身を紹介します。
5つのうち4つはそこまで大きな処理を行っていないのでまとめて紹介します。
選択項目リストの値変更イベントだけ、他と比べるとやっていることが多いです。
このステートでは、選択項目リストのクラスタを配列に変換して、どのボタンが押されたかという情報をその配列の要素番号として取得、これをステートの配列に追加していきます。
ステートの配列に追加する際には、列挙体から列挙体配列という、比較的最近のLabVIEWで導入された関数を使用して、指標配列とともに要素番号を適切に変換する必要があります。
古いLabVIEWを使用されている場合には、下の図の下部の吹き出しにこの関数の中身を公開しているので自作できると思います。
なお、1D配列検索の後に3を足していますが、これはステートの数と選択項目リストのブールボタンの数の補正です。この3は、initステート、event_waitステート、そしてfinishステートの合計3ステートを表わしています。そのためもし他のステートもあった場合にはこの補正値はその数に合わせて変える必要があります。
次にfinishステートです。これはWhileループを止めてステートマシンを終了させるためのステートです。
そして残りは選択項目リストに対応するステートですが、はっきり言って中身は何でも構いません。例えば初期化ステートについては以下のようにしています。
UIループに情報を渡すという処理は設けていますが、それ以外はお好みの処理を実装してください。待機関数に1000が配線されているのも特に意味はありません。
他のステートも同様です。例えばテストAというステートも以下のように、この初期化ステートと全く同じです。
それぞれの、選択項目リストに対応するステートに任意の処理を入れたらプログラムの完成です。
選択項目リストの更新
選択項目リストのそれぞれのブールテキストは列挙体の中身と一致させています。プログラム作成の段階でこのリストのそれぞれの項目名を固定している場合には問題ないのですが、もし途中で列挙体を編集して名称が変わった場合に、ブールテキストも忘れずに変える必要があります。
その作業、つまり列挙体の項目名とブールテキストの項目名をプログラム的に合わせる方法があり、それは例えば以下のようなコードをブロックダイアグラムを追加することでできるようになります。
複数の項目があり、任意の順番で行わせるといったことを実行の度にカスタマイズすることができるプログラムは、今回の記事で紹介したようにステートマシンのステート管理を配列で行うことで実装できてしまうので、参考にしてもらえるとうれしいです。
ここまで読んでいただきありがとうございました。
コメント