繰り返さないループで内部状態を保持 のバックアップの現在との差分(No.2)

更新


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[公開メモ]]

* 概要 [#cf353635]

繰り返さないループで内部状態を保持するというテクニックを使うと、
通常通りにシフトレジスタを使った場合にはロジックが入り組んでしまい、
サブVI 化しにくいようなデザインからサブVIを切り出して見やすくできる場合があります。

下記のブロックダイアグラム画像はVIスニペットになっているので、
画像を LabView へドロップすると、簡単に試せます。→ [[プログラミング/LabView/VIスニペット]]

* 入力値が変更されたことを検出するには [#d52d127c]
* 例:入力値が変更されたことを検出するには [#d52d127c]

普通こんな風にするのではないかと思います。

&attachref(detect_change.png);

フロントパネルはこう。

&ref(detect-change-frontpanel.png);

数値を変更すると、「変更された」のランプが光ります。

動作的には、

- 前回の値をループのシフトレジスタに保存する
- 前回の値と今回の値が異なればランプを光らせる

という形です。

** ループをまたぐ線が邪魔 [#v2208d57]
でもこれ、それほど完璧な回路とも言えなくて、以下の欠点を持っています。

ループの端から端まで線が延びるので、ダイアグラムがごちゃごちゃします。
- ループをまたぐ線が邪魔~
ループの端から端まで線が延びるので、大きなループでこれをやるとダイアグラムがごちゃごちゃします。~
~
- サブ VI として切り出せない~
上の形だと「変更を検知する」という機能をサブVIとして切り出すことができません。

** サブ VI として切り出せない [#xc940ce9]

上の形だと「変更を検知する」という機能をサブVIとして切り出すことができません。
* 繰り返さないローカルループを使って書き換える [#l5c31449]

下記の回路は上記と同じ動作をします。

&attachref(detect_change2.png);

フロントパネルは同じです。

- 内側のループの繰り返し条件は False なので1度しか実行しない、繰り返さない「ループ」になっている
- このループのシフトレジスタに、前回の値を保存する
- 保存した値はループへ再入した際に使えるため、このシフトレジスタは「ローカル変数」のような働きをする
一見しただけだとよくわからないので1つ1つよく見てみると、

- 内側のループの繰り返し条件は False なので、「繰り返さないループ」になっている
- 外側にループがあるので、「1度も繰り返さないループ」を「繰り返し呼び出している」
- 内側のループのシフトレジスタに保存された値は、
「次にループが呼び出された時」に読み出せる ← これが重要
- このシフトレジスタに、「前回の値」を保存して、「今回の値」と比較することで変化を検出する
- 初回はシフトレジスタに値が入っていないので読まないようにする

外側ループの端から端まで伸びる線がなくなって、かなりすっきりします。
この「1度も繰り返さないループ」の中から見ると、
まるで「ループの外側の処理を繰り返している」ような働きをすることになります。

全体としては外側ループの端から端まで伸びる線がなくなるため、かなりすっきりします。

この形であれば内側ループ部分をサブVI化できるので、

&ref(detect-change3.png);

こうしてしまえばとても見やすいです。

** 別解 [#y177b8ba]

「前回の値」を参照するには「繰り返さないループのシフトレジスタ」
を使う方法のほかに「フィードバックノード」を使う方法もあります。

&ref(プログラミング/LabView/スニペットライブラリ/detect-change2.png);

こちらは初期値を入れる機能も標準で備えているため、
簡単な回路であれば非常に手軽に記述できます。

ただ「フィードバックノード」を使う方法は
「前回の値」に依存する回路部分があいまいになる傾向があるため、
むしろ多少面倒な記述が必要になるとしても(慣れた人にとっては)
「繰り返さないループのシフトレジスタ」を使う方法の方が
読みやすい回路を描けます。

そのため、LabView の標準ライブラリでもフィードバックノードよりも
繰り返さないループがより多用されているようです。

* 応用例1:IIR ローパスフィルタ [#l3194342]

入力値にローパスフィルタを掛けた値を出力します。

前回の出力の値をシフトレジスタに保存しています。

&attachref(iir-lowpass.png);

&ref(iir-lowpass-frontpanel.png);

&attachref(iir-lowpass.gif);

* コメント・質問 [#a656371b]

#article_kcaptcha


Counter: 5312 (from 2010/06/03), today: 1, yesterday: 1