質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.25%

  • Raspberry Pi

    507questions

    Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

  • UWP

    58questions

    UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

RaspberryPi3にWindows10IoTCoreを入れて、I2Cで加速度センサーを制御したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 86

asika

score 0

前提・実現したいこと

RaspberryPi3にWindows10IoTCoreを入れて、I2Cで加速度センサーを制御することを実現したいです。
加速度センサーとしての用意は、MPU6050(GY521)とADXL345(GY291)です。
チュートリアルとして、Microsoft公式のI2CAccelermeterというものを使用し、試しているのですが、

MPU6050は上記のプログラムで使用されているのがADXL345ということもあり、
データシートを参照してアドレスなどを変えたうえで、リモートデバッグをやってみたのですが、
以下のエラーメッセージが発生し、失敗。
ちなみに配線はパワーランプが点灯する状態にできていました。

ADXL345はパワーランプがついていないのか、配線もよく分からず、
ピン4本同士の配線でそのままのプログラムを用いてリモートデバッグしてみたのですが、
同じく以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

プログラムのリモートデバッグ自体は成功しますが、画面上に以下のエラーが表示されます。
Failed to communicate with device: The system cannot find the file specified
Slave address was not acknowledged.

エラー部分のコード

/* Write the register settings */
try
{
I2CAccel.Write(WriteBuf_DataFormat);
I2CAccel.Write(WriteBuf_PowerControl);
}
/* If the write fails display the error and stop running */
catch (Exception ex)
{
Text_Status.Text = "Failed to communicate with device: " + ex.Message;
return;
}

言語はUWP用のC#で、VisualStadio使用。
上記のエラー部分のコード全体像
ADXL345

// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Threading;
using Windows.UI.Xaml.Controls;
using Windows.Devices.Enumeration;
using Windows.Devices.I2c;

namespace I2CAccelerometer
{
    struct Acceleration
    {
        public double X;
        public double Y;
        public double Z;
    };

    /// <summary>
    /// Sample app that reads data over I2C from an attached ADXL345 accelerometer
    /// </summary>
    public sealed partial class MainPage : Page
    {
        private const byte ACCEL_I2C_ADDR = 0x53;           /* 7-bit I2C address of the ADXL345 with SDO pulled low */
        private const byte ACCEL_REG_POWER_CONTROL = 0x2D;  /* Address of the Power Control register */
        private const byte ACCEL_REG_DATA_FORMAT = 0x31;    /* Address of the Data Format register */
        private const byte ACCEL_REG_X = 0x32;              /* Address of the X Axis data register */
        private const byte ACCEL_REG_Y = 0x34;              /* Address of the Y Axis data register */
        private const byte ACCEL_REG_Z = 0x36;              /* Address of the Z Axis data register */

        private I2cDevice I2CAccel;
        private Timer periodicTimer;

        public MainPage()
        {
            this.InitializeComponent();

            /* Register for the unloaded event so we can clean up upon exit */
            Unloaded += MainPage_Unloaded;

            /* Initialize the I2C bus, accelerometer, and timer */
            InitI2CAccel();
        }

        private async void InitI2CAccel()
        {

            var settings = new I2cConnectionSettings(ACCEL_I2C_ADDR); 
            settings.BusSpeed = I2cBusSpeed.FastMode;
            var controller = await I2cController.GetDefaultAsync();
            I2CAccel = controller.GetDevice(settings);    /* Create an I2cDevice with our selected bus controller and I2C settings */


            /* 
             * Initialize the accelerometer:
             *
             * For this device, we create 2-byte write buffers:
             * The first byte is the register address we want to write to.
             * The second byte is the contents that we want to write to the register. 
             */
            byte[] WriteBuf_DataFormat = new byte[] { ACCEL_REG_DATA_FORMAT, 0x01 };        /* 0x01 sets range to +- 4Gs */
            byte[] WriteBuf_PowerControl = new byte[] { ACCEL_REG_POWER_CONTROL, 0x08 };    /* puts the accelerometer into measurement mode */

            /* Write the register settings */
            try
            {
                I2CAccel.Write(WriteBuf_DataFormat);
                I2CAccel.Write(WriteBuf_PowerControl);
            }
            /* If the write fails display the error and stop running */
            catch (Exception ex)
            {
                Text_Status.Text = "Failed to communicate with device: " + ex.Message;
                return;
            }

            /* Now that everything is initialized, create a timer so we read data every 100mS */
            periodicTimer = new Timer(this.TimerCallback, null, 0, 100);
        }

        private void MainPage_Unloaded(object sender, object args)
        {
            /* Cleanup */
            I2CAccel.Dispose();
        }

        private void TimerCallback(object state)
        {
            string xText, yText, zText;
            string statusText;

            /* Read and format accelerometer data */
            try
            {
                Acceleration accel = ReadI2CAccel();
                xText = String.Format("X Axis: {0:F3}G", accel.X);
                yText = String.Format("Y Axis: {0:F3}G", accel.Y);
                zText = String.Format("Z Axis: {0:F3}G", accel.Z);
                statusText = "Status: Running";
            }
            catch (Exception ex)
            {
                xText = "X Axis: Error";
                yText = "Y Axis: Error";
                zText = "Z Axis: Error";
                statusText = "Failed to read from Accelerometer: " + ex.Message;
            }

            /* UI updates must be invoked on the UI thread */
            var task = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                Text_X_Axis.Text = xText;
                Text_Y_Axis.Text = yText;
                Text_Z_Axis.Text = zText;
                Text_Status.Text = statusText;
            });
        }

        private Acceleration ReadI2CAccel()
        {
            const int ACCEL_RES = 1024;         /* The ADXL345 has 10 bit resolution giving 1024 unique values */
            const int ACCEL_DYN_RANGE_G = 8;    /* The ADXL345 had a total dynamic range of 8G, since we're configuring it to +-4G */
            const int UNITS_PER_G = ACCEL_RES / ACCEL_DYN_RANGE_G;  /* Ratio of raw int values to G units */

            byte[] RegAddrBuf = new byte[] { ACCEL_REG_X }; /* Register address we want to read from */
            byte[] ReadBuf = new byte[6];                   /* We read 6 bytes sequentially to get all 3 two-byte axes registers in one read */

            /* 
             * Read from the accelerometer 
             * We call WriteRead() so we first write the address of the X-Axis I2C register, then read all 3 axes
             */
            I2CAccel.WriteRead(RegAddrBuf, ReadBuf);

            /* 
             * In order to get the raw 16-bit data values, we need to concatenate two 8-bit bytes from the I2C read for each axis.
             * We accomplish this by using the BitConverter class.
             */
            short AccelerationRawX = BitConverter.ToInt16(ReadBuf, 0);
            short AccelerationRawY = BitConverter.ToInt16(ReadBuf, 2);
            short AccelerationRawZ = BitConverter.ToInt16(ReadBuf, 4);

            /* Convert raw values to G's */
            Acceleration accel;
            accel.X = (double)AccelerationRawX / UNITS_PER_G;
            accel.Y = (double)AccelerationRawY / UNITS_PER_G;
            accel.Z = (double)AccelerationRawZ / UNITS_PER_G;

            return accel;
        }
    }
}


MPU6050

ACCEL_I2C_ADDR = 0x530x68
ACCEL_REG_POWER_CONTROL = 0x2D0x6B
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
※ACCEL_REG_DATA_FORMAT = 0x31 → ACCEL_CONFIG = 0x1C 
ACCEL_REG_DATA_FORMAT = 0x31に関しては、
そのものずばりが見つからず同じ機能を持つと思われるアドレスを使用
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ACCEL_REG_X = 0x320x3B
ACCEL_REG_X = 0x340x3D
ACCEL_REG_X = 0x360x3F
※ジャイロ部分のレジスタは放置

byte[] WriteBuf_DataFormat = new byte[] { ACCEL_REG_DATA_FORMAT, 0x01 }; 
↓
byte[] WriteBuf_DataFormat = new byte[] { ACCEL_CONFIG, 0x18 }; 

byte[] WriteBuf_PowerControl = new byte[] { ACCEL_REG_POWER_CONTROL, 0x08 };
↓ 
byte[] WriteBuf_PowerControl = new byte[] { ACCEL_REG_POWER_CONTROL, 0x20 }; 

const int ACCEL_RES = 1024 → 65536;
const int ACCEL_DYN_RANGE_G = 8 → 16;

試したこと

資料をwebで探してみましたが色々と見てみましたが失敗する原因が分からず、
問題の切り分けも難しく困っております。

補足情報(言語/FW/ツール等のバージョンなど)

I2CAccelerometerサンプルプログラム参照
https://developer.microsoft.com/en-us/windows/iot/samples/i2caccelerometer
MPU6050データシート参照 
https://cdn.sparkfun.com/datasheets/Sensors/Accelerometers/RM-MPU-6000A.pdf
ADXL345データシート参照 
www.analog.com/media/jp/technical-documentation/data-sheets/ADXL345_jp.pdf

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

一部自己解決できたため、投稿します。

MPU6050用のコードを変えてみながら試した結果、一度成功し検出した値が変わる状態にできました。
結局は、センサーとピンヘッダをはんだ付けできず接触不良の不安が残るまま試行したせいのようでした。
MPU6050についてはパワーランプが点灯していたため大丈夫だと思っていましたが、残りのI2C用のバスで接触不良が起きていたようです。

また、コードも最終的に以下のように改変しました。

MicrosoftのADXL345用I2CAccelerometerサンプルプログラム初期状態より、改変部分のみ記載。
すべてMainPage.xaml.csのコード

23行目 ACCEL_I2C_ADDR = 0x530x68
24行目 ACCEL_REG_POWER_CONTROL = 0x2D0x6B
25行目 ACCEL_REG_DATA_FORMAT = 0x31 → 削除
26行目 ACCEL_REG_X = 0x320x3B
27行目 ACCEL_REG_X = 0x340x3D
28行目 ACCEL_REG_X = 0x360x3F

60行目 byte[] WriteBuf_DataFormat = new byte[] { ACCEL_REG_DATA_FORMAT, 0x01 }; 
↓
削除

61行目 byte[] WriteBuf_PowerControl = new byte[] { ACCEL_REG_POWER_CONTROL, 0x08 };
↓ 
byte[] WriteBuf_PowerControl = new byte[] { ACCEL_REG_POWER_CONTROL, 0x20 }; 

66行目 I2CAccel.Write(WriteBuf_DataFormat); → 削除

120行目 const int ACCEL_RES = 1024 → 65536;
121行目 const int ACCEL_DYN_RANGE_G = 8 → 16;

未解決の問題:
・成功した際も、途中からエラー表示と数値0.000のランニング表示とを行き来する状態になってしまう。
・パワーランプが点灯した状態で、何度かリモートデバッグを試行して5回に1回しか成功しない。
やはり接触不良?により安定しないようですが、サンプル実行についての問題は解決できたので一旦よしとします。

状況の写真:
成功時はこの数値が変動しつつ表示されます
エラーが発生
エラー画面から正常時の画面には戻らずこれになる
指で固定しています

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.25%

関連した質問

同じタグがついた質問を見る

  • Raspberry Pi

    507questions

    Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

  • UWP

    58questions

    UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。