[Solved] nRF24L01 pipe "addresses" - have I gone mad!

Hi All,

I've just started out with the nRF24L01+ boards and have several of them linked to Arduino ProMini's and Arduino Uno's. After trying out the basic examples in the "Simple nRF24L01+ 2.4GHz transceiver demo" thread (thankyou Robin), i've started to put together my own setup.

I've come up with some human readable node addresses for my pipes such that:
Device#1: Pipe0="N001a", Pipe1="N001b", ... Pipe5="N001f"
Device#2: Pipe0="N002a", Pipe1="N002b", ... Pipe5="N002f"

I thought that this would then comply with the node addressing requirements of Figure 13, Page 40 of the nRF24L01+ datasheet, such that pipes 2->5 would have the unique LSByte of either 'c','d','e' or 'f'.

However, I started running into problems and decided to try out the CheckConnection code posted by Robin from forum.arduino.cc/index.php?topic=421081.0 post #29.

So the basic code from post #29 works fine and produces the detailed information.

I then modified that code to replace the single slave address with 6 different addresses:

const byte thisSlaveAddress[][5] ={ {'R','x','A','A','1'},
                                    {'R','x','A','A','2'},
                                    {'R','x','A','A','3'},
                                    {'R','x','A','A','4'},
                                    {'R','x','A','A','5'},
                                    {'R','x','A','A','6'} };

And replaced the one line openReadingPipe() call with code to open 6 reading pipes:

    radio.openReadingPipe(0, thisSlaveAddress[0]);
    radio.openReadingPipe(1, thisSlaveAddress[1]);
    radio.openReadingPipe(2, thisSlaveAddress[2]);
    radio.openReadingPipe(3, thisSlaveAddress[3]);
    radio.openReadingPipe(4, thisSlaveAddress[4]);
    radio.openReadingPipe(5, thisSlaveAddress[5]);

The code runs and produces the following output:

STATUS		 = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	 = 0x3141417852 0x3241417852
RX_ADDR_P2-5	 = 0x52 0x52 0x52 0x52
TX_ADDR		 = 0xe7e7e7e7e7
RX_PW_P0-6	 = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA		 = 0x3f
EN_RXADDR	 = 0x3f
RF_CH		 = 0x4c
RF_SETUP	 = 0x23
CONFIG		 = 0x0e
DYNPD/FEATURE	 = 0x00 0x00
Data Rate	 = 250KBPS
Model		 = nRF24L01+
CRC Length	 = 16 bits
PA Power	 = PA_LOW

What's confusing is the pipe names. Rx Pipe 0 address is 0x3141417852='1AAxR' and Rx pipe 1 address is 0x3241417852='2AAxR'. Rx Pipes 2->5 all have the address 'R'.

I'm currently looking through the source code of the RF24 library (TMRh20 v1.3.4) to see if there's an error in the way the addresses are written to the registers or maybe simply an error in the way printDetails() is presenting the results.

Has anybody else seen this behaviour?

Thanks.

I thought i'd answer my own query in the hope that it helps somebody else out.

It seems that you need to define the 5 byte address in reverse order for it to be presented correctly to the onchip pipe address registers.

Simply changing the addresses to:

const byte thisSlaveAddress[][5] ={ {'1','A','A','x','R'},
                                    {'2','A','A','x','R'},
                                    {'3','A','A','x','R'},
                                    {'4','A','A','x','R'},
                                    {'5','A','A','x','R'},
                                    {'6','A','A','x','R'} };

This produces the expected results and I can also send messages to each specific receive pipe and receive the ACK back.

It seems part of the reason my code may have gone wrong before is that in specifying the Rx pipe addresses forwards, I ended up with Rx pipes 2->5 having the same address, i.e. they all had the byte 'R' as their unique byte.

According to the datasheet (bottom of page 39): "Note: Always ensure that none of the data pipes have the same address."

Anyway, hope that helps somebody else out.

Thanks for that. I confess I had not thought about it although, now that you mention it, I was vaguely aware that the data was used in the reverse order.

I have never needed to use more than one pipe even with projects that communicate with several nRF24 equipped Arduinos.

...R

PS ... your Title could be a source of confusion - they are not pipe names, they are addresses as you correctly state in your text. If you modify your Original Post you can change the Title.

Title changed.

I'm hoping to setup a system with only 2 Rx pipes - a broadcast receive pipe (that all nodes have) and a second pipe with a unique address for each node.

I'm now doing battle with the Ack mechanism to try and get the Tx to send a message to the broadcast address so that each Rx doesn't send back an Ack.

Mark.

markd833:
I'm now doing battle with the Ack mechanism to try and get the Tx to send a message to the broadcast address so that each Rx doesn't send back an Ack.

If you mean that a receiver should not send and acknowledgement for some messages and should send it for other messages I think you will have a problem because AFAIK the acknowledgements apply to the module rather than an specific pipe.

Two thoughts ...

Is there any real value in sending a broadcast message rather than sending a series of individual messages?

OR

If you include a slaveID in the broadcast message then the slave that detects its own ID in the message could transmit a reply to the master while all the other slaves stayed silent. In other words there would be no need for individual messages.

My own preference would be for individual messages and the reassurance that an acknowledgement gives.

...R

Thanks for the insight Robin.

After lots of variations of code I managed to get my scenario working with 2 simple changes.

I have a "base" node that is essentially the data collector for all the other nodes. This node has 1 receive pipe in use.

I have a number of other nodes that have various sensors that provide reading back to the data collector node. They use 2 receive pipes: pipe 0 has the same address on all nodes & pipe 1 has a unique address.

That way the base node can notify all the other nodes at once (via rx pipe 0) in 1 message with, say, a time or a request to reset something. The base node can also communicate with each node individually (via rx pipe 1).

The way I got it to work was to enable the dynamic ack for the radio in setup(). Then when I want to communicate with the node(s), I used the 3 parameter version of write(), setting parameter 3 to true when I don't want an ack, and setting parameter 3 to false when I do want an ack.

I can post the code here if you think it would help others out?

Mark.

1 Like

markd833:
The way I got it to work was to enable the dynamic ack for the radio in setup(). Then when I want to communicate with the node(s), I used the 3 parameter version of write(), setting parameter 3 to true when I don't want an ack, and setting parameter 3 to false when I do want an ack.

I don't think I ever noticed that version of write() - good of you to point it out
bool writeFast (const void *buf, uint8_t len, const bool multicast)

...R