Exchanging packets over an nRF24L01+

nrf24l01radioRF

I have two nRF24L01+ chips each attached to a Bus Pirate. I'm trying to write some code to test exchanging packets between them, at first entirely on my laptop before I eventually move out to an AVR chip.

If I set one of the chips in PRX mode and poll the RPD status bit and set the other chip into PTX mode with PLL_LOCK + CONT_WAVE enabled I observe the carrier in the PRX side. So I can confirm most of my code is working and the radio modules themselves are working, as this simple carrier-detect test proves.

However, any attempt to pass a real packet around is utterly failing. Every time I try to send, the PTX module hits a MAX_RT error condition, and the PRX module never sees anything.

The (intended) configuration of the modules is as follows:

RF_DR=2M RF_CH=30 ARD=1500usec ARC=9 AW=5
TX_ADDR=55:AA:55:AA:55 RX_ADDR_P0=55:AA:55:AA:55 RX_PW_P0=16

With additionally the PRX module having PRIM_RX=1 and the PTX module at PRIM_RX=0. I then proceed on the PRX:

FLUSH_RX_FIFO
W_REGISTER(STATUS) to clear the interrupt flags
W_REGISTER(CONFIG) to set PWR_UP
Enable the CE line
Poll NOP, waiting on RX_DR in the returned status

meanwhile on the PTX:

FLUSH_TX_FIFO
W_REGISTER(STATUS) to clear the interrupt flags
W_REGISTER(CONFIG) to set PWR_UP
W_TX_PAYLOAD a 16-byte payload
Enable the CE line
Poll NOP, waiting on either TX_DS or MAX_RT in the returned status

What happens every time is that I eventually get MAX_RT on the PTX module (and see the expected counts in OBSERVE_TX), meanwhile the PRX module never sees anything. I'm now rather stuck for knowing what might be wrong.

I'm unsure if the bug is a mistake in my register configurations, or what else it could be. Here's two dumps of the register values from each module, just before the test:

PTX config:
{
  ARC         => 9,
  ARD         => 1500,
  AW          => 5,
  CONT_WAVE   => 0,
  CRCO        => 1,
  EN_ACK_PAY  => 0,
  EN_CRC      => 1,
  EN_DPL      => 1,
  EN_DYN_ACK  => 1,
  MASK_MAX_RT => 0,
  MASK_RX_RD  => 0,
  MASK_TX_DS  => 0,
  PLL_LOCK    => 0,
  PRIM_RX     => 0,
  PWR_UP      => 0,
  RF_CH       => 30,
  RF_DR       => 2000000,
  RF_PWR      => 0,
  TX_ADDR     => "55:AA:55:AA:55",
}
{
  DYNPD     => 0,
  EN_AA     => 1,
  EN_RXADDR => 1,
  RX_ADDR   => "55:AA:55:AA:55",
  RX_PW     => 16,
}
[00] 08         | 00001000
[01] 3f         | 00111111
[02] 03         | 00000011
[03] 03         | 00000011
[04] 59         | 01011001
[05] 1e         | 00011110
[06] 0e         | 00001110
[07] 1e         | 00011110
[08] 29         | 00101001
[09] 00         | 00000000
[0A] 55aa55aa55 | 0101010110101010010101011010101001010101
[0B] c2c2c2c2c2 | 1100001011000010110000101100001011000010
[0C] c3         | 11000011
[0D] c4         | 11000100
[0E] c5         | 11000101
[0F] c6         | 11000110
[10] 55aa55aa55 | 0101010110101010010101011010101001010101
[11] 10         | 00010000
[12] 00         | 00000000
[13] 00         | 00000000
[14] 00         | 00000000
[15] 00         | 00000000
[16] 00         | 00000000
[17] 01         | 00000001
[1C] 00         | 00000000
[1D] 00         | 00000000

PRX config:
{
  ARC         => 9,
  ARD         => 1500,
  AW          => 5,
  CONT_WAVE   => 0,
  CRCO        => 1,
  EN_ACK_PAY  => 0,
  EN_CRC      => 1,
  EN_DPL      => 0,
  EN_DYN_ACK  => 0,
  MASK_MAX_RT => 0,
  MASK_RX_RD  => 0,
  MASK_TX_DS  => 0,
  PLL_LOCK    => 0,
  PRIM_RX     => 1,
  PWR_UP      => 0,
  RF_CH       => 30,
  RF_DR       => 2000000,
  RF_PWR      => 0,
  TX_ADDR     => "55:AA:55:AA:55",
}
{
  DYNPD     => 0,
  EN_AA     => 1,
  EN_RXADDR => 1,
  RX_ADDR   => "55:AA:55:AA:55",
  RX_PW     => 16,
}
[00] 09         | 00001001
[01] 3f         | 00111111
[02] 03         | 00000011
[03] 03         | 00000011
[04] 59         | 01011001
[05] 1e         | 00011110
[06] 0e         | 00001110
[07] 0e         | 00001110
[08] 00         | 00000000
[09] 00         | 00000000
[0A] 55aa55aa55 | 0101010110101010010101011010101001010101
[0B] c2c2c2c2c2 | 1100001011000010110000101100001011000010
[0C] c3         | 11000011
[0D] c4         | 11000100
[0E] c5         | 11000101
[0F] c6         | 11000110
[10] 55aa55aa55 | 0101010110101010010101011010101001010101
[11] 10         | 00010000
[12] 00         | 00000000
[13] 00         | 00000000
[14] 00         | 00000000
[15] 00         | 00000000
[16] 00         | 00000000
[17] 11         | 00010001
[1C] 00         | 00000000
[1D] 00         | 00000000

Anyone have any suggestions where I go from here?

Best Answer

I have now managed to fix this problem; for posterity I'll explain the solution here.

There turned out to be two problems, neither of which was in fact visible from the config dump pasted above. The configuration is correct. The problems were:

  1. The auto-retransmit delay of 1500usec is fine for tiny packets, but my example program was sending 16-byte packets, for which this delay is too small. Sending a single-byte packet works fine.

  2. The nRF24L01+ needs a power-decoupling capacitor attached close to the chip, as the long power lines in use in my case (laptop -> USB cable -> Bus Pirate -> bus pirate probe cable -> nRF) meant too much of a power dip at just the moment it turns on the transmitter.

Having attached this cap and using 1-byte packets, it seems all to be working fine.