先ほど作成した「SkeletonDanceScript.cs」のコードを修正する。
まず、VS2015のソリューションエクスプローラーの「参照」で右クリック→「参照の追加」を選択する。表示される参照マネージャーから、「Universal Windows」→「拡張」→「Windows IoT Extension for the UWP 10.0.10240.0」を選択する。選んだAPIがソリューションエクスプローラーの「参照」内に追加される(図1)。
ソリューションエクスプローラーから「SkeletonDanceScript.cs」を開く。最初は、エラーを示す赤い波線が幾つか表示されるが、気にしなくてもいい。
SkeletonDanceScript.csのコードを、以下のように追加修正する(リスト3)。
using UnityEngine; using System; using Windows.Devices.I2c; using Windows.Devices.Enumeration; using System.Threading; public class SkeletonDanceScript : MonoBehaviour { private I2cDevice ADT7410; private Timer periodicTimer; static public int Temperature; GameObject obj; void Start() { obj = GameObject.Find("skeletonDark"); InitADT7410(); } void Update() { if (Temperature >= 25) { obj.GetComponent<Animation>().Play("dance"); } else { obj.GetComponent<Animation>().Play("idle"); } } private async void InitADT7410() { string aqs = I2cDevice.GetDeviceSelector(); var dis = await DeviceInformation.FindAllAsync(aqs); var settings = new I2cConnectionSettings(0x48); settings.BusSpeed = I2cBusSpeed.FastMode; ADT7410 = await I2cDevice.FromIdAsync(dis[0].Id, settings); periodicTimer = new Timer(this.TimerCallback, null, 0, 1000); } private void TimerCallback(object state) { byte[] readBuf = new byte[2]; ADT7410.Read(readBuf); int valh = ((int)readBuf[0]); int vall = ((int)readBuf[1]); double temperature = CalcTemperature(valh, vall); Temperature = (int)(temperature); } private static double CalcTemperature(int valh, int vall) { int val = (valh << 5) + (vall >> 3); if (val > 4096) { val = -1 * (8192 - val); } double temperature = val * 0.0625; return temperature; } }
修正した「SkeletonDanceScript.cs」のポイントは以下の通りだ。
アプリケーションから内蔵回路(I2C)バスを介して接続された周辺機器との通信に使用するクラスの含まれる、Windows.Devices.I2c名前空間を読み込んでおく。
I2cDevice型のメンバー変数TMPSENSOR、Timer型のmyTimerメンバー変数を宣言。続いて、Unity 5.3内で宣言しておいたグローバルな変数Temperature、同じくUnity 5.3内で宣言しておいたGameObject型のobj変数を宣言している。
I2C関連の初期化処理を記述したInitADT7410();メソッドを実行する。
グローバルな変数Temperatureの値が「25以上」だったら(温度がセ氏25度以上だったら)、ガイコツキャラが踊る。それ以外の値では、キャラの動きが停止する。
// Raspberry Pi3上のI2Cコントローラーに関する情報を取得 string aqs = I2cDevice.GetDeviceSelector(); (1) // 上記で取得した情報文字列に一致するDeviceInformationオブジェクトを列挙する。 var dis = await DeviceInformation.FindAllAsync(aqs); (2) // ※I2Cデバイスセンサーの接続設定として、デバイスアドレスと速度を設定する。 var settings = new I2cConnectionSettings(0x48); (3) settings.BusSpeed = I2cBusSpeed.FastMode; (4) // ※上記の接続設定を使用して、I2Cコントローラー上のI2Cデバイスセンサーオブジェクトを取する。 TMPSENSOR = await I2cDevice.FromIdAsync(dis[0].Id, settings); (5)
上記5行の処理は、I2Cデバイスを使用する際のテンプレートとなる処理なので覚えておこう。
と記述している箇所のアドレスを変更すれば、他のセンサーにも応用ができる。デバイスのアドレスについては、各センサーのデータシートまたはPDFマニュアルなどに記載されているはずだ。筆者が購入した温度センサーの説明書には、図2のように記載されていた。よって、アドレスには「0x48」を指定している。この他、Raspberry Pi 3の標準OSであるRaspbianにて、センサーを接続して「i2cdetect -y 1」を実行してもアドレスを取得できる
最後に、myTimer = new Timer(this.TimerCallback, null, 0, 1000);と記述して、1秒ごとにセンサーからの値を読み取るように、タイマー処理を実装する。
ここでは、1秒ごとにセンサーからの値を読み取っている。
グローバルな変数Temperatureに、変数temperatureの値を格納する。この処理によって、Unity 5.3上では取得データがないために「0」と表示されていた場所に、現在の温度がリアルタイムに表示される。
温度データを含む2バイト(0x00、0x01)を、InitADT7410メソッド内のADT7410から読み出している。高位の1バイトをvalh、低位の1バイトをvallとして、CalcTemperature()で実際の温度に変換している。
ここでは、valhを左へ5ビット、vallを右へ3ビットシフトしている。戻り値として、現在の温度の入ったtemperatureを返している。なお、シフト演算はかなり難しいので、以下の解説サイトも参照するとよいだろう。
(参考サイト)シフト演算について
Copyright © ITmedia, Inc. All Rights Reserved.