nrf24l01+ Bidirectional link using W_ACK_PAYLOAD

Discussion about wireless devices

nrf24l01+ Bidirectional link using W_ACK_PAYLOAD

Postby Ray » Thu Jan 28, 2010 10:19 am

I've managed to get data in both directions using enhanced shockburst with the auto-ack enabled. The PTX sends to the PRX which in turn activates the TX function and sends back to the PTX and so on.

I notice that on the datasheet, they whisper about the W_ACK_PAYLOAD command. This should allow the Receiver to send a payload with the ACK packet back to the transmitter.

If this is possible, then it would most likely allow a bidirectional link without the receiver having to put itself specifically into transmit mode and then send a regular packet. There would be a lot less overhead in theory and there would be a higher data rate. It would not be as reliable a link as with both specifially sending and receiving with ACK's but it would be good enough to get data back from the receiver with the packet.

So I've been trying to figure out how to use the excellent library by Brennen to add in the W_ACK_PAYLOAD part.

So far I've come up with these additions:

nrf24l01.h

#define nrf24l01_W_ACK_PAYLOAD 0xA8
#define nrf24l01_W_TX_PAYLOAD_NACK 0xB0
#define nrf24l01_ACTIVATE 0x50
#define nrf24l01_DYNPD 0x1C
#define nrf24l01_FEATURE 0x1D



main unit:

//setup the dynamic packets and put the data into the W_ACK_PAYLOAD to send with the next ACK
nrf24l01_write_register(nrf24l01_ACTIVATE,0x73,1,false);
nrf24l01_write_register(nrf24l01_ACTIVATE,0x73,1);
nrf24l01_write_register(nrf24l01_DYNPD,0x01,1);
nrf24l01_write_register(nrf24l01_FEATURE,0x06,1);
nrf24l01_clear_csn();
nrf24l01_execute_command(nrf24l01_W_ACK_PAYLOAD,&data[1], 32, true);
nrf24l01_set_csn();
nrf24l01_write_register(nrf24l01_ACTIVATE,0x73,1);

nrf24l01_set_as_rx(true);

for(count = 0; count < 2000; count++) //a 2000 timeout to stop the chip from waiting forever if there is no received data.
{
if (nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active())
{
nrf24l01_read_rx_payload(&data[1], 32); //get the payload into data
nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01
break; //data came in so exit this loop
}
}

Now my questions:
1. Is it correct to be using the write_register() function to put the data into the registers?
2. Am I writing the correct data to the registers?
3. Is the order correct?
4. In the transmitter code, how do I read it? I am currently just using the nrf24l01_read_rx_payload(&data[1], 32); after I send the packet - i.e. after the ACK is received from the Receiver
Ray
 
Posts: 1
Joined: Thu Jan 28, 2010 10:02 am

Re: nrf24l01+ Bidirectional link using W_ACK_PAYLOAD

Postby brennen » Fri Jan 29, 2010 10:14 am

1. Is it correct to be using the write_register() function to put the data into the registers?
Yes, this should work fine.

2. Am I writing the correct data to the registers?
Since I can't see all your code, notice that the datasheet says, "A new ACTIVATE command with the same data deactivates them again. This is executable in power down or stand by modes only." Therefore, make sure you only write the ACTIVATE register *once* (it appears you are writing it at least twice in this code), and you are either in standby or power down when you do it (i.e., when CE is *low*). I would probably initially test DYNPD by enabling auto-ack on all pipes instead of pipe 0. I also *would not* enable dynamic payload length in the FEATURE register until you get payload with ACK working first. Also, take out the calls to clear_csn() and set_csn(), as those are already handled in the driver functions.

3. Is the order correct?
I would probably set up the FEATURE register and the EN_AA register before setting up the DYNPD register, but it shouldn't matter. You should also remove all writes to the ACTIVATE register except for the second one you have in the code below (the first one should have caused a syntax error).

4. In the transmitter code, how do I read it? I am currently just using the nrf24l01_read_rx_payload(&data[1], 32); after I send the packet - i.e. after the ACK is received from the Receiver
It doesn't really seem to specify how to read it in the manual, so I assume that you're write by reading the RX payload.
brennen
Site Admin
 
Posts: 157
Joined: Sun Aug 17, 2008 10:15 am

Re: nrf24l01+ Bidirectional link using W_ACK_PAYLOAD

Postby zristic » Mon Feb 08, 2010 6:04 am

I finally got it working. My source code is a bit messy at the moment, but I will post it when I get it organized. It is entirely written in mikroPascal as a part of a commercial project, but I will publish a portion which sets the ack payload feature.

The few main points are:
1. Turn on dynamic payload,
2. Turn on ack payload feature,
3. Make sure that the ARD is set to at least 500us,
4. Prepare the ackpayload data on Rx side before any data arrives,

Points 1. and 2. are done by writing 0x06 to the Feature register. After setting the Feature register, read it back. If it returns zero then call the Activate command with the parameter 0x73. Then set the feature register again.

Reading the payload on Tx side is done simply by reading the RxBuff register.

I am doing tests at the moment, so far I am very happy with how it works.
zristic
 
Posts: 3
Joined: Sat Apr 25, 2009 10:38 am

Re: nrf24l01+ Bidirectional link using W_ACK_PAYLOAD

Postby zristic » Tue Mar 02, 2010 4:12 pm

Here are pieces of my code which is a part of a commercial project, so I cannot reveal all the details, but I am sure this will be more than enough to make ACK PYLD feature working.
I hope you guys can read Pascal, at least we learned it in school at the beginning of our programming days. Let's not forget it, it is such a beautiful language. :ugeek:

1. 2. Turn on dynamic payload and ack payload:
Code: Select all
 
procedure TurnOnAckPayload;
var temp, buffer: byte;
begin
  temp := Read_Register(Feature);  // read feature Register

                                   // prepare the data for writing to the feature register
  buffer := temp or 0x06;          // turn on ack payload and dynamic payload
  Write_Register(Feature, buffer); // write to the feature register

  temp := Read_Register(Feature);  // read feature Register to see if the setting has taken effect
  if temp = 0 then                 // no success, execute the "Activate" command and try again
     begin
       buffer := 0x73;
       Write_Command(Activate, buffer);
                                   // prepare the data for writing to the feature register
       buffer := temp or 0x06;     // turn on ack payload and dynamic payload
       Write_Register(Feature, buffer); // write to the feature register
     end;
end;


3. Make sure that the ARD is set to at least 500us:

Code: Select all
  buffer := 0xFF;  // max Number of retries = 15; 4ms between two retries
  Write_Register(Setup_Retr, buffer);


4. Prepare the ackpayload data on Rx side before any data arrives:
Code: Select all
  // write some data to the outgoing buffer
  PayLoadBuff[0] := 0;
  PayLoadBuff[1] := 1;
  PayLoadBuff[2] := 2;
  ... etc
  // clear the previous payload buffer, it might not have been sent yet
  FlushTxBuffer();
  // put the new payload data into the outgoing buffer
  write_ack_payload(PayLoadBuff, 0);
  // now we wait for the Tx to call us:
  while IRQ <> 0 do
    begin
      // do something while waiting
    end;


Here are some auxiliary functions:

Code: Select all
procedure write_ack_payload(var payload : array[20] of byte; pipe : byte);
var i, buffer : byte;
begin
  Write_Register(w_ack_payload, pipe);
  for i := 0 to 19 do
    begin
        buffer := payload[i];   
       Write_Register(w_ack_payload, buffer);
    end;
end;


Flushing the Tx Buffer
Code: Select all
procedure FlushTxBuffer();
begin
  //flush The Tx_fifo Buffer
  Write_Command(Flush_tx);
end;


This is what i did in order to make the ACK PAYLOAD feature work on NRF24L01 and L01+.
I am using this code for some time now. It is not perfectly organized, but at least it is working for me.
Any suggestions/improvements are welcomed.
zristic
 
Posts: 3
Joined: Sat Apr 25, 2009 10:38 am


Return to Wireless

Who is online

Users browsing this forum: No registered users and 1 guest

cron