検索
連載

加速度センサーを使い、「人の動きと連動して動作するUWPアプリ」を作るラズパイ3&Toradex、Windows 10 IoT Coreで楽しみながら検証するIoT実践入門(4)(2/3 ページ)

ITエンジニアに向け、「ビジネスに貢献するIoT活用」の第一歩を踏み出す「ひらめき」を得てもらうための本連載。今回は、IoTハードウェアと加速度センサーを使い、Unityで作成したUWPアプリを操作するシステムを作ってみよう。

Share
Tweet
LINE
Hatena

「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」の中身

 修正箇所は以下の通りだ。

photo
photo
photo
photo

 続いて、「TextScript.cs」のコードも記述する(次ページのリスト2)。

Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る