本シリーズでは、このブログで紹介してきた「まずこれ」のシリーズを凝縮して、LabVIEWによるプログラミングはこんな風にできるんだ、ということを比較的すぐに体験できるよう、内容を絞って紹介しています。
また、紹介する画面はLabVIEW Community Editionという、非商用の目的であれば無料で使用できるエディションを使っています。なので、LabVIEWに興味を持ったらCommunity Editionを実際にダウンロード、インストールして触りながらプログラムを作り、LabVIEWの楽しさに触れてもらえればと思います。
第二回の今回は、LabVIEWプログラミングの基本的な考え方をまとめて一気に紹介します。
ここで紹介することは、どれもLabVIEWでプログラムを書く上で必須な内容ばかりですが、慣れてくるとそこまで難しい話でもない・・・と思います。
なお、前回の記事はこちらです。
独特な表現に慣れる
前回の最後で、Hello Worldという文字を表示させるプログラムを作りました。
初めてLabVIEWを触る方にとっては、見様見真似でやってみた、という感じで、あまりプログラムを書いたという実感もないかもしれませんが、文字を表示するというごくごく単純な操作であったとしても立派なプログラムです。
見様見真似になるのは、LabVIEWに慣れていないから、と思いますが、これからLabVIEWでのプログラム作成について解説していくにあたって、LabVIEW独特な表現や考え方については早めに慣れておいた方が、以降の説明の意味も伝わりやすいと思います。
そこで、以下では最低限知っておくべき4つの項目について紹介していきます。
LabVIEWの基本①フロントパネルとブロックダイアグラム
まず基本的な項目の一つ目として、フロントパネル(Front Panel)とブロックダイアグラム(Block Diagram)の区別を覚えてしまいましょう。
これらは、新規のプログラムを作る時に二つで1セットになって表れていました。これら二つが揃って一つのLabVIEWプログラムになっています。
LabVIEWで作ったプログラムは、拡張子がviとなっているので、「1つのviにはフロントパネルとブロックダイアグラムがある」と言えます(viはvirtual instrumentの略)。
見分け方は簡単で、背景がグレーの方がフロントパネル、背景が白の方がブロックダイアグラム、ですが、そもそもそれぞれのウィンドウのタイトルを見れば書いてあるので一目瞭然ですね。
それぞれのウィンドウはクリックして編集する方を選べますが、Windowから選んだり、Ctrl + Eのショートカットで切り替えることもできていたのでした。
二つあるのはいいとして、それぞれ何のためにあるか、ですが、
- フロントパネル・・・ユーザーインタフェースになる
- ブロックダイアグラム・・・プログラムの「中身」になる
と言えます。
ユーザーインタフェースとは、プログラムを実際に実行した際に、そのプログラムを使う人=ユーザが、プログラムに対して何か値を指定したり、プログラムによって処理された結果を確認するための画面です。
難しく考えずに、要はプログラムを実際に実行している間に見る画面だと思ってください。これがフロントパネルです。
一方のブロックダイアグラムは、プログラムの「中身」になる部分で、様々な処理やアルゴリズムの具体的な内容を書いていく部分になっています。
なので、プログラムをいざ実行する際にはブロックダイアグラムは基本的に見ません。(デバッグ時を除く)
とても簡単な例で二つを説明すると、例えばユーザーが自由に決めた二つの数を足し合わせるというプログラムがあったとすると、
- フロントパネルでは、ユーザーが足したい二つの数を入力する、そして足し算の結果を表示する
- ブロックダイアグラムでは、ユーザーが決めた二つの数を実際に足す
という役割分担があります。
フロントパネルだけだと、ただ単に数字を書いているだけで、足し算は行われません。一方で、ブロックダイアグラムだけだと、どんな数を足していいかわかりません。
下の図はNumericとNumeric 2という二つの数字を足してNumeric 3という場所に表示している場合のプログラムで、左がフロントパネル、右がブロックダイアグラムです。
何らかの処理をするには、(ユーザーが)入力する部分と、それを処理する部分、二つが必要なわけで、それがフロントパネルとブロックダイアグラムといった具合に分かれています。
なお、ブロックダイアグラムはウィンドウ右上のバツボタンを押しても、viそのものは閉じられません。フロントパネルを閉じることでviを閉じることができます。
LabVIEWの基本②制御器と表示器、定数
次に、制御器、表示器、そして定数について紹介します。
これらはそれぞれLabVIEW上の表記としてはControl(制御器)、Indicator(表示器)、Constant(定数)となっています。
これらは何かというと、フロントパネルもしくはブロックダイアグラム上に配置する、プログラムを構成する要素の一種で、
- 制御器・・・フロントパネル、ブロックダイアグラムどちらにも存在するユーザーが値を入力する場所
- 表示器・・・フロントパネル、ブロックダイアグラムどちらにも存在するユーザーが結果を確認できる場所
- 定数・・・ブロックダイアグラムのみに存在する、固定された値を入力する場所
という区別があります。
この区別を見たときに、「あれ、ユーザーが値を入力したり出力するのはフロントパネルだけなのでは?」と思う方がいるかもしれません。
実際に、ユーザーが値を入力するために「触る」あるいは処理の結果を「見る」のはフロントパネルになりますが、このフロントパネル上の制御器の「化身」がブロックダイアグラムに存在しています。
例えば、新規のviを開いて、フロントパネル上に制御器を置いてみます。
そのために、前回の記事の最後でも、フロントパネル上で右クリックして何やら一覧表のようなものを出しました。
この一覧表、名前がついていて、制御器パレット(Controls palette)と呼ばれます。塗り絵なんかをするパレット上には様々な色の絵の具があってそこから色を選んで絵を描くように、制御器パレット上には様々な制御器があってそこから必要なものを選んでユーザーインタフェースを作っていきます。
ここでは、前回とは異なり、数字の制御器であるNumeric controlを選択してフロントパネル上の好きな場所に置いてみます。
置いた後に、ブロックダイアグラムを見てみてください。何も編集をしていないのに、フロントパネル上に置いた制御器であるNumeric controlと同じ名前がついたオレンジ色のアイコンが表示されているのがわかると思います。
これが、ブロックダイアグラム上における、制御器の「化身」です。
先ほどのフロントパネルとブロックダイアグラムの説明で足し算の話を例に出しました。足し算には二つの数が必要で、それらがそろって初めて足し算という処理を実行することができます。
このときに二つの数を指定するのがフロントパネルであり、それらを実際に足し合わせるのがブロックダイアグラムという話をしましたが、じゃあブロックダイアグラムがどうやってフロントパネル上でユーザーが指定した数を認識できるかというと、ここで「化身」が使われます。
つまり、ブロックダイアグラム上に置かれた制御器の化身(今回でいえばNumeric control)は、ブロックダイアグラム上では、フロントパネルで指定した値と同じ値を持つプログラムの要素であるとみなされます。
せっかくなので、実際に足し算のプログラムを書いて確かめます。今はフロントパネル上に一つしか数字はないと思いますが、一旦その状態でブロックダイアグラムの操作に移ります。
ブロックダイアグラムを選択したら、右クリックします。ここでもまた何か別の一覧表が出ました。これは、関数パレット(Functions palette)と呼ばれ、ブロックダイアグラム上で使う様々な「関数」をここから選ぶことができます。
関数とは何ぞやという話ですが、ひとまず「特定の処理を行うための機能のまとまり」という認識をしてもらえればOKです。
ではここで、関数パレットから足し算(Add)を選択します。数値に関する関数なので、関数パレットのNumericという部分にこれがあります。
選択したら、Numeric controlの近くに置きます。
そうしたら、Numeric controlのアイコンの右端をクリックします。すると、マウスカーソルの形が変わり、点線が出てくる状態になるかと思います。この状態で、足し算の関数の左上部分をクリックします。これで、Numeric controlとAddが細い線でつながれたことがわかると思います。
これは、「Numeric controlの値をaddの関数の入力(の一つ)に渡した」状態を表しています。
LabVIEWではこのように値をあるところからべつのところに渡すのにこうした線でつなぐという表現方法をしていて、この線をワイヤ(wire)と呼びます。
ではもう一つの数を決めて実際に足し算に必要な二つの数を用意することにします。
フロントパネルに戻ってNumeric controlを用意するのもいいのですが、ここではもう一つ便利な方法で制御器を用意する方法を紹介します。
やり方は簡単で、制御器を用意したい部分、今回でいえばAddの左下の入力部分で右クリックして、CreateからControlを選ぶだけです。このようにすることで、制御器をブロックダイアグラムから作成することができます。
実際、この方法はとても便利な場面が多いです。今回はAddという足し算の処理だったため、どんな制御器(あるいは定数)を用意すればいいか明白だったのであまり恩恵はないですが、もしある初めて使う関数があったとしてその関数にどんな値を渡せばいいかわからない場合に、この方法を使うことでその関数への入力に適した制御器や定数が自動的に選ばれて現れ、しかもワイヤの接続まで自動的になされます。
例えば以下の図で示しているように、Draw Text at Pointという関数(これ以降出ることはないので覚える必要はないです)に対するuser specified fontという制御器は複雑な形をしているのですがこれも自動的に生成してくれます。
実はこれは表示器に対しても同様です。試しに、Addの右側をクリックして、CreateからIndicatorを選択します。すると、数値に対する表示器であるNumeric Indicatorが自動的にフロントパネルに表れることがわかります。
あとは、ユーザーが使いやすいような配置になるように各制御器や表示器をフロントパネル上でドラッグして整理します。
このとき、フロントパネル上の各制御器や表示器の配置と、ブロックダイアグラム上のそれぞれの化身は、配置が全然違っても全く問題ありません。ただ、敢えて配置をバラバラにすることに意味はないので基本的には同じような配置が望ましいです。
また、必要に応じてラベル名も変えておきます。
では、この足し算のプログラムを実行してみます。二つの制御器に好きな数を入力して、実行ボタンを押します。何個か値を変えて試してみるのがいいと思います。
ここまでの説明で、定数はまだ全然出てきていませんね。
今の足し算の場合、既に足し合わせる数二つを制御器として用意しているのですが、例えば「ある数に常に2を足す」という処理を行う場合に定数の出番となります。
定数はブロックダイアグラム上でしか現れないので、ブロックダイアグラムに移動し、先ほど右クリックで作った二つ目の制御器を選択します。ここで、右クリックしてChange to Constantを選択すると、これでもう定数の完成です。
この定数の部分をダブルクリックして2を入力しておきます。
このプログラム、フロントパネルを見ると、数値を入力する部分は一つしかなく、ユーザーはこの値は自由に決めることができますが、足し算のもう片方の値は決めることができません。ではどうなっているかというと、ブロックダイアグラム上で2と書いてあるので、常にユーザーが入力した値に2を足すことになります。このように、毎回同じ、固定した値を使用するときに定数を使います。
このように制御器と表示器はユーザーがプログラムを実行する際の入力値を指定したり出力値を確認するためになくてはならない存在となっています。
長々と制御器、表示器、定数の違いを説明しましたが、制御器と表示器のブロックダイアグラム上の見分け方も覚えてしまってください。三角形の位置で判断することができます。
制御器は、ユーザーが入力した値なので、ブロックダイアグラム上ではこの値が使われることになります。
少し表現を変えると、制御器からワイヤを経由して何かの処理に値を渡すので、制御器から値を出すイメージとして、右向きに三角形が表示されます。
逆にブロックダイアグラム上の表示器は処理の結果を受け取り、この受け取った値をフロントパネル上で実際にユーザーが確認できるようになります。なのでブロックダイアグラム上では表示器のアイコンは値を受け取ることになるため左に三角形があります。
これらのアイコンを見る事で、ブロックダイアグラム上でも制御器や表示器を素早く確実に区別することができるので、この見分け方のルールは絶対に覚えてください。
さて、最後に好みの問題ともいえる話ですが、ブロックダイアグラム上の制御器や表示器の「化身」は、ぜひ「アイコン表示(View As Icon)」をやめることをオススメします。
アイコン表示をやめると下の図のように見た目に違いが現れます。
アイコン表示の時には制御器と表示器を見分ける三角形は白かったのですが、アイコン表示をやめると三角形は黒くなります。
いちいちそれぞれの項目に対してView As Iconのチェックを外すのはめんどくさいですが、Toolsの中のOptionsからBlock Diagramのカテゴリで設定をすることで、それ以降生成した制御器や表示器の化身はアイコン表示ではなくなります。
ただ単に化身の大きさが変わっただけのように見えますが、実はこれは結構重要だったりします。
デフォルトの設定であるアイコン表示のままだと、大きく表示されています。わざとらしく嫌な言い方をすると、「幅を取っている」状態です。
ブロックダイアグラムはプログラムの中身を記述する場所でした。プログラムの規模が大きいほど、たくさんの処理を書いていくことになります。
そんなとき、ブロックダイアグラム上で制御器や表示器の化身が大きいことで、見た目がごちゃごちゃするようになります。
まだ大きな規模のプログラムを書いたことがない時だと「なんだそれだけのことか」と思うかもしれませんが、それだけのことでも結構変わってきます。
もちろん、最終的にどういった表示にするかは人それぞれですが、これ以降で紹介する画像はこのアイコン表示をやめた状態での表示としている場合があります。
LabVIEWの基本③データタイプ
さて、前回の記事も含めこれまでの説明で、「Hello Worldと表示する」ことや「二つの数を足し合わせる」というプログラムを書けるようになりました。
まぁこんなプログラムは序の口ですが、ここで注目してほしいのは、それぞれのプログラムで扱っている「データ」の話になります。
Hello Worldと表示する、というプログラムでは、「Hello World」という文字を扱っていました。一方で、足し算をするプログラムでは、数字を扱っていました。
何を当然のことを、と思うかもしれませんが、それぞれを「データタイプ」として区別し、「文字列」、「数値」といった表現をしているということが重要です。
つまり、何か文字情報を扱うには「文字列」データを使用することになるし、1や2.7や-12といった数字を扱う場合には「数値」データを扱うことになります。
数字を文字として扱うことは、文字列データとして数字を記入することでできますが、他の言語(例えばPython)でできるような、「文字同士の足し算」は数値に対して使う足し算(Add)ではできません。
文字列には文字列に対して使用する関数パレット上の関数しか使えないので、その中に自分のやりたいことが実現できる処理がないかを探す必要があります。
もちろんLabVIEWで扱えるのは文字や数字だけではありません。様々なデータタイプを使用して処理をしていくことになります。
これまでに登場した文字や数値はその中でもとりわけわかりやすいデータタイプですが、他にも「ブール」データや「波形」データ、「配列」データなどというように、データタイプは数多くあります。
そしてものによっては複数の見た目がある場合があります。
見た目が変わっても、やれることは同じです。
使いやすいプログラムにするためにどの見た目が適切なのかはそのデータタイプがどのような役割を持つかである程度決まっていますが、ブロックダイアグラム上ではフロントパネル上の見た目の違いは一切関係なく、「Numeric Control」(数値制御器)、「String Indicator」(文字列表示器)などの化身として働くだけです。
で、大事なことは、LabVIEWはこれらのデータタイプを色で区別しているという点です。
もちろん、フロントパネル上では比較的区別がつきやすいのですが、ブロックダイアグラム上でも各データタイプを区別することができて、文字ならピンク、数値なら青やオレンジなど、ブールなら緑といった決まった色があります。
そして今までのプログラムを見て気づいた方もいると思いますが、制御器や表示器を関数とつなげているワイヤの色も、データタイプによって変わっています。なので、あるワイヤを見たときにその部分でどのようなデータが扱われているか色で判断することができます。
また、制御器や表示器をつなげるときに使用するワイヤも同じ色同士を結ぶと覚えておけば、データタイプの不一致でプログラムが実行できないという状態を防ぐことができます。
ちなみに、「決まった色と言っておきながらなんで数値は複数の色があるのか」という点に対しては、数値は数値でも、それが「整数」なのか「小数も扱える」のかで色が異なり、整数は青、小数(厳密には浮動小数点)はオレンジになっています(他にも固定小数点に対してはグレーがありえます)。
これはRepresentationという項目から変えることができ、選択したものによって整数でも正の数しか扱えない「Unsigned」、負の数も扱える「Integer」、そして扱える数の範囲に違いが出ます。
メモリ管理をシビアに行うためにはこの点について注意しますが、本シリーズではこの部分をシビアに考えなくてはいけないものは出てきません。
とにかく、LabVIEWは視覚的にプログラムを表す以上、様々な工夫でプログラムの中身を見やすくすることができ、この「データタイプによって色が違う」のもその一環です。
よく使うデータタイプはすぐに色を覚えてしまえると思いますが、あまり出てこないデータタイプについては覚えるのが難しいかもしれません。とはいっても、10個も20個も種類があるわけではないので、比較的よく使うデータタイプはここでもう色を覚えてしまってください。
LabVIEWの基本④データフローの順番を知る
次の基本事項は、データフローの順番についてです。基本事項の中ではこれが一番難しいかもしれません。とはいっても、覚えることは一つだけです。
LabVIEWで書くプログラムには、処理の順番に決まったルールがあり、これを覚えようというだけの話です。
そのルールとは、
「ある処理に対して、全ての入力が揃ってから処理が行われ、処理が終わってから結果が出力される」
というものです。
上で紹介した足し算の例をこのルールに当てはめると
「足し算に対して、二つの数値が揃ってから足し算を行い、その結果が出力される」ということになります。
よく考えたら当たり前の話ですね。だって、足し算をするためには二つの数が必要で、その二つの数が揃ってないと足し算として計算ができないわけなので。
この、よく考えると当たり前、のルールが、LabVIEWのプログラムの順番を理解するうえでとても重要になります。
足し算だとつまらないので、もう少し別の例を見てみます。
いきなり処理が増えて面喰うかもしれないですが、四則演算が比較的身近で説明もしやすいのでこの一連の流れの順番を考えていきたいと思います。
足し算以外の関数の説明はしていませんが、演算記号がそのまま見た目に表れているので何をしているのかはわかると思います。
まずは以下の例です。
図にも書いていますが、この場合にはまずはNumericとNumeric 2の足し算が行われ、その結果とNumeric 3の掛け算が行われ、その結果がNumeric 4と足し算され、そしてその結果をNumeric 5で割る、という計算になっています。
四則演算は足し算や(上の図には出ていませんが)引き算より、掛け算や割り算の方が先に実行されますが、上の計算の場合には二つ目の掛け算を行うために必要な二つの数のうち一つはNumeric3として値がありますが、もう片方はNumericとNumeric2の計算が終わらないと得られません。そのため、掛け算が行われる条件は最初の足し算が完了しないと達成されないことから、①と②の前後関係が生まれます。
それ以降も全て同じ理屈で説明できます。
なお、割り算の関数の部分で入力部分に赤い印がついていますが、これは「強制ドット」と呼び、LabVIEWが勝手にデータタイプを変換しましたということを示す記号になっています。
変換しましたと言っても数値が文字になったという話ではなく数値は数値でも違う表記法(Representation)になったことを表します。
これは、足し算、引き算、掛け算の場合には整数同士の計算で必ず整数の結果が得られるのに対し割り算のみ整数同士の計算でも答えが小数点を含む浮動小数点データになることがあるため、入力が整数で出力結果が浮動小数になることを示しているだけです。(処理した後、結果的に割り算の商が整数だったとしても、です)
本来はこの強制ドットはない方が望ましいのですが、プログラムに慣れないうちには「LabVIEWが自動的に良い感じにデータタイプを変えてくれたんだな」程度に思っておくことにしてください。
話をプログラムの実行順番に戻して、次の図の場合はどうでしょうか。
この場合、NumericとNumeric 2の足し算、そしてその結果とNumeric 3の掛け算の流れはこれで確定です。
が、Numeric 4とNumeric 5の足し算は、上の掛け算の処理と関係なく実行できてしまいます。なぜなら、Numeric 4とNumeric 5の足し算はもう既に「Numeric 4」と「Numeric 5」として値が確定しているからですね。
となると、「NumericとNumeric 2の足し算の結果とNumeric 3の掛け算」と「Numeric 4とNumeric 5の足し算」は順番が決まらないことになります。いや、もっというと「NumericとNumeric 2の足し算」と「Numeric 4とNumeric 5の足し算」すら、どちらが先に実行されるかは確定していません。
でも、この「確定していない」という理解が正しいです。あくまで順番が確定しているのは以下の図の部分だけです。
重要なことは、上で書いたルールが絶対であり、プログラムの流れを読み解く上でこれ以外の「状態」は無視できる、ということです。
例えば
- ワイヤの長さが短い方が先に計算される
- 左側に書かれているから先に計算される
などといった「追加ルール」は一切ありません。全て上で書いた「入力が揃ってから処理されて結果が出る」ということを常に意識してみてください。
「順番決まっていない部分があって大丈夫?」と思うかもしれません。
実はほとんどの場合について、順番が決まっていないものは「どんな順番でも構わない」ため、問題となりません。先ほどの例でも、色々な処理の順番のパターンを考えても「Numeric 4とNumeric 5の足し算」がどのタイミングで行われるかによって最終的な答えが変わることはないことは考えたら納得してもらえると思います。
むしろ、順番が決まっていないといけないプログラムは、LabVIEWのプログラムの書き方上ほとんどの場合「順番が確定する」ような書き方に自然となります。
ただし一部例外があり順番が決まっていないといけないのに(一見)決められないという場面もあります。が、順番を決める術自体はあるので、結局どんな場合であっても順番が問題となり特定の処理をLabVIEWで表せないということはありません。
ではここまでの話を踏まえて、最後に以下のプログラムがどのように実行されるかを考えてみてください。
計算式を紐解いていくと、(x+y)×zと(p-q)/rという二つの計算を行っていることがわかると思います。
では、これらはどちらが先にどういう順番で実行されるでしょうか?
上でさんざん紹介してきた、「ある処理に対して、全ての入力が揃ってから処理が行われ、処理が終わってから結果が出力される」というルールで考えてもわからないですね?
正解は、「(x+y)×zという処理と(p-q)/rという処理が並列で行われる」、です。
このように、LabVIEWでは処理の順番が決まらない、独立した処理同士は並列で実行するという特徴があります。つまり、複数の処理を並列で行わせるためのプログラムが簡単に書けてしまいます。
まぁこれもルールっちゃルールなのですが、「独立した処理は並列で実行される」というのはより複雑なプログラムで重要になるものの本シリーズで扱うような内容では強く意識しないといけない部分は多くないので、覚えるルールは少ない方が良いだろうということで絶対的ルールからは外しました。
とはいえ、「LabVIEWは並列処理を簡単に書けるんだ」ということはLabVIEWの特徴の一つにもなっており、これからもちょこちょことこの考え方を使う必要がある場面は出てくるので、一応頭の中にとどめておいてください。
今回の記事で紹介した4つの基本的な内容は、可能な限り本記事内ですべて覚えてください。この記事の内容を覚えずに次の記事を見てもどんどんわからないことだらけになると思います。
これらはLabVIEWでプログラムを書く以上絶対に必要なことで、どれかだけでもあやふやな覚え方をしているとまともにプログラムが書けないし読めません。
まぁ、データタイプの色については書いているうちに覚える、という側面はあると思いますが、とにかくどれも基本的な事なので、くどいようですがしっかり覚えてください。
次回は、いよいよプログラムを書いていくということに焦点を置いて、どのようなプログラムを書くにしてもアルゴリズム構築の上で必要となる要素を紹介していきます。
よければ次の記事もみていってください。
ここまで読んでいただきありがとうございました。
コメント