2
1

More than 5 years have passed since last update.

[C#/WinIoT/I2C] ラズパイ+WindowsIoTCore+C# で9軸センサ(MPU-9150)の値をとる

Last updated at Posted at 2019-08-26

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

Windows Iot Coreを使って、I2Cに接続するデバイスと通信したい。
たまたま手元にある掲題の9軸センサで、I2Cで通信する練習をしたい。

作成作業

下記の機材とソフトを使用する。

  • ラズベリーパイ3
  • 9軸センサーモジュール(共立のKP-9150/InvenSenseのMPU-9150センサを搭載)
  • VisauStudio2019(UWP/C#)

また、下記のようなイメージで作業を進める。

  • 回路作成。ラズパイ3とセンサをつなげる回路を作成
  • センサとのやり取りの流れ確認。何をどう読み書きすればよいか確認
  • プログラム作成。センサとI2Cで通信するWinIoT上で動くUWPプログラムを作成

回路作成

下記のような回路を作成する。
image.png

image.png

センサとのやり取りの流れ確認

下記のような手順で、通信を行う。

  • I2Cで通信するための準備
    • Windows IoT Extensions for UWPを参照に追加する
    • usingの追加
  • イニシャライズ通信
    • アドレス0x75を指定して読み込み
    • アドレス0x6Bに0x00を書き込み
    • アドレス0x37に0x02を書き込み
  • センサ値の取得
    • アドレス0x3Bを指定して読み込み

プログラム作成

Windows IoT Extensions for UWPを参照に追加する

  • プロジェクトの参照を右クリックし、[プロパティ]をクリック
  • 「Universal Windows」の「拡張」の中から、Windows IoT Extensions for UWP(今回は10.0.15063.0)を選択し追加 image.png

usingの追加

I2Cデバイスの制御に必要な、下記のusingを追加する。

  • using Windows.UI.Xaml.Controls;
  • using Windows.Devices.Enumeration;
  • using Windows.Devices.I2c;

イニシャライズ通信

上の[センサとのやり取りの流れ確認]のところで確認した流れを実装する。

MainPage.xaml.cs
private async void InitI2CAccel()
{
    // すべてのI2Cデバイスを取得するためのセレクタ文字列を取得
    string aqs = I2cDevice.GetDeviceSelector("I2C1");

    // セレクタ文字列を使ってI2Cコントローラデバイスを取得
    var dis = await DeviceInformation.FindAllAsync(aqs); 

    if (dis.Count == 0)
    {
        Text_Status.Text = "I2Cコントローラデバイスが見つかりませんでした";
        return;
    }

    // I2Cアドレスを指定して、デフォルトのI2C設定を作成する
    // private const byte ACCEL_I2C_ADDR = 0x68;
    var settings = new I2cConnectionSettings(ACCEL_I2C_ADDR);

    // バス速度を設定(FastMode:400 kHz)(指定しないと、標準設定(StandardMode:100kHz)になる)
    settings.BusSpeed = I2cBusSpeed.FastMode;

    // 取得したI2Cデバイスと作成した設定で、I2cDeviceのインスタンスを作成
    I2CAccel = await I2cDevice.FromIdAsync(dis[0].Id, settings);

    if (I2CAccel == null)
    {
        Text_Status.Text = string.Format(
            "スレーブアドレス {0} の I2C コントローラー {1} はほかのアプリで使用されています。他のアプリで使用されていないか、確認してください。",
            settings.SlaveAddress, dis[0].Id);
        return;
    }

    // ジャイロセンサ(MPU-9150)の設定を行うための通信
    try
    {
        // 送信用バッファ
        byte[] WriteBuf;
        // 受信用バッファ
        byte[] ReadBuf;

        // アドレス取得(イニシャルに必須ではない。どこのサンプルにも書いてるので一応やっとく)
        WriteBuf = new byte[] { 0x75 };
        ReadBuf = new byte[1];
        I2CAccel.WriteRead(WriteBuf, ReadBuf);

        // センシング開始要求(レジスタ0x6Bに00を書き込み)
        WriteBuf = new byte[] { 0x6B, 0x00 };
        I2CAccel.Write(WriteBuf);

        // センシング開始要求(レジスタ0x37に02を書き込み)
        WriteBuf = new byte[] { 0x37, 0x02 };
        I2CAccel.Write(WriteBuf);
    }
    catch (Exception ex)
    {
        Text_Status.Text = "デバイスとの通信に失敗しました。: " + ex.Message;
        return;
    }

    // 初期化完了。100msごとにデータを採るためのコールバックを作成する
    periodicTimer = new Timer(this.TimerCallback, null, 0, 100);
}

これで、センサーに、通信開始を要求したことになる。

イニシャライズ通信の時に読んでるAPIについて

・I2CAccel.Write(WriteBuf);
引数の1バイト目に書き込みたいレジスタのアドレス、2バイト目以降にそのレジスタ以降に書き込みたいデータをいれておくと、書き込みを行ってくれる。

I2CAccel.WriteRead(WriteBuf, ReadBuf)
WriteBufに読み込みたいアドレス、ReadBufに呼んだデータのバッファを渡すと、WriteBufで指定したレジスタから読んだデータをReadBufに入れてくれる。
指定したレジスタアドレスから何バイト読むかは、バッファ(ReadBuf)のバイト数で決まる。
(var ReadBuf = new byte[14] としてたら、勝手に先頭から14バイト読んで入れてくれる))

レジスタ0x6Bに00を書き込み、レジスタ0x37に02を書き込みしている部分について
なぜこの2つに値を書き込むのか、忘れてしまった。(レジスタのデータシートを見ても、よくわからなかった)
一旦、MPU-9150ではお決まりの手順としてこのまま置いておく。
(後で調べる)

⇒19/08/26追記
0x6Bの方は「Sleep解除」(こちら参照)
0x37の方は「I2Cで磁気センサ機能(AK8963)へアクセスできるようにする(BYPASS_EN=1)」(こちら参照)

センサ値の取得

上のperiodicTimer = new Timer(this.TimerCallback, null, 0, 100);のところで、100msごとに呼ぶようにしたハンドラを実装する。

private void TimerCallback(object state)
{
    // 送信用バッファ
    byte[] WriteBuf;
    // 受信用バッファ
    byte[] ReadBuf;

    // アドレス取得
    WriteBuf = new byte[] { 0x3B };
    ReadBuf = new byte[14];
    I2CAccel.WriteRead(WriteBuf, ReadBuf);

    var task = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        Text_X_Axis.Text =      "加速度X:" + (ConvertSignedShortData2Decimal((short)ReadBuf[0] * 0x100 + (short)ReadBuf[1]) / 16384.0m).ToString("F1") + "";
        Text_Y_Axis.Text =      "加速度Y:" + (ConvertSignedShortData2Decimal((short)ReadBuf[2] * 0x100 + (short)ReadBuf[3]) / 16384.0m).ToString("F1") + "";
        Text_Z_Axis.Text =      "加速度Z:" + (ConvertSignedShortData2Decimal((short)ReadBuf[4] * 0x100 + (short)ReadBuf[5]) / 16384.0m).ToString("F1") + "";
        Text_Temperature.Text = "温度:"    + (ConvertSignedShortData2Decimal((short)ReadBuf[6] * 0x100 + (short)ReadBuf[7]) / 340.0m + 35.0m).ToString("F1") + "℃";
        Text_X_Axis_Gyro.Text = "Gyro X:" + (ConvertSignedShortData2Decimal((short)ReadBuf[8] * 0x100 + (short)ReadBuf[9]) / 131.0m).ToString("F1") + "";
        Text_Y_Axis_Gyro.Text = "Gyro Y:" + (ConvertSignedShortData2Decimal((short)ReadBuf[10] * 0x100 + (short)ReadBuf[11]) / 131.0m).ToString("F1") + "";
        Text_Z_Axis_Gyro.Text = "Gyro Z:" + (ConvertSignedShortData2Decimal((short)ReadBuf[12] * 0x100 + (short)ReadBuf[13]) / 131.0m).ToString("F1") + "";
        Text_Status.Text = "Status:計測中";
    });
}

とれたデータを、画面の各表示用テキストに書き込んでいる。
各値で計算しているのは、データシートに従い生データを意味の分かる値に計算するためのもの。
こちらを参照。

コード

参考

パイソンでの超わかりやすいMPU-9150制御プログラム
言語は違うが、制御の流れはほぼこちらのやり方で行けると思う。すごいわかりやすい
https://qiita.com/boyaki_machine/items/915f7730c737f2a5cc79

I2CDeviceクラス(MsDocs)
https://docs.microsoft.com/en-us/uwp/api/windows.devices.i2c.i2cdevice

Windows IoT Coreのサンプル
https://github.com/microsoft/Windows-iotcore-samples/blob/develop/Samples/Accelerometer/CS/

9軸センサモジュールのページ
http://www.kyohritsu.jp/eclib/PROD/MANUAL/kp9150.pdf

MPU-9150の通信開始手順の参考にしたもの
https://strawberry-linux.com/pub/mpu-9150-manual.pdf

MPU-9150レジスタマップ
https://strawberry-linux.com/pub/RM-MPU-9150A-00.pdf

データ送信/受信時のフォーマット(1バイト目がアドレス、2バイト目が書き込みたいデータ)(5.タイミングパラメータのところ)
https://monolizm.com/sab/pdf/%E7%AC%AC16%E5%9B%9E_%E3%83%97%E3%83%AC%E3%82%BC%E3%83%B3%E8%B3%87%E6%96%99(IC2%E9%80%9A%E4%BF%A1%E7%B7%A8).pdf

センサ値の計算式参考
http://www.widesnow.com/entry/2015/09/10/061128

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1