連載
加速度センサーを使い、「人の動きと連動して動作する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を実践してみる。まずは概要とインストールから始めよう。

