【Raspberry Pi】UWP 앱을 만들어 RaspberryPi(IoT Core)에 접속한 I2C 디바이스로부터 값을 취득한다

소개



RaspberryPi가 얻은 값을 HoloLens에 보내고 싶었기 때문에 RaspberryPi에 Windows 10 IoT Core를 도입했습니다.
따라서 UWP 앱에서 RaspberryPi를 실행하고 연결된 모듈에서 값을 가져 와서 GUI로 표시합니다.

환경


  • Raspberry Pi 3 Model B(OS: Windows 10 IoT core ver10.0.17134.1)
  • MPU6050 (가속도 센서)
  • VisualStudio2017

  • 절차



    MPU6050의 데이터 시트를 보면서 취득하고 싶은 데이터 레지스터의 주소를 지정합니다.
    결과 값을 GUI의 텍스트에 반영합니다.

    MPU6050 데이터시트 ↓↓↓
    htps //w w. 응 ㄔ 센센세. 이 m/wp-콘텐 t/우 pぉ아ds/2015/02/M푸-6000-다시에 t1. pdf


    소스 코드



    cs에서만 xaml을 생략합니다.

    ReadValuesByRaspberryPi.cpp
    using System;
    using System.Diagnostics;
    using System.Threading;
    using Windows.UI.Xaml.Controls;
    using Windows.Devices.Enumeration;
    using Windows.Devices.I2c;
    
    namespace ReadValuesByRaspberryPi
    {
        struct Acceleration
        {
            public int X;
            public int Y;
            public int Z;
        };
    
        /// <summary>
        /// app that reads data over I2C from an attached MPU6050 accelerometer
        /// </summary>
        public sealed partial class MainPage : Page
        {
            private const byte I2C_ADDR = 0x68;                 /* Address of MP6050 */
            private const byte POWER_CONTROL = 0x6B;            /* Address of the Power Control register */
            private const byte ACCEL_REG_X = 0x3B;              /* Address of the X Axis data register */
            private const byte ACCEL_REG_Y = 0x3D;              /* Address of the Y Axis data register */
            private const byte ACCEL_REG_Z = 0x3F;              /* Address of the Z Axis data register */
    
            private I2cDevice MPU6050; //Module name
            private Timer periodicTimer;
    
            private int cnt;
    
            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(I2C_ADDR); 
                settings.BusSpeed = I2cBusSpeed.FastMode;
                var controller = await I2cController.GetDefaultAsync();
                MPU6050 = 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_PowerControl = new byte[] { POWER_CONTROL, 0x20 };    /* puts the accelerometer into measurement mode */
    
                /* Write the register settings */
                try
                {
                    MPU6050.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 */
                MPU6050.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}", accel.X);
                    yText = String.Format("Y Axis: {0}", accel.Y);
                    zText = String.Format("Z Axis: {0}", 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;
                    //Debug.Write(xText + "\n");
                });
            }
    
            // Write the address then read data from accelerometer
            private Acceleration ReadI2CAccel()
            {
                byte[] RegAddrBuf_X = new byte[] { ACCEL_REG_X }; /* Register address we want to read from */
                byte[] RegAddrBuf_Y = new byte[] { ACCEL_REG_Y };
                byte[] RegAddrBuf_Z = new byte[] { ACCEL_REG_Z };
    
                byte[] ReadBuf_X = new byte[1];                   /* We read 3 bytes sequentially to get all 3 two-byte axes registers */
                byte[] ReadBuf_Y = new byte[1];
                byte[] ReadBuf_Z = new byte[1];
    
                /* 
                 * Read from the accelerometer 
                 * We call WriteRead() so we write the address of the each-Axis I2C register, then read each axes
                 */
                MPU6050.WriteRead(RegAddrBuf_X, ReadBuf_X); //
                MPU6050.WriteRead(RegAddrBuf_Y, ReadBuf_Y);
                MPU6050.WriteRead(RegAddrBuf_Z, ReadBuf_Z);
    
                cnt++;
                Debug.Write(ReadBuf_X[0] + "\n");
    
                Acceleration accel;
                accel.X = ReadBuf_X[0];
                accel.Y = ReadBuf_Y[0];
                accel.Z = ReadBuf_Z[0];
    
                return accel;
            }
        }
    }
    
    

    실행 결과



    Raspberry Pi 측의 출력 화면 (수시로 갱신됩니다)

    확실히 값은 잡히고 있군요.

    문제점



    왠지 값이 갱신되는데 800ms 정도의 간격이 비어 버린다.
    또 조사해 해결할 수 있으면 갱신합니다.

    좋은 웹페이지 즐겨찾기