0

When I try something like this, everything works.

Slave:

    # define DEFAULT_DATA_SIZE 256
    
    byte DATA[DEFAULT_DATA_SIZE];
    
    void requestEvent()
    {
      Wire.write( (byte*) DATA, sizeof(DATA));
    }
    
    void receiveEvent(int numBytes)
    {
      for (int i = 0; i < numBytes; i++) {
        DATA[i] = Wire.read();
      }
    }

Master:

    # define DEFAULT_DATA_SIZE 5

    void writeData(byte data[], int numBytes) {
      Wire.beginTransmission(I2C_SLAVE_ADDRESS);
      for (int i = 0; i < numBytes; i++)
      {
        Wire.write(data[i]);
      }
      Wire.endTransmission();
    }

    void readData() {
      byte data[DEFAULT_DATA_SIZE];
      Wire.requestFrom( I2C_SLAVE_ADDRESS, DEFAULT_DATA_SIZE );
      if ( Wire.available() == sizeof( data))
      {
        Wire.readBytes( (byte *) data, DEFAULT_DATA_SIZE);
      }
      Serial.print("Byte Array: ");
      for (int i = 0; i < DEFAULT_DATA_SIZE; i++ ) {
        Serial.print(data[i]);
        Serial.print(" ");
      }
      Serial.println();
    }

    byte data[5] = {0x1, 0x2, 0x3, 0x4, 0x5 };
    
    void setup()
    {
      Wire.begin();
      Serial.begin(9600); 
    
      writeData(data, sizeof(data));
      delay(500);
      readData();
    }
    
    void loop() {
    
    }

But this only works when the master knows how long the array needs to be. If I set the value of DEFAULT_DATA_SIZE not to 5, but more, then I get a set of random numbers.

I tried to make the slave pass the length of the array first, and then the array itself. But for some reason it doesn't work and I also get random numbers.

Slave:

    #include <Wire.h>
    # define I2C_SLAVE_ADDRESS 12
    # define DEFAULT_DATA_SIZE 256
    
    byte DATA[DEFAULT_DATA_SIZE];
    int RECEIVED_NUMBYTES = 0;
    bool isNumBytesSended = false;
    
    void setup()
    {
      Wire.begin(I2C_SLAVE_ADDRESS);
      delay(1000);
      Wire.onRequest(requestEvent);
      Wire.onReceive(receiveEvent);
    }
    
    void loop()
    {
    }
    
    void requestEvent()
    {
      if (!isNumBytesSended) {
        isNumBytesSended = true;
        Wire.write(RECEIVED_NUMBYTES); 
      }
      else {
        isNumBytesSended = false;
        Wire.write( (byte*) DATA, sizeof(DATA)); 
      }
    }
    
    void receiveEvent(int numBytes)
    {
      RECEIVED_NUMBYTES = numBytes;
      for (int i = 0; i < numBytes; i++) {
        DATA[i] = Wire.read();
      }
    }

Master:

    #include <Wire.h>
    # define I2C_SLAVE_ADDRESS 12
    # define DEFAULT_DATA_SIZE 10
    
    
    void writeData(byte data[], int numBytes) {
      Wire.beginTransmission(I2C_SLAVE_ADDRESS);
      for (int i = 0; i < numBytes; i++)
      {
        Wire.write(data[i]);
      }
      Wire.endTransmission();
    }
    
    void readData() {
      Wire.requestFrom( I2C_SLAVE_ADDRESS, 1 );
      int numBytes = Wire.read();
      Serial.println("numBytes: " + String(numBytes));
      
      byte data[numBytes];
      if ( Wire.available() == sizeof( data))
      {
        Wire.readBytes( (byte *) data, numBytes);
      }
      Serial.print("Byte Array: ");
      for (int i = 0; i < numBytes; i++ ) {
        Serial.print(data[i]);
        Serial.print(" ");
      }
      Serial.println();
    } 
    
    byte data[5] = {0x1, 0x2, 0x3, 0x4, 0x5 };
    
    void setup()
    {
      Wire.begin();
      Serial.begin(9600); 
    
      writeData(data, sizeof(data));
      delay(100);
      readData();
    }
    
    void loop() {
    
    }

Master outputs:

01:20:13.844 -> numBytes: 5
01:20:13.878 -> Byte Array: 11 8 212 8 22
01:21:51.222 -> numBytes: 0
01:21:51.255 -> Byte Array:
01:21:54.323 -> numBytes: 5
01:21:54.323 -> Byte Array: 11 8 212 8 22
01:22:01.682 -> numBytes: 0
01:22:01.717 -> Byte Array:
01:22:04.280 -> numBytes: 5
01:22:04.314 -> Byte Array: 11 8 212 8 22
01:22:06.879 -> numBytes: 0
01:22:06.912 -> Byte Array:
01:22:10.386 -> numBytes: 5
01:22:10.420 -> Byte Array: 11 8 212 8 22

Please tell me the best way to solve this problem. Maybe transfer all values one byte at a time, and put a special delimiter between the beginning of new data?

2
  • I get a set of random numbers ... the numbers are not random because they repeat ... the numbers are invalid though
    – jsotola
    Jul 17, 2022 at 19:04
  • 1
    Try making the first byte the length. That will keep you from sending a zero size but the first byte would be 0. Create a function that will send the array byte by byte. Your receiving would also have to know the format.
    – Gil
    Jul 17, 2022 at 19:55

1 Answer 1

1

yes, the idea of sending one byte at a time and specifying the length of the array worked. I'm surprised that I didn't do that sooner :)

SLAVE:

#include <Wire.h>
# define I2C_SLAVE_ADDRESS 12
# define DEFAULT_DATA_SIZE 256

byte DATA[DEFAULT_DATA_SIZE];
int pointer = 0;

void setup()
{
  Wire.begin(I2C_SLAVE_ADDRESS);
  delay(1000);
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent);
}

void loop()
{
}

void requestEvent()
{
  if (pointer > DATA[0]) {
    Wire.write(0);
  }
  else {
    Wire.write(DATA[pointer++]);
  }
}

void receiveEvent(int numBytes)
{
  DATA[0] = numBytes;
  for (int i = 1; i <= numBytes; i++) {
    DATA[i] = Wire.read();
  }
  pointer = 0;
}

MASTER:

#include <Wire.h>
# define I2C_SLAVE_ADDRESS 12

void writeData(byte data[], int numBytes) {
  Wire.beginTransmission(I2C_SLAVE_ADDRESS);
  for (int i = 0; i < numBytes; i++)
  {
    Wire.write(data[i]);
  }
  Wire.endTransmission();
}

void readData() {
  Wire.requestFrom( I2C_SLAVE_ADDRESS, 1 );
  int numBytes = Wire.read();
  Serial.println("numBytes: " + String(numBytes));

  byte data[numBytes];
  
  for (int i = 0; i < numBytes; i++) { 
    Wire.requestFrom( I2C_SLAVE_ADDRESS, 1 );
    data[i] = Wire.read();
  } 
  Serial.print("Byte Array: ");
  for (int i = 0; i < numBytes; i++ ) {
    Serial.print(data[i]);
    Serial.print(" ");
  }
  Serial.println();
}

byte data[8] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };

void setup()
{
  Wire.begin();
  Serial.begin(9600);

  writeData(data, sizeof(data));
  delay(100);
  readData();
}

void loop() {

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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