繰り返さないループで内部状態を保持

(2663d) 更新


公開メモ

概要

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

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

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

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

detect_change.png

フロントパネルはこう。

detect-change-frontpanel.png

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

動作的には、

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

という形です。

でもこれ、それほど完璧な回路とも言えなくて、以下の欠点を持っています。

  • ループをまたぐ線が邪魔
    ループの端から端まで線が延びるので、大きなループでこれをやるとダイアグラムがごちゃごちゃします。

  • サブ VI として切り出せない
    上の形だと「変更を検知する」という機能をサブVIとして切り出すことができません。

繰り返さないローカルループを使って書き換える

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

detect_change2.png

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

一見しただけだとよくわからないので1つ1つよく見てみると、

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

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

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

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

detect-change3.png

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

別解

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

detect-change2.png

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

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

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

応用例1:IIR ローパスフィルタ

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

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

iir-lowpass.png

iir-lowpass-frontpanel.png

iir-lowpass.gif

コメント・質問





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