0

The following code works correctly in reading single int values. It also works correctly for 3-4 seconds if I 'stream' the values in constantly (Mouse move coordinates) before I get an IO error and the i2C bus connection is dropped. I assume this is some sort of buffer overrun...or? Can anyone get me on the right track here? What changes do I need to make so that I can constantly stream in serial data?

    #include <Wire.h>

#define SLAVE_ADDRESS 0x04
int zeroByte;
int state = 0;
int receivedValue = 0;

int numBytes = 0;

bool newData = false;

void setup() {
    pinMode(13, OUTPUT);
    Serial.begin(9600);         // start serial for output
    // initialize i2c as slave
    Wire.begin(SLAVE_ADDRESS);

    // define callbacks for i2c communication
    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);

    Serial.println("Ready!");
}

void loop() {
    delay(100);
    if(newData){

      Serial.println(receivedValue);
      newData=false;
    }
}

// callback for received data
void receiveData(int byteCount){

    while(Wire.available()) {
        newData = true;
        zeroByte = Wire.read();

         if(Wire.available() == 2)
  {
    receivedValue = Wire.read() | Wire.read() << 8;


  }

     }                               
}

// callback for sending data
void sendData(){

    Wire.write(receivedValue);
}
1
  • Please specify which arduino board you are using and where you see the I2C io error. – user2973 Jul 22 '14 at 20:02
0

Your I2C bus is operating at 100 kHz. Your serial connection is set to 9600 baud. In case you are sending coordinates at a pace faster than the serial interface can keep up, the buffer will fill up. I assume you are using hardware serial (uno, mega, etc). Once the buffer is filled up Serial.write (which is called by Serial.println) will block until the buffer has free space. But the serial transmission depends on interrupts, and you are calling Serial.write inside an interrupt routine. By defult interrupt routines block other interrupts from happening. So your program gets stuck there and locks up both the serial transmission and the I2C interface.

It would be a good idea to put the serial write outside the interrupt routine, in the loop. Make a global variable bool newData = false; and set it true in the receiveData function. In your loop check the flag and transmit the data. Then set the flag to false.

You will still experience data loss if the serial interface can't keep up, but your application wont lock up. To solve the data loss simply use a higher baud rate, eg. 115200.

4
  • brilliant answer! will test and provide feedback. Thanks – Bachalo Jul 22 '14 at 20:46
  • I've made you're suggested changes (see above) but I'm only seeing the 2nd receivedValue(y value) in my println statement. Could you possibly suggest what changes I need to make and I will approve your answer. Thanks again. – Bachalo Jul 22 '14 at 21:13
  • You need to remove the delay from loop(). Also consider using Serial.begin(115200) if you don't want data loss. – user2973 Jul 22 '14 at 21:29
  • Works!.....But how do I separate out my x,y coordinates in my main loop? Serial.println(receivedValue); – Bachalo Jul 23 '14 at 15:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.