I2C sending byte array problem

I have been working on a project where i have 2 arduinos, one gets a data from nrf24l01 module (i2c slave) and the other one (i2c master) requests the received data via i2c and controls 4 motors depending on the nrf24l01 data. The problem is the following: i know that slave receives data from nrf24l01 as it should, so no problem there, but when the master requests data (exactly 4 bytes) the slave sometimes sends identical bytes - all the exact value the last array byte holds. Sometimes it works perfectly, but then sometimes it happens one transmittion is successful but the second one is false, sometimes it happens all of the sent data is false.
I have both i2c wires pulled up with two resistors, both 3K3.
The way this works exactly is - the slave first gets a value from radio module, then signals the master that its ready for transfer (i did this so the master doesnt interfere with slave while its getting info from radio) . When the master sees the signal is high, it requests data. When data is transfered the slave turns off the signal and goes on to get data from radio again. So slave loops like that. In the meanwhile, when master gets the data from the slave, it then processes the data and makes an output (at this moment its just serial.print).
I will also post the code and the serial output.

Some things to note:
The rate of successful transfers vs the false ones also depends on which serial prints i comment/uncomment. So i assume it has to do something with timing?

master.ino (2.35 KB)

slave.ino (1.29 KB)

  while (wait == true) { //this while loop contains the code for nfr24l01 radio module

    while (radio.available()) {
      bool done = false;
      while (!done) {
        done = radio.read(msg, 4);
        digitalWrite(7, HIGH);
        wait = false;
      }
    }
    wait = false;
  }

The second “wait=false” should not be there. When you first enter the outer loop, there is no guarantee that there’s a radio message waiting, but you set wait to false anyway which causes you to exit the loop and signal the master that you have data.

Pete
BTW. You really don’t need to attach such small files. Nor do you need to post a 141kB photo of what could be copied and pasted as text. In each case they can be posted in code tags - see How to post code properly.

      while (!done) {
        done = radio.read(msg, 4);
        digitalWrite(7, HIGH);
        wait = false;
      }

This code will not compile on the better/newer NRF24 library http://tmrh20.github.io/RF24/index.html, read() is a void function in this library.

That while loop is not very sensible anyway, silently discarding packets is normally counterproductive.

void loop() {

  waitTime = 0;
  while (wait == true) {
  msg[0] = analogRead(A0)/4;
  msg[1] = analogRead(A1)/4;
  msg[2] = analogRead(A2)/4;
  msg[3] = analogRead(A3)/4;
  wait = false;
  }

  if (wait == false) {
    digitalWrite(slaveReady, HIGH);
  }

}

For purposes of explanation, you can just change the radio code to just getting the values from direct analogRead on the slave.

My code was kinda messy and big, so i actually removed a lot of it so it was as simple as possible. So yeah, the second wait = false; is unnecessary. The reason for the while loop when getting info from radio is also because i will have to also count in the fact that this arduino might not get the signal from the transmitter, so i actually used this:

    if (radio.available()) {
      bool done = false;
      while (!done) {
        done = radio.read(msg, 4);
        digitalWrite(7, HIGH);
        wait = false;
      }
    }

So it skips the radio if its not available, and it stays in the while loop for 15 iterations, then it lowers the thrust and gets out of the loop.

Anyways, does anyone know the timings that you need to include when using wire library? For example, i thought the problem causer was that when master requests data from the slave, i didnt do any delay (since the slave has to acknowledge the request. So i put a delay there:

  if (digitalRead(comReady) == HIGH) {
    Wire.requestFrom(1, 4);    //(device addr, # of bytes)
    delayMicroseconds(200); //this delay here
    while (Wire.available()) {
      for (i = 0; i <= 3; i++) {
        dataFromCOM[i] = Wire.read();
      }
    }
  }

Despite the slave requiring less than 50us to respond, i still increased the delay to 1ms, but still same problem. I still think that this delay is unnecessary since you have the while(Wire.available()){} so it probably waits for the slave to acknowledge.

I will try fixing this with additional changes to the code, but if anyone has any idea why this is happening, please let me know.

And i really dont use the forum that much, so apologies for incorrect use of code posting.

Thank you both for the replies.

Again:

      done = radio.read(msg, 4);

This code will not compile on the better/newer NRF24 library http://tmrh20.github.io/RF24/index.html, read() is a void function in this library.

So if you can compile it, you are using an outdated and known buggy library.

I am using this one: https://github.com/maniacbug/RF24 I guess this one is the old one. I will download and install the updated one. Thanks for your help