本シリーズでは、このブログで紹介してきた「まずこれ」のシリーズを凝縮して、LabVIEWによるプログラミングはこんな風にできるんだ、ということを比較的すぐに体験できるよう、内容を絞って紹介しています。
また、紹介する画面はLabVIEW Community Editionという、非商用の目的であれば無料で使用できるエディションを使っています。なので、LabVIEWに興味を持ったらCommunity Editionを実際にダウンロード、インストールして触りながらプログラムを作り、LabVIEWの楽しさに触れてもらえればと思います。
第四回目の今回は、プログラムを作るうえで、繰り返しの仕組みと同じくらい欠かせない、条件分岐の仕組みについて紹介していきます。
の前に、例によってこの条件分岐と相性のいいデータタイプ、ブールと列挙体の紹介から始めていきます。
なお、前の記事はこちらです。
条件を指定するのに役立つデータタイプ①:ブール
まずはブール(Boolean)データタイプの紹介です。
既にWhileループの停止条件として前回登場しています。

このデータタイプは、「真偽値」を扱うもので、値が「真」か「偽」のどちらかにしかなりません。真偽値という表現は日本語感がすごいですが、もっとシンプルに「True」、「False」の二択とも表現します。
あとで出てくる条件分岐の表示でもこのTrueとかFalseという表現で出てくるのでまずはこれらを覚えておいてください。
True、Falseの二値を扱うことしかできませんが、条件を満たしたか、ということを表すのにとても便利なデータタイプです。

上記のような、Whileループを停止させる条件を示すために使われているように、条件分岐の仕組みを使う際に「これこれの条件を満たしていたらTrue、満たしていないならFalse」といった具合に場合分けが行えるため、条件分岐のプログラムでは活躍の機会がとても多いデータタイプになっています。
活躍の機会が多いのですが二値しか扱えないためブロックダイアグラム上の挙動の説明はもう他にすることがありません。
一方で、制御器としての扱い方が他のデータタイプと異なり全部で6種類あるということは覚えておく必要があります。
覚えることが6つもあると聞いて大変そうと思われるかもしれませんが、実際大きく分けて2つであり、これらをさらに細分化すると全部で6つ、となります。
大枠としての2つは、「スイッチ」(Switch)と「ラッチ」(Latch)になります。

言葉として馴染み深いのはスイッチ(switch)だと思いますが、これは文字通り、TrueとFalseの値を切り替える操作となります。
重要なのは、「ユーザー」か「プログラム」どちらかが切り替える、ということです。
ユーザーが切り替える場合には、フロントパネル上のスイッチ動作になっているブールの制御器をクリックするたび、TrueとFalseが切り替わります。言い換えれば、クリックしなければ切り替わりません。
また、プログラム的にあるブールの値をTrueもしくはFalseに変えることもできます。(が、本シリーズではそのやり方は扱いません)

もう一つ、聞きなれないものかもしれませんが、ラッチ(latch)もブールの動作として重要です。
ラッチは、FalseからTrueにする動作はユーザーが変えることができます。しかし、Trueになった後のそのブール制御器を、LabVIEWが「このブール制御器はTrueになっているな」ということを読み取った後、LabVIEW自体がTrueからFalseに戻します。
そのため、ユーザーがFalseにしなくても、TrueであることがLabVIEWによって認識されたらFalseの状態に自動的に戻る、そんな動作になります。
ただし、LabVIEWがラッチ動作のブール制御器の値がTrueになっていることを認識する前にユーザーがもう一度クリックしたらFalseに戻すこともできます。

なお、ラッチはこの性質上、プログラムから意図的にTrueもしくはFalseにすることができません。FalseからTrueにするのは常にユーザー側から、ということになります。(厳密にはできるのですが、基本する場面がないので、実質的にできないと思って差し支えないです)
ボタンを押して何かの処理を行わせるきっかけを与える場合にはラッチ動作にしておくことが多いです。
で、これらスイッチとラッチの大枠に対して、それぞれ「押されたら」(When pressed)「放されたら」(When released)「放されるまで」(until released)の3つの動作を組み合わせるので2×3で6通り、となります。

実は、ブール制御器の種類(見た目)によってデフォルトの機械的動作が決まっています。ただ、どの制御器であっても全ての機械的動作に変更することができます。
これらの6つの動作の違いはぜひ、サンプルを確認してみてください。
LabVIEWのサンプルは、HelpメニューからFind Examplesで開くNI Example Finderから見つけることができます。
この中にあるMechanical Action.viというサンプルがこれらの動作の違いを調べるのに適しています。

条件を指定するのに役立つデータタイプ②:列挙体
もう一つ、条件分岐に役立つデータタイプが列挙体(Enum)です。
聞きなれないかもしれませんが、読んで字のごとく、何かしら項目を「列挙」するのに使用するデータタイプです。

条件分岐というのは、「計算結果が0より小さかったらAをする、5より大きかったらBをする、それ以外はCをする」とか「配列の中にAというキーワードがあったら処理1をする、Bというキーワードがあったら処理2をする、それ以外は何もしない」といった、二者択一以外でも条件を作ることができます。
複数の選択肢の中からユーザーが特定の項目を選んだらAを行う、別の項目を選んだらB、さらに別の項目ならC、などといった感じで複数の項目がある状態から条件分岐を行わせるのに使うのがこの列挙体です。
この説明だともしかしたら「それって文字列の配列と何が違うの?」と思われるかもしれません。
確かに、文字列の配列でも一つ一つの要素に別々の項目名をつければ、項目を列挙した状態にすることができます。
そして実際、文字列をうまく使用して条件分岐に活かす、というプログラムも組むことはできます。
ただ、列挙体の方が実装はより簡単になります。(そもそも後で紹介する条件分岐の条件として配列を直接は使えないという事情もありますが)

列挙体はフロントパネル上のRing&Enumにあります。
作り方としては、列挙体をフロントパネル上において右クリックし、項目を編集(Edit Items)を選択して、列挙したい項目名を記述するだけです。

これで、フロントパネル上で項目名を選べるようになりました。
なお、列挙体はブロックダイアグラムからも作成することができます。ブロックダイアグラムから作成する列挙体は列挙体定数となりますが、これは後々の記事で紹介するプログラムの組み方で重要になります。

・・・とまぁ列挙体についてはこれくらいで十分です。
条件分岐をケースストラクチャで実装する
準備はこれくらいにして、LabVIEWで条件分岐を実装するやり方を紹介していきます。
条件分岐は、ケースストラクチャ(case structure)で実装します。
見れば気づくと思いますが、WhileループやForループ同様、四角い枠で表します。

この四角い枠の中身は、特定の条件でしか実行されません。枠の外に書いたプログラムは条件に関係なく実行されるといった事情は、枠の外のプログラムは繰り返されないというWhile/Forループと同じですね。
また、その条件の内容が上のラベル部分に表示されます。

では、どこで「条件」を指定するかというと、ケースストラクチャの左に表示された「?」の部分に条件を入力します。

使い方をブールデータタイプを例に紹介します。
フロントパネル上でブールボタンを用意し、これをケースストラクチャにつなげます。

あとは、各ラベルの中身に、実装したい処理の内容を書いていきます。
例えば以下のようなプログラムをそれぞれの枠の中に作ってみてください。

作り終えたら、実際に実行して動きを確認してみます。
フロントパネル上で選んだブール制御器の状態によって結果が変わるのがわかると思います。

次に、列挙体を条件として入力してみてください。
すると、ラベル部分に列挙体の項目の一部が表示されるはずです。
これも、列挙体でこの項目を選んだらこの内容を実行するよ、ということを指し示しています。

なお、列挙体をケースストラクチャに配線しただけだと、列挙体の項目が3つ以上あったとしても、最初の2つの選択肢しか上部のラベルに表れません。
列挙体の全ての項目を条件として指定する場合にはすべてのケースに値を追加(Add Case for Every Value)とすると、列挙体で設定した全ての項目に対して別々のラベルが用意され、それぞれの処理を書いていくことができます。

なお、列挙体やブールのデータタイプについては考える必要がありませんが、後述するようにケースストラクチャは他のデータタイプも条件判定に使用することができます。
そして他のデータタイプについては、ケースストラクチャを右クリックしてAdd Case AfterあるいはAdd Case Beforeで新しいケースを追加することができます。

ケースストラクチャからの出力値について
ケースストラクチャで注意する点としては、出力値の扱いについて、が挙げられます。
ケースストラクチャは複数ある条件のうち、どれか一つでも値をケースストラクチャの外に出したい場合、出力トンネルを介して出すこと自体はできるのですが、特定のケースだけでなく全てのケースに対してその値を定義しなくてはいけません。
簡単な例を紹介すると、例えば列挙体で選んだ選択肢によって表示させる文字列を変えたいとします。
この白抜きの出力トンネル(下の図の赤枠)がある場合、プログラムは実行することができません。

LabVIEWでは、ケースストラクチャの内側から外側に値を出す場合、特定の条件でだけ値を出すということはできず、ケースストラクチャ中の全ての条件に対して何らかの値を出すように指定する必要があります。

これはケースストラクチャを使用する以上、避けて通ることができません。絶対に、必ず、出力は何かしら決める必要があります。これは条件を指定するデータタイプの種類に依りません。
そんなこと言ってもケースが多くあっていちいち定義するのは面倒、という場合には、デフォルトを使用(Use default)こともできます。
この設定をすることで、ケースストラクチャの内側から何か値を配線されていない状態の場合、その出力トンネルからはそのデータタイプのデフォルト値が出てくるというものになっています。

各データタイプのデフォルト値は、例えば数値なら0、文字列なら空文字、ブールならFalseになります。なので、一つの選択肢としてはこのデフォルトを使用して出力値を決めてしまう、ということが考えられます。
ただし、私個人の経験からすると、極力デフォルトは使わない方が良いです。とにかく明示的に、出力する値を指定する、この方が(メンドクサイですが)デバッグやトラブル回避に有効です。
別の選択肢としては、ケースストラクチャへの入力値をそのまま使用するという方法があります。「ある条件では入力値を二倍した値を出力するけれど、別の条件では入力値をそのまま出力する」といった場合にこの方法を使います。

なお、特に紹介はしていなかったですが、出力トンネル側ではなく入力トンネル側については、全てのケースで全ての入力値を使用しなくてはいけないという決まりはありません。
例えば以下の図ではケースストラクチャにXとYという数字を入力していますが、条件によってはXだけしか使用しない、あるいはXもYも使用しない状態となっていますが、これは問題ありません。

デフォルトケースを定義する
条件分岐の話ももう終盤ですが、デフォルトケースの扱い方についても知っておく必要があります。
これまで紹介してきた条件分岐の条件は、ブールと列挙体でした。
これらは、ブールであればそもそもTrueかFalseしかなく、また列挙体を条件にした場合には列挙体に登録された項目しかなくそれ以外の項目が指定されることはないのであまり気にすることはなかったですが、実際には数値や文字列を条件とすることもできます。

ただし、例えば数値を指定する場合、数値なんてのは無限にあるのでそれらすべてに対して条件を指定することはできません。
以下のように、ある程度の範囲を決めていくつかの条件指定を行うことはできますが、毎回このように指定を行うとは限らないですし、それこそ文字列はそもそも範囲という概念がありません。
(数字や文字で条件を指定する際には、条件が表示されている上部のラベルをダブルクリックして直接条件を入力します。条件を増やす場合には、既に紹介したようにケースストラクチャを右クリックしてAdd Case AfterあるいはAdd Case Beforeで新しいケースを追加していきます)

そこで役に立つのがデフォルトケースです。このケースは「指定されていない「その他」すべて」の場合に適用される条件となります。

デフォルトケースを指定する場合には、指定したい条件を表示した状態で右クリックし、Make This The Default Caseと指定します。
出力トンネル同様、このデフォルトケースはブールや列挙体以外だと必ず指定する必要があります。

ここで、条件分岐の話も終わりです。
さて、ここまでで繰り返しを行うというWhileループやForループ、そして条件分岐のためのケースストラクチャについて紹介しました。
実は、これらの知識(+α)があれば、それなりのプログラムが書けてしまいます。
そのため次回は、そんな「それなりのプログラム」の作り方について紹介していこうと思います。
よければ次の記事もみていってください。
ここまで読んでいただきありがとうございました。
コメント