ブレッドボードの準備ができたら、次はVisual Studioでプログラムを作成してみる。まず[ファイル]メニューの[新規作成]−[プロジェクト]で新しいプロジェクトを開始する。利用するテンプレートは前回と同じく、[Visual C#]−[Windows]−[ユニバーサル]の中にある「空白のアプリ(ユニバーサルWindows)」を利用する。
プロジェクトを作成したら、最初にソリューションエクスプローラーで「参照の追加」を実行する。次の手順を実行するか、[プロジェクト]メニューの[参照の追加]を実行する。
参照マネージャーが起動するので「Windows IoT Extensions for the UWP」を選択して追加しておく。これを追加していないとWindows.Devices.Gpioクラスが利用できない。
以上でVisual Studioのプロジェクトの準備は完了である。後はページのデザインやコードの追加を行えばよい。
今回のプログラムだと、まずXAMLのデザイナー画面でLEDを表す円(Ellipse)を描き、スイッチの状態などに応じて描画を更新するコードを追加していく。GUI描画などの部分は通常のWindowsプログラミングと同じだが、GPIOポートを利用する部分はWindows IoT独自のクラス呼び出しなどが必要なので、先ほどのWindows IoTのサンプルプログラムを参考にして記述していく。
プログラムの詳細はコードを見ていただくとして、ここではWindows IoTに固有の部分だけをいくつか取り上げ、簡単にコメントしておく。
Raspberry PiのGPIOを利用するためには、最初にGPIOピンの初期化作業が必要になる。利用するピンごとに入力にするのか出力にするのかを決め、出力にするなら初期状態(HにするかLにするか)もセットする。入力にするなら、Raspberry Piに内蔵されているプルアップ抵抗を利用するかどうかなどを設定する。今回のプログラムでは、LEDの出力用にピンを3本、スイッチの入力用にピンを2本利用している。
// LED駆動用(出力用)にGPIOピンを初期化する例
// LED pin
pinLedR = gpio.OpenPin(PIN_LED_R);
pinLedRValue = GpioPinValue.Low;
pinLedR.Write(pinLedRValue);
pinLedR.SetDriveMode(GpioPinDriveMode.Output);
Windows IoTのプログラムは、例えばデータを取得しながらずっと動くだけ、といったものが少なくない。これを実現するために、Windows IoTのサンプルでは、タイマーによる周期的なタスクの繰り返しや、イベントによるメッセージの通知などが使われている。この辺りは定型なので、サンプルからコピーして使うとよいだろう。
今回のプログラムでは、青色LEDはスイッチに関係なく、この周期的なタイマーイベントを使って点滅させている。
ユーザーがスイッチをオン/オフすると、GPIO端子の入力レベルがHigh(1)もしくはLow(0)になるので、それを読み取ればスイッチの状態が分かるのだが、現実のスイッチ部品では「チャタリング(chattering)」という現象が起きるため、その対策が必要である。チャタリングとは、スイッチをオン/オフしてもすぐに値が落ち着くことなく、しばらく「バタバタ」と暴れている状態のことである。スイッチの接点が汚れたりしていると特に激しくなる。
以下にチャタリングの例を示す。これは今回使用した回路にチャタリングが多めのスイッチを接続して、GPIO端子の部分をオシロスコープで見たところだ。信号レベルが落ち着くまでに4msec弱かかっているし、その間に何度もHighとLowレベルの変化を繰り返している。
チャタリング対策の方法はいろいろあるが、一般的には、信号の変化を検知してから数msec〜数十msecだけ入力信号を無視し、その後改めて信号入力を検知し直す、という処理を行うことが多い。
Windows IoTでは、スイッチ入力をイベントとして取り扱うようになっているが、さらにスイッチ入力の場合は、指定された時間だけスイッチ入力イベントの処理を無視するという機能が用意されている。これを使ってチャタリングを除去する。
// Switch pin
pinButtonR = gpio.OpenPin(PIN_BUTTON_R);
pinButtonR.DebounceTimeout = TimeSpan.FromMilliseconds(20); // 20ミリ秒待つ
pinButtonR.ValueChanged += pinButtonR_ValueChanged; // スイッチ入力イベントの登録
pinButtonR_ValueChanged()は、スイッチ入力イベントがあった場合に呼び出されるルーチンである。今回のスイッチ回路では、、信号の「エッジ(変化)」が「High→Low」ならスイッチが押された、「Low→High」ならスイッチが離された、と判断できる。
サンプルプログラムでは、赤のスイッチでは立ち上がりと立ち下がりのエッジを処理しているが、緑のスイッチは立ち下がりエッジのみを処理している。そのため、赤のスイッチだと押している間だけLEDが点灯するが、緑のスイッチは、押すたびに点灯と消灯が切り替わる。
今回はRaspberry Pi 2 Model Bにパーツを接続して制御してみた。といってもLEDやスイッチは、デジタル的にオン/オフするだけの非常にシンプルなデバイスであり、プログラム的にも特に面倒なことは何もない。次回はもう少し複雑な制御が必要なデバイスを接続してみよう。
Copyright© Digital Advantage Corp. All Rights Reserved.