eminus hatena lab

技術系のメモと解説

LabVIEWで電卓を作る(3): ループと条件分岐、ローカル変数について少し

プログラミングで必須*1とも言えるループと条件分岐を簡単な例を使って紹介する

このシリーズの初回はこちら:

eminus.hatenablog.com

例題

カウンター(ボタンをカチカチ押してカウントアップ・ダウンするやつ)をLabVIEWで作る

(注)ここではループと条件分岐について紹介するために以下のような構造にしているが、実際にはevent structureを使った方がきれいに書ける

Front panel

  1. 現在のカウントを表示するためのNumeric indicatorを一つ用意する。今回は整数しか扱わないのでReprensatationをI32 (32bit符号付き整数)にしておこう
  2. カウントアップ・ダウン・0にリセットの押しボタン(push button)3つを置く
  3. これらのボタンは通常Falseとして読み出されるが、押すとTrueになる。今回はTrueを読み出した後はボタンが勝手にFalseの状態に戻ってほしいので、右クリックメニューからMechanical actionを探し、Latch when pressedを選んでおく。こうするとTrueを読み出した瞬間にボタンがFalseの状態に勝手に戻る

f:id:eminus:20190109195419p:plain

カウンターのfront panel

f:id:eminus:20190109200014p:plain

ボタンのMechanical action

Block diagram

まずどのように作るか考えると、ループを回し続けて毎回ボタンの状況を調べて

  • Upがtrueだったらcountを1増やし、falseだったらなにもしない
  • Downがtrueだったらcountから1減らし、falseだったらなにもしない
  • Resetがtrueだったらcountを0にし、falseだったらなにもしない

ことにする。同時に複数のボタンが押された場合の動作は既定しないことにする

条件分岐

case structure(場合分け)を使う。case structureは中にいくつかのblock diagramを書けるページがある構造をしており、そのサイズは自由に変えられる。複数あるページのうちどれが実行されるかは左側にある[?]アイコンの入力端子で決められる。

f:id:eminus:20190109201159p:plain

case structure

たとえば、「Upがtrueだったらcountを1増やし、falseだったらなにもしない」を実現するには

f:id:eminus:20190109201658p:plain

カウントアップ

のように+1(increment)の部品をTrueの場合に置いておけば良い

(ちなみにUpのボタンのblock diagramでのアイコンが小さくなっているが、これは右クリックメニューから変更することができる。筆者は面積が小さい方が好きなので上記のように小さくしておくことが多い)

ローカル変数(local variable)

カウントアップするには当然ながら現在のカウンターの値を読み出して、それに1を足す必要がある。しかし前々回述べた様に、Numeric indicator(表示器)は基本的に出力専用なので読み出すことが一見できないように見える

それをできるようにする仕組みがローカル変数(local variable)。これはCのポインターみたいな感じ(同じではない。似たようなものにreference=参照というのがあり、そっちの方がポインターに近いかもしれない)で、同じ部品にアクセスするショートカットと見なせば良い。これを作るには対象の部品の右クリックメニューからCreate->Local variableを押すと良い。おそらくデフォルト状態では端子が左側に付いているwrite-onlyの部品ができると思うが、右クリックメニューから"change to read" (読み取りモードに切り替え)すると端子が右側に付くようになる。

f:id:eminus:20190109202935p:plain

ローカル変数

カウントアップの実装

やりたいことを復習すると「Numeric indicatorである"Count"から数字を読み取り、UpがTrueの場合は1を加算、Falseの場合は何もしないで、最後に"Count"に書き直す」

f:id:eminus:20190109203803p:plain

カウントアップの実装(左はTrueの場合を表示した場合、右はFalseの場合を表示した場合)

カウントダウンの実装

同じようなことをDownにもすればよい。このとき、+1と-1は同時に押されても順番は関係ないことを利用すると

f:id:eminus:20190109204551p:plain

カウントアップとダウン

こんな感じにしてしまって良い。

リセットの実装

Countを強制に0にする場合、Up/Downと同時押しされた場合にどっちを優先するか、という問題が起きるが、同時押しされないだろうという仮定のもとでは上記のカウントダウンの条件分岐のあとに作ってしまって構わない。

リセットの場合、Countの値にかかわらず「定数0」をCountに書き込めば良い。定数0は様々な方法でBlock diagramに置くことができるが、よく使うのは適当な数字の部品を右クリックし(この場合"Count")、Create->Constantを押すという手順。この方法で定数(constant)を作ると右クリックした部品と同じ型の定数を作ることができる。

f:id:eminus:20190109205210p:plain

リセットの実装

ループ

case structureと同じカテゴリーにあるwhile loopを使う。While loopを作るモード(カーソルが変わる)に入ったら、今まで作ったカウンターのブロック図を全部囲むように四角を描く。すると、自動的にWhile Loopの中にブロック図が入った状態でループが完成する。

While loopには2つ特徴的な端子があり、左下に[i]というアイコン、右下になにやら赤い丸が入ったアイコンがある。[i]というアイコンは想像できるかもしれないが、ループのカウンターで、何回目のループかをカウントしている。今回は特に使わないので何もつなぐ必要はない

右下の赤い丸みたいなやつはループの条件を指定する端子で、Booleanを入力する必要がある。この端子にTrueが入力された場合ループが終了する。

(注)ループは「Falseの間実行」(デフォルト)か「Trueの間実行」の二通りがある。切り替えは右クリックメニューからか直接アイコンを左クリックしても良い。

よくこの手のプログラムでは、ループ条件の端子(右下の赤丸アイコン)の右クリックメニューからCreate Controlを押して[STOP]ボタンを作る

ついでにループ毎に100ms秒くらいのwaitを入れておけば完成。

f:id:eminus:20190109210603p:plain

完成したブロック図

今回のまとめ

  • Case Structure(場合分け)を使って複数のブロック図を切り替えること(=条件分岐)ができる
  • While Loopの中のブロック図は条件端子がFalseの間(設定による)繰り返し実行される
  • 定数は右クリックメニューなどからブロックダイアグラム上に作成できる
  • ローカル変数を使うとFrontpanel上の部品の値を自由度高く読み書きできる

 第四回はこちら:

eminus.hatenablog.com

 

*1:ループと条件分岐がない言語があるのだろうか... なんかありそうな気がする。ではどういう要素があればプログラミング言語と言えるのだろう?