[SOLVED]NRF24L01 in multiceiver mode

Hi Guys

I try to use nrf24l01 in multiceiver mode for some home application.
I'm new with nrf24l01 so since few days i started to play with it in a set-up with 2 arduinos - 1x pro mini and 1x mega each with a nrf module connected. Pro mini doing tx and Mega doing rx.
I use NRF_HAL library (1.0.2 - GitHub - pstolarz/NRF_HAL: Port of Nordic Semiconductor nRF24L01 transceiver's Hardware Abstraction Layer API (NRF HAL) for the Arduino platform.), went to various examples, and everything fine ... till multiceiver mode.

Here are the details how i plan to test this mode
Configure both TX and RX with 5B addr length, 32B payload size, 2B CRC, feature and dyn payload both set to 0
In RX side i enabled 4 pipes 0 to 3 with this addresses

#define PIPE0_ADDR "RCVP0"
#define PIPE1_ADDR "RCVP1"
#define PIPE2_ADDR "2"
#define PIPE3_ADDR "3"

On TX side i defined same addresses but slightly different for pipes 2 and 3

#define PIPE0_ADDR "RCVP0"
#define PIPE1_ADDR "RCVP1"
#define PIPE2_ADDR "RCVP2"
#define PIPE3_ADDR "RCVP3"

Now i took the nrf_rx and nrf_tx examples provide with the library and did some minor modifications for my test

TX side setup() function

hal_nrf_set_address(HAL_NRF_PIPE0, (uint8_t *)PIPE0_ADDR);
hal_nrf_set_address(HAL_NRF_TX, (uint8_t *)PIPE0_ADDR);

and also configured and open pipe 0

hal_nrf_config_rx_pipe(HAL_NRF_PIPE0, NULL, true, NRF_MAX_PL);

RX side in init_rx() function i configured them

hal_nrf_config_rx_pipe(HAL_NRF_PIPE0, (uint8_t *)PIPE0_ADDR, true, NRF_MAX_PL);
hal_nrf_config_rx_pipe(HAL_NRF_PIPE1, (uint8_t *)PIPE1_ADDR, true, NRF_MAX_PL);
hal_nrf_config_rx_pipe(HAL_NRF_PIPE2, (uint8_t *)PIPE2_ADDR, true, NRF_MAX_PL);
hal_nrf_config_rx_pipe(HAL_NRF_PIPE3, (uint8_t *)PIPE3_ADDR, true, NRF_MAX_PL);

Full code is also attached.

Hit start on RX, hit start in TX and got only a timeout message on TX and nothing on RX

Here is the TX output
P0 addr: 52:43:56:50:30
TX addr: 52:43:56:50:30
REG addr: 00 = 0e
REG addr: 01 = 3f
REG addr: 02 = 3f
REG addr: 03 = 03
REG addr: 04 = 05
REG addr: 05 = 14
REG addr: 06 = 07
REG addr: 07 = 0e
REG addr: 08 = 03
REG addr: 09 = 00
REG addr: 0a = 52
REG addr: 0b = c2
REG addr: 0c = c3
REG addr: 0d = c4
REG addr: 0e = c5
REG addr: 0f = c6
REG addr: 10 = 52
REG addr: 11 = 20
REG addr: 12 = 00
REG addr: 13 = 00
REG addr: 14 = 00
REG addr: 15 = 00
REG addr: 16 = 00
REG addr: 17 = 11
REG addr: 1c = 00
REG addr: 1d = 00
TX timeout
TX timeout
TX timeout

And here is the RX output
P0 addr: 52:43:56:50:30
P1 addr: 52:43:56:50:31
P2 addr: 32
P3 addr: 33
REG addr: 00 = 0f
REG addr: 01 = 0f
REG addr: 02 = 0f
REG addr: 03 = 03
REG addr: 04 = 03
REG addr: 05 = 14
REG addr: 06 = 07
REG addr: 07 = 0e
REG addr: 08 = 00
REG addr: 09 = 00
REG addr: 0a = 52
REG addr: 0b = 52
REG addr: 0c = 32
REG addr: 0d = 33
REG addr: 0e = c5
REG addr: 0f = c6
REG addr: 10 = e7
REG addr: 11 = 20
REG addr: 12 = 20
REG addr: 13 = 20
REG addr: 14 = 20
REG addr: 15 = 00
REG addr: 16 = 00
REG addr: 17 = 11
REG addr: 1c = 00
REG addr: 1d = 00
Tuned up, waiting for messages...

I commented out the configuration of the pipe1 to 3 on rx side, power cycle the board and communication started to work

TX output is identical (except message sent successful) and here is the RX output
P0 addr: 52:43:56:50:30
P1 addr: c2:c2:c2:c2:c2
P2 addr: c3
P3 addr: c4
REG addr: 00 = 0f
REG addr: 01 = 01
REG addr: 02 = 01
REG addr: 03 = 03
REG addr: 04 = 03
REG addr: 05 = 14
REG addr: 06 = 07
REG addr: 07 = 0e
REG addr: 08 = 00
REG addr: 09 = 00
REG addr: 0a = 52
REG addr: 0b = c2
REG addr: 0c = c3
REG addr: 0d = c4
REG addr: 0e = c5
REG addr: 0f = c6
REG addr: 10 = e7
REG addr: 11 = 20
REG addr: 12 = 00
REG addr: 13 = 00
REG addr: 14 = 00
REG addr: 15 = 00
REG addr: 16 = 00
REG addr: 17 = 11
REG addr: 1c = 00
REG addr: 1d = 00
Tuned up, waiting for messages...
PIPE: 0
Received: "ard-msg no. 0"
PIPE: 0
Received: "ard-msg no. 1"
PIPE: 0
Received: "ard-msg no. 2"

I said OK and made anew experiment put back the configuration for all pipes (0 TO 3) and switched the communication over pipe 1 which means i configured tx addr and pipe 0 addr on tx side with PIPE1_ADDR.
Hit start on both sides and communication worked again.

Here is the TX output
P0 addr: 52:43:56:50:31
TX addr: 52:43:56:50:31
REG addr: 00 = 0e
REG addr: 01 = 3f
REG addr: 02 = 3f
REG addr: 03 = 03
REG addr: 04 = 05
REG addr: 05 = 14
REG addr: 06 = 07
REG addr: 07 = 0e
REG addr: 08 = 00
REG addr: 09 = 00
REG addr: 0a = 52
REG addr: 0b = c2
REG addr: 0c = c3
REG addr: 0d = c4
REG addr: 0e = c5
REG addr: 0f = c6
REG addr: 10 = 52
REG addr: 11 = 20
REG addr: 12 = 00
REG addr: 13 = 00
REG addr: 14 = 00
REG addr: 15 = 00
REG addr: 16 = 00
REG addr: 17 = 11
REG addr: 1c = 00
REG addr: 1d = 00
Sent message no. 0
Sent message no. 1
Sent message no. 2
Sent message no. 3

And here the RX output
P0 addr: 52:43:56:50:30
P1 addr: 52:43:56:50:31
P2 addr: 32
P3 addr: 33
REG addr: 00 = 0f
REG addr: 01 = 0f
REG addr: 02 = 0f
REG addr: 03 = 03
REG addr: 04 = 03
REG addr: 05 = 14
REG addr: 06 = 07
REG addr: 07 = 0e
REG addr: 08 = 00
REG addr: 09 = 00
REG addr: 0a = 52
REG addr: 0b = 52
REG addr: 0c = 32
REG addr: 0d = 33
REG addr: 0e = c5
REG addr: 0f = c6
REG addr: 10 = e7
REG addr: 11 = 20
REG addr: 12 = 20
REG addr: 13 = 20
REG addr: 14 = 20
REG addr: 15 = 00
REG addr: 16 = 00
REG addr: 17 = 11
REG addr: 1c = 00
REG addr: 1d = 00
or messages...
PIPE: 1
Received: "ard-msg no. 0"
PIPE: 1
Received: "ard-msg no. 1"
PIPE: 1
Received: "ard-msg no. 2"
PIPE: 1
Received: "ard-msg no. 3"

And the last experiment.
With the previous configuration (all 4 pipes enabled) but using pipe2 for communication again communication failure.

What do I miss!!! :confused:

rx-hal.cpp (5.25 KB)

tx-hal.cpp (4.92 KB)

Do you really need to use more than 1 pipe? I never do.

...R
Simple nRF24L01+ Tutorial

The application i have in mind requires multi pipe operation.
Its about to make 1 device to aggregate the input from several sensors and based on the reported values to take some decisions. NRF looks to be designed exactly for this type of applications

ves011:
Its about to make 1 device to aggregate the input from several sensors and based on the reported values to take some decisions. NRF looks to be designed exactly for this type of applications

You can easily do that for dozens of connections with a single pipe on the master nRF24. Just include a byte in each message that identifies the device sending the message.

Or, better still, have the master poll each of the other devices in turn. See the ackPayload example in my Tutorial.

Keep in mind that the nRF24 has only one wireless so it can't receive messages any better by the use of multiple pipes.

...R

Yes definitely there could be several solutions, but that will be an workaround for a built in feature.
Not a nice approach, but in the end functionality matters more than the way it is implemented.

I raised the same question to Nordicsemi. lets see if will get any help.

ves011:
but that will be an workaround for a built in feature.
Not a nice approach

I don't agree. To my mind using multiple pipes is more troublesome - as you seem to be finding out yourself.

If you really do want to use multiple pipes the TMRh20 RF24 library that I use has good documentation and you should also study the Nordic nRF24L01+ datasheet.

...R

Here is the answer i got from Nordic

First off I have to mention that the nRF24L01 has been deprecated for a long time and we don't recommend this device for new designs. We still sell it so we can support existing products in the market, but the support we can provide is limited.

On to the issue, it is possible that this is address related. In general using an address starting with 0x5 or 0xA is not recommended, as it will make the address an extension of the preamble leading to reduced RF performance.

Could you try to change the first byte of the pipe 0 address to something not starting with 0x5 or 0xA and see if it makes a difference?

I did change the pipe names to CHNN0...3 but still same failure.
Finally i took the same addresses from the example in their document "nRF24L01+ Product Specification" - Fig 14. With these addresses pipes 0 and 1 work fine but the others not.

Bottom line it looks this feature has some bugs and quite unlike they will release a new rev of the chip to fix it. So its not something i will relay on :frowning:

I disagree. Study the datasheet again.

Addresses of pipes 2 to 5 have to have the same upper 4 bytes as pipe 1.
Your addresses violate that requirement and will even invoke undocumented behaviour
as you are loading identical addresses to pipes 1 2 and 3 in the second set.

I added the really used addresses behind the ->.

#define PIPE0_ADDR "RCVP0"
#define PIPE1_ADDR "RCVP1"
#define PIPE2_ADDR "2" -> "2CVP1"
#define PIPE3_ADDR "3" -> "3CVP1"
//
#define PIPE0_ADDR "RCVP0"
#define PIPE1_ADDR "RCVP1"
#define PIPE2_ADDR "RCVP2" -> "RCVP1"
#define PIPE3_ADDR "RCVP3" -> "RCVP1"

According to the datasheet registers A and B are 40 bits wide
Receive address data pipe 1. 5 Bytes maximum length.
** (LSByte is written first. Write the number of bytes defined by SETUP_AW)**

while register C to F are only 8 bits wide
Receive address data pipe 2. Only LSB.
** MSBytes are equal to RX_ADDR_P1[39:8]**

and both libraries RF24-master and NRF_HAL-master, pipe address configuration function is different depending on pipe number.
For pipes 0,1 it writes a number of bytes equal to address length while for pipes 2 to 5 it writes only 1 byte.

ves011:
According to the datasheet registers A and B are 40 bits wide
Receive address data pipe 1. 5 Bytes maximum length.
** (LSByte is written first. Write the number of bytes defined by SETUP_AW)**

while register C to F are only 8 bits wide
Receive address data pipe 2. Only LSB.
** MSBytes are equal to RX_ADDR_P1[39:8]**

and both libraries RF24-master and NRF_HAL-master, pipe address configuration function is different depending on pipe number.
For pipes 0,1 it writes a number of bytes equal to address length while for pipes 2 to 5 it writes only 1 byte.

I know. So what?

Does that change your misunderstanding of byte order in memory and resulting effective addresses?

#define PIPE0_ADDR "RCVP0"
#define PIPE1_ADDR "1RCVP"
#define PIPE2_ADDR "2RCVP"
#define PIPE3_ADDR "3RCVP"

could work, pipe 0 can be any address, the limitations are imposed on pipe 2-5 only.

If i would use
#define PIPE2_ADDR "RCVP2"

then this function
hal_nrf_config_rx_pipe(HAL_NRF_PIPE2, (uint8_t *)PIPE2_ADDR, true, NRF_MAX_PL);
will write 'R' in register 0c which will end with the address "RCVPR"

isnt it?

No, it isn't.

It will load the lowest byte (which is the first in memory and strings) with 'R'.

So the resulting address is "R1111" with the '1's representing bytes of pipe 1.

i might be wrong. Will give tomorrow a try

You will see the chip works just as advertised.

Sometimes the datasheet could be clearer, but all information is in there and I did not find any technical error so far.

Even some of the quirks are specified if you look very closely.

I'm using multiple pipes with different ack characteristics all the time. :wink:

yes i was wrong and you are right :slight_smile: (damn mistake)

On my set-up it works even with address starting with 0x5 or 0x5a, but it might have some impact in performance according to Nordic.

thx Whandall!!!

ves011:
On my set-up it works even with address starting with 0x5 or 0x5a, but it might have some impact in performance according to Nordic.

I doubt that.

The preamble bytes are 0x55 or 0xAA depending on the first byte (highest) of the addressed pipe,
so there is no risk that your address may be seen as a preamble extension.

You should avoid many adjacent zeros or ones in the pipe addresses to minimize false packet detection
by making the beginning of the packet more unique.
For me printable chars as address bytes worked without any noticable problem.

I'm glad I could help you.

It would be nice if you could add a [SOLVED] tag to the thread title.

Whandall:
Even some of the quirks are specified if you look very closely.

I think much about the chip is quirky.

First, the transmitted packed doesn't contain the source address, just the destination address. So, in order to auto-ACK, the PRX must send the reply on the address it was just listening to while the PTX must listen on the address it just sent to.

As a result, the whole "pipe" concept is implemented backwards (IMHO). Rather than listening to different address on different pipes, the PRX should listen to a single address that any PTX could send to. The receive pipes would be assigned by SOURCE address. Then, the PRX hardware could filter the received packets into different "pipes" based on the SOURCE address. Thus, when a packet arrived at a given pipe, the PRX would know which PTX sent it.

gfvalvo:
Then, the PRX hardware could filter the received packets into different "pipes" based on the SOURCE address. Thus, when a packet arrived at a given pipe, the PRX would know which PTX sent it.

Considering that Nordic considers the chip to be obsolete I reckon it's a bit late to change it :slight_smile:

The Pipe systems seems to me the equivalent of mail arriving through one letter box for several residents in a block of flats. The mail all falls on the mat and somebody picks it up and sorts the envelopes into the pigeon holes for the different residents.

Frankly I have never seen any value in this. I prefer to use a single pipe and include a byte in the message that identifies the sender - which achieves the system you suggest.

...R

Robin2:
I prefer to use a single pipe and include a byte in the message that identifies the sender - which achieves the system you suggest.

True, although "my" implementation of the pipes would have the identification process done by hardware.

Though, as noted, the point is moot given that the chip has been deprecated.