I2C связь между Arduino Uno и Raspberry. Неправильные значения на Пи
Я пытался настроить связь I2C с помощью библиотеки Wire.h между Arduino Uno (Slave) и Raspberry Pi (Master), работающей под управлением Windows IoT, чтобы прочитать значения двух кнопок, подключенных к Arduino.
Проблема в том, что на Пи я получаю неправильные значения. В серийном мониторе Arduino значения buttonStatePin2
а также buttonStatePin4
может быть постоянно 0
но на отметке таймера пи, см. код MainPage, получит неправильные значения, что означает, что он получит 1
хотя я никогда физически не нажимаю кнопку.
Поведение, кажется, не имеет никакого паттерна. Иногда Пи не получит 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);
}
}