I2C and wire.recieve

The back story. I am trying to get an emc32 to send a single byte (a number) to a MEGA using ReceiveEvent on the slave. Based on the number sent, when the emc than requests the data packet using Wire.requestFrom on the master and RequestData on the slave, the MEGA will respond with the corresponding packet. From all the debug print statments it looks like both programs are flowing correctly. The slave receives the single number and responds with the correct data packet.

Problem, the received data is totally wrong.

Developed the code using a single data packet (no ReceiveEvent). Works great. I than added the ReceiveEvent to tell the slave which data packet to send and the received data packet is garbage. Below are the code sinpits.

Question, Why is sending a byte before requesting the data packet cause the received data to be scrambled?

Thanks.

 // Get the data from the MEGA. First send which dataPacket to get than
  // request the data.

  Serial.println("Sending which packet to get");

  // Start transmiting, take control of the bus
  Wire.beginTransmission(8);
  WhichOne=1;
  Serial.print("Requesting: ");
  Serial.println(WhichOne);

  Wire.printf("%c", WhichOne);
  error = Wire.endTransmission(true); 
    Serial.printf("endTransmission: %u\n", error);
  // End transmiting, free the bus

  Serial.println("Requesting data");
  byteCount = Wire.requestFrom(8, sizeof(dataPacket1));    // request data from slave device #8
  byte *ptr = (byte*) &dataPacket1;

  // check if the recieved data is correct.  If it is processed
  if ( byteCount != sizeof(dataPacket1)) {
    Serial.print( "Received bad packet.  Expected " );
    Serial.print(sizeof(dataPacket1));
    Serial.print( " bytes but got " );
    Serial.println( byteCount );
  }
  else {
   Serial.print("Size of dataPacket: ");
   Serial.println(sizeof(dataPacket1));
    for ( byte i = 0; i < sizeof(dataPacket1); ++i ) {
      byte c = Wire.read(); // receive a byte as character
      ptr[i] = c;
      Serial.print(c,HEX);
      Serial.print(" - ");
      Serial.println(c,DEC); 
    }      
 }
  
  Wire.beginTransmission(8);
  WhichOne=2;
  Serial.print("Requesting: ");
  Serial.println(WhichOne);

  Wire.printf("%c", WhichOne);
  error = Wire.endTransmission(true); 
  Serial.printf("endTransmission: %u\n", error);
 
  Serial.print("Requesting dataPacket: ");
  Serial.println(WhichOne);
  byteCount = Wire.requestFrom(8, sizeof(dataPacket2));    // request data from slave device #8
  byte *ptr2 = (byte*) &dataPacket2;

  // check if the recieved data is correct.  If it is processed
  if ( byteCount != sizeof(dataPacket2)) {
    Serial.print( "Received bad packet.  Expected " );
    Serial.print(sizeof(dataPacket2));
    Serial.print( " bytes but got " );
    Serial.println( byteCount );
  }
  else {
   Serial.print("Size of dataPacket: ");
   Serial.println(sizeof(dataPacket2));
    for ( byte i = 0; i < sizeof(dataPacket2); ++i ) {
      byte c = Wire.read(); // receive a byte as character
      ptr[i] = c;
    }
  }
This is on the slave.

void ReceiveEvent(int howMany)
{
  Serial.println("received request for datapacketno"); // while(1 < Wire.available()) // loop through all but the last
  Serial.print("howMany = ");
  Serial.println(howMany);
  dataPacketNo = Wire.read(); // receive byte as a character
  Serial.print("Data Packet Rec: ");
  Serial.println(dataPacketNo);         // print the character
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}


//  This is the event for when a request for data comes over the I2C bus, See setup()
  
// *************** Event handler for I2C.  ********************
void RequestData() {

  if (dataPacketNo == 1){
  Serial.print("received request for data: ") ;
  Serial.println(dataPacketNo);

  Wire.write((byte*)&dataPacket1, sizeof(dataPacket1)); //send packet
  
  Serial.println(dataPacket1.DiscreteState1,BIN); 
  Serial.print(sizeof(dataPacket1));
  Serial.println(" Bytes sent");    
  }//
  
  else if (dataPacketNo == 2){
  Serial.print("received request for data: ") ;
  Serial.println(dataPacketNo);
  Wire.write((byte*)&dataPacket2, sizeof(dataPacket2)); //send packet
  
  Serial.print(sizeof(dataPacket2));
  Serial.println(" Bytes sent");
  }
  else  
  {
    Serial.print("Unknown dataPacketNo: ");
    Serial.println(dataPacketNo);}

}

Minimize the above codes as follows:

void ReceiveEvent(int howMany)
{
  dataPacketNo = Wire.read(); // receive byte as a character
  byte x = Wire.read();    // receive byte as an integer
  flag = true;   
}

Use flag in the loop() function and do all the printings.

In the similar way, minimize the codes of requestData() handler.

How do you think that data is put into dataPacket1?

You don't get garbage, you always get the same unchanged random content of dataPacket1. Add wire.read() to copy the bytes into dataPacket1.

All are set in the MEGA. I define a identical structure at the beginning of each script. The first element of the first structure is for the desecrates (on/off). Each bit is set in a for loop. The rest are temperatures. they are read in another loop (readingds18b20S). The second structure is for soil moisture. Once I get the esp reading the mega both structures correctly will read the moisture probes in a for loop similar to the temperatures in the first structure. The issue is not how do I fill the structures. I can send one or the other but when I have the esp send a number telling the mega which one to send I get garbage.

Print statements are for debug. They will go away when I get this working.

Don't know what I you mean. Consider me just above a novice.

Assume that the variable dataPacket2 is a 4-byte wide array space. Then you have requested for 4-byte data which you can store in the said array by executing the following codes:

for(int i = 0; i < sizeof dataPacket2; i++)
{
    dataPacket[i] = Wire.read();
}

or

byte *ptr2;
ptr2 = (byte*)&dataPacket2;  //pointer variable holds the base address of the array
for(int i = 0; i < sizeof dataPacket2; i++)
{
      *ptr2 = Wire.read();
      ptr2++;
}

Can you please explain what is being done by your following code seen in your sketch after the requestFrom() method?

byte *ptr2 = (byte*) &dataPacket2;

The above code line could be broken into:

byte *ptr2;
ptr2 = (byte*) &dataPacket2;
*ptr2 = (byte*) &dataPacket2;   //???
or
*ptr2 = Wire.read(); //?

Remember that receiveEvent() and requestData() handlers are interrupt context where print() methods are not recommended to execute.

void loop()
{
    if(flag == true)
   {
        //do all the printing for debug purposes
        flag = false;
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.