nrf24L01 -- broadcasting and polling

I have questions below. This is about the using of nrf24l01, particularly the using of “broadcasting” and “polling” of the radio data, in the same code.

(1) When ACK is “ON” on the Master device, does it mean when Master receives a radio from Slaves, it will automatically send an ACK to Slaves? or it means when the Master device broadcasts a radio to Slaves, it will ask Slaves to reply back the ACK? I am confused if this is one-way or two-way? The answer will help me determine to set ACK ON or OFF on the Master and Slaves.

For my application, I want Master to broadcast a radio “once per second” to all Slaves to activate them to start collecting a time sensitive measurement at exactly the same time, and Master do not need Slaves to reply back the ACK. I assume i need to set “Retries” to be (0,0) because Master can send only one synchronization radio per second. With ACK set to OFF on both Master and Slaves, things shall work for this step, based on my experience.

(2) After above step, Master needs to poll all Slaves’ measured data back, without the lost or missing of measured data, and of course before Master’s next broadcasting, and this is where I have problems. I command Master to Poll Slaves’ measured data, one by one, because if all Slaves send the data to Master at the same time, collisions will occur. Unfortunately, for the tests I have done, Master always miss some Slaves’ data, and I suspect the issue is related to ACK and Retries? Please note that when we do the first step (1), the ACK is set to OFF and the Retries is set to (0,0), and when I do the step (2), I found switching ACK from OFF to ON will cause the communication to fail. If I can reset ACK to be ON, i will like to change the Retries, so slaves can send the measured data to Master.

If we are doing only (1) or only (2), there are lots of working examples out there, but I am trying to do both, actually (1) first then (2), and keep repeating (1) and (2). So far I have not succeed. Attached please see Arduino codes of Master and the 1st Slave. You will need 6 nrf24l01 to test, one for master and 5 for slaves. Please advise me if you can have solutions to ensure Master to receive Slaves’ measured data without missing. Thanks

master.ino (4.6 KB)

slave1.ino (2.34 KB)

When ACK is enabled it is a two-way process. The device that sends a message expects to get an automatic acknowledgement from the device the message is sent to.

If you want to send a message that will be received by several devices then you must ensure that not more than one of the receiving devices has ACK enabled or else they will all send an ack and everything will be garbled. If you turn off ACK on the Master then there is no need for any of the slaves to send an ack

If the Master polls the slaves one at a time (a round-trip message is very fast - less than 5 millisecs) then you can have ACK enabled for everything.

The examples in this Simple nRF24L01+ Tutorial may help. The concept of AckPayload in the second example makes the programming very much easier if it can be used.

...R

Hi Robin2,

Please correct me if I am wrong. I believe the situation is a little bit different from your example codes, because my application needs to do both “broadcasting” and “polling”, one after another, and keep repeating. The situation is not doing only the broadcasting or only the polling. In another word, the ACK may need to be switched ON and OFF every 1 second, depending on if they are doing Broadcasting or Polling, and I have difficulties to do it. Master can not perfectly capture all Slaves’ measured data.

For Master to broadcast one syn signal, once per second, to all Slaves, I set ACK to be OFF on both Master and all Slaves, and things are working. You can see Slaves print out “syn received” stably. After broadcast, Master needs to poll Slaves’ data back, and the situation become weird, because when we do the Polling, ideally we want Master and Slaves’ ACKs and Retries to be all ON, to ensure the success of data transfer. The Broadcasting and Polling need different settings, and I am struggling in the middle.

I will appreciate very much for any comments, reviews, revisions, or suggestions of my codes.

Sincerely,

E

You can send a single broadcast without Ack without touching any global Ack setting.

bool write (const void *buf, uint8_t len, const bool multicast)

You can have pipes that use Ack and pipes that don't at the same time (I would use this config).

ericcouyang:
I believe the situation is a little bit different from your example codes, because my application needs to do both "broadcasting" and "polling", one after another, and keep repeating.

Please explain in more detail the reason why that is necessary. Maybe there is a better way?

What is the project that you are trying to create. When we understand the context it is much easier to give useful advice. At the moment this has many of the hallmarks of an XY Problem

...R

Let me try to explain, using a simpler example. You may image that the slaves are placed at different spots to collect time-dependent chemical reaction data. However, these slaves need to be activated to have the chemical reaction. Without activation, slaves will not have reaction data. After chemical reaction, the data is saved locally. The important thing is that all slaves must be activated at the same time, so I can check the distribution of the data. If they are not activated at the same time, the data is meaningless, because i can not compare them.

The broadcast signal Master sent to all slaves is a syn signal and also an activation signal. I believe all slaves will receive the syn signal almost at the same time, probably different < 20 micro seconds? if we consider the latency of the devices. For this step, I will set ACK to be OFF on the Master, and leave ACK to default, which is ON, on all slaves. To be more specific, on the Master, i will try radio.write(&dataToSend, sizeof(dataToSend), 1), as Whandall suggested, to enforce this particular writing pipe to have NO ACK.

After broadcast, Master needs to collect Slaves’ data back, and polling is probably the only solution. I agree with you that the polling shall take very short time, and I am trying to make sure Master can poll all the data back quickly without missing any one of slaves’ data – this is still quite challenging, considering that Master has to keep sending a syn signal and keep polling slaves’ data, ~ every 1 second. The good thing is that, for each cycle, Master do not need to collect all slaves’ data back at exactly the same time, which is impossible, because we know if all slaves send the data back to Master at the same time, collisions occur. I believe Master still has plenty of time to poll lots of slaves’ measured data back.

for above reason, i probably do not have choice, both broadcasting and polling must be done together in the code. thanks

ericcouyang:
i will try radio.write(&dataToSend, sizeof(dataToSend), 1), as Whandall suggested, to enforce this particular writing pipe to have NO ACK.

It’s not the pipe that gets ACKs disabled, it is this specific packet that will not trigger an ACK.

There is a control bit in the header that controls ACK on a packet base,
in addition to the global and per pipe settings of that attribute.

PControlField.png

ericcouyang:
The broadcast signal Master sent to all slaves is a syn signal and also an activation signal. I believe all slaves will receive the syn signal almost at the same time, probably different < 20 micro seconds? if we consider the latency of the devices. For this step, I will set ACK to be OFF on the Master, and leave ACK to default, which is ON, on all slaves.

[…]

After broadcast, Master needs to collect Slaves’ data back, and polling is probably the only solution.

Some numbers would help.

What is the maximum acceptable error in the timing of the SYNC received by all the slaves?

What are the shortest and longest acceptable intervals between sending the SYNC signal and starting the polling process?

I agree with you that the polling shall take very short time, and I am trying to make sure Master can poll all the data back quickly without missing any one of slaves’ data –

To broadcast a SYNC signal all the slaves will need to be listening on the same address. I guess you could also have each slave listening on another pipe using a private address for the polling requests. (I think this is the first time I have come across a use for a second pipe :slight_smile: )

The messages from each slave should include an ID for the slave and some sort of counter for the message number so that the master can be aware that it has missed a message and can ask a second time - or at least make a note of the gap in the record.

…R

PS … where tight timing and reliability matter a wired system may be more sensible

thanks Whandall for more insights of nrf24l01. For master to send out SYNC every 1 second, I did (a) radio.enableDynamicAck(); then (b) radio.write(&dataToSend, sizeof(dataToSend), 1); Are these correct? They seem working very well. Slaves receive stable SYNC, and i believe Master do not receive ACK back from slaves.

To answer Robin2’s questions below:

  • All slaves shall receive SYN about the same time, the maximum acceptable error in the timing of the SYN shall be ~ < 50 us. Somehow, i do not feel nrf24l01 latency differences can be so high but i never verify and I do not know how to verify.

  • Master needs to send our SYNC every 1 second, so the interval is 1 second, but any other fixed, non varying intervals, in between 0.5 and 1.5 (or 2) second shall be fine. The interval must be fixed, not changing.

  • For the broadcasting or SYNC signal from Master to Slaves, i believe the Master and Slaves already used the same pipe address to talk to each other. For the polling, the Master and Slaves already used different pipes to communicate.

  • I simplify Slaves’ measured data, I give each slave a simple data, because i can not show complicated data collecting procedures. When Master poll slaves’ data back, master will poll one by one, using different pipes, so Master shall know the measured data is from which pipe. For this reason, i do not ask Slaves to send an ID along with the measured data. I already asked Master to print out something, if Master does not receive any poll data from any slave, and this is how i know the missing data is there. This is actually a good question, because currently I am using only 5 slaves so i can use 5 different pipes, but in the future, if i have 15 slaves, i will have problems, because I can have only 6 listening pipes for 6 different slaves. In the future, i may add a “key” somewhere for Master and slaves, so slaves know when are their turns to listen/talk. This will be the future works.

Coupling of broadcasting and polling together is probably not very common. I am still trying to make it work perfectly – not missing data.

ericcouyang:
I did (a) radio.enableDynamicAck(); then (b) radio.write(&dataToSend, sizeof(dataToSend), 1); Are these correct?

You only need the radio.enableDynamicAck(); once in setup.

ericcouyang:

  • Master needs to send our SYNC every 1 second, so the interval is 1 second, but any other fixed, non varying intervals, in between 0.5 and 1.5 (or 2) second shall be fine. The interval must be fixed, not changing.

That does not answer my question about the time interval between sending the SYNC and starting the polling.

It would help a great deal (me anyway) if you tell us what the slave devices are being used for.

...R

after slaves receive the SYNC signal, all slaves will start the measurements and they will finish the measurements within 50 ms (or max 50 ms), and save the the measured data locally. Different slaves may take different times to finish and i can not control the needed time to finish. The good thing is that, after 50 ms, all slaves shall have the measured data ready, and Master can start polling the measured data back. Thanks

ericcouyang:
The good thing is that, after 50 ms, all slaves shall have the measured data ready, and Master can start polling the measured data back.

Is this a secret project? Why are you not telling us what you are doing?

if it is a commercial project then I don't like the idea that you are expecting to get free advice to increase your profit.

...R

I purchased a lot of Arduino devices for some hobby projects here and there in the past 10 plus years. I am not a software engineer, not an electronic engineer, but sometimes, like to try crazy ideas, and unfortunately so far none of the ideas are commercialized and materialized. I wish the hobby project can be so great and i have unlimited budget to hire professionals :slight_smile: , but as you may see, this is not the case :(. The hobby project is to build a home robot and robot is able to detect surrounding objects using an array of laser, or infrared, or ultrasonic devices, or cameras, so robot is able to able to know what is going on of its surroundings. I am not able to share all the details, but anyway, i believe "broadcast" and "polling" will be useful for a lot of applications. However, i am not sure if nrf24l01 is the right one to do the works? thanks

If you send a SYNC message and as each slave collects its data it should put it in the ackPayload. Then after (say) 150 millisecs the master can poll each slave in turn to collect the data. That should easily allow the next SYNC message to be sent after 1000 millisecs.

Have the slaves listening on 2 pipes - one with a general address for the SYNC message and one with a private address for the polling call.

In fact there would be plenty of time to do it all with one pipe by changing the address it is listening on, but using 2 pipes is probably simpler.

...R

after some times of testing, finally i am able to make things working. here i have one question, but i am not sure if the question is appropriate here? if not, i apologize and please ignore. I used below commands to enforce Arduino master device to have "NO ACK" while broadcasting the "dataToSend" to all Arduino salve devices, and it works. But when i replace the master device with raspberry pi using python language, i was not able to find equivalent commands of radio.enableDynamicAck() and radio.write(&dataToSend, sizeof(dataToSend), 1) in python3. I just could not find the equivalent ones and i am not sure they are there? To clarify, my slave are still the Arduino devices (arduino nano), because nanos are smaller, cheaper, better for sensor devices.

void setup() {
...
radio.enableDynamicAck(); // this is the key, so i can control no ack below
...
}

void loop() {
...
radio.write(&dataToSend, sizeof(dataToSend), 1); // 1 mean no ACK for this particular radio write
...
}

ericcouyang:
But when i replace the master device with raspberry pi using python language, i was not able to find equivalent commands of radio.enableDynamicAck() and radio.write(&dataToSend, sizeof(dataToSend), 1) in python3.

I don’t have a RaspberryPi so I can’t help.

…R

Robin2:
I don't have a RaspberryPi so I can't help.

But you are using the python RF24, so you could confirm the existance of the two functions.

I had a look at the code which seems to cover the functions,
but I'm no expert in the mechanisms for python/cpp extensions.

Whandall:
But you are using the python RF24, so you could confirm the existance of the two functions.

I don't understand why that is a response to my comment. I have never used an nRF24 with Python. I have only used them with Arduinos.

...R

Sorry @Robin2, somehow I had the impression you had experience with a Raspi NFR24 setup.

I have a Raspi but never used it with an NRF24L01.