2015-12-15 12 views
1

Я довольно новый в мире малины и ардуино (особенно вместе с Windows IoT). Мой план состоит в том, чтобы считывать с помощью Arduino различные датчики (темп и давление), а затем отправлять значения на мой RP2, где я могу использовать их в графическом интерфейсе.Соединение I2C между Windows IOT и Arduino Nano с использованием C#

Итак, это не проблема для считывания датчиков. Я получаю правильные значения. Впоследствии я отправляю их на шину I²C (на основе требований к каналу Wire.h).

Для моего RP2 я нашел два похожих проекта, и мой код на C# основан на них.

Пока все хорошо, но когда я запускаю оба устройства, я не получаю никаких данных на своем RP. Мой RP находит Ардуино.

Чтобы локализовать проблему, я использую эскиз образца Wire.h для отправки случайных значений в мой RP. Но есть еще одна проблема, поэтому я думаю, что есть проблема с моим кодом на C#. Также я установил точку останова в месте, где мой RP должен записать значения в массив. Но похоже, что входящих значений нет.

I прилагается оба кода. Надеюсь, кто-то может мне помочь. Я застрял очень плохо ...

спасибо! Тимо

Arduino код:

#include <Wire.h> 
    #define SLAVE_ADDRESS 0x40 


byte val = 0; 
byte val_2 = 100; 

void setup() 
{ 
    Wire.begin(SLAVE_ADDRESS); // join i2c bus 
    Serial.begin(9600); 
} 

void loop() 
{ 
    Wire.beginTransmission(SLAVE_ADDRESS); // transmit to master device 
           // device address is specified in datasheet 
    Wire.write(val);    // sends value byte 
    Wire.write (val_2); 
// Serial.write(val); 
// Serial.write(val_2); 
    Wire.endTransmission();  // stop transmitting 

    val++;  // increment value 
    val_2++; 
    if(val == 64) // if reached 64th position (max) 
    { 
    val = 0; // start over from lowest value 
    } 

    if (val_2 == 164) 
    { 
    val = 100; 
    } 
    delay(500); 
} 

C# код:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Runtime.InteropServices.WindowsRuntime; 
using Windows.Foundation; 
using Windows.Foundation.Collections; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Controls.Primitives; 
using Windows.UI.Xaml.Data; 
using Windows.UI.Xaml.Input; 
using Windows.UI.Xaml.Media; 
using Windows.UI.Xaml.Navigation; 
// i2c Libs 
using Windows.Devices.Enumeration; 
using Windows.Devices.I2c; 
using System.Diagnostics; 
using System.Threading; 


// Die Vorlage "Leere Seite" ist unter http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 dokumentiert. 

namespace _007_Test7_I2C 
{ 
    /// <summary> 
    /// Eine leere Seite, die eigenständig verwendet werden kann oder auf die innerhalb eines Rahmens navigiert werden kann. 
    /// </summary> 

    public sealed partial class MainPage : Page 
    { 

     private I2cDevice Device; 
     private Timer periodicTimer; 


     public MainPage() 
     { 
      this.InitializeComponent(); 
      initcomunica(); 
     } 

     private async void initcomunica() 

     { 

      var settings = new I2cConnectionSettings(0x40); // Arduino address 
      settings.BusSpeed = I2cBusSpeed.StandardMode; 
      string aqs = I2cDevice.GetDeviceSelector("I2C1"); 
      var dis = await DeviceInformation.FindAllAsync(aqs); 
      Device = await I2cDevice.FromIdAsync(dis[0].Id, settings); 
      periodicTimer = new Timer(this.TimerCallback, null, 0, 1000); // Create a timer 

     } 

     private void TimerCallback(object state) 
     { 

      byte[] RegAddrBuf = new byte[] { 0x40 }; 
      byte[] ReadBuf = new byte[7]; 

      try 
      { 
       Device.Read(ReadBuf); 
      // Debug.WriteLine(ReadBuf); 
      } 
      catch (Exception f) 
      { 
       Debug.WriteLine(f.Message); 
      } 


      char[] cArray = System.Text.Encoding.UTF8.GetString(ReadBuf, 0, 7).ToCharArray(); // Converte Byte to Char 
      String c = new String(cArray); 
      Debug.WriteLine(c); 
      // refresh the screen, note Im using a textbock @ UI 

      var task = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,() => 
      { Temp_2.Text = c; }); 

     } 

    } 
} 

ответ

3

Ваш код должен быть синхронизирован с обеих сторон. Arduino является подчиненным I2C и может отправлять байты только по запросу мастером, который является RPi2 (Windows IoT).

Есть следующие ошибки в вашем Arduino Sketch:

  • устройство Подчиненный не может инициировать запрос записи на шине (кроме мастер запросов на него)
  • Чтобы разобрать действительный символ или строку в Windows, IoT стороне , Arduino должен послать байт (ы) в допустимом формате ASCII

Я прилагаю основной Arduino Sketch и RPi2 UWP Код:

Arduino Sketch (I2C Slave), который реагирует с байтом по просьбе хозяина:

#include <Wire.h> 
#define MyAddress 0x40 

byte DataToBeSend[1]; 
byte ReceivedData; 

void setup() 
{ 
    /* Initialize I2C Slave & assign call-back function 'onReceive' on 'I2CReceived'*/ 
    Wire.begin(MyAddress); 
    Wire.onReceive(I2CReceived); 
    Wire.onRequest(I2CRequest); 
} 

void loop() 
{ 
    /* Increment DataToBeSend every second and make sure it ranges between 0 and 99 */ 
    DataToBeSend[0] = (DataToBeSend[0] >= 99) ? 0 : DataToBeSend[0] + 1; 
    delay(1000); 
} 

/* This function will automatically be called when RPi2 sends data to this I2C slave */ 
void I2CReceived(int NumberOfBytes) 
{ 
    /* WinIoT have sent data byte; read it */ 
    ReceivedData = Wire.read(); 
} 

/* This function will automatically be called when RPi2 requests for data from this I2C slave */ 
void I2CRequest() 
{ 
    /*Send data to WinIoT */ 
    Wire.write(DataToBeSend,1); 
} 

Окна IoT UWP - I2C Master Code Snippet:

using System; 
using Windows.Devices.Enumeration; 
using Windows.Devices.I2c; 

namespace Windows_10_I2C_Demo 
{ 
    public class I2cHelper 
    { 
     private static string AQS; 
     private static DeviceInformationCollection DIS; 

     public static async System.Threading.Tasks.Task<byte> WriteRead_OneByte(byte ByteToBeSend) 
     { 
      byte[] ReceivedData = new byte[1]; 

      /* Arduino Nano's I2C SLAVE address */ 
      int SlaveAddress = 64;    // 0x40 

      try 
      { 
       // Initialize I2C 
       var Settings = new I2cConnectionSettings(SlaveAddress); 
       Settings.BusSpeed = I2cBusSpeed.StandardMode; 

       if (AQS == null || DIS == null) 
       { 
        AQS = I2cDevice.GetDeviceSelector("I2C1"); 
        DIS = await DeviceInformation.FindAllAsync(AQS); 
       } 


       using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id, Settings)) 
       { 
        /* Send byte to Arduino Nano */ 
        Device.Write(new byte[] { ByteToBeSend }); 

        /* Read byte from Arduino Nano */ 
        Device.Read(ReceivedData); 
       } 
      } 
      catch (Exception) 
      { 
       // SUPPRESS ANY ERROR 
      } 

      /* Return received data or ZERO on error */ 
      return ReceivedData[0]; 
     } 
    } 
} 

Как использовать выше Windows, IoT UWP - фрагмент кода мастер-кода I2C?

public async void TestFunction() 
{ 
    byte DataToBeSend = 100; 
    byte ReceivedData; 
    ReceivedData = await I2cHelper.WriteRead_OneByte(DataToBeSend); 
} 


Прежде чем идти дальше, вы должны иметь четкое представление о I2C communinication.Обратитесь к следующей статье, чтобы получить четкое представление о Master-Slave связи между Arduino: http://www.instructables.com/id/I2C-between-Arduinos/?ALLSTEPS

Чтобы попасть в более глубокие, см следующие проекты:
Arduino I2C communication with Raspi 2 WIOT
Windows IoT (RPi2) - I2C Accelerometer

+0

Привет Анураг, спасибо за вашу помощь и лекции ! До сих пор я понял часть Ардуины. Я попробовал ваш код, и теперь я получаю одно значение (128). И похоже, что Arduino не получает запрос (я проверил его с помощью Serial.write()). Правильно ли, что я зашел в TestFunction() с помощью задачи? Например: «Task Task1 = новая задача (TestFunction)»; Мне жаль мое невежество! – TRS

+0

«TestFunction», упомянутый выше, отправляет байт в подчиненное устройство I2C и получает от него байт. Вы должны вызывать эту функцию всякий раз, когда вы собираетесь запрашивать ведомый. Вам нужно изменить код с обеих сторон, если вам нужно передать несколько байтов. Вышеприведенный код является просто образцом, чтобы дать вам четкое представление о том, как вы можете общаться через I2C. –

+0

Я модифицировал эскиз Arduino (приведенный выше) и включил другой обратный вызов I2C, который будет вызываться, когда RPi2 запрашивает данные (методом Device.Read (ReceivedData)). Проконсультируйтесь с этим и дайте мне знать, если вы не получите желаемого результата. –