I succeeded in designing a driver to send a packet with nRF24L01. Now I want to do a higher layer protocol to send packets bigger than 32 bytes, and for this I need to split them into 32-byte chunks. I have at most 4 chunks per big packet.
Now, my problem is that if I push packets in TX FIFO until it is full, and then after one packet is transmitted, I push the last one, at the receiver side I get all times only 3 packets. If I push the packets in turn, one by one, after DS interrupt, sometimes I get 4 packets at the receiver, sometimes 3 packets. I am not using auto-ack and retransmission, and this would probably solve the problem, but this is a particular case of the protocol, when I can’t enable this: I’m sending broadcast packets, so I cannot wait for ACK.
Does anyone of you have an idea about this problem, or tried doing something similar and succeeded ? Thank you in advance for your help !
I’m also working on a higher layer protocol using the previous version of that chip.
You will find that every packet is not guaranteed - especially since the band it uses (2.4Ghz) usually has tonnes of wireless routers etc doing their thing. So you can’t guarantee anything will reach the other end. So naturally you need to take care of this yourself, or on the nRF24L01, you can as I understand it, have the chip itself retransmit if it doesn’t get an ack.
In any case, it’s always important to make sure data gets across okay if it’s important.
The main problem is with the broadcast messages, as for the peer-to-peer messages it uses Enhanced Shockburst, which automatically makes sure that one packet arrived successfully on the other side. For broadcasting messages to more receivers, I cannot use this feature. I think that I will design my protocol in such a way that important messages are sent only peer-to-peer and not broadcasted.
Sometimes it is hard to avoid broadcasts, for example if you want to discover all nodes within range of the host.
In the protocol that I am planning to design, I will just transmit the same broadcast packet a few hundred times during 2 seconds, and have the nodes reply to this packet after 2 second + a random time between 10 and 100 ms.
This procedure can be repeated a few times to discover as many nodes as possible.
Advantages are:
chance that broadcast packet arrives is much higher
sensor node can receive this message even in a ‘standby’ mode where it turns on the (‘battery eating’) receiver only a few times per second.
lower chance that the packets of replying nodes collide
I think it is a very good idea. But you should also take into consideration that nodes could be on different channels - sometimes you need to include frequency agility into your application. So you would need 2sec * MAX_NR_OF_CHANNELS_FOR_YOUR_TRANSCEIVER, which could become pretty big. My transceiver allows many channels, from which I use half - I have a step of 2 to avoid interference between adjacent channels.
My approach in the application is the following: have a coordinator that starts and takes a default address. Nodes that come online search for this coordinator by periodically sending ping messages and cycling through all the channels, until a coordinator is found. Then the connection is made.
Does your transceiver allow listen-before-talk ? If yes, you could avoid using the random interval. Are you thinking of sending each broadcast packet in your application for 2 seconds, or only a message to discover neighbour nodes ? If you plan to send each one, it could become a problem when you have many broadcasts to make.
I would be glad to exchange application ideas with anyone interested in this domain (wireless networks).
Thanks, your idea is indeed more elegant! The frequency agility can be a serious advantage, and on my TRF2.4G module, receiving ‘costs’ 18 mA and sending at 0dBm takes 13 mA. So it may save batteries as well.
The node discovery was the only phase where I’ld need to broadcast packets. I plan a star topology afterwards.
I can not completely understand how with ‘listen before talk’, the randomization of the response moment can be avoided. My transceiver can do ‘listen before talk’. However, if several nodes receive the same broadcast message at the same time, they will all listen, and ‘hear’ at the same moment that the channel is free. Then they’ll start to send response packets all on the same time, making a big collision. Or not?
Well I like the discussion.
You now plan to send the ‘important’ packets peer-to-peer and not by broadcast. However that multiplies broadcast traffic by the number of nodes. How many nodes do you plan for?
Maybe there is a way in between. You could add a field to each broadcast message, telling the nodes at what ‘time’ to expect the next broadcast message. The nodes keep track of the time (maybe using a timer/counter). When the nodes do not receive a packet at the planned time, they send e.g. 10 packets with the same ‘request for broadcast retransmit’. Etcetera.
You may be right about the collision when all listen at the same time. Anyway it’s a useful feature and you should make use of it.
I need to find a solution for a connection management so a node knows when it is not connected to its coordinator anymore. The coordinator sends periodically beacon signals as broadcast, and if a node doesn’t receive them for some time, it will start pinging the coordinator (and this is peer to peer). Then it might decide to start looking for its coordinator.
I am not thinking of sending important packets to each node in the system. I plan the system to accomodate a high number of nodes, so this would not be a suitable solution. I will just design the protocol in such a way that for an important message, a device will contact another device, and after this do a broadcast. I cannot use the timing scheme because broadcasts are irregular, based on the medium states. But anyway, I could send a broadcast packet x times, just to be sure one of them arrived.
I believe I have an answer to your packet problem if you do not. Unlike the Chipcon parts that will take up to the bytes per packet number you state, the 24L01 must get a packet of the exact length of the number you put into “pipe width”. If your final packet is less than 32 bytes, pad the rest.
Or, you can enable the variable byte payload and send any number of bytes up to 32. This drove me crazy for days because the data sheet is unclear that the pipe width number must be the exact number of bytes sent.
Thank you for your answer. I am aware of the length problem for the packets, and I am always writing 32 bytes into the TX PAYLOAD register. I am not sure about the cause of the initial problem, but currently I’m sending each packet in turn and it’s working. After the driver is finished, maybe I’ll try finetuning it.
Now I have another problem regarding the pipes and the addresses for them. If I set the module to use only pipe 0, I can send data to the other module. However, only changing EN_RXADDR to 0x07 to use pipes 0, 1 and 2, I cannot send the packet to the same address. This seems very strange, and I have contacted Nordic support to get help.
There seems to be an issue regarding the addresses for receiving pipes. Assume I want them to have the addresses ABCDD, ABCED, ABCEE, I write the data as DDCBA, DECBA, EECBA. The transmit address is written the same. Still, I cannot get packets through. If I only write to Pipe0 address, then the packets are transmitted.
What could be the cause of that ? Can any of you enlighten me about how the RX addresses are written ? Has any of you tried and succeeded using other addresses than the default ones for the RX pipes ?
AFAIK, I tested sending and receiving on all the pipes with my library and everything worked out OK. I know that I tested all 6 pipes with the default addresses, and I’m pretty sure that I checked them with different addresses, too. I know for sure that I tested pipes 0 and 1 with different addresses, though, and that worked fine. If you want to see my code, go to my website (in my tagline below) and it’s in the tutorials.
I have looked over your code, but I’ve seen no significant differences. I have Tutorial3 from your site and I see it uses default addresses. Is there anything special about writing those addresses ? Except that the last byte needs to be first, if I really care about the order.
Nothing special that I recall needs to be done. And you are right, the tutorial does use default addresses. I did tests on my own to test out the changing of addresses. There’s another one to add to the tutorials list.
Have you guys checked out the new version of the nRF24L01 specifications ? It does explain better some things, and adds documentation for some hidden features of the chip, like dynamic packet width and TX with no ACK
I will try tonight to solve the addresses problem… It is very strange that if I write only to Pipe0’s address, then the communication works, but if I write also the addresses of Pipe1 and Pipe2, I cannot get to communicate with Pipe0 neither. This keeps going until I power cycle the nRF… so it seems that I am overwriting Pipe0’s address when I think I’m writing Pipe1 or Pipe2 address…
The problem is solved. With the aid of Nordic’s technical support, I’ve found my mistake: the LSByte was unique only for pipes 1 to 5. I had misunderstood the datasheet and thought that for pipe 0 it is completely independent. It’s not ! The last byte need be unique for all 6 pipes.
Now I’m happy because a small creepy problem with nRF24L01 has disappeared
This new spec is a bit bittersweet. After learning just about everything there was to know about this little guy (or so I thought), they come and say that they had kept like 3 features hidden that would have been really helpful. Now I have to go back and rewrite Tutorial 0. :x
On the other hand, it is pretty sweet to get the use of the additional features, especially the dynamic payload feature. If nothing else, the user manual is far superior to the old one (although I almost knew the old one by heart 8)).