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?

Rohit Gupta
6122 gold badges5 silver badges18 bronze badges
asked Jul 17, 2022 at 17:54
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() {
}
answered Jul 18, 2022 at 4:58

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.