本シリーズでは、このブログで紹介してきた「まずこれ」のシリーズを凝縮して、LabVIEWによるプログラミングはこんな風にできるんだ、ということを比較的すぐに体験できるよう、内容を絞って紹介しています。
また、紹介する画面はLabVIEW Community Editionという、非商用の目的であれば無料で使用できるエディションを使っています。なので、LabVIEWに興味を持ったらCommunity Editionを実際にダウンロード、インストールして触りながらプログラムを作り、LabVIEWの楽しさに触れてもらえればと思います。
第八回目の今回は、ステートマシン実装にあたって直面するであろう、いくつかの問題について具体的な対処方法を紹介します。
LabVIEWでプログラムを書く上で強力な武器であるステートマシンというプログラムのテンプレートの紹介は前回までで一通り終わったので、今回の記事はおまけ的な要素が強いですが、それでも知っておくとステートマシンを構築するうえでとても役にたつ知識が多いです。
また、このシリーズを読み終えた後に次にどうすればいいかについても最後に少し紹介したいと思います。
なお、前の記事はこちらです。
こんなときどうする:状態を増やす
前回の記事でも少し紹介しましたが、ステートマシンの特徴である「状態」を列挙体を編集することで追加しようとすると、ケースストラクチャのラベルが数字に変わってしまうということが起こりました。

これは、シフトレジスタに複数の種類の列挙体(定義されている「状態」の種類や数が違うもの)が配線されていることによるもので、解消するためにはプログラムの中で使われている、同じシフトレジスタに関わる全ての列挙体に対して変更を加える必要があります。
小さな規模のプログラムならまだしも、大きくなるとこの作業は現実的ではなくなります。
そんなときに役立つのが、タイプ定義という機能です。
簡単な実験をするために、まずは適当な要素を3つもつ列挙体を作り、これをコピーして二つにします。

それから、片方の列挙体を右クリックしてMake Type def.を選択します。そうしたら、この列挙体もコピーします。これで、合計三つ(タイプ定義していないもの、タイプ定義したもの、タイプ定義したものをコピーしたもの)の列挙体がある状態となります。
なお、タイプ定義は、下の図のように、左上に黒い目印がつくことで判別できます。

ではここで、タイプ定義した列挙体を一つ選択してOpen Type Def.でタイプ定義を開きます。そして、開かれたタイプ定義上で列挙体に項目を追加して、Apply Changesで変更を適用します。
Apply Changesをする前は、タイプ定義の列挙体が薄い表示になっているのが、Apply Changesすることで明るい表示になるのがわかると思います。

さて、ここで、編集を加えていない二つの列挙体を見てみます。
まずは、一番最初にコピーした際に生成された列挙体(タイプ定義されていないもの)です。こちらは、元の通り三つの項目を持っていることが確認できます。

次に、編集を加えていない、タイプ定義した列挙体を見てみます。すると、もう片方の列挙体で加えた編集の影響を受けていることが確認できると思います。
つまり、タイプ定義した列挙体定数は全て同じ項目を持っていることがわかります。

タイプ定義は、このように、一つのタイプ定義をいわば「マスター」として設定する状態で、このマスターに編集を加えることで、これを参照している全てのタイプ定義された列挙体に一斉にその編集の結果を反映させることができる機能になっています。

この機能は、列挙体に限った話ではなく、他のデータタイプに対しても使用することができます。
なんで他のデータタイプに対してタイプ定義をするのか、ちゃんと利点はあるのですが、本シリーズでは扱っていないクラスタの話が絡んできたりするので、本シリーズでは割愛します。
なお、既に作ってしまったステートマシンについては、残念ながら一つずつタイプ定義した列挙体に置換するしか方法がありません。
つまり、列挙体のタイプ定義はステートマシンを作成する一番最初にやっておくべきこと、になります。

じゃあ初めからタイプ定義を紹介してくれ、と思われた方もいるとは思いますが、不便な事態に陥ることを経験しないとタイプ定義のありがたみが伝わりづらいかなと思い、最後の最後に紹介、ということにしてみました。
こんなときどうする:意図していない順番でユーザーが操作してしまう
次に問題となるであろうことは、プログラムを書いた人が意図していない順番で、ユーザーが操作をしてしまう、という場面です。
前回の記事で紹介した、波形を取得、保存するプログラムでも、意図しない順番で操作されてしまうと画面に何も変化が出なかったりして、動いているかわからない状態になる可能性があります。

実際、これはとても厄介になりうる問題です。
プログラムを書く側としては、(自分で書くべきプログラムがわかっているため)ある程度「こういう操作をしてほしい」という前提を元にプログラムを書くことがあると思います。
なので、プログラムを作りながら正しく動くか確認する際にも、「正しい順番で操作」することが多いと思います。
もちろん、意図しない順番でユーザーが操作しても不具合が起きないことを確認したりする作業は大事ですが、全ての操作シナリオを検証するのはなかなか厳しい話です。
そこで、そもそも意図しない順番での操作ができないようにしておく、という手が考えられます。
ではどうするか?単純な話、「意図しないタイミングでの操作をしようとしてもできない」ように設定すればいいんです。
こういった設定は、そのままずばり「Disable(無効)」設定というもので、プログラム的に無効の有無を切り替えることができます。

試しに、以下のように数値制御器を例にこの設定を試してみます。
数値制御器を右クリックして、CreateからProperty、その中にあるDisabledを選択します。

ブロックダイアグラム上にDisabledと書かれたものが表示されるので、右クリックしてChange to Writeを選択します。
デフォルトではReadのモードになっています。Readは「現在のこの機能に対する設定を読み取る」ことを表していて、Writeにすることで「現在のこの機能に対する設定を変更する」ことができるようにします。

このDisabledという機能に対しては、専用の列挙体を入力する必要があります。
右クリックしてCreate Constantとすると、この専用の列挙体が自動的に生成されるので、これを使用できます。
Enabledは「操作可能」、Disabledは「無効」、Disabled and Grayed Outは「無効かつグレーアウトする」という設定になっています。なので、Enabled以外で「無効」状態にすることはできますが、見た目上分かりにくいのでGrayed Outさせる方が良いと思います。

新しい機能を使用する場合には簡単なプログラムを作ってその効果を確かめるのが上達への近道です。
例えば今回の無効設定であれば、選択の関数と組み合わせて、以下のようにプログラムを作ってみると、ブールのボタンを押すたびに数値の制御器の値の変更可否を変えることができるようになります。

なお、ここで紹介したDisableという機能は、制御器を右クリックしたときに表示されるように、Property Nodeというものを使っています。これは、LabVIEWの制御器や表示器のプロパティ、つまり主に外見に関する設定、をプログラム的に変更するために使用するものです。

前の記事で紹介した、データ測定のプログラムに対してこの無効の設定を適用させる場合のプログラムの一例を以下で紹介します。
既に前の記事でプログラムを作成している場合には、この無効の設定を各ケースに以下で示すような感じで配置すれば、意図しない操作を防ぐことができます。
まずは初期化の状態です。最初に使用する設定完了のボタン以外は全て無効にしておきます。

次の設定の状態は少し複雑です。
これは、後から(測定を開始させてから)でも戻ってこれる状態であるため、ボタンの種類に対して異なる条件を用意する必要があるためです。

あとは測定待機の状態です。

他の状態に対してはもう無効プロパティを追加する必要はありません。
もちろん、サンプリングレートやサンプル数の数値制御器に対して無効プロパティを設定する、ということもできます。
今回はDisableというプロパティに対しての操作を例に紹介しましたが、設定できるプロパティはここでは書き表せないほど数多くあります(またデータタイプによっても選択肢に違いが出ます)。
LabVIEW初心者の方にはハードルが高いかなと思い、このDisabledの機能の紹介だけにとどめますが、プロパティノードを使用することでプログラムでできることのバリエーションが増えるので、もしこの先もLabVIEWを勉強しよう、と思った方はぜひ色々なプロパティノードの設定を試してみてください。
このシリーズを終えた後は
さて、速習LabVIEWと題して用意した記事としてはこれでもうおしまいです。
LabVIEWでプログラムを書くという経験をステートマシンを題材に紹介してきましたが、LabVIEWがどんなものか何となくでもイメージできたでしょうか?
「もっとLabVIEWのことを知りたい!」と思ってくれる方が多いことを願って、最後に、このシリーズの後に何をすればいいのか、について私の考えを紹介して締めようと思います。
関数の使い方を知る
プログラムを書く上でなんと言っても大事なのが、「どんな機能が使えるか」を知ることです。
これまで本シリーズで紹介してきた「繰り返し」や「条件分岐」といった、プログラム全体の動きについて機能もさることながら、やはり関数パレットを開いたときに表示される数々の関数それぞれがどのような役割を持つかについて覚えるのは必要不可欠です。

まさに「そんなことができるなんて、知らなきゃできない」の世界です。そう、知っているか知らないかの違いはとても大きいです。
ただし、いっぺんに全部覚えようとする必要はないと思います。関数パレットに表示される関数が全てどれも等しく使用する機会があるかというとそうではなく、大抵よく使用するものなんてのは決まっています。
とはいえ、最初はどうしても慣れないことばかりだと思うのですが、そんなときに役に立つのはヘルプです。
「ヘルプなんて見たってわからんよ」、と、ヘルプの中身もみていないのに思ったりしていませんか?LabVIEWのヘルプはそれなりに親切にできています。
特に便利なのがContext Helpという機能です。よくショートカットキーとしてCtrl + Hで使用することが多い機能です。

Context HelpからさらにDetailed Helpに飛ぶとより詳しいヘルプのページが開きます。
特にCommunity EditionのLabVIEW上だとContext Helpは英語ですが、ここからDetailed Helpに飛ぶと日本語のヘルプに飛べるので便利です。
なお、日本語のLabVIEWだと、Context Helpが「詳細ヘルプ」に、Detailed Helpが「オンラインヘルプ」に表記が変わっているのでそこはご注意(英訳のミスかな?と思っています)。

もっと細かい知識を身に着ける
プログラムを書く上で、どうしてもステートマシンでは実現しづらいorできないという場面も出てくると思います。
実際、ステートマシンは強力なテンプレートではあるものの万能ではありません。もっと他にも有用なテンプレートは存在しています。
そんなときには、本シリーズで扱った以外のプログラミングの方法について調べることが大事です。
もし本シリーズの記事で「LabVIEW面白そう!」と興味を持てた方はぜひ色々と調べてみてください。
「テンプレート」とか「デザインテンプレート」というのは本ブログ特有の表現ではないので、ネットの検索でも情報が出てくると思います。
なお、本ブログを書くきっかけになった「まずこれ」シリーズでは、速習のシリーズではあまり説明していない内容やステートマシン以外のテンプレートも紹介しています。

最終的に初心者が扱うようなものではないようなそれなりに高度な内容も載せていますが、もしよかったら見てみてください。
速習のシリーズを読み内容が理解できているよ、という方でも、別の説明の仕方をしている部分はあるのでいくつか発見はあると思います。
エラーの処理について
速習のシリーズでは、意図的にエラーの対応方法については説明してきませんでした。
エラーは、可能であれば起こってほしくないものです。ただ実際、エラーは今後(LabVIEWに限らず)プログラムを書く上で必ず出てきます。
どちらかというとエラーは嫌われるものなので、エラーについての話題は意図的に避けつつ、LabVIEWの楽しい面ばかりにフォーカスを当てて本速習の記事を書いていました。
エラーについては大きく分けて二種類があります。
一つは、プログラムの書き方上間違っている場合の、いわばプログラムを実行する前の段階で発生するエラーです。
これまでの記事で紹介した内容を試した際に、途中で経験した方もいるかもしれません。
もしプログラムの構造的なエラーがある場合には実行ボタンは壊れた状態になり、その状態でも構わず実行ボタンを押すとエラーのリストが表示されます。
逆に言うと、このエラーのリストに書いてあるエラー全てを解消しないとプログラムは動きません。

もう一つは、プログラムの書き方自体は間違っていないものの、アルゴリズムや使う関数の違いなどで、意図した結果が出ないという、実行時のエラーです。
後者については様々な種類のエラーが起こりえるので、一概に言えないのですが、前者についてはある程度デバッグにより解消される場合が多いと思います。
エラー処理にはいくつか手法があります。これまでに扱ってきた内容の中では、ケースストラクチャを使用する方法が理解しやすいと思います(実際、エラーをケースストラクチャで処理するという場面はよくあります)。
エラーの情報をケースストラクチャのケースセレクタに配線しエラーが起きた場合とエラーが起きていない場合とでそれぞれ処理を書くようなイメージです。
エラーについては、以下の記事を参考にしてもらうとより対処しやすくなるかもしれません。
プログラムの例をもっと見る
最後に、プログラムは自分で作ることが大事なのですが、それと同時に「どうやって組む方法があり得るのか」などの、サンプルプログラムを確認することも習熟の近道と言えます。
ブールの説明の際に少し出ましたが、LabVIEWにはサンプルファインダという、サンプルが集約された機能があり、ここから様々なサンプルにアクセスできるようになっています。

他の選択肢としては、宣伝になりますが、本ブログで紹介している記事も参考にしてもらえるものはあるのではないかな、と思います。
主にTipsとして公開している記事が多いですが、サイト最下部のサイトマップを見てもらうと本ブログ中で公開している全記事が見つかるので、バッと眺めてみて興味のありそうなタイトルの記事があればそれを参考にしてもらえればうれしいです。
速習シリーズはここで終わりです。
少しでもLabVIEWのこと、知って、触って、楽しめる人が多くなることを期待しています。 ここまで読んでいただきありがとうございました。
コメント