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);
}
asked Jul 22, 2014 at 18:48
1
  • Please specify which arduino board you are using and where you see the I2C io error. Commented Jul 22, 2014 at 20:02

1 Answer 1

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.

answered Jul 22, 2014 at 20:22
4
  • brilliant answer! will test and provide feedback. Thanks Commented Jul 22, 2014 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. Commented Jul 22, 2014 at 21:13
  • You need to remove the delay from loop(). Also consider using Serial.begin(115200) if you don't want data loss. Commented Jul 22, 2014 at 21:29
  • Works!.....But how do I separate out my x,y coordinates in my main loop? Serial.println(receivedValue); Commented Jul 23, 2014 at 15:05

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.