I2C and wire.h questions...

A few questions regarding this sample I2C, wire.h code. I pasted the code at the bottom of the post. It’s from the tutorials page.

question 1:

does the Wire.onReceive function in the slave code essentially act as an interrupt, where it is instantly called any time data is available to be received? I noticed the loop() function is blank except for a delay().

question 2:

do you have to use some sort of delay while streaming data? What if you don’t want to use delay() in your loop() routine, and every cycle of loop() you want it to refresh the value of a variable on the slave? This would run thousands of times per second. Does the master ‘wait’ in a sense, until all of the data in a begin/end transmission clause is completely sent to the slave before it moves on? What would happen if the master’s loop() has no delay and is constantly trying to send data to the slave, but the slave’s loop() has, say a delay(5000) in it for whatever reason? I assume an interrupt or Wire.onReceive cant break a delay() once its active.

question 3:

how many bytes can be sent at one time in a single begin/end transmisison to a slave?

question 4:

is there an easy way to send an integer-defined variable’s value in one shot, or do you have to break the integer value up into bytes and send it byte by byte, then reassemble it by shifting bits on the slave?

Slave code:

#include <Wire.h>

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  while (1 < Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

Master code:

#include <Wire.h>

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 0;

void loop() {
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write("x is ");        // sends five bytes
  Wire.write(x);              // sends one byte
  Wire.endTransmission();    // stop transmitting

  x++;
  delay(500);
}
  1. Yes

  2. Instead of 'delay()', look at 'millis()'-based timing like in the "BlinkWithoutDelay" example provided with the IDE.

  3. The default I2C buffer size is 32 bytes, from memory. (Check out the library files or search to verify.)

  4. Search for "I2C_Anything", a library on Nick Gammon's website.
    Edit: You'll find I2C_Anything here:- Send and receive any data type
    (There's also lots of other good I2C info on that page.)