我一直在尝试使用 Wire.h 库在运行 Windows IoT 的 Arduino Uno(从属)和 Raspberry Pi(主)之间设置 I2C 通信,以便读取连接到 Arduino 的两个按钮的值。
问题是在 Pi 上我收到错误的值。在 Arduino 的串行监视器中,buttonStatePin2
和的值buttonStatePin4
可以不断0
,但在计时器上,pi 会收到错误的值,请参见 MainPage 的代码,这意味着1
即使我从未实际按下按钮,它也会收到。
这种行为似乎没有任何模式。有时 Pi 不会收到1
价值,有时它会持续收到,通常来自pin 4
/button4
这看起来很奇怪。
我按照这里的建议使用了 Arduino IDE 1.06来上传草图,但没有成功。而不是Timer
我使用 DispatcherTimer 导致相同的行为。我还怀疑void loop()
Arduino 和计时器之间的延迟必须以某种方式“同步”,所以我尝试在任一侧添加更高/更低的延迟或 timerTick 间隔,但问题保持不变。
这是 Arduino 草图。
#include <Wire.h>
#define SLAVE_ADDRESS 0x40
const int pinButton2 = 2;
const int pinButton4 = 4;
byte Response[2];
byte receivedByte;
void setup() {
pinMode(pinButton2, INPUT);
pinMode(pinButton4, INPUT);
Serial.begin(9600);
Wire.begin(SLAVE_ADDRESS);
Wire.onRequest(sendData);
Wire.onReceive(receiveData);
}
void loop() {
int buttonStatePin2 = digitalRead(pinButton2);
int buttonStatePin4 = digitalRead(pinButton4);
Serial.println("Button 2: ");
Serial.println(buttonStatePin2);
Serial.println("Button 4: ");
Serial.println(buttonStatePin4);
if (buttonStatePin2 == HIGH) {
Response[0] = (byte)1;
}
if (buttonStatePin4 == HIGH)
{
Response[1] = (byte)1;
}
// delay(500);
Wire.onRequest(sendData);
}
void sendData()
{
Wire.write(Response, 2);
}
void receiveData(int huh)
{
receivedByte = Wire.read();
Serial.println(receivedByte);
if (receivedByte == 1)
{
sendData();
}
}
在 Raspberry Pi 上,I2cHelper 处理连接/读取等。
class I2cHelper
{
private static string AQS;
private static DeviceInformationCollection DIS;
private I2cDevice i2cDev;
private int button2 = 0, button4 = 0;
const byte SLAVE_ADDRESS = 0x40;
//button event handlers
public event EventHandler Button2Pressed;
public event EventHandler Button4Pressed;
public int Button2
{
get { return button2; }
set
{
this.button2 = value;
OnButton2Pressed(value);
}
}
public int Button4
{
get { return button4; }
set
{
this.button4 = value;
OnButton4Pressed(value);
}
}
public I2cHelper()
{
}
private void OnButton2Pressed(int value)
{
if (value == 1)
{
Button2Pressed.Invoke(this, new EventArgs());
}
}
private void OnButton4Pressed(int value)
{
if (value == 1)
{
Button4Pressed.Invoke(this, new EventArgs());
}
}
public async void Setup()
{
var Settings = new I2cConnectionSettings(SLAVE_ADDRESS);
Settings.BusSpeed = I2cBusSpeed.StandardMode;
if (AQS == null || DIS == null)
{
AQS = I2cDevice.GetDeviceSelector("I2C1");
DIS = await DeviceInformation.FindAllAsync(AQS);
}
i2cDev = await I2cDevice.FromIdAsync(DIS[0].Id, Settings);
}
public async Task<byte[]> AsyncGetResponse()
{
byte[] response = new byte[2];
i2cDev.Read(response);
return response;
}
}
在 MainPage 中,我使用如下帮助类:
Library.I2cHelper i2cDev;
Library.Connection connection;
private DispatcherTimer timer;
//private Timer periodicTimer;
private int tickCount;
public MainPage()
{
timer = new DispatcherTimer();
timer.Tick += Timer_Tick;
timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
connection = new Library.Connection();
connection.ReceivedDataHandler += Connection_ReceivedDataHandler;
Task t = Task.Run(() =>
{
i2cDev = new Library.I2cHelper();
i2cDev.Setup();
i2cDev.Button2Pressed += I2cDev_Button2Pressed;
i2cDev.Button4Pressed += I2cDev_Button4Pressed;
});
t.Wait();
//periodicTimer = new Timer(this.timerCallback, null, 0, 100);
timer.Start();
this.InitializeComponent();
}
private void timerCallback(object state)
{
readButtons();
}
private async void I2cDev_Button4Pressed(object sender, EventArgs e)
{
listBoxClients.Items.Add("Button 4: " + i2cDev.Button4.ToString());
i2cDev.Button4 = 0;
}
private async void I2cDev_Button2Pressed(object sender, EventArgs e)
{
listBoxClients.Items.Add("Button 2: " + i2cDev.Button2.ToString());
i2cDev.Button2 = 0;
}
private void Timer_Tick(object sender, object e)
{
readButtons();
}
private void readButtons()
{
try
{
var response = i2cDev.AsyncGetResponse().Result;
i2cDev.Button2 = response[0];
i2cDev.Button4 = response[1];
}
catch (NullReferenceException exc)
{
Debug.WriteLine("Read failed with error: " + exc.Message);
}
catch (AggregateException exc)
{
Debug.WriteLine("Read failed with error: " + exc.Message);
}
}