0

I need to send 259 bytes as answer to I2C master read request. AFAIK there is a buffer limit of 32 bytes in Wire.h and in HW (Arduino Nano). Is there a way sending 259 byte answer, or I have to choose another HW?

The code is:

void serveInitCommunication() {
  Serial.println("serveInitCommunication()");
  static unsigned int counter = 0;
  auto answer = findInitAnswer(counter);

  uint8_t buffer[260]; //maximum size from dataLengths[] in comm_init_data.h
  memcpy_P(buffer, answer.dataPtrProgmem, answer.dataSize);

  Serial.print(" dataSize:");
  Serial.print(answer.dataSize);
  Serial.print(" data:");
  Serial.println(int(buffer[answer.dataSize - 1]));

  auto bytesToWrite = answer.dataSize;
  uint16_t bytesWritten{0};

  while (bytesToWrite > BUFFER_LENGTH) {
    Serial.println("Write part");
    Wire.write(buffer + bytesWritten, BUFFER_LENGTH);
    bytesToWrite -= BUFFER_LENGTH;
    bytesWritten += BUFFER_LENGTH;
  }
  Serial.print("Bytes written:");
  Serial.print(bytesWritten);
  Serial.print(" Bytes yet to write:");
  Serial.println(bytesToWrite);
  Wire.write(buffer + bytesWritten, bytesToWrite);

  counter++;
}

And called is it:

void requestHandler() {
  char buff[100];
  sprintf(buff, "requestHandler addr:0x%x counter:%d", readAddress, msgReadCounter);
  Serial.println(buff);

  if (readAddress == INIT_MSG_ADDRESS) {
    serveInitCommunication();
  }
}

I've tried moving the serveInitCommunication() into void loop() and setting a just a flag in requestHandler() but without success. Sending up to 32 bytes works fine. Tnx

update: uint8_t twi_transmit(const uint8_t*, uint8_t); so twi library self limit data to 255 bytes

update2: there is a hacker way doing it, by replacing the twi.c twi_txBuffer and twi_txBufferLength with buffer from the sketch

1 Answer 1

1

The limitation is purely in software. The I2C hardware has a limit of one byte at a time, and the software creates a 32 byte buffer and feeds each byte from that in turn.

While it would be perfectly possible to increase that buffer size, you may find you have other problems when you get above 255 bytes, since lots of parameters and internal variables for the library are limited to 8 bit values.

It would also be considered very "hacky" since you can't easily upgrade the Wire library in future.

A better strategy would be to split your data into chunks and make multiple requests, each one saying "Give me chunk number ..." and then recombine them upon reception.

2
  • I have to communicate with existing HW. For now I've passed the data pointer and data size from the sketch into twi.c and using it directly. A "hacky" way indeed. However I'm hoping there is some standard way doing that. Oct 28, 2019 at 10:32
  • 1
    Not using Arduino software, no. It's not designed for that kind of amount of data. Neither, really, was I2C...
    – Majenko
    Oct 28, 2019 at 10:38

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.