連載
加速度センサーを使い、「人の動きと連動して動作するUWPアプリ」を作る:ラズパイ3&Toradex、Windows 10 IoT Coreで楽しみながら検証するIoT実践入門(4)(2/3 ページ)
ITエンジニアに向け、「ビジネスに貢献するIoT活用」の第一歩を踏み出す「ひらめき」を得てもらうための本連載。今回は、IoTハードウェアと加速度センサーを使い、Unityで作成したUWPアプリを操作するシステムを作ってみよう。
「AccelerometerScript.cs」「TextScript.cs」のコードを記述する
今回は、マイクロソフトのGitHub Pagesに登録されているWindows 10 IoT Coreの開発者向けサンプルである「samples-develop.zip」の、Accelerometerフォルダにあるサンプルコードをベースに、今回のUWPアプリ用に追記・改変していくことにする。
Unity 5.3で書き出したUWPのプロジェクトファイルをVS2015で開き、「AccelerometerScript.cs」を以下のように修正する。コードの文字列はかなり長いが、該当するコードの近くにコメントアウトで解説を追記しているので、必要に応じて参照してほしい。
using UnityEngine; using System; using System.Threading; using Windows.Devices.Enumeration; /*アプリケーションから内蔵回路 (i 2 c) バスを介して接続された周辺機器との通信に使用する型が含*まれているWindows.Device.12c名前空間を読み込む*/ using Windows.Devices.I2c; /*doube型の変数X、Y、Zを定義したAccelerationという構造体を定義しておく*/ struct Acceleration { public double X; public double Y; public double Z; }; /*Protocol列挙体を宣言してI2Cで初期化しておく*/ enum Protocol { I2C }; public class AccelerometerScrpt : MonoBehaviour { /*プロトコルにはI2Cを指定*/ private Protocol HW_PROTOCOL = Protocol.I2C; /*各レジスタのアドレスについては下記のPDFの22ページ目の「レジスタ・マップ」を参照のこと*/ /* http://akizukidenshi.com/download/ds/freescale/ADXL345_jp.pdf*/ /* 電力制御レジスタのアドレスを指定*/ private const byte ACCEL_REG_POWER_CONTROL = 0x2D; /* データ形式レジスタのアドレスを指定 */ private const byte ACCEL_REG_DATA_FORMAT = 0x31; /* X軸のデータレジスタのアドレスを指定*/ private const byte ACCEL_REG_X = 0x32; /* Y軸のデータレジスタのアドレスを指定*/ private const byte ACCEL_REG_Y = 0x34; /* Z軸のデータレジスタのアドレスを指定 */ private const byte ACCEL_REG_Z = 0x36; /*今回使用する加速度センサーのアドレスを指定*/ private const byte ACCEL_I2C_ADDR = 0x53; private I2cDevice I2CAccel; private Timer periodicTimer; /*TextScript.cs内でも使用する変数であるため、グローバルな変数として宣言しておく*/ /*各変数には加速度センサーのX、Y、Zの値が格納される*/ public static double xValue; public static double yValue; public static double zValue; /*四次元数の回転を表すメンバー変数accelerationを宣言する*/ private Quaternion acceleration; void Start() { /* I2Cバス、加速度計、およびタイマーを初期化するInitAccel()メソッドを実行する */ InitAccel(); } void Update() { /*別スレッドからAccelerometerValueメソッドを1秒ごとに呼び出す*/ Invoke("AccelerometerValue", 1.0f); } /*Update()メソッドより常に呼び出されるAccelerometerValueメソッド*/ private void AccelerometerValue() { /*float型に変換した加速度センサーの各値を指定し、その値に応じてCubeを回転させる*/ /*引数には、X、Y、Z、Wの値が必要だが、今回Wの値は不要なので、0.0fと指定しておく*/ acceleration.x = (float)xValue; acceleration.y = (float)yValue; acceleration.z = (float)zValue; transform.rotation = new Quaternion(acceleration.x, acceleration.y, acceleration.z, 0.0f); } /* I2Cバス、加速度計、およびタイマーを初期化する処理 */ private void InitAccel() { /* プロトコルと加速度計を初期化する */ switch (HW_PROTOCOL) { /*プロトコルがI2Cの時にはInitI2CAccel()メソッドを実行する*/ case Protocol.I2C: InitI2CAccel(); break; default: break; } } /*プロトコルがI2Cの時に実行される処理*/ private async void InitI2CAccel() { try { /*加速度センサーのアドレスを2cConnectionSettingsに指定する*/ var settings = new I2cConnectionSettings(ACCEL_I2C_ADDR); /*バス速度を400 kHzに指定する */ settings.BusSpeed = I2cBusSpeed.FastMode; /* システム上のすべてのI2Cコントローラーを返す、セレクタ文字列を取得する。 */ string aqs = I2cDevice.GetDeviceSelector(); /* 択されたバスコントローラとI2C設定された、I2Cデバイスを作成する。*/ var dis = await DeviceInformation.FindAllAsync(aqs); I2CAccel = await I2cDevice.FromIdAsync(dis[0].Id, settings); if (I2CAccel == null) { return; } } catch { return; } /*加速度計を初期化し、2バイトの書き込みバッファを作成する*/ /*0x01のセットは±4GSの範囲になる */ byte[] WriteBuf_DataFormat = new byte[] { ACCEL_REG_DATA_FORMAT, 0x01 }; /*0x08は、測定モードに加速度計を置く*/ byte[] WriteBuf_PowerControl = new byte[] { ACCEL_REG_POWER_CONTROL, 0x08 }; /* レジストリ設定を書きこむ */ try { I2CAccel.Write(WriteBuf_DataFormat); I2CAccel.Write(WriteBuf_PowerControl); } /* 書き込みに失敗した場合は実行を停止する */ catch { return; } /*100ms毎のデータを読み取るようにタイマーを作成、初期化する*/ periodicTimer = new Timer(this.TimerCallback, null, 0, 100); } /*タイマーから呼び出されるTimerCallback()メソッド処理*/ private void TimerCallback(object state) { /* 読み取りおよびフォーマット加速度計データ処理 */ try { /*Acceleration型のaccel変数にReasAccel()メソッドの戻り値を格納する*/ Acceleration accel = ReadAccel(); /*各変数に、戻り値からX、Y、Zを取得して格納する*/ xValue = accel.X; yValue = accel.Y; zValue = accel.Z; } catch { return; } } /*TimerCallbackから呼び出されるReadAccell()メソッド処理*/ private Acceleration ReadAccel() { /* ADXL345は、1024のユニークな値を与える10ビットの解像度を持つ*/ const int ACCEL_RES = 1024; /* ADXL345は、8Gの合計ダイナミックレンジを持っている*/ const int ACCEL_DYN_RANGE_G = 8; /*Gユニットにrawのint型の比の値を設定する*/ const int UNITS_PER_G = ACCEL_RES / ACCEL_DYN_RANGE_G; byte[] ReadBuf; byte[] RegAddrBuf; /* 加速度センサーからの読み込み。第1のX軸レジスタのアドレスを書き込み、 *ReadBufにI2Cの軸を読みむ*/ switch (HW_PROTOCOL) { case Protocol.I2C: /*32バイトの軸を得るために6バイト順次読み出す*/ ReadBuf = new byte[6]; /*読み込んだアドレスを登録する*/ RegAddrBuf = new byte[] { ACCEL_REG_X }; I2CAccel.WriteRead(RegAddrBuf, ReadBuf); break; default: ReadBuf = new byte[6]; break; } /* システムのエンディアンを確認し、必要に応じてバイトを反転する*/ if (!BitConverter.IsLittleEndian) { Array.Reverse(ReadBuf, 0, 2); Array.Reverse(ReadBuf, 2, 2); Array.Reverse(ReadBuf, 4, 2); } /* rawの16ビットデータ値を得るために、各軸(X、Y、Z)の2つの8ビットバイトを連結する*必要がある */ short AccelerationRawX = BitConverter.ToInt16(ReadBuf, 0); short AccelerationRawY = BitConverter.ToInt16(ReadBuf, 2); short AccelerationRawZ = BitConverter.ToInt16(ReadBuf, 4); /*rawの値をGに変換する*/ Acceleration accel; accel.X = (double)AccelerationRawX / UNITS_PER_G; accel.Y = (double)AccelerationRawY / UNITS_PER_G; accel.Z = (double)AccelerationRawZ / UNITS_PER_G; /*accelを戻り値とする*/ return accel; } }
リスト1 修正した「AccelerometerScript.cs」の中身
修正箇所は以下の通りだ。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 「Raspberry Pi 3」で早速チェック──「IoTハードウェア」を準備する
ITエンジニアに向け、「ビジネスに貢献するIoT活用」の第一歩を踏み出す「今後のひらめき」を得てもらうための本連載。初回は、登場間もない「Raspberry Pi 3」を中心に、IoTハードウェアとWindows 10 IoT Coreを準備するまでを解説する。 - 「Raspberry Pi 3」が登場。Windows 10 IoT Coreは早速サポートを表明
無線通信モジュール付きのRaspberry Pi 3が登場。搭載チップの性能も向上している。マイクロソフトは発売当日にWindows 10 IoT Coreでのサポートを表明している。 - 第1回 Windows IoTを始めよう
見聞きしない日はないほど流行している「IoT」。でも、どうやったら使えるのか? 本連載では読者諸氏が慣れ親しんだWindowsのIoT版を使って、IoTを実践してみる。まずは概要とインストールから始めよう。