LabVIEWを触ったことがない方に向けて、それなりのプログラムが書けるようになるところまで基本的な事柄を解説していこうという試みです。
シリーズ4回目としてLabVIEWにおけるエラー処理を扱います。
この記事は、以下のような方に向けて書いています。
- LabVIEWでエラーはどのように扱われるか知りたい!
- 自動エラー処理と手動エラー処理って何?
- エラー処理はどのようにすればいいの?
もし上記のことに興味があるよ、という方には参考にして頂けるかもしれません。
なお、前回の記事はこちらです。
プログラムにエラーがあることを知る
さて、プログラムの流れがワイヤを配線したことで制御できることがわかった今、改めて以前エラーが出ていたプログラムを見返してみます。
以前のプログラムで、文字列定数と文字列表示器がワイヤでつながっているところに、文字列制御器をつなげたところ、ワイヤに×がついていました。
×マークがついた状態は見た目でもわかるかと思いますが×、つまり正しくない状態になっていることを表しています。LabVIEWはグラフィカルにこういったことを表してくれるのでエラーが起きてもどこにエラーがあるのかわかりやすいのでとても便利ですね。
それで以前は、とりあえず理由は何も言わないまま文字列定数を取り除けばエラーは回避できる、ということで紹介していました。
さて、この状態のときに、実行ボタン(メニューバーの下の、右向き白矢印)に注目してみると、矢印が「壊れた」状態になっていることがわかるかと思います。
これはプログラムにエラーがあって文字通りプログラムが「壊れている」状態を表しています。ではこの壊れた状態で実行ボタンを押すとどうなるか、早速クリックしてみましょう。すると、下のようなエラーリストが表示されるはずです。
LabVIEWではこのようにエラーが発生している場合に
- ブロックダイアグラム中に×印が表示される
- 実行ボタンが壊れる
- エラーリストが表示される
といった形でユーザーにプログラムが実行できない状態を知らせてくれます。壊れている場合には、実行ボタンはプログラムの実行をしないだけ、ではなく、実行できない原因を教えてくれるのです。
今回のエラーの場合、「このワイヤには複数のデータソースが接続されています」と出ているのでこれを修正すればプログラムが動作するということになります。
既に試した通り、定数をDeleteすることでエラーなく動作させることができるようになりました。複数のデータソース、とはこの場合、文字列定数と文字列制御器を指します。
実際、エラーリストの「詳細」にも「ワイヤは、制御器の端子や関数の出力など、1つのデータソースにのみ接続できます。」と書いてありますね。つまり、一つの表示器に定数と制御器という二つの「データソース」をつなぐことができないためにエラーが起きていて、定数を消すことで制御器のみになったことでエラーが解消された、と言えます。
考えてみれば自然なことで、定数はブロックダイアグラム上で記述したある文字列を、制御器はフロントパネル上で記述した文字列を、それぞれ表示器に渡していました。これら二つをつなげていると、プログラムとしては「どちらの文字列を表示すればいいの?」となってしまうわけです。
ユーザーが指定したんだから制御器の値を優先するべきだ、というのは暴論ですね。定数だってプログラムを作った人が決めた値になるわけなので。作った人かユーザーか、になんて優劣はなく、LabVIEWは文字通り「機械的に」判断するしかないのです。
エラー自体は、そのエラー箇所にマウスカーソルを合わせても確認できる場合があります。例えば、今回で言えば×マークで点線となっているワイヤにマウスカーソルを合わせると、エラーリストと同様なエラーメッセージが確認できます。
こうした、エラーリストやマウスカーソルを合わせた際のエラーの内容表示に従ってプログラムを修正し、実行ボタンが白い矢印の状態になるまで繰り返す必要があります。
プログラムの作り方も習っていないのに、エラーが起きたときのことばかり話しても仕方ないと思うかもしれません。でも、エラーが起きたときの対処、つまりデバッグの仕方を知ることで、プログラミング能力はより一層身に着きやすいと思います。
自分の作ったアルゴリズムが正しくない、とかLabVIEWの使い方が間違っている、などあらゆる失敗を経験しないとプログラムはなかなか書けるようになりません。自力である程度エラーの解消ができるようになれば、その後の上達も早いと思います。
実行中のエラーを知る
ところで、上で紹介していたのはプログラムを実行する前のエラーでした。でもそれとは別に、プログラムを実行中にエラーが起きることも当然考えられますよね?
もちろんエラーが起きないに越したことはないわけですけれど、実際にプログラムを最後まで完成させるに至るまでに適宜実行させ動作を確かめる中で、実行中のエラーに必ず遭遇していくはずです。
プログラムを実行している間にどういったエラーが起こったかを知る手段としては、
- エラーの表示器を使用する
- ポップアップさせる
という方法があります。ポップアップについてはこの直ぐ後に説明するのですが、エラーの表示器の見方は今のうちに見ておきましょう。
適当な関数のエラー出力部分で右クリックして作成、表示器とします。すると下の図のようなエラー出力という名前の表示器がフロントパネルに表れたかと思います。(図では、ブロックダイアグラム上で右クリックして表示される関数パレットの中のファイルI/Oというパレットの中にあるファイルを開く/作成/置換関数を使用しています。)
なんだかいろいろなものがひと固まりになっていますよね?これはクラスタと呼びますが今はそれは置いておきましょう。
このエラー表示器がエラーの内容を表示してくれるわけですが、このエラークラスタにはこんな情報が含まれています。
- そもそもエラーが起きたか
- エラーの内容は何か?
- エラーがどこで起きたか?
一番上の、「エラーが起きたか」を知る必要があるのか?と思われる方もいるかもしれません。そんな方はこのように考えてみてください。
エラー表示器をつけた関数があったとします。で、プログラムを実行した結果、表示器がある以上はエラーがなくてもその表示器には何かしらの情報を渡し、表示器はそれを表示する必要があります。
であれば、その関数が特にエラーなく実行された場合には「エラーは出ませんでしたよ」という情報をエラー表示器にわたし、ユーザーが見ても「エラーは出ていなかったんだな」と判断できるようにすればいいわけです。
さて、上の3つの要素が、エラークラスタにどう対応しているかを見てみます。
- そもそもエラーが起きたか:ステータスを表すブール
- エラーの内容は何か?:コードを表す数値
- エラーがどこで起きたか?:ソースを表す文字列
これら3つの情報で、エラーが起きてその内容はこれこれでこんな場所で起きました、ということを表せます。
文字列や数値はわかりやすいのですが、ブールについてはあまり良く分からないという方もいるかもしれません。これは二択のうちどちらか、を表すデータタイプです。TRUEかFALSEか、0か1かみたいなことですね。
なのでステータスを表すブールはエラーが出ているとTRUE、出ていないとFALSEを表します。エラークラスタの中でブールはLEDとなっていて、TRUEの場合は明るく光ります。
実は、LabVIEWではいわゆるエラーの他に「警告」というものがあります。これはエラーではないのでステータスとしてはFALSEなのですが、コードは0以外の値を持ちます。
この警告とは「この関数は実行できたよ、でも正しい結果が得られていない可能性があるよ」ということをユーザーに警告します。関数に渡すパラメタであったり、処理の仕方やタイミングの都合で「期待される正しい結果」とは異なる状態になってしまった可能性があるときにこの警告状態となります。
自動エラー処理と手動エラー処理
LabVIEWにはプログラム実行中のエラーの扱いについて二つの処理方法があります。「自動エラー処理」と「手動エラー処理」と呼ばれるものです。
これらの違いは単純で
- 自動エラー処理:エラーが発生次第、LabVIEWが自動でエラー箇所でプログラムの実行を止める
- 手動エラー処理:エラーが発生してどうするかをプログラマー自身が決めないといけない
といった具合です。
こう聞くと「では自動エラー処理の方が楽だしいいのでは?」と思われるかもしれません。確かに、LabVIEWをインストール時のデフォルトの設定は自動エラー処理が有効になっている状態です。
ただし、この自動エラー処理は基本的にオススメしません。便利なのになぜ?と思うかと思いますが、その一見便利そうな機能が仇となるのです。
これからそれぞれの処理についてより具体的に見ていきますね。
まず自動エラー処理です。例えば、次のようなプログラムを考えたとします。
ここに上げた関数は、ブロックダイアグラムの「ファイルIO」というパレットに全て入っています。もしこの後の説明を実際にプログラムを動かして確かめたいという方は、このパレットにある三つの関数を用意して、図のようにワイヤをつなげてみてください。
図の通りにプログラムを書いている場合、このプログラムを実行すると、最初の関数でエラーが起きます。そして、起きた瞬間に、どこでエラーが起きたかがハイライトされてプログラムが一時停止します。
もしハイライトされない場合には、自動エラー処理が無効になっている可能性があります。その場合、すぐ下で自動エラー処理の有効無効の切替を紹介しているので、あとで自動エラー処理有効に切り替えて確かめてみてください。
上の図のような表示がでた時点で、ユーザーが「継続」を選択すればプログラムはその次の関数に進みます。一方で、「停止」を選択すればプログラムはそこで終了します。
自動エラー処理が行う動作は以上です。エラーの表示器も付けていないのに、エラー発生時にそこで自動的にいったん止まってユーザーにエラーの箇所を知らせてくれる・・・ので一見とても便利なように思います。
次に手動エラー処理にも触れておきます。手動エラー処理にするためには、LabVIEWの設定を「オプション」から変えます。オプションの中の「ブロックダイアグラム」カテゴリで「エラー処理」と書かれた部分の二か所のチェックマークを外す、これで自動エラー処理ではなくなります。
では、自動エラー処理のときと全く同じプログラムを実行してみます。実行の結果はどうなるかというと、
スクリーンショットではわかりづらいのですが、エラーのポップアップ表示が出なくなりました。自動エラー処理の時と違って、ハイライトもされなくなりました。でも、全く同じプログラムのはずなので、本来最初の関数からエラーが起こっていたはずです。
実際、最初の関数からエラーは「ちゃんと」起こっています。試しに表示器を付けるとエラーが表示されていますね。
ここで、プログラムに「シンプルエラー処理」という関数をつけてみます。試しに、最初の関数につけてみます。エラーの出力をそのままシンプルエラー処理のエラー入力に配線します。その後、プログラムを実行してみてください。
すると、自動エラー処理の時と同じように、エラーが出たよということを知らせてくれるポップアップが出ました。シンプルエラー処理は、エラーがあった場合、このようなポップアップを表示させる関数となっています。
さて、では次にもう少しプログラムに手を加えてこの図のようにしてください。
最後にシンプルエラー処理をつけています。これを実行するとまたシンプルエラー処理が実行されたことでポップアップが出るはずです。
LabVIEWのプログラムの流れは、すべてのノードに配線されたワイヤから入力値がそろわないと関数が実行されないのでした。つまり、シンプルエラー処理が実行された、ということは・・・たどっていくとわかると思いますが、それ以前のすべての関数は実行され終わったことを意味しています。
手動エラー処理がオススメ
実はこの「すべての関数が実行され終わった後にエラーが出る」という動作が手動エラー処理の方がオススメな理由なんです。なぜかピンとこない方、このように考えみてはいかがでしょうか?
- 自動エラー処理:エラーが起きたら、必ずそこでプログラムがいったん停止してしまう
- 手動エラー処理:エラーが起きても、シンプルエラー処理を置かない限りプログラムは停止しない
エラーは、往々にして予期せぬタイミングで起きます。ただ、エラーが起きても、そのエラーに対処できるようにプログラムを書くのが正しい姿勢だと思います。対処、とは例えば「エラーが起きなかったらこの処理をするが、エラーが起きた場合には別の処理をしておこう」といった具合にプログラムを組むことですね。
そんなプログラム(条件によって処理を分ける)をどうやって書くかはともかく、この「エラーに対処」するためには、当然プログラムは動き続けなくてはいけません。
もし自動エラー処理の設定としていて途中で止まったら、ユーザーが継続なり停止なりのボタンを押さないと延々と止まったままになります。
そのため、エラーが起きたらエラーの処理ができるように正しく処理を続ける、こういったプログラムを書くために手動エラー処理にする必要があります。
もし自動エラー処理のようにエラーが起きていたことをユーザーに知らせたければシンプルエラー処理の関数を用意します。
すべての場合ではないですが、これはプログラムの一番最後であることが多いです。「このプログラムはこのエラーが起きて終了しましたよ」、ということを知るのは最後にするということですね。
いやいや途中でエラーが起きたことを知りたいよ、という場合にはもちろんシンプルエラー処理をプログラムの途中に置くこともあると思います。が、「そこでプログラムが止まっても問題ない」という箇所で止めるようにしてください。
また、シンプルエラー処理のようにエラーをポップアップで表示させなくても、エラー表示器を置けば事足りるかもしれません。その表示器をおいたワイヤに値が通るたび、エラーが起きている、起きていないが確認できます。当然この場合プログラムは(自動エラー処理を無効にしていれば)止まりません。
手動エラー処理のためのベストプラクティス
え、たかがエラー処理について覚えることが多いって?そういう方には、ぜひベストプラクティスを覚えていただければと思います。
それは、「エラーワイヤを極力配線する」ことです。似たようなセリフ、既にありましたけれど、ここでもエラーワイヤが活躍します。
エラーワイヤ、は、LabVIEWのデータの順番を決定する際に使用する便利なもの、と紹介しました。しかしもともとはその名の通りエラーの情報を流すワイヤです。
そしてなんと、このエラーワイヤをつけると、自動エラー処理が有効になっていてもプログラムがエラー箇所で止まらなくなります。
実際に試してみるために、再びオプションの設定で自動エラー処理を有効にした状態からスタートします。
どの関数もエラーワイヤがつながっていない状態でプログラムを実行すると、最初の関数でエラーが起こるのでした。では、エラーワイヤを一つ最初と次の関数の間で繋げてみます。そして実行してください。
エラーのハイライトが起きてポップアップが出るタイミングが最初の関数ではなくなったことが分かると思います。このように、エラー出力側のエラーワイヤを配線していると、配線された関数からはエラーのポップアップが出なくなり、エラー出力にエラーワイヤを配線していない関数でようやくエラーが出るようになります。
なのでもし3番目の関数にもエラーワイヤを配線してさらに3番目の関数のエラー出力にはエラー表示器を付けていた場合、ポップアップは発生しません。
すると、エラーのポップアップは全く出ずに、エラー表示器にエラーが表示されるようになりました。自動エラー処理を有効にしているのにもかかわらず、です。
つまり、すべての関数でエラー出力側のエラーワイヤを何かしら(関数かあるいはエラー表示器)につないでいるとエラーのポップアップ表示が起こらなくなります。
一番良いのは、念のためツールのオプションの設定でも自動エラー処理のチェック2か所を外しておくことだと思いますが、エラーの余計なポップアップをなくしたい場合にはとにかくエラーワイヤの配線を意識して行うことをオススメします。
エラーが起きたときの関数の動作
ところで、エラーが起きたときの各関数の動きについてお話ししていませんでした。つまり前の関数からエラーの情報が渡ってきた場合に、エラーを渡された関数はどうなるか、です。
答えは、エラーの情報が関数に入ると、その関数は全く何もせずに、入力されたエラーをただ左から右に流していくだけ、です(一部例外はありますがほとんどがこのルールに従います)。
これも例を見てみます。次の図のように正弦波形の関数をおいてみます。関数は関数パレットの「信号処理」パレットから「波形生成」というパレット上に見つかるはずです。
Sine Waveform、つまり正弦波形の関数は、文字通り、ある周波数や振幅を持った正弦波のデータを生成する関数です。そしてその生成されたデータが見えるように視覚的にデータをプロットする波形グラフというものをつなげています。また、エラーが起きたことを模擬するためにエラー入力にエラー制御器をつけています。
これをそのまま実行すると、グラフ表示器にはこのように波(正弦波)が表示されます。
では、この関数にエラー入力を模擬します。ステータスの部分をTRUEにして(緑がFALSEで赤がTRUEです。緑色の部分をクリックすると赤に変わります)、コードの部分に0以外の数値例えば1を入力して実行します。
実行すると、自動エラー処理が有効になっている場合、ポップアップが出るので「継続」とする必要がありますが、下の図のような結果になるはずです。
グラフに何も表示されていないですよね?エラーのポップアップ表示が出ていたので、関数自体は実行されたことに間違いありません。
つまり、この関数はエラーを入力として受け取った後、関数本来の動作(正弦波のデータを生成する)は何も実行していないということです。一方でエラーは出力しています(もし気になるのであればエラー出力にエラー表示器をつけてみてください)。
このように、プログラムのある部分で何かのエラーが起きたとして、エラーの情報をエラーワイヤで渡すと、それを渡された関数はその関数本来の動作は何もせずにエラーを次の関数あるいは表示器に出力していきます。このバケツリレーがプログラムの最後まで到達してプログラムを終えます。
例えば上の図のプログラムの場合、エラーの出ないプログラムでは「振幅」「DC値波形」という部分に何かしら値が出ています。一方、エラーが出るプログラムではこれらに値は出ていません(表示されているのは各表示器のデフォルト値です)。
「振幅」「DC値波形」はそれぞれFFTスペクトルと平均DC-RMSの関数が実行された際の出力ですがエラーが起きるとこれらの関数は実行されないことになります。とはいえ、各表示器に何かしらの値は出す必要があるので、デフォルト値が出ている、と考えてください。
一方で、エラーは全て-20061となっています。このエラーは正弦波形の関数特有のエラーなのですが、一度このエラーが起きるとFFTや平均DC-RMSの関数に渡った際も受け取ったエラーをそのまま左から右に流していきます。
ちなみに、シンプルエラー処理はエラーの入力があっても実行(ポップアップを表示という動作をする)されます。まぁエラーが起きたときにポップアップを表示するための関数なので当たり前ですね。
なお、エラーが起きたときでもどうしてもこの関数を実行したい、という場合には、
- (手動エラー処理にして)その関数には入力側のエラーワイヤを配線しない
- エラークリアの関数を使う
といったことが考えられます。
エラークリアの関数は、この関数に渡されたエラーワイヤ上を通ってきたエラーのうち、どのエラー(コードで指定します)をクリア、つまり消去するかを指定することができます。特定のエラーが入ってきたら無視するけれどそれ以外のエラーだったら無視しない、みたいな使い方ができます。
実際エラーが起こってしまった際にこれを修正するためのデバッグの方法については数多くありますが、それらは今後また紹介していきます。
さて、次はいよいよプログラムを作り始めるための基本要素となるデータタイプについてみていきます。
もしよろしければ次の記事も見ていってもらえると嬉しいです。
ここまで読んでいただきありがとうございました。
コメント