この記事では、LabVIEWでシリアル通信を行う際の基本的な流れを紹介しています。
LabVIEWが強みの一つにしている、計測器制御の一種、シリアル通信にフォーカスした記事ですが、別の通信バスであるGPIBの通信について知りたいよという方は以下の記事が参考になるかもしれません。
LabVIEWによる計測器制御の大まかな流れやドライバソフトウェアの準備についてはこちらの記事と重複するので本記事では説明を省いています。
NI MAXで計測器との通信ができているかを確認する
シリアル通信やGPIBなどの通信バスの種類に依らず、いきなりLabVIEWプログラムで通信プログラムを書き始める、のではなく、まずそもそも通信ができる状態なのかを確認するのは大事なことです。
そのためにNI MAXを使用して通信ができるかをテストしてみます。
NI MAXは、LabVIEWでハードウェア操作を行う際にそのハードウェアの名前を決めたり、簡単なテストを行うことができるソフトで、LabVIEWがインストールされているのであれば通常は勝手に(?)インストールされていると思います。
やることの流れはGPIB通信の場合と変わりませんが、NI MAX上での見え方が異なります。
シリアル通信用の機器として今回はNI社製のUSB 232というケーブル(片端がUSBでもう片端がRS232端子となっている)を使用しています。
このとき、通信バスは以下のように表示されます。

GPIBの記事で使用したのと同じく、通信相手はNI Instrument Simulatorというものを使っていきます。
この上でVISAテストパネルを実行します。

シリアル通信の場合のVISAテストパネルは、GPIB通信の場合のそれと多少表示される項目が違います。
例えばConfigurationのタブには以下のように表示されます。(GPIBの方は別記事をご確認ください)

今は特にConfigurationでの設定は行わない(この部分は通信機器によって設定が異なるので、各機器のマニュアルを参照する必要があります)ものとし、通信テストを行います。
Input/Outputのタブで、通信のテストができるので、送りたいコマンドを書いてWriteでそのコマンドを送信します。
応答が来るようなコマンドの場合には、その応答をReadで受け取ることができます。
また、送って受け取るということを一つのボタンで行うにはQueryを選択します。

他にAdvancedのタブもありますが、今回は細かい設定を行わないのでこのままテストパネルを終了します。
一応、Advancedのタブには以下のような項目が表示されるので画像だけ紹介しておきます。

テストパネルで通信ができなければLabVIEWで扱えない、というわけではないと思います。
例えばテストパネルで最初にコマンドとして表示されるIDN?コマンドはSCPIの規格にあるコマンドですが、このコマンドに対応していない機器もありますし。
ただ、コマンドはIDN以外にも自由に入力できるので、まずはこのテストパネルを使用して通信そのものができているかを確認すると、あとあとのデバッグが楽になることがあるので、「プログラムで動かす前にテストパネル」というのはクセを付けておくに越したことはないと思います。
LabVIEWプログラムで計測器に対してコマンドを送る
NI MAXで確認ができたところで、LabVIEWプログラムによる通信へ移ります。
シリアル通信の場合、GPIB通信時には設定しなくてよかった、ボーレートやパリティなど、いくつかの設定をプログラム中で指定します。
この辺りのことは、LabVIEWのツールバーのヘルプから「サンプルを検索」で開くNIサンプルファインダに入っているサンプルプログラムが参考になると思います。

通信機器や要件によってパラメタは調整が必要ですが、各機器のマニュアル等を参考に適切なパラメタを選んでください。
あとはプログラムを実行するだけです。
最もベーシックなプログラムは、「簡易シリアル」というサンプルで、テストパネルと同じような動作をします。
ブロックダイアグラム上で送るコマンドは変えられますが、サンプルそのままだとIDNコマンドを送ります。

ここで改めてNI MAXのテストパネルと同じ結果が得られるか確認してみます。
ただ実際は、一つのコマンドを送ってそれで終わり、ということはないと思います。
色々なコマンドを送ったり、あるいは応答を受け取ったりを繰り替えすということが想定されますが、サンプルファインダには、連続的に通信を行うサンプルもあります。

このプログラムでもまた、VISAテストパネルと同じ結果を得ることができます。

このサンプルを動かしているとき、もしかするとエラー-1073807339が出るかもしれません。
操作が完了する前にタイムアウトした、というエラーです。
このエラー、「コマンドを送っていないのに応答を待つ」という操作をしてしまう場合に起こります。

このサンプル、デフォルトの状態だと「書き込み」や「読み取り」のボタンの機械的動作は「スイッチ」になっていると思います。
つまりこのサンプルでは、「スイッチ」動作にしてボタンをTrueにしておくと書き込みあるいは読み取りを連続的に行ってしまいます。
そのため、何回コマンドを送ったか(書き込んだか)が判別しにくい状態が発生し、結果、読み取り回数も適切な回数できずに上記のエラーが起こってしまいます。
これを防ぐには、必要に応じて書込みや読み取りのボタンの機械的動作を「ラッチ」にしておくと便利です。

一応、ブロックダイアグラムは以下のようになっています。
単にWhileループの中で書き込みと読み取りのブールの値からケースストラクチャを制御し、TRUEケースの場合にのみ送信、あるいは受信をしています。

シリアル通信の工夫
シリアル通信を行うプログラムを書く場合、読み取りのバイト数が正しくないと読み取り値を全て受け取れません。
また、「下手に」読み取り操作を行うと、来もしない応答を待ち続けるという状態になり上でも紹介したタイムアウトエラーが起こることがあります。
なるべく効率よく応答を受け取りたい、という場合に工夫することで、ポートに来ているデータを来ている分だけ都度受け取るという方法が有効なことがあります。
それは、プロパティノードで「Number of Bytes at Serial Port」を選択しこれで得た値をVISA読み取りのバイトカウント入力に配線する方法です。
常にポートにあるデータ数の分だけ読み取りそれを繰り返す(そしてポートのデータ数が0になったらWhileループを止める)ことで、うまい具合にデータの受信ができます。

ユーザーとしては、バイトカウント数をいちいちフロントパネルで指定する必要がなくなるので、「余計なことを考える」手間が一つなくなって楽ですね。

なお、この方法であっても、コマンドを書き込んだ後、読み取り動作をする前にどの程度待つか、や、ポートに来ているデータを読み取るループの速度を調整するために使用している待機関数への入力は、適宜最適な値にする必要があります。(以下で紹介するプログラムにも例があります)
また、何かコマンドを送ってその応答を受け取る、つまり「書いて読む」という動作をボタン一つで、それこそVISAテストパネルの「クエリ」と同じような形で操作をしたい場合には、以下のように組むことでクエリ動作を実現できます。

クエリ機能を加えつつ、VISA読み取りをうまい具合に行わせる工夫を行ったプログラムの例が以下のものです。
書いてから読むまでの間の時間や、読みとりのループの早さについては待機関数へ配線する数値を適宜調整してみてください。

うまく調整できれば、ある程度長い応答を受け取る通信であっても適切にデータを受信できるようになります。

本記事では、LabVIEWでシリアル通信を行うための流れと具体例を紹介しました。
LabVIEWを活用して計測器制御を行う際に最低限必要な情報だけですが、参考になればうれしいです。
ここまで読んでいただきありがとうございました。
コメント