NRF24L01+ and writeAckPayload

I am trying to use the NRF24L01+ in a peer to peer association between two Arduinos. Neither is a master nor a slave and both the NRFs are in listening mode.

An event happens in one Arduino, it goes into writing mode, sends a message to the other Arduino, reads the ack payload form the target and then goes back to listening. My code does this correctly.

The response of the receiving Arduino can only determined after it has read the data it has been sent.
Initially I thought I could use writeAckPayload to put the appropriate data into the ack payload and the original sender would then get the required information.

I am using ManiacBug, TmrH20 and StanleySeow libraries which are essentially the same at what appears to be the critical code which is the function writeAckPayload.

I get an ack payload back into the original sender just after the write with a read and this confirms that the message has been received.

I was really hoping that ack payload could have been filled with the data that should be sent back BUT IT ISN’T.
The returned ack payload in fact contains the data that was set in the previous call to writeAckPayload. The data is always one call behind.

In the library function

void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len)
{
  const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);

  uint8_t data_len = min(len,32);

  #if defined (__arm__) && ! defined( CORE_TEENSY )

  SPI.transfer(csn_pin, W_ACK_PAYLOAD | ( pipe & B111 ), SPI_CONTINUE);
  while ( data_len-- > 1 ){
    SPI.transfer(csn_pin,*current++, SPI_CONTINUE);
  }
  SPI.transfer(csn_pin,*current++);

  #else
  csn(LOW);
    
  SPI.transfer(W_ACK_PAYLOAD | ( pipe & B111 ) );

  while ( data_len-- )
    SPI.transfer(*current++);
    

  csn(HIGH);

  #endif
}

It looks like the ack payload is called and then loaded with the data (in buf) afterwards, thereby making it ready for the next call. So using the data that was previously there.

I rather hopefully thought this was a bug and moved the code to send the ack payload
SPI.transfer(W_ACK_PAYLOAD | ( pipe & B111 ) );
after copying the buffer but alas it causes subsequent read calls to fail.

I’m sure in some documentation I read that this is the way it is but my brain says to be there must be a way to update the ack payload before it gets sent back.

Anyone been here and solved the problem or can simply confirm it can’t be solved.

I do have a work around but getting the writeAckPayload function to do what I want would be much nicer.

Cheers.

It's quite obvious that ack payload has to be preloaded.

Just send two requests, the second will have fresh data.

I was hoping there was a way to register a callback that was invoked prior to the ack response.

The library documentation does say "next time" so perhaps it would be better if the function was called "fillAckPayloadFor NextAckReply"...

Time to work with what we have.

Just send your request data twice.

And don't forget to preload the very first payload.

Whandall:
Just send your request data twice.

And don't forget to preload the very first payload.

Another oversight in the examples!

acboother:
Another oversight in the examples!

Not so in @Robin2's code, I remember we added that a long time ago.

Most people don't really understand the preload necessity of the ACK payload.

As you said, it is what it is. The double request is a simple workaround, if you really need fresh data.

IMHO it is better not to have direct dependencies between a packet and its ACK payload.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.