08-07-2019 01:29 AM
お世話になります。Labview初心者になります。
やりたいことは、下記のとおりです。
・リアルタイムなUSB6009のアナログインプットにいろいろな処理(たとえば正弦波を合成)をかけてグラフに表示したい
※作ったメインルーチンを抜粋したのが添付のviです。
VIにおいて、目標レートを例えば10や50にすれば、アナログインプットも目的の正弦波もうまく出るのですが、たとえば500にすると正弦波の周波数(グラフで見える周波数)が低くなってしまいます。これは、実際のループにかかる時間が、タイミングループのタイミングよりも時間がかかるからだと推測しますが、このよう場合でもちゃんと一定の周波数の正弦波を出したいと思っています。つまり、たとえばPC上で、labview以外のアプリの負荷が増えて、labviewのタイミングループのレートが下がっても特定の周波数の正弦波がちゃんと実時間で表示されるようにしたいのです(間に合わなかったデータは破棄で、飛び飛びでも構わないです)。
最初、タイミングループの設定で、「間に合わなかった周期を無視」をチェックをしたら実現できるのではないかと考えましたが、うまくいきませんでした。理由は、VI内のsin関数を考えるに、関数の種がループのカウント[i]なので、「周期は無視」となってもカウンタ[i]は実際に動いたループ分が増えていくからだと思いました。つまり、周期は無視されても、カウンタはスキップしてくれないのだと思っています。
つきましては、私のやりたいことを実現するためには、ループ内のsin関数の種に、間に合わなかった周期のカウンタをスキップしたカウンタ変数(理想通り動いた際のクロックのカウンタ?)を入れてあげれば解決するのではないかと考えましたが、どうやるのかわかりませんでした。この点、ご助言いただけましたら幸いです。
※もちろん、そのようなカウンタの方法でなくとも、いいアイディアがありましたら教えていただきたく存じます。
どうぞよろしくお願いいたします。
解決済! 解決策の投稿を見る。
08-08-2019 04:40 PM
平素よりNI製品をご愛顧頂きありがとうございます。
日本ナショナルインスツルメンツ技術部の上野です。
添付いただいたコードでは、アナログ入力にDAQmx Express VIが使用されておりますが、サンプルモードは1サンプル(オンデマンド)を設定させておりますので、ソフトウェアタイミングによるデータ収集ということになります。
よって、目標レートがデータ収集のサンプリングタイミングとなるのですが、ソフトウェアタイミングの収集ではそれほど速いレートで実行することができません。どのくらいのレートで実行できるかは、下記のようにループ時間を求めて数値が安定する周期をご確認いただければと思います。
ご質問では正弦波生成にフォーカスされておりますが、アナログ入力が正確にできなくなってしまっている部分は無視して一定の周波数を生成したいのでしょうか?
もしアナログ入力も指定したレートで正確に収集したいのでしたら、ハードウェアタイミングで収集することをお勧めします。この場合、ハードウェアのバッファ(メモリ)を使用して複数サンプル(一度に読み取るサンプル数)をまとめてLabVIEWに渡します。よって、結果は配列となります。そのように設定した例を添付致しますのでご確認いただけると幸いです。
08-08-2019 09:20 PM
早速のご回答をいただき、ありがとうございます。
説明不足で申し訳ございません。
やりたいことは、人間工学的なマン-マシンインタフェースの人間の特性を図るような実験でして、リアルタイムに自動で変化する値(目標値:私の例で言うなら正弦波)を見ながら、人間がそれをハンドルのようなもので追従(私の例で言うならUSB6009のアナログインプット)するというものです(途中、操作値にエフェクトを掛けたりとかいろいろありますが)。
重要なことは、実験中に体感的な周波数が変化してしまうと、後の人間工学的な解析ができなくなってしまうので、それは避けたいということになります。
>ご質問では正弦波生成にフォーカスされておりますが、アナログ入力が正確にできなくなってしまっている部分は無視して一定の周波数を生成したいのでしょうか?
はい。そのとおりです。
アナログ入力につきましても、人間にとってのリアルタイム性が重要で瞬間・瞬間の時間解像度はさほど重要ではありません。読み取った値がよほどとびとびでなければ(グラフで描画した際にあまりにもカクカクでなければ)、保存されるデータは常に一定のdtである必要はありません(変動しても飼かまいません)。
そういう意味では、リアルタイムOS的なものを使えばいいのでは?ということになるのですが、メンテナンス性やその他の学習コストを考えますと、そこまでの実験ではないという感じになります。
・・・というような質問であったのですが、今回の件に関しましては、色々考えました結果、sin関数の種に、カウンタ[i]ではなくループ開始からの経過時間を毎度入れることで、おおよそ私が求める理想的な結果を得ることができました。
つきましては、追加の質問になり大変恐縮なのですが、最初に添付いたしました私のVIは、実験VIの中心部分の抜粋でして、本当のプログラムはもっと複雑なコードがループ内にあります。そのようなVIで実際のループレートを可能な限り速くしたいとは考えてはいるのですが、私が書いているコードが(私がlabview初心者ゆえ)無駄なオーバーヘッドが入っているのではないかと心配しています。つまり本当に最適な書き方をすれば、もっと速いループレートを得られるのではないかと。
たとえば、このスレッドに本来の私のVIを投稿しましたら、それがおおよそ最適なVIかどうか(無駄なことをしていないか)ということをご判断していただくことは可能なのでしょうか。もしそういったことはトピックの範囲外のことでしたら、本件は「解決」でフィックスさせていただきたいと思います。
どうぞよろしくお願いいたします。
まずは取り急ぎ御礼申し上げます。
08-08-2019 11:29 PM
詳しいご説明ありがとうございます。前回添付したファイルがハードウェアタイミングではなかったため、改めて添付致します(Loop Test.vi)。
今回の件は自己解決とのことですが、同じようなソフトウェアタイミングでオーバーヘッドを減らしたいのでしたら、DAQアシスタントExpress VIよりDAQmx APIを使用するほうがよいかと思います。下図がその例です。
そして、長時間このループを回して、グラフに表示するデータが大きくなってくるとループ速度が低下します。この原因が配列連結追加関数が実行時にデータをコピーして追加や連結がおこなわれるため、サイズが大きいとデータのコピーに時間がかかるようになります。動作比較用のVIを添付致します(Build Array vs Replace Array Submit.vi)。
08-09-2019 12:52 AM
ご回答ありがとうございます。
DAQアシスタントExpress VIよりDAQmx APIを使用するほうがよい旨、また配列の追加のより時間がかかるようになる旨、理解いたしました。注意してプログラムを作りたいと思います。
それでは、これにて解決とさせていただきます。
大変ありがとうございました。
また、機会がございましたらどうぞよろしくお願いいたします。
08-09-2019 02:42 PM
また何かございましたらご投稿いただけると幸いです。
今後ともよろしくお願い申し上げます。