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 Commented 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. Commented 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() {

}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.