Windows IOT 和 Arduino Nano 使用 C# 之间的 I2C 连接
I2C connection between Windows IOT and Arduino Nano using C#
我对 Raspberry 和 Arduino 的世界还很陌生(尤其是 Windows 物联网)。我的计划是,用 Arduino 读出不同的传感器(温度和压力),然后将值发送到我的 RP2,我可以在 GUI 上使用它们。
所以,读出传感器不是问题。我收到正确的值。然后我将它们发送到 I²C 总线(基于 Wire.h 库的要求)。
对于我的 RP2,我发现了两个类似的项目,我的 C# 代码基于这些项目。
到目前为止一切顺利,但是当我启动这两个设备时,我的 RP 上没有任何数据。我的 RP 找到了 Arduino。
为了定位问题,我使用 Wire.h 样本草图将随机值发送到我的 RP。但是还是有同样的问题,所以我猜是我的C#代码有问题。我还在我的 RP 应该将值写入数组的地方设置了一个断点。但看起来,没有传入值。
我附上了两个代码。希望有人能帮助我。我卡得很厉害...
非常感谢!
蒂莫
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; });
}
}
}
你的代码必须在双方同步。 Arduino 是 I2C Slave,只能根据 RPi2 (Windows IoT) 主机的请求发送字节。
您的 Arduino Sketch 中存在以下错误:
- Slave设备不能在总线上发起写请求(Master请求除外)
- 要在 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);
}
Windows IoT UWP - I2C 主代码片段:
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 Master Code Snippet?
public async void TestFunction()
{
byte DataToBeSend = 100;
byte ReceivedData;
ReceivedData = await I2cHelper.WriteRead_OneByte(DataToBeSend);
}
在深入了解之前,您应该对I2C通信有一个清晰的认识。参考以下文章了解Arduino之间的主从通信:http://www.instructables.com/id/I2C-between-Arduinos/?ALLSTEPS
要深入了解,请参考以下项目:
Arduino I2C communication with Raspi 2 WIOT
Windows IoT (RPi2) - I2C Accelerometer
我对 Raspberry 和 Arduino 的世界还很陌生(尤其是 Windows 物联网)。我的计划是,用 Arduino 读出不同的传感器(温度和压力),然后将值发送到我的 RP2,我可以在 GUI 上使用它们。
所以,读出传感器不是问题。我收到正确的值。然后我将它们发送到 I²C 总线(基于 Wire.h 库的要求)。
对于我的 RP2,我发现了两个类似的项目,我的 C# 代码基于这些项目。
到目前为止一切顺利,但是当我启动这两个设备时,我的 RP 上没有任何数据。我的 RP 找到了 Arduino。
为了定位问题,我使用 Wire.h 样本草图将随机值发送到我的 RP。但是还是有同样的问题,所以我猜是我的C#代码有问题。我还在我的 RP 应该将值写入数组的地方设置了一个断点。但看起来,没有传入值。
我附上了两个代码。希望有人能帮助我。我卡得很厉害...
非常感谢! 蒂莫
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; });
}
}
}
你的代码必须在双方同步。 Arduino 是 I2C Slave,只能根据 RPi2 (Windows IoT) 主机的请求发送字节。
您的 Arduino Sketch 中存在以下错误:
- Slave设备不能在总线上发起写请求(Master请求除外)
- 要在 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);
}
Windows IoT UWP - I2C 主代码片段:
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 Master Code Snippet?
public async void TestFunction()
{
byte DataToBeSend = 100;
byte ReceivedData;
ReceivedData = await I2cHelper.WriteRead_OneByte(DataToBeSend);
}
在深入了解之前,您应该对I2C通信有一个清晰的认识。参考以下文章了解Arduino之间的主从通信:http://www.instructables.com/id/I2C-between-Arduinos/?ALLSTEPS
要深入了解,请参考以下项目:
Arduino I2C communication with Raspi 2 WIOT
Windows IoT (RPi2) - I2C Accelerometer