eminus hatena lab

技術系のメモと解説

LabVIEWで電卓を作る(7): キー入力を処理して画面に表示する部分

前回はこちら

 

eminus.hatenablog.com

仕様

  • 0,1,2,3,4,5,6,7,8,9,-2いずれかの数字をキー入力として受け取る
  • 0-9はそれぞれの数字のキー入力、-2はドット(小数点)を表すことにする
  • また、現在画面表示されている数値の文字列も受け取る
  • 基本的には受け取ったキー入力を入力文字列の後ろに追加して返す
  • ただし結果が「00」や「01」等となる場合、頭の0は消す
  • ドット「.」が既に存在する場合は「.」の入力を無視する

解説

まずは素直に文字を連結する。StringのConcatenate Stringってやつ。また、キー入力を文字列に戻すのはFormat Into Stringでやるのが普通だが、ASCIIコード48が「0」に対応するのを利用してキーコード-2から9に48を足し、要素数1の配列を作り、Byte Array To Stringで長さ1の文字列に変換している。もちろんキーコードが-2から9に限られることを既に知っているからできること

次に条件分岐の部分は次のようなロジック

『「キーコードが-2」かつ「入力文字列にドットが含まれる」』が真なら何もしない。偽なら上記の処理を行う。とある文字列にある部分文字列が含まれるかどうかは文字列検索をして、Offset Past Matchが0以上の整数なら含まれていることが分かる。

最後に後処理として先頭のゼロを消す方法は正規表現の置換で実装している

意味は以下の通り

^0+ : 先頭の1個以上のゼロ

(?=xxx): 肯定的先読み(xxxをその先に含む場合にマッチ。xxxはマッチ範囲にふくまない)

\d+ : 1文字以上の数字

f:id:eminus:20190419215621p:plain

今回のあとがき

やっと時間がとれたので続きを。D3のこの時期に忙しいというとあれなのだが、何週間か前に終えてたまっていた実験なども進み始めて、時間に余裕が出てきた

最近解析プログラムをPyQtで作るのにはまっている。ファイルダイアログとかLinux版のLabVIEWがなんか使いにくいっていうのと、単に趣味

LabVIEWで電卓を作る(6): キーボード操作に反応させる+サブVIの使い方について少し

前回の続き。まずは動画でどんな感じかを


LabVIEWで電卓を作ってみた:キーボード操作を処理する

大まかな流れは以下の通り

  1. イベントストラクチャでAdd Event CaseからThis VIのKey->Key Down?を追加
  2. Char, VKey, PlatModsを別に作ったサブVIで処理し、読みやすい形に変える

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

 

eminus.hatenablog.com

 

Key Downのイベント

キーが押されたときに起きるイベント。二種類あってKey Down?とKey Downというのがある。これらは(筆者が正しく理解していれば)LabVIEW自体のキーボードショートカットとの兼ね合いになっていて

  • Key Downの場合、キー入力に応じたLabVIEWのキーボードショートカットが押された後、その結果が”通知”される
  • Key Down?の場合、LabVIEW本体で評価される前にEvent Structureに入り、場合によっては無視したりできる(右側の入力端子)。
  • たとえばF1キーはヘルプになっているが、別な機能に割り当てたい場合はKey Down?の端子(右側)を使って機能をoverrideしないといちいちヘルプウィンドウが立ち上がってうっとうしい。ちなみに上記動画の例だとoverrideしていないので、F1を押すとヘルプウィンドウが立ち上がってから「F1が押された」と言い始める

forums.ni.com

いずれにせよ、3つくらいの端子を読み取ることでキー入力のすべてを知ることができる。例えばCtrl, Shift, Altが押されているかどうかはPlatModsからわかり、どのキーが押されているかはVKeyとCharを組み合わせれば解読できる。

筆者は研究室でたまにキーボード入力を受け付ける計測・解析プログラムを書くので、上記3つの出力を自分に読みやすいような形にするサブVI=関数を作っている。中のブロックダイアグラムは上記動画を一時停止してみてもらうとして、(中でやっているのはこれまでに紹介した内容で理解できるはず)以下ではサブVIについて簡単に述べる。

注:上記VIはWindows/Linux環境だけで動かす場合を想定している。Macでも使いまわす場合、話がすこしだけ複雑になる(CtrlじゃなくてCmdなので、とかそういう話)

サブVI

それなりのサイズのプロジェクトなどで、よく使うプログラムはサブVIとして共通化するのが便利。普通のプログラミング言語でいうところの関数であるので、とても基本的な使い方の一つ。サブVIと今作っているようなトップレベルのVIと作り方は全く同じで、任意のControlとIndicatorを選択することでn入力m出力の四角い箱(細かい話をすると四角くなくてもいいのだが...)にすることができる。

入出力端子を選択するための枠(下図左側)とアイコン(下図右側)はフロントパネルのウィンドウの右上らへんにある。

f:id:eminus:20190115224249p:plain

サブVIの入出力端子(左)とアイコン(右)

入出力端子の選択

通常は入力端子が左側半分、出力端子が右側半分になるように作る。デフォルトではどこにも接続されていないため、白く塗られた四角がデフォルトでは12個くらいあると思う。これらの四角にControlやIndicatorを割り当てる。例えば左上の枠にどれかのControlを割り当てたい場合(ワイヤボンディングするみたいな感じ?)、先に白い四角をクリックして反転させた後、フロントパネル上でそこに接続したいControlをクリックする。そうするとそのControlのデータ型に応じた色で塗りつぶされる。

アイコンの編集

アイコンは上記の入出力端子の右側に表示されており、ダブルクリックで編集できる。これは別のVIからこのサブVIを呼び出すときに表示される画像になるので、わかりやすいアイコン(文字でもよいが)にしておくとよい。今回の例ではめんどくさいのでデフォルトのままにしている

別のVIからの呼び出し

別のVIから呼び出すには

  • VIのファイルをExplorerからドラッグする
  • VIを開いたウィンドウ右上に出ているアイコンをドラッグする

などをすればよい。適切に端子が設定されていれば、LabVIEW標準のブロック(加算など)と同じように入出力ができるはずだ。今回は単純に電卓のVIにEvent Caseを追加してキー入力を表示するだけの構造にしてみた(動画最後のほう参照)

次回以降の予定(順不同)・今後について

  • 数字キー入力を受け取って画面に表示する部分の解説
  • 配列
  • ループとループの入出力形式いろいろ
  • 実際に計算する部分の解説
  • クリアの実装(ここまでプロトタイプで実装済み)
  • メモリ機能の実装
  • 正負反転・ルート・2乗・逆数の実装、完成

本業が忙しいのと電子工作とかもしたいので、LabVIEW電卓の投稿は数日おきにしようと思います

第7回はこちら

 

eminus.hatenablog.com

 

LabVIEWで電卓を作る(7): EnumとType Definition

今日は(休日なので)少し短い記事を。電卓には四則演算(足す引くかける割る)があるがそれを何らかの定数で表現しておくと場合分けがしやすい。単純に文字ベースの場合分けでも良いが、C言語にもあるように列挙型(enum)を使うとよりそれっぽくなる

Enumの作成

LabVIEWEnumはRing & Enumの中にある。RingとEnumで何が違うかは...そんなに意識していなかったが、調べたところ

https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z000000P9NKSA0&l=en-US

  • Enumは連続したunsigned intが0から順に勝手に割り振られる
  • Ringはデフォルトでは上記と同じだが、小数点や連続しない数字など自由に設定できる
  • Case structureなどに繋いだ時はEnumは名前と紐付けられるが、Ringは数値扱いされる。また、ringはプログラム的に項目を編集できるがenumは定数なのでできない(ご指摘ありがとうございます)

らしい。今回は値そのものに特別な意味はないのでEnumでよい

項目(entry)の編集

Enumは最初は空で作成されるが、右クリックメニューからEdit Itemsとすると編集できる。電卓の場合、以下の演算子を定義する

  • Add: 加算
  • Subtract: 減算
  • Multiply: 乗法
  • Division: 除法
  • None: 何もしない演算子
  • Equal: イコール

Noneはプログラミング上の便宜のため、イコールは演算子に含めるかどうかは判断が分かれるだろうが、今回は同じくくりで処理することにする

Enumを別ファイルとして保存 (Type definition)

Enumで割り振られる番号は他の場所(VI中の別の場所で定数を定義したり、他のVI=サブVI)で使うと、あとで項目を追加したり順番を変えたりしたときに番号の不整合が生じてしまう。それを回避するためにEnumの情報を別ファイルとして保存することができる。保存は以下の手順でできる

  1. 右クリックメニューからMake Type Def.を行う
  2. 同じメニューからOpen Type Def.を押す
  3. Block Diagramのない新しいウィンドウが立ち上がる。これはControl(フロントパネルの部品)の定義ファイルになっていて、.ctlという拡張子になっている
  4. 好きな名前で保存する

f:id:eminus:20190113210745p:plain

演算子のType Definition

これ以降同じEnumの定義を参照するには今保存したファイルをドラッグ&ドロップすれば貼り付けることができる

更新履歴

  • 2019.01.16 タイトルを第7回に変更。(第6回を重複して作ってしまったのだが、第6回の方は動画に第6回と書いてあって変えるのが面倒なので)

LabVIEWで電卓を作る(5): Event Structureでボタンが押された時に動かす

今日からは昨日紹介したプロトタイプの動作を解説しながら各部品の動作の説明をする。まずは昨日の電卓がどのようなブロックダイアグラムで動いていたかを下図に一部示す。(正直に言うとあの後少しデバッグをしてあの動画のときのとは変わっているが動作は同じ)*1

f:id:eminus:20190111201658p:plain

電卓のブロックダイアグラム

といってもこれをいきなり全部解説するのは大変なので部分毎に区切り、かつそれぞれの部品の動作が分かるような形で分割して説明する。今日はユーザーから入力を受け取るときに欠かせないEvent Structureに注目する

f:id:eminus:20190111202429p:plain

今回解説する範囲

フロントパネル

まず電卓と言えば0から9までの数値のキーがあるので、それに該当するボタンをフロントパネルに作ってしまう。形は何でも良いが、Mechanical ActionはSwitch Until Released(右上のやつ。電子工作で言うタクトスイッチ的な動作で、押している間だけONになり、離すとOFFになる)を選ぶ。おすすめはBooleanにあるOKボタンのラベルを書き換えることだが、ボタンのスタイル(デフォルトだと「Modern」)がWindows98かと思うような感じで古めかしいので好みに応じて「System」や「Silver」スタイルのボタンを使ってみても良いだろう。LabVIEW2018だとNXGスタイルというのが登場して筆者は研究室ではそれを好んで使っている。(家のPCは2017なので使えない...)

f:id:eminus:20190111203342p:plain

電卓のボタンを配置

ところで、このボタンには左上にラベルが一つとボタン本体にラベルが1つある。左上に付いているのがボタン本体の名前で、ボタン自体にのっかっている文字列はBoolean Textといって単純に人間が読むための文字列になっている。Visual Studioなどでプログラミングしたことがあれば、ボタンの名前とボタンのラベルは別々だったと思うが、そういうことである。

Event Structure

Event Structureではボタンが押されたかどうかを監視し続け、押されたタイミングでしかるべきプログラムが走るようにできる。

簡単な例を示そう

f:id:eminus:20190111204046p:plain

Event StructureでNumeric Controlの変化を読み取る

作る手順と解説は以下の通り(初心者向けを意識しているので人によってはくどい説明だと思うが、適宜読み飛ばして構わない)

  1. Numeric Controlを一つ作る
  2. Block diagramでEvent Structureを適当に作る
  3. Event Structureの枠を右クリックし、Add Event Caseを押す
  4. 出てきたウィンドウでどの部品がどうなったときを監視するかを選ぶ。今回は作ったNumeric ControlであるXのValue Changeという事象が起きた場合のプログラムを書いてみることにする。もちろん、マウスでクリックしたとき、とかキーボードのキーを離したときなどいろいろある。
  5. するとEvent Structureに新たなページができる。これはCase Structureと似たような感覚で、たくさんのブロックダイアグラムがまとまった状態になっており、検出されたイベントに応じて対応するプログラムが実行される。
  6. Value Changeのイベントの場合、便利なことに値が変わる前と変わった後の値が直接読み出すことができ、それはEvent Structure左側のOldValとNewValという端子からアクセスできる。
  7. 今回の例では引き算をしてdXというIndicatorに表示してみることにする。dXというIndicatorは引き算の部品の出力端子を右クリックし、Create Controlすれば簡単に作ることができる。今回の例ではEvent Structureの中でdXに表示しても一旦外に引き延ばしてからdXに表示しても(示した例は後者)どちらでも良い。

実行してみるとイベントの待機状態に入る。何もしなければいつまでも待ち続けるが、Xの値を変えた瞬間、dXが表示されプログラムが終了するだろう。何が起きているかと言えば、

  1. VIを実行するとEvent Structureブロックの実行に取りかかる
  2. デフォルトの状態では待機時間の制限なく(i.e. タイムアウトなしで)登録されているイベントが起きるまで寝ている
  3. Xが書き換わると起床して該当するイベントのページにあるプログラムが実行される
  4. これが終わるとEvent Structureの実行は終わるのでそのままVIも終了する

ここが筆者も初めてEvent Structureを見たときに誤解したポイントで、Event Structureは一度に一つのイベントしか処理できず、しかもその後2つめのイベントが来てもそれは処理しない。

ならどうするか

結論から言うとWhileループで囲んでしまえば良い。つまり、一度に処理できるのは一つのイベントだけだが、ループを回せば何度でもEvent Structureを走らせることができる。筆者はほとんどの場合でループで囲んで初めて御利益がある、と思っているのだが言い過ぎだろうか?

電卓の数字キーのイベント

話を電卓に戻すと、やりたいのは「ボタンが押された」というイベントを検出することと、「どの数字が押されたか」を知ることである。今まで述べた様に、ボタンが押されたことを検出するのはAdd Event CaseであるボタンのMouse Upのイベントを使えば良いのだが、どの数字を押されたかを上手くやる方法は少し悩んだ。

すぐに思いつく方法はイベントを10種類登録して、0のボタンの時は0の処理、1なら1、...等とやれば良いのだが、さすがに10個もあると冗長すぎて面倒くさがりの筆者は2個くらいコピーしたところで飽きてしまった

f:id:eminus:20190111213311p:plain

0-9と.のイベントを一括で処理する部分

別な方法としてはButton 0からButton 9までどれかのボタンが押されたら実行される共通のイベントケースを作っておき、押されたボタンのラベルの文字列から場合分けをするという方法がある。Event Structure中にある端子を眺めているとCtlRefというこれに便利そうな出力があるのに気づく*2。これはControlのありとあらゆるPropertyやMethodにアクセスするためのポインタのようなもので、イベントが起きると具体的にどのボタンが押されたかを教えてくれる。ただ、これはボタンのオブジェクトへの参照を返すので直接読んでもラベルは入手できない。(オブジェクト指向をあまり知らない人のために説明すると、CtlRefから返ってくるのはボタンのサイズ、場所、色などボタンの属性が全部固められた情報であって、今ほしいボタンのラベルはその一部なので、ワンクッション挟まないとラベルを入手できない。その方法を以下に書いている)

LabVIEWでは細かいプロパティなどは端子を右クリックした先のCreate->Property for ... Classの中にある。今回はその中のBoolean Text -> Textというのを選べば良い。選ぶと、いままで扱っていない長方形が出てくると思う。これをEvent Structureの中に配置してプログラムを書き始める。

できた長方形は2入力、3出力のブロックになっている。入力はボタンのオブジェクトへの参照とエラー入力(これは今のところ無視して良い)、出力は入力されたボタンへの参照と同じ元とエラー出力(これも無視して良い)、そしてほしかったラベルの文字列になっている。エラーの入出力とオブジェクトの参照の出力は今は使わなくて良いので無視すると、「オブジェクトへの参照を受け取ってラベルの文字列を返す」という長方形ブロックであることが理解できる。

文字を数字に変換

普通ならscanf的な関数で数字に変換するところだが(実際LabVIEWにもそのような部品(サブVI)が存在する)、ひねくれ者の筆者はこういうときはASCIIコードに変換して48を引くということをする(個人用以外でまねをしてはいけない)。これはちょっとしたメリットもあって、0-9だけでなく小数点「.」も条件分岐無しで同じイベントで処理できてしまう。

具体的にどういう構造になっているかというと

  1. 文字を受け取り文字列型から8bit符号無し整数の配列に変換する
  2. 8bit符号無し整数の配列から最初の要素を取り出す
  3. 型変換を行い、8bit符号有りの整数にする
  4. そこから定数48を引く。このマジックナンバー48は文字'0'のASCIIコードで、0から9はASCIIコード上で連続しているので48を引けば数字に変換できる。ちなみにドット'.'は0の2つ前なので、-2が出てきたときはドットが押されたと思えば良い

まとめ

  • Event StructureもCase Structure同様に複数のブロックダイアグラムを分けて実行でき、登録したイベントに応じて条件分岐される
  • Event Structureは一回の実行で一つのイベントしか処理しないため、よくWhile Loopと一緒に使う
  • Event Structureの左側に出てくる端子は使い勝手が良いものが多いので眺めていると幸せになれることがあある

たくさんボタンがある場合の場合分けの仕方については、いろいろやり方があると思うが、これより一般的だったり、エレガントな方法があればコメント欄でご教授ください

*1:User Eventが4つ並列なのは自分でもどうかなぁと思っていてTwitterデモ指摘を受けたのだが、実のところはUser Eventというのを使ってみたかったので無理矢理取り入れてみた、というのが正直な理由

*2:知っていたように書いているがいろいろ試行錯誤した。最初はボタンを全部クラスタに突っ込んでCluster to Arrayでbooleanの配列にしてごにょごにょ、等とやったが、なんかしっくりこないのでやめた

LabVIEWで電卓を作る(4): 電卓の仕様について

前回までごく基本的なことを解説した。

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

 

eminus.hatenablog.com

 

このさきちまちま解説しても良いのだが、最初にどーんと完成形を見せてしまおうと思う。(正直に言うと、作り始めたらスクリーンショットを取るのが面倒になって一気に作ってしまったというだけなのだが)

以下に足し算をしている様子を動画にしてみた。なにげにYouTubeにアップするのが初めてだったりする


LabVIEWで電卓をつくって1から10まで足してみた

ここでは足し算しかやっていないが四則演算はすべて対応している。また、イコールを連打すると前の演算を繰り返す機能(仕様?)も再現してある

電卓の仕様を考える

いわゆる普通の「電卓」の動作は考えていくと思っているほど単純ではない。例えば足し算1+2をする場合

[1]→[+]→[2]→[=]

とキーを押すと以下のような作業をしていることになる

  1. 初期状態では画面に0、もしくは前回の計算結果が表示されている
  2. キー[1]が押されたので画面に1を表示する
  3. キー[+]が押されたので画面の数字を一旦待避させておき、[+]が押されたことを記憶しておく
  4. キー[2]が押されたので画面の表示を2に更新する
  5. キー[=]が押されたので待避させていた数字、画面に表示されている数字、記憶しておいた演算子の種類を使って計算を行い、結果を画面に表示する

目標

動画に示したプロトタイプには実装していない機能も含め、Windows 10標準の電卓(の「標準」モード)

数字の入力と演算

基本的にはテンキーのボタンを作っておいて、ボタンが押されたら表示されている数字の後ろに一桁追加するという作業をすれば良いが、例外処理として

  • 二つ目の小数点が入力された場合、その小数点は無視する
  • 0が入力された場合、もともと0が表示されていた場合は無視する

必要がある。[=]を押して画面に数字が表示されている場合、次に数字が入力された場合画面をクリアしなければならない。

(例1)1+2+3=1+2= →1+2+3=のあと6が表示され、次に1を押しても61にはならない。最終的には3が表示される

(例2)1+2+3=+1+2= → 1+2+3=のあと6になるのは同じだが、+を押してから1+2をすると、6+1+2をして9になるべき

0除算

LabVIEWの場合0除算してもNaNやInfなどと表示してくれるので気にしないことにする。

(ちゃんと確認してないが確か0/0はNaNで、1/0みたいなのはInfだったと思う)

 

入力した演算子の取り消し

これを書きながら気づいたが、動画に示したやつにはバグがあって、0+-1=としたときに-1と表示してくれない。つまり演算子が連続して入力された場合、演算子のフラグを上書きしないといけない

前の演算を繰り返す

0+1=====のように入力した場合ほとんどの電卓は5と表示するはず。これは最後の演算が+1ということを覚えており、=が続く限り表示値+1をし続けるという仕様にする必要がある。

まだ実装していない機能

  • 1++=で2と表示する
  • 1++==で3
  • 正負反転のボタンをつける
  • モリー(MR, MC, MS, M+, M-)
  • ルート
  • 2乗
  • 1/x
  • %キー (使ったことないが...)

 

 

第5回はこちら:

 

eminus.hatenablog.com

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

LabVIEWで電卓を作る(2): データ型

今回は条件分岐の話を書こうと思っていたが、その説明をするにはデータ型にどんな問があるか述べておいた方が良いと思ったので、まずはデータ型についてざっくり紹介する。配列とクラスタは別の回にまとめて説明しようと思っているので、今回はほとんど説明しない。

前回も書いたように、LabVIEWでは基本的に変数がFront panelの部品と紐付いている。なので、どんな部品があるかを眺めているとどんな変数があるかが大体分かる

第一回はこちら:

eminus.hatenablog.com

単一要素

数値

数値の部品はいろいろな外見のもの(テキストボックスみたいなのもあればダイヤルみたいなものも)があるが、それらは全部数字。数字と言っても、PC上で扱う以上、整数と浮動小数点数(≒小数)だったり、二進数の桁数(8, 16, 32, 64ビット)などいろいろな種類がある。これら全部ひっくるめて数値(numeric)に分類される。デフォルトでは倍精度(double)になっているはず。

明示的に型を指定したい場合(例えば測定機器と通信する場合、ダイナミックライブラリを呼び出す場合、はたまた大きな数字を扱う場合など)、部品を右クリックしてRepresentationメニューから選べる

f:id:eminus:20190109192337p:plain

数値の型選択

筆者はdouble, int, unsigned intあたりは使うが、そのほかは全く使ったことがない。

文字列

String & Pathの中にある。普通のテキストボックスが2種類(制御器=control、表示器=indicator)とコンボボックス(リストが表示されるが、読み出すときは選択された文字列が返ってくる)がある。

ファイルパス

文字列と同じくくりにあるが独立した変数の型としてファイルパス型がある。

真偽値(boolean)

trueとfalseの2値だけをとる型。これは単なるON/OFFを制御・表示するだけでなく、押しボタンもこのジャンルに分類される。下図右側3つは見た目が違うだけで論理的には全部true/falseとして読み出せる。

筆者はスライドスイッチはどっちがONかよく分からなくなるのであまり使わないようにしている。もし使うときはラベルを表示させておくと良い。

f:id:eminus:20190109193601p:plain

文字型(左上)、ファイルパス(左下)とboolean(右)

複数要素の型

配列

もちろんLabVIEWでも配列を避けて通ることはできない。配列はLabVIEW上のどんな型でも配列にすることができる(数値配列、文字配列、booleanの配列、n次元配列、クラスタの配列、...)。これは別途説明しようと思う

クラスタ

これも別途説明するが、C言語で言うところの構造体みたいなやつ。複数の変数(配列や別のクラスタでも良い)を1つに固めるために使う

 

第三回はこちら:

eminus.hatenablog.com