この記事で扱っていること
- ハードウェアで受けたトリガで特定の処理を実行する方法
を紹介しています。
注意:すべてのエラーを確認しているわけではないので、記事の内容を実装する際には自己責任でお願いします。また、エラー配線は適当な部分があるので適宜修正してください。
特定の処理を行わせるタイミングを決める方法の一つとして、外部からいわゆるトリガ信号を受けてその信号を合図に処理を開始するといったプログラムを書くことができます。
例えば、「特定の処理」が外部からのトリガ信号を受け取って測定対象となる信号を集録し始めるような動作であれば、文字通りその「信号を集録し始める」もの(ハードウェア)が外部からトリガ信号を受け取ったら集録を開始するようにプログラムを組めばいいと思います。
ただ、ソフトウェア上の処理を外部からのトリガ信号を受けて行う場合もあると思います。
当然外部からのトリガを取り込むためのハードウェアは必要ですが、このハードウェアがトリガ信号を受けてから、ある特定のソフトウェア上の処理を実行させるためにはいくつかプログラムの書き方があると思います。
この記事ではそんな場合の例を紹介しています。
なお、この記事では「トリガを受けるハードウェア」としてはNational Instruments社のデジタルIO用のハードウェア(DAQ)であるNI 9402を使用していますが、ハードウェアタイミングでデジタル入力できるデバイスであればなんでも構いません。
どんな結果になるか
フロントパネルとしては、デジタル信号としてのトリガを取得するラインの選択、測定時のサンプリングレートや一回のグラフに表示するサンプル数、そしてこのデジタルデータの表示を行うグラフをつけています。
トリガに対する反応として次の2パターンを考えます。
(a)一度トリガを受けたら特定の処理をして終わり
(b)トリガを受けるたびに特定の処理を行う
本記事の例では、「特定の処理」として時間を取得するという処理を実装していますが、複雑な処理を行わせたい場合であっても手順は同じです。
(a)について、以下のような動作となります。
(b)についてもフロントパネルは同じなのですが、トリガを何度も受け付けられるようにしています。
プログラムの構造
まずは(a)について。これは、トリガを受けたらもうハードウェア側でトリガを受ける必要がなくなるため、トリガ信号を監視していたチャンネル(ライン)の操作を終了するように組めばいいので楽です。
トリガ検知には、測定したブールの信号の配列を調べ、LowからHighになっている部分があるかどうかで検出します。このLowからHighになっているかを調べるのに、シフトレジスタと不等号を用いています(HighはLowより「大きい」ので、High > Lowとなる場合TRUEと判別されます)
なお、以下に紹介する(b)でも同じことが言えますが、この方法は厳密にはハードウェアタイミングのトリガにはなっていません。
トリガ信号そのものはハードウェア側で受け取りますが、「信号を読み取ってトリガを検知してから、実行したい動作が起きるようにする」部分はソフトウェア上の話であり、ソフトウェアの処理スピードの影響を受けるためです。
ただまぁ実際は(指定するサンプリングレートやループ当たりのサンプル数に依りますが)人間が明らかに感じ取れるほどの遅延は起きないと思います。
一方で(b)については、単純には以下のように組むことで簡単に組むことはできます。
ただしこの方法には弱点があり、ハードウェア側でサンプリングしていたデータがどんどんたまることになりかねません(理由が知りたい方は下の方で説明をしているので参考にしてみてください)。
そこで、よりトラブルが起きにくい方法としては、トリガ信号を監視するためのループと、トリガを受けてから行いたい処理を実行するループに分けるデザイン、生産者・消費者デザインが挙げられます。
その一例が下のようなプログラムです。このように組めば、トリガを受けたという情報を生産者ループから消費者ループに渡すことはあるものの、生産者ループの動作を妨げることは基本的にないため、DAQmx読み取りの関数が実行されないことによるバッファのオーバーフローのエラーが起きません。
立下りの信号をトリガ検知したい場合
上で紹介したトリガは、デジタル信号がLowだったものがHighになった状態、いわゆる立上がりを検知して「トリガがきた」と判断させています。
しかし場合によってはHighからLowになったいわゆる立下りタイミングを検知して処理を行いたいケースもあると思います。
上のプログラム例で察しがついた方も多いと思いますが、不等号の向きを逆にすればいいだけです。
また、立上りおよび立下りそれぞれに対し処理を繰り返し行いたい場合にはFALSEあるいはTRUEが連続して続かないことを条件に消費者ループに渡すように組めば対応できます。
サンプリングレートとサンプル数のバランス
トリガを受ける際に考慮しなくてはいけないこととして、サンプリングレートとサンプル数の関係が挙げられます。
サンプリングレートは、1秒間に何個のデータ(サンプル)を取得するかに関係しているため、大きいほど、トリガ信号の立上りもしくは立下りの状態をより早く検知することができます。ただし、1秒間に得られるデータの数も増えるということになります。
DAQのプログラムの場合、DAQハードウェアで取得されたデータがバッファにたまりこれをLabVIEWが読み出しているため、読み取るサンプル数の大きさがあまり小さいと、ひっきりなしに読み取るためのDAQmx読み取りの関数が実行できれば(つまりそれだけ早くWhileループが回ることができれば)いいのですが、そうではないとバッファにデータがたまりすぎてある段階でエラー(例えば-200279)が起こります。
そのため、読み取るサンプル数を大きくすることでデータがバッファにたまる状態を防ぐことも考えられます。ただ、読み取るサンプル数をあまり大きくすると今度はデータが指定した個数収録されるのを待つことによる繰り返しの遅延が発生しえます。
そのため、サンプリングレートと読み取るサンプル数はよく考えて両者決める必要があります。
対策として、生産者・消費者デザインで作成しておくと、この「バッファにデータがたまりすぎる」問題が起こりにくくなります。
トリガ受付の間隔をコントロールする場合
一度トリガを受け付けたら、指定した時間以内に次のトリガが来てもそれを無視するようなプログラムも可能です。
方法としては、一度トリガを受け付けたらその時点でのティックカウント値を取得し、あとは常にティックカウントの値を見つつ「現在のティックカウントの値」から「最後にトリガを受け付けたときのティックカウントの値」を引いてその値が指定した数値を超えるようならトリガを受け付けるようにします。
上の図のように組むことで、「トリガ禁止時間」で指定した時間が過ぎないと次のトリガ信号が来ても消費者ループにその情報が渡らないため、トリガが来たのを無かったことにできます。
この記事ではハードウェアで受けたトリガで特定の処理を実行する方法を紹介しました。外部からの信号を取り込めるような環境(本記事ではDAQハードウェアを使用)があればDAQでなくても本記事で紹介したプログラム例の書き方を当てはめることができると思うので参考になればうれしいです。
ここまで読んでいただきありがとうございました。
コメント