この記事で扱っていること
- しきい値をまたいだ時間を知る方法
を紹介しています。
注意:すべてのエラーを確認しているわけではないので、記事の内容を実装する際には自己責任でお願いします。また、エラー配線は適当な部分があるので適宜修正してください。
信号を測定する中で何か特徴を見つけたいと思った場合に、あるしきい値をまたいだ時間を知りたいと考えました。
実はこの処理、NIサンプルファインダの中のサンプルで「しきい値検出の比較」というサンプルにある方法でもできるのですが、これは「下から上にまたいだとき」つまり信号が定められたしきい値より大きくなった部分を拾い上げるものになっています。
一方で、「上から下にまたいだとき」つまり定められたしきい値より小さくなった部分は検出しません。
そこで、どちらの方向からまたいでも検出するような仕組みを作ってみました。
どんな結果になるか
このサンプルでは簡単に、適当な波形データを生成してその波形データに対ししきい値を設定、そのしきい値を下から上あるいは上から下にまたいだときの値を表示させ、グラフ上でもこれがわかるようにしています。
プログラムを実行すると、下から上へまたいだ部分は赤丸で、上から下へまたいだ部分は緑丸で、それぞれ示しています。
プログラムの構造
今回の実装は、ブールの大小のやりくりでまたいだ方向を検出するようにしました。
まず、対象となる波形データのY値全てに対してしきい値との大小を比べこれをブールの配列として得ています。
ここで、値が下から上あるいは上から下へしきい値をまたぐとはどういう状態かを考えてみます。波形データのY値としきい値との大小を比べたときに、Y値がしきい値以上であることをTRUE、しきい値未満であることをFALSEと定義すると、
- 下から上へまたぐ:FALSEからTRUEになる
- 上から下へまたぐ:TRUEからFALSEになる
と言えます。
つまり、このブール配列の前後関係を見たときに、TRUEからFALSEあるいはその逆が起こった場合にしきい値をまたいだと判断できます。
これを行うため、ブールの配列をForループに自動指標付け有効で渡し、一つ前の値と交互に比べるようにしています。
ブールどうしにも大小関係があり、TRUEの方がFALSEよりも「大きい」ことを利用して、
- 今のブール値の方が一つ前のブール値より大きい=FALSEからTRUEになった=下から上へまたいだ
- 今のブール値の方が一つ前のブール値より小さい=TRUEからFALSEになった=上から下へまたいだ
と言えるため、これらそれぞれ調べて何番目の指標でそうなったかを調べています。
判定の仕方の説明はここまでにして、実際のブロックダイアグラムはこのようにしてみました。
まず、Whileループに入る前に、波形配列の初期化を行っておきます。今回のサンプルでは、波形グラフには3つのプロットが表示されている状態であり、
- 本来の波形
- 下から上へまたいだデータ点のみの波形
- 上から下へまたいだデータ点のみの波形
となっています。これら3つの波形を使用するために、配列初期化で波形データが3つ入った波形配列を用意しています。また、後半二つの波形は色を付けてわかりやすくするためにプロパティノードを使用しています。
この後にWhileループに入っていきますが、メインVIをコンパクトにまとめるために二つのサブVI、compare_sub.viとthreshold_point.viを作りました。
compare_sub.viでは、波形に対してしきい値を超えたかどうかを判定、その後にその判定結果のブールの配列の前後関係でFALSEからTRUEあるいはTRUEからFALSEになった部分を抽出しています。
ただし、各波形の最初の一点は比べる対象を気を付ける必要があります。メインVIのWhileループ一回目については最初の一点よりも前のデータというものはないので、ここは判定していません。しかしメインVIのWhileループ二回目以降は、前のループでの最後のYの値と現在のループの波形の一番最初の点を比較して下から上あるいは上から下へまたいだかを判定しています。
二回目以降の処理で、前のループでの最後の値を見るために初期化されていないシフトレジスタが活躍します。
このサブVIのフロントパネルは以下のようです。
このサブVIで、下から上へあるいは上から下へまたいだデータ点の番号をそれぞれ配列として取得したら、あとはその番号を元々の波形データの要素番号と対応させ、その要素番号のときの要素のみを抽出して波形データにします。
この役割を担っているのが以下のthreshold_point.viのサブVIです。またいだX値の配列にある数値の要素だけ、元々の波形データのY値配列から抜き出し、その他のデータはNaNとします。今回は1D配列検索を使用してみました。
フロントパネルは以下のようです。
メインVIではこのthreshold_point.viを二つ(下から上へまたいだ場合と上から下へまたいだ場合)使用していますので、これらが滞りなく実行されるように非再入実行の設定は外しておきます。Ctrl + Iで開くVIプロパティで、実行のカテゴリにて操作します。
なお、サブVI全編を通してエラーの入出力は特に何もしていません。が、メインVIでの見た目の良さからあえてエラー入出力をつけてみました。
処理速度はどうか
波形グラフに、あらたに波形データを2つ加えてForループで計算させているということなので、普通に一つ波形をグラフに表示させるよりも当然負荷がかかります。
このことによりWhileループの速度が遅くなってしまうのではないかと思いましたが、実際Whileループの速度を測ったところ、検出する点の数にもよりますが、そこまで数が多くない場合にはティックカウントに依る計測では1ミリ秒以下程度の速度になっていました。
もちろん大量のデータを扱う場合(もともとの波形データの点数が多い場合)にはより時間がかかりますが、その場合には測定のループと表示のループで分けるために生産者・消費者ループのデザインにするのがいいと思います。
あるいは、測定中はとりあえずすべてのデータをとって保存しておき、後処理として保存データから読み出して解析を行う、という方法の方が望ましい場合もあるかもしれないと思います。
本記事では、特定の点を検出する方法として、しきい値の大小をブールデータの大小で判断する方法を紹介してきました。
とびとびのデータを表したり特定の点の色を変えるために、プロット数を増やして表現するという今回のサンプルのやり方が参考になればうれしいです。
ここまで読んでいただきありがとうございました。
コメント