
Introduction
LabVIEWのCommunity Editionが出てこの界隈が賑わっている。個人的にはLabVIEWが本領を発揮するのは外部機器と通信をしてデータのやりとりをする時だと思っているが、なかなか個人レベルでやれKeysightのマルチメータだ、GPIBの計測器だ、なんかを持っている人は、そんなに多くはいない(そういう人も居るのは知っているが大多数ではないであろう)。外部に通信する手段として最も簡単なのはGPIO(general purpose I/O; 汎用入出力)であろう。Raspberry PiやBeagle Bone BlackなどのLinuxが動くシングルボードコンピュータなどはGPIO端子が簡単に手に入るものの一つであり、実際すでにLabVIEWを用いてLチカを動かしてみたという報告がされている[1,2]。GPIOとはその名の通りデジタル値を入出力する端子のことであり、プログラム的な視点からは値を「書き込む」ことでデジタル値を出力し、「読み込む」ことでデジタル値を入力する。デジタル値を出力するというのが具体的に何を意味するか、であるが、暗黙の了解として2進数の1が電源電圧(5Vや3.3V)、0が電圧0Vを意味している。つまり1を書き込むというのは例えば5Vを出力すると言うことを物理的には意味する。読み込みについてはその逆である(2.5V以上なら1として読み、以下なら0として読む)。
[1]https://www.denshi.club/pc/labview/labview-makerhubraspberry-pil3.html
[2] https://qiita.com/ktyubeshi/items/4e23fd2e9960f7c021f2
このような結構アナログな操作を、WindowsやLinux、macといった通常のPCに直接GPIOをつけることは大変そうに思えるが、無理ではない。かつてはプリンタ用のパラレルポートがその役割を果たしていたが、今時そんな古いポートがついている化石の様なPCではLabVIEWのCommunity Editionは動作しないだろう。このようなパラレルポートに替わって最近ではUSB端子が一般化しているが、もちろんUSBケーブルをぶった切って信号線を出してきたところで、これらをGPIOとして使うことはできない。ではUSBをGPIOに良い感じに変換できるアダプター的なものはないのかという話になるが、まさにその用途として(も)用いることのできるチップがFT232RLというICである[3]。
[3] https://www.if.t.u-tokyo.ac.jp/~mita/EInfo/JSAP2015/01-FT245-LED.html
本来、このICはUSB-シリアル変換用のICとして使われる。シリアルというのはシリアル通信(RS-232C)のことを言っていて、見たことがある人ならLabVIEWを含むWindows上(Linux等も)からはCOMポートとして見えるあれ、といえば分かると思う。非常に便利なことに、本来USB-シリアル変換ICであるこのチップはシリアル通信の制御端子をそれぞれプログラム的に、独立に制御するためのライブラリも提供されている。そこで本稿では、LabVIEWからFT232RLを操作しGP(I)Oとして用いる例としてLチカを実装してみたのでそれをまとめる。
回路の準備
当然すぐにばらす回路なのでブレッドボード上に配線する[4]。FT232RL自体は表面実装のチップであるため、ブレッドボードには直に刺さらないが、かの有名な電子部品屋である秋月電子でモジュールという形で扱いやすい変換基板上に実装されたものが販売されている[5]。
[4]ブレッドボードについては例えばGoogleで一番上に出ているのは https://denshi-kousaku.nazotoki-k.com/kiso/eic-801.htm 等
[5]http://akizukidenshi.com/catalog/g/gK-01977/
- ブレッドボード 1個
- AE-UM232R 1個
- USB-mini A – USB-Type Aケーブル 1本
- 好みのLEDと電流制限抵抗 8組
- ジャンパーケーブル 9本くらい?
知っている人には自明だが初めての場合は自明でないと思うので、下記について念を押しておく。ここには出力ポート8本あるが、後のプログラムでは全部ひとまとめに1バイト(8ビット)として扱う。例えば2進数で0000 0001を書き込んだ場合TXDという端子だけに電源電圧が出力される。同様に16進数でFF (2進数で1111 1111)を書き込めば全部ONとなる。

LabVIEWプログラミング
まずFT232RLをGPIOで操作するためのドライバとライブラリをまずは入手する。
https://www.ftdichip.com/Drivers/D2XX.htm
より、インストーラーを用いてドライバーをインストールする。また、対応するWindowsのZIPファイルもダウンロードし解凍しておく。中にDLLファイルがあり、それを使用する。なお、LabVIEW Community Editionは32bit版であるが、ライブラリ自体はOSのビット数に応じてx86かx64を選択する(はず)。
今回のプログラミングで鍵となるのは、Block diagramから関数パレットの中にあるConnectivity → Libraries & ExecutablesのCall Library Functionである。平たく言えばDLLを呼び出すための部品である。
まずは実際のライブラリ関数の操作を行う前に、LabVIEW上でDLLを呼び出す方法について自分の知る範囲で解説する。Call Library Functionでは、どのDLLを参照し、どのDLL関数を用いるかという設定(a)と、手動で引数と返値の型を適切に設定(b)する必要がある。いずれもダブルクリックで開く画面から設定可能である
(a) DLL関数の選択

- Library name or path: 先に述べたとおり、LabVIEW 2020 Community Editionの場合おそらく32bit版なので、ダウンロードし展開したライブラリの内i386(32bit)版のDLLを選択する。なお、amd64内にある64bit版のDLLを選択するとビット数が違う旨怒られる。
- Function nameはコンボボックスから選択する。
- Calling conventionはよく知らないがとにかくこのDLLの場合WINAPIを使用しないとエラーで実行できない。デフォルトはC
(b) 返値、引数の設定


- まず左側にDLL関数の返値と引数の一覧が表示されている。デフォルトでは返値のみが存在する。
- 返値(return typeと名前がついているところ)は省略することができない。voidならTypeとしてvoidを選択。ftd2xx.dllの場合、ftd2xx.hというヘッダーファイルを読むとFT_Open関数のプロトタイプ宣言がされているため、これを参考に返値の型を設定したり、必要に応じて引数を追加する
- FT_Openの例では以下の通りである
- 返値はFT_STATUSであり、ヘッダファイル冒頭にULONGとあるため、unsigned long、つまり32bit のunsigned intと設定した
- 次のdeviceNumberはint型であるため、32bit signed intで良い
- 最後のpHandleはよく読むとPVOID型へのポインタであり、よく分からなかったのでとりあえず32bit intとしておいた。本当はsizeofで確認しないとならないが、これについても動くので大丈夫だと思う。
- ここで最後のpHandleはポインタで渡しているためPassとしてPointer to Valueを選択する。これはCで言うところの&xで渡すことに対応する。LabVIEWでは定数か何かでメモリ領域を確保した状態で、Call Library Functionに接続するとこのメモリ領域へのポインタがDLLに渡される
GPIOプログラミング
FT232RLをGPIOとして用いるモードのことをbit bangモードという。この節では上記を踏まえLabVIEW上でbit bangモードでの出力を用いる方法について説明する。具体的な方法はC言語での実装を参考にしている[6]。
[6] 例えばhttps://ore-kb.net/wordpress/wp-content/uploads/2013/03/how_to_use_bitbang.pdf
- まずライブラリを初期化する。FT_Initialize(void) (後日注記:不要?)
- 接続をopenする。uint32_t FT_Open(int32_t device_number, int32_t *handle); ここで取得したhandleをは接続が切れるまで有効であり、接続IDのようなものである。(ようなものというか、そのもの)
- モードをリセットし、非同期bit bangモードとする。uint32_t FT_SetBitMode(int32_t handle, uint8_t mask, int8_t enable);
- 書き込む。uint32_t FT_Write(int32_t handle, uint8_t *buffer, int32_t length, int32_t *bytes_written);ここについては詳細を後述する
- 接続を閉じる。uint32_t FT_Close(int32_t handle);


データの書き込み、もとい電圧の出力にはFT_Writeという関数を用いる。引数は(筆者がかみ砕いて名前を変えたが)以下の通りである
- handle:確立した接続IDを表す数値
- buffer:書き込むデータ配列
- length:書き込むデータ配列の長さ
- bytes_written:書き込まれた長さ。ポインタ渡し(関数実行後書き換えられる)
なんで配列の長さを教えてやる必要があるのかと疑問に思う人も居るかもしれないが、C言語の配列には配列長の情報がないため、こちらから明示的に何個要素があるか教えてやらないとならない。ところで、今回は8bitの整数(各bitが各ポートに対応)を一度だけポートに出力すれば良いので、配列を書き込むと言っているが実際は要素数1の配列を書き込めばそれで済むため、見た目ほど面倒な事をする必要はない。単に書き込みたい8bit整数を準備し、Build Arrayを用いて要素が1つしかない配列をつくり、あとはlength=1としてFT_Writeを実行すれば良い

完成形

この例ではSTOPを押すまで50ms間隔(だいたい)でリフレッシュする。この辺を毎回書くのは面倒なので当然サブVI化する必要があるが、とりあえずテストとしては完了。
(最初はSnippetでアップロードしてたがDLLの参照フォルダ名にユーザー名が出てしまっていたのでスクリーンショットで)