Wire.onReceive() and Wire.onRequest() interference

Hi All,

Currently I'm working to create an extension for my Lego NXT brick and I would like to connect my arduino Duemilanove to it. The Lego NXT brick has i2c ports and with this I am partly able to communicate with my arduino.

The NXT has the limitation that it should be a master, this implies that my arduino should be a slave listening to its superior. So far I have been able to receive data from the arduino and I have also been able to send data to it. Using the Wire.onRequest() and Wire.onReceive() function within my arduino code.

However, I have not been able yet to receive and send data within the same sketch. If I initialize the Wire.onRequest(requestEvent) and Wire.onReceive(receiveEvent) in the same Setup the only function that response is the onReceive(). Sending data from the NXT works normally, but getting data from the Arduino does not work. The onReceive function is called with only one byte of data. And it never goes to the requestEvent function. Has somebody encountered this problem?

Here is my code arduino sketch.

#include <string.h>
#include <Wire.h>   //Voor i2c communicatie

#define senderLength 28
 
char URL[36] = "/okay/variables.php?var1=32&var2=vs"; // 
byte dataBack[senderLength] = "/okay/variables.php?var1=32"; // De variable om data terug te sturen

//Function to give values back to NXT
void requestEvent()
{
    Serial.print("Request");
    Wire.send(dataBack, senderLength);
 }
// ---------------------------------------------------------------------------
// function that executes whenever data is received from master 
// this function is registered as an event, see setup() 
void receiveEvent(int howMany) 
{ 
  Serial.print("howMany: "); 
  Serial.print(howMany); 
  Serial.print(". "); 
  char c;
  int s;
  int availables = howMany-1; 
 //The first char should be the register byte. I set this to 12 in the java code
  if(Wire.available()) {
    s = Wire.receive(); 
  }
  if(s ==12) {
    while(0 < availables) // 12 is indicated in the send REgister .loop through all but the last Check if goed adress is
    { 
      availables = Wire.available();  
      char c = Wire.receive(); // receive byte as a character 
      //Serial.print(availables, DEC); 
      URL[(howMany-1)-availables] = c; 
     // Serial.print(c); 
      //Serial.print("-");     // print the character 
    } 
    Serial.println(URL); 
  }
} 

void setup() {
    Serial.begin(57600);
    Wire.begin(27);                // join i2c bus with address 127
   Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent); 
  
}

int incomingByte = 0; 

void loop(){

  delay(10);
}

Thank you in advance!

One thing to remember is that "OnReceive" and "OnRequest" are interrupt handlers and you should not execute anything time consuming within these events. Also the sender (e.g. Lego NXT in your case) will block (stop execution) and possibly timeout/fail if the operation takes too long.

For initial tests I would remove the Serial.print functions from the handlers and just set a global flag (e.g. RequestCalled = true), Then in your loop function you can test this flag and then print.

E.g.

if (RequestCalled) {
RequestCalled=false;
Serial.println("Request Called");
}

Hi Ben F,

thank you for your reply! That was the problem! Timing. :smiley: Thank you very much!