0

我一直在尝试使用 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);
                }

    }
4

0 回答 0