0

I have been trying to setup a I2C communication using Wire.h library between an Arduino Uno (Slave) and Raspberry Pi (Master), running Windows IoT, in order to read the values of two push buttons connected to the Arduino.

The issue is that on the Pi I receive wrong values. In the Arduino's serial monitor values of buttonStatePin2 and buttonStatePin4 can be constantly 0 but on a timer tick the pi, see code of MainPage, will receive wrong values, meaning that it will receive 1 even though I never physically press the push button.

The behavior doesn't seem to have any pattern. Sometimes the Pi won't receive 1 as value, sometimes it continuously does, usually from pin 4 / button4 which seems strange.

I used Arduino IDE 1.06 as suggested here to upload the sketch but no success. Instead of Timer I have used DispatcherTimer resulting in the same behavior. I was suspecting also that the delay inbetween the void loop() on the Arduino and the timer have to be somehow "synced", so I try and error added higher/lower delay or timerTick interval on either side but issue remained the same.

This is the Arduino sketch.

#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();
  }
}

On the Raspberry Pi the I2cHelper handles connection/reading etc.

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;
        }
    }

In the MainPage I am using the helper class as follows:

    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);
                }

    }
  • If you're getting events at all, your I2C config is probably ok. Is this as simple as not having a resistor on your button and because of that you are getting random HIGH and LOW? If you do not have a resistor on your button you could also use INPUT_PULLUP instead of INPUT in your sketch. http://electronics.stackexchange.com/questions/67007/whats-the-difference-between-input-and-input-pullup – Steven Hook May 24 '16 at 18:59
  • I have been using resistor for the buttons already. – Jan-Niklas Schneider May 25 '16 at 12:43
  • Yesterday I swapped out the Arduino with a different one. Suddenly, everything seems to be working fine. This leaves me wondering what the problem is because when I changed them back it seemed to be working fine, too. I even made a second setup (Pi + Arduino) which didn't have the issue either. – Jan-Niklas Schneider May 25 '16 at 12:45

0 Answers0