This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PTX with dyn ack, sleep problem

Hi, There's a problem when using dynamic ack with return payload plus timer/sleep. Sending a single packet doesn't work. sending two packets works. not sleeping/using timer works. I've attached details (and code) files. Thanks in advance for your help! Best, Mahesh

OVERVIEW:

------------

The PTX device needs to send data to PRX and get ACK and a return payload of data. It should then SLEEP for two seconds, wake up, and do it all over again. It does not work properly. PTX and PRX C files (ptx-main.c, prx-main.c) are attached and the output for 3 test cases follow.

Case 1: WORKS (but we don't need this): wake, send data continuously. packets are received and the return ack payload is received by PTX.

Case 2: DOES NOT WORK (but we want this!!!): send ONE packet, sleep. PRX IRQ is fired ONLY the first time. PTX, strangely, gets an ack BUT it always has only the data from the first (and only) return packet.

Case 3: WORKS (but we don't need this): wake, send TWO packets, sleep. both packets are received and the return ack payloads are received by PTX.

PTX & PRX OUTPUTS:

----------------------

TEST CASE 1: (send packets continuously, no sleep)
-------------------------------------------------------------------
PTX:
Sent. Ack pack:length:32, Payload: C9, 02, 03
Sent. Ack pack:length:32, Payload: CA, 02, 03
Sent. Ack pack:length:32, Payload: CB, 02, 03
Sent. Ack pack:length:32, Payload: CC, 02, 03
Sent. Ack pack:length:32, Payload: CD, 02, 03
Sent. Ack pack:length:32, Payload: CE, 02, 03
Sent. Ack pack:length:32, Payload: CF, 02, 03
Sent. Ack pack:length:32, Payload: D0, 02, 03
Sent. Ack pack:length:32, Payload: D1, 02, 03
Sent. Ack pack:length:32, Payload: D2, 02, 03
Sent. Ack pack:length:32, Payload: D3, 02, 03
Sent. Ack pack:length:32, Payload: D4, 02, 03
Sent. Ack pack:length:32, Payload: D5, 02, 03
Sent. Ack pack:length:32, Payload: D6, 02, 03
Sent. Ack pack:length:32, Payload: D7, 02, 03
Sent. Ack pack:length:32, Payload: D8, 02, 03
Sent. Ack pack:length:32, Payload: D9, 02, 03
Sent. Ack pack:length:32, Payload: DA, 02, 03
Sent. Ack pack:length:32, Payload: DB, 02, 03
PRX:
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
(etc...)
TEST CASE 2: (send one packet, then go sleep, repeat)
-------------------------------------------------------------------
PTX: gets a first ACK payload, but it never gets updated. PRX sends only one and never again.
woke up:
Sent. Ack pack:length:32, Payload: 1B, 02, 03
woke up:
Sent. Ack pack:length:32, Payload: 1B, 02, 03
woke up:
Sent. Ack pack:length:32, Payload: 1C, 02, 03
woke up:
Sent. Ack pack:length:32, Payload: 1C, 02, 03
(etc...)
PRX: (prints the following ONCE, and that too, not always)
got packet!
TEST CASE 3: (sending two packets, then going to sleep, and repeat)
-------------------------------------------------------------------
PTX: (byte #1 of payload increments, my packet counter)
woke up:
Sent. Ack pack:length:32, Payload: 7C, 02, 03 -------> packet 1
Sent. Ack pack:length:32, Payload: 7D, 02, 03 -------> packet 2
woke up:
Sent. Ack pack:length:32, Payload: 7E, 02, 03
Sent. Ack pack:length:32, Payload: 7F, 02, 03
woke up:
Sent. Ack pack:length:32, Payload: 80, 02, 03
Sent. Ack pack:length:32, Payload: 81, 02, 03
woke up:
Sent. Ack pack:length:32, Payload: 82, 02, 03
Sent. Ack pack:length:32, Payload: 83, 02, 03
woke up:
Sent. Ack pack:length:32, Payload: 84, 02, 03
Sent. Ack pack:length:32, Payload: 85, 02, 03
woke up:
Sent. Ack pack:length:32, Payload: 86, 02, 03
Sent. Ack pack:length:32, Payload: 87, 02, 03
woke up:
Sent. Ack pack:length:32, Payload: 88, 02, 03
Sent. Ack pack:length:32, Payload: 89, 02, 03
woke up:
Sent. Ack pack:length:32, Payload: 8A, 02, 03
Sent. Ack pack:length:32, Payload: 8B, 02, 03
PRX:
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
got packet!
(etc....)

prx-main.c

ptx-main.c

  • Hi, I really need to get it done this week (deadline); I'd greatly appreciate it if you could send me a response today! Thanks!! Mahesh

  • Hi Mahesh,

     

    It looks like your application relies on reading the data from the PTX, then bouncing the data back via ACK payload dynamically. In such a scenario you will have to send two payloads from the PTX to successfully receive the ACK-payload.

    Case 2 does not work because there's not enough time for the PRX to upload the ACK payload. Therefore you must send another one to fetch the ACK-payload.

     

    The recommended procedure is:

    * PTX sends "ack payload prepare" to PRX

    * PRX uploads ACK-payload

    * PTX sends "fetch ACK-payload" command to PRX

    * PRX sends ACK with payload back to PTX device.

     

    Based on this, case 3 is the recommended procedure.

     

    Best regards,

    Håkon

  • Hi Håkon,

    I don't quite understand.

    Case 2 is Wake, send 0, sleep, where PTX gets an ack but not the ack payload.

    Case 3 is wake, send 1, send 2, sleep. where PTX gets BOTH the ack payloads ackp1 and ackp2 (which have different data in them).

    Both case 2 and 3 end with send, sleep (for 2 seconds). Why would case 3 get ackp3?

    In case 2, I've tried putting in a delay before sleep: wake, send 0, delay_ms(1000), sleep. Makes no difference.

    Thanks!

    Mahesh

  • Hi Mahesh,

     

    In order for the PRX device to send an ACK-payload, this has to be updated to a specific RF pipe.

    If you are, on the PRX, uploading this to the radio at the time of receiving a packet, the hardware simultaneously controlling the radio and performing the RX->TX turnover. At this point, you have a race-condition between the CPU and the radio-hardware, and you're not guaranteed to successfully upload the ACK-payload before the radio has started transmitting the empty ACK.

     

    This is the reason why case 3 will work. You send one TX-payload, the PRX is then able to upload the ACK, then you send a new TX-payload to fetch the ACK-payload.

     

    Best regards,

    Håkon

  • Hi Håkon,

    Do you mean that if the PTX asks for ACK+payload, the PRX radio will AUTOMATICALLY send an ACK + the payload ALREADY in its buffer? The PRX CPU has NO control over this, correct?

    Does this mean that calling hal_nrf_write_ack_payload(pipe, payload_data, length) on the PRX ONLY "uploads" the packet to the radio and DOES NOT actually send the ACK packet out? So it's best to have the PRX radio "primed" with the ACK packet as far as possible. Correct?

    Thus, if no new ACK packet is uploaded to the PRX radio by its CPU, it will send the SAME ACK packet to the PTX over and over and over again. Correct?

    This is a race condition that could happen:

    1. PTX sends a packet, asks for ACK+packet.

    2. PRX radio raises an IRQ.

    3. PRX CPU then (because of my code) starts assembling an ACK packet and then uploads it to the radio by calling hal_nrf_write_ack_payload, which uploads it using SPI.

    4. In the meantime, PRX radio is AUTOMATICALLY getting ready to send out the ACK packet.

    5. PRX radio sends out an ACK packet. The PRX CPU **may** have updated the ACK packet buffer in the radio before it was sent out... or not. Race condition, we don't know what will happen.

    THUS, a good solution is to have PTX send a packet, notifying PRX that an ACK packet will be required soon. PRX then hurries up, creates a packet and uploads it to its radio by calling hal_nrf_write_ack_payload(). PTX now sends a second packet. PRX gets this packet too and since the ACK packet is already uploaded into the PRX radio's buffer, it is AUTOMATICALLY sent out with no interference from the CPU.

    So, use the first packet to get the ACK packet ready. Then when the second packet comes, DO NOTHING, and the ACK packet will be sent out AUTOMATICALLY.

    BTW, this is how I set PTX to ask for ACK + payload:

    hal_nrf_setup_dynamic_payload(0xFF);// Enable dynamic payload on all pipes

    hal_nrf_enable_dynamic_payload(1); //Enable Dynamic payload

    hal_nrf_enable_ack_payload(1); // Enable ACK with payload

    hal_nrf_enable_dynamic_ack(1); // need this to be able to get & read ack payload sent by prx.

    D. What do you mean by "this has to be updated to a specific RF pipe?" Shouldn't the PRX use the same pipe on which the RX packet was received to transmit the ACK packet? 

    Thanks!

    Mahesh

Related