New RF24 Library Fork for NRF24L01 modules

I've been working on a new library fork to improve upon the current state of the RF24 driver. Mainly, the new library fork should be more reliable and responsive, while providing faster data transfer rates, especially with multicast or NOACK streaming. As I've found with any system or scenario, its not about having the right recipe or ingredients, its always about the process. Users will notice notice differences when using things like ACK payloads, as data is never flushed from the FIFO buffers unless required, and responsiveness is much faster. The new fork also makes better use of the FIFO buffers, which improves things greatly when transmitting large quantities of data, or streaming realtime data such as audio data, and should be more reliable due to how it manages and checks for incoming data.

I've done a direct comparison between this fork and the gcopeland fork, which I think is about the fastest alternative. https://www.youtube.com/watch?v=mODflsK1Ab0

The new library includes the sketch used in the transfer testing, as well as simplified versions and additional examples.

The main issue with compatibility, is that radio.read() no longer returns a boolean value if more data is available. The new library is more in-line with standard Arduino libraries, in that radio.available() will always return 1 if data is available to be read instead. This is the only change required for compatibility with the original RF24Network library.

I've added full support for the Arduino Due as well, with the extended SPI methods, which improves performance quite a bit for the Due as well. note: Do not include printf.h and don't do printf_begin(); , this is already enabled on Due.

ATTiny support is there, but my chip is in the mail, so testing is not complete. To use, Don't include SPI.h, and optionally uncomment #define MINIMAL in RF24_config.h

Source Code: https://github.com/TMRh20/RF24 Library Package: https://github.com/TMRh20/RF24/archive/master.zip Documentation: http://tmrh20.github.io/RF24/index.html

Blog ( Overview and more detailed info ): http://tmrh20.blogspot.com

Hi Tmrh20

Not sure if you're going to see this message - but I'm just wondering if you have any documentation yet for the RF24Mesh library.

I've been playing around with the examples (they all work perfectly for me) as I'm trying to build an orchard monitoring system based on the Arduino and NRF24L01. (I basically want to have a number of 'sensor nodes' that transmit temperature, soil moisture, etc data to a controller. The controller can then perform whatever needs to be done based on analysis of that info.)

I am not a programmer (although I studied Basic & GBasic a lifetime ago) - I am having a hell of a battle trying to transmit actual data (which is in mostly in float form). The milliseconds work great - but not very useful for my application.

In one of the examples you refer to 'M' type data, and despite consulting Dr. Google - can find not much info on it (at least none that makes sense to me)

Despite having looked at all of your examples I still don't understand how the data packets are structured - and so I was wondering if you maybe have written some documentation (that us stupid people can make sense of)

I also have no idea what functions (maybe functions is the wrong word) can be called - for e.g. to set the data rate, radio power levels, putting the radio to 'sleep' in between transmissions, etc, etc...

By the way - I think your stuff is fantastic & you are doing great work!

Very excited about trying this new fork, nrf24 seems to be my life as-of-late

Thank you TMRh20

By the way, my new MINI NRF24L01+'s have arrived, going to test them very soon (see pic)

Dubdub: Not sure if you're going to see this message - but I'm just wondering if you have any documentation yet for the RF24Mesh library.

Well, I seem to be having some problems with the email notifications from some threads, so hopefully this is not too late to be helpful.

RF24Mesh is really just a simple 'mesh protocol' that works over top of RF24Network, so you can really just refer to the RF24Network documentation (DEV fork is recommended) RF24Mesh has functions to translate between nodeIDs (1-255) and RF24Network addresses.

Dubdub: I am not a programmer (although I studied Basic & GBasic a lifetime ago) - I am having a hell of a battle trying to transmit actual data (which is in mostly in float form). The milliseconds work great - but not very useful for my application.

In one of the examples you refer to 'M' type data, and despite consulting Dr. Google - can find not much info on it (at least none that makes sense to me)

Despite having looked at all of your examples I still don't understand how the data packets are structured - and so I was wondering if you maybe have written some documentation (that us stupid people can make sense of)

Well when sending, RF24 takes a void pointer, so what ends up happening is you input any datatype, and the raw bytes/bits will be sent/received exactly as they are.

I would suggest taking a look at the core RF24 driver and the gettingstarted and gettingstarted_handlingdata examples.

From there, take a look at the RF24Network examples. The main difference here, is that a header needs to be created and included. This contains information like the sender,recipient, and other information required for network functionality.

The only thing you need to specify is the recipient and the 'type'. The type is used by the user (you) to identify different 'types' of messages. An 'M' type message means nothing, unless you assign an action to that type of message when received.

Dubdub: I also have no idea what functions (maybe functions is the wrong word) can be called - for e.g. to set the data rate, radio power levels, putting the radio to 'sleep' in between transmissions, etc, etc...

By the way - I think your stuff is fantastic & you are doing great work!

Thanks. A recent update allows you to set the datarate and channel when calling mesh.begin(); . Sleeping is as usual with RF24Network, although you may want to 'release' the mesh address.

All documentation is available at http://tmrh20.github.io

mcnobby: Very excited about trying this new fork, nrf24 seems to be my life as-of-late

Thank you TMRh20

By the way, my new MINI NRF24L01+'s have arrived, going to test them very soon (see pic)

Np, its been a lot of work, but a lot of fun too.

Those really are small! I'm mostly sticking to non-PA models with external antenna, as they seem to be a good balance between range, cost & power requirements. If course it depends on your requirements, but it can be surprising just what you can do with such small and inexpensive modules.

AHA! ......

No, wait .....

Yes, it works!!!

Thanks TMRh20 - I've played around with your gettingstarted_handlingdata example and somehow created a structure that includes temp, humidity and a name. I don't really understand the syntax, but I imagine the structure is kinda like an array with a bunch of different types of data ..?

What I don't get is what controls the size of the packet & how it's divvied up? Is that handled in your library?

Also, how large can the structure get (how many different variables can there be in the structure) ?

Sorry for all the stupid questions, but I really do appreciate your help (and your work)

Np, normally I try to avoid tech support type questions, but I think some of these questions would add nicely to an FAQ or something.

This page explains structs much better than I probably could.

Technically, you control the size of the packet and how it gets divided up.

  1. The radio will handle max 32Byte payloads.
  2. RF24Network uses an 8-byte header, so handles 24 bytes in a single, non-fragmented payload
  3. RF24Network can use fragmentation, so will handle X bytes in a single payload, where x is the defined MAX_PAYLOAD_SIZE (see RF24Network_config.h) The default is 144 byts/payload.

These are things that are not very well documented, so I'll see about adding some of this info to the docs.

Thanks TMRh20, I understand why you wouldn't want to get involved with support, so I really appreciate that you've taken the time to respond to me.

Wow - I might have to read through the STRUCTS page a few more times, but I already feel like my head is going to explode!!!

OK, so I started with your datahandling example and modified that to send the data I wanted across, and that worked perfectly. Then I went on to the RF24Mesh example and modified that; I still don't really have a handle on the whole data structure bit, but somehow I managed to fumble my way through and get that working too - so now I have 2 nodes (on the mesh / in the mesh?) sending their data back to the controller (Master), and it's working perfectly!! (WHOOHOO!!)

What really confuses me here is that on the sensor side we do a "mesh.write" - but on the Master it's a "network.read" Looking at the documentation (or the library files) they seem (to my simple brain, at least) to work on different "data construction" (for lack of a better word) - so I'm not really sure why it works. Sigh!

I added the optimised RF24 library (along with the latest IDE) yesterday.. what a difference, and solved a few little comms issues too - thanks :)

??

Dubdub: What really confuses me here is that on the sensor side we do a "mesh.write" - but on the Master it's a "network.read" Looking at the documentation (or the library files) they seem (to my simple brain, at least) to work on different "data construction" (for lack of a better word) - so I'm not really sure why it works. Sigh!

RF24Mesh is just an overlay for RF24Network:

mesh.write(&msg,'M', sizeof(msg));

is equivalent to:

RF24NetworkHeader header(00,'M');
network.write(header,&msg,sizeof(msg));

Ahaaa..... OK, I think I'm starting to get it now.....

Man, this is awesome! I've been running a little 3-node network for the weekend & it has behaved perfectly. Just waiting for some more radios to arrive.

Now, If I can only get my head around how to get this lot web-connected ....

Thanks TMRh20 - you're the man!!

Dubdub: I've been running a little 3-node network for the weekend & it has behaved perfectly. Just waiting for some more radios to arrive.

Which type of RF24's are you using Dubdub ? What kind of separation are you getting ?

I have been making some notes on all the variety of NRF24L01+ boards out there - http://forum.arduino.cc/index.php?topic=313195.0

Dubdub: Now, If I can only get my head around how to get this lot web-connected ....

I would suggest having a RPi as the controller. On my sensor network I still have and arduino + ethernet shield but I dont recomend it for the controller job. I will replace it with an RPi.

Besides, TMRh20 has done a very good tutorial and installation package of his fork for the RPi.

@mcnobby - I'm just using a cheap Chinese NRF20L01 + These have an external antenna, but no amplifier. (Had a brain fade when I ordered them) At 50 - 60 m I start losing packets, but it may be interference from one of my neighbors down the road (they play with some weird stuff!) In my building I get perfect coverage - upstairs, downstairs, through walls & floor doesn't seem to make any difference. I've ordered a bunch of the amplified version, so curious to see how they work.

Now if I can only figure out how to receive a String as a String .... sigh .... it's a steep hill.

Dubdub: @mcnobby - I'm just using a cheap Chinese NRF20L01 + These have an external antenna, but no amplifier. (Had a brain fade when I ordered them) At 50 - 60 m I start losing packets, but it may be interference from one of my neighbors down the road (they play with some weird stuff!) In my building I get perfect coverage - upstairs, downstairs, through walls & floor doesn't seem to make any difference. I've ordered a bunch of the amplified version, so curious to see how they work.

Very similar results to myself, I have also been testing THESE - they are tiny (which to me is an advantage, and I have found them perfectly usable as a sensor sender as long as the receiving nodes are the low-cost version with the external antenna

I have quite a collection of different types of NRF board now, I am sorting the wheat from the chaff !! :)

mcnobby: I have quite a collection of different types of NRF board now, I am sorting the wheat from the chaff !! :)

mcnobby, can you check if all your different modules talk to each other, using TMRh20 RF24Network with dynamic payloads? :)

So far they all talk to each other, but I do have some on order which might not, they are the ones based on the SE8R01 and have the two extra bytes in the header, apparently they will work with each other and transparent to the RF24/Mirf but they wont work with a normal nordic-based module

I shall report back when I find out :)

I'm having a bash at writing a programmers guide (as opposed to a programmers reference). As I study, I start to find some questions.

When we use the write() method, we specify the size of the data we are transmitting which can be up to 32 bytes in length. I see that the write method takes a size parameter, so, for example, I could choose to only send 4 bytes of data.

On the read() method, we supply a buffer and the size of that buffer into which the received data will be written.

If I send 4 bytes of data and supply a buffer of 32 bytes, I am assuming that only the first 4 bytes will contain the transmitted data. Can I assume the remaining 28 bytes will be zerod?

I am also assuming that the transmitter and receiver have to have an implicit understanding of the size of data transmitted and received as there doesn't appear to be a "size received" value.

kolban: I'm having a bash at writing a programmers guide (as opposed to a programmers reference).

Excellent!

kolban: If I send 4 bytes of data and supply a buffer of 32 bytes, I am assuming that only the first 4 bytes will contain the transmitted data. Can I assume the remaining 28 bytes will be zerod?

Yup. This is mostly handled by the radio/driver. With standard payloads, 32 bytes are always written to the radio via SPI, regardless of the length of the data. Anything over and above is null/zeroed. With dynamic payloads, this is not required, but works out the same.

kolban: I am also assuming that the transmitter and receiver have to have an implicit understanding of the size of data transmitted and received as there doesn't appear to be a "size received" value.

Yes and no? With the default config, no, but with dynamic payloads ( radio.getDynamicPayloadSize() ) the radio can report the size of the incoming payload. This can sometimes report as zero if the payload is corrupted, in which case the driver also flushes all of the RX buffer. In my experience, this generally only happens at high-transfer rates or when a lot of active communication is taking place. More info is in the earlier versions of the datasheet.