4

I am trying to get 2-Arduinos passing data. The Master will request the data and the Slave send it. But, the length of the string the Slave will send is unknown each cycle.

I found some things here on writing strings with I2C but it seems it is limited to 32 bytes no matter what the Master requests. How can I get the full string sent each time?

Master makes request for string that could be about 180 bytes max - ever.

Wire.requestFrom(8,200);  // I2C-ID = 8, Length = 200 
while (Wire.available()) 
{char c = Wire.read(); 
cmdInStr.concat(c);
}

Slave sends

int len = cmdOutStr.length()+1;
char ascii_num[len];
for (int i=0; i<len; ++i)
{ Wire.write(ascii_num[i]);
}

2 Answers 2

1

You can only send and receive fixed length amounts of data with I2C. The master has to know how much to request from the slave - or the slave to accept from the master.

There's a number of ways around it though:

  1. Splitting / joining.

The trick here is to split the data into packets and re-assemble it at the remote end.

For instance, you split your string into 16-byte chunks. Then you send each chunk separately. Prefixed to each chunk (so the chunk becomes 17 bytes) is a byte telling the remote end how many characters are in this chunk. Any spare space in a chunk is padded with something (0x00 for instance) so it remains 17 bytes long in total.

  1. two-stage transaction

In this method you first make a transaction which tells the remote end how many characters to receive in the next transaction, or retrieves the number of characters that need to be received from the remote end. The second transaction then receives (or sends) that specific number of characters.

If your strings are longer than the internal I2C buffer (32 bytes) then method 1 is probably the best way.

You can also combine the two methods so both ends know how much to expect to be transferred in total as well as how much of each packet is valid data. The sum of the second should match the first.

1
  • I may be being lazy but the data string is passed to other nodes on the network so getting it all the same meant I can manipulate it with common functions in my own project Library file. I wonder if there is a better or different Wire Library. This one shows four functions for directly sending Int/long but no "read" counterpart that I have found. Commented Aug 22, 2016 at 21:22
0

There is no maximum length for sending/receiving in I2C. It is the Wire library BUFFER_LENGTH 32 macro, causing this limitation.

You can either copy some code from Wire library and implement your own requestFrom function which will store data directly to your cmdInStr string buffer or you can change Wire.h to have bigger BUFFER_LENGTH.

Or another way is to extend Wire.h like this:

#ifndef BUFFER_LENGTH
#define BUFFER_LENGTH 32
#endif

and in your sketch:

#define BUFFER_LENGTH 180
#include <Wire.h>

All depends on your preferences, but implementing own requestFrom and storing it directly into your cmdInStr buffer will be little bit more efficient than copying it into Wire buffer and then into your own buffer again.

And do you really need all these data in one string, isn't it possible to proceed it on the fly?

2
  • Thanks before posting, I had tried changing the buffer size in Wire.h file but it had made no difference. I may need to go looking for specific buffer definitions as it seems that the Receive buffer was not set. But, I will try the second suggestion as that might fix it. Commented Aug 22, 2016 at 21:18
  • Well, there can be more hardware directories. Depends if you've upgraded boards. I've usually editted wrong one...
    – KIIV
    Commented Aug 22, 2016 at 21:24

Your Answer

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

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