Maniacbug- Network Layer for RF24L01+ Radios

Hi i opened a new topic because these will be focused on the Network Layer for RF24 Radios ...

I just received 10 rf24 so i will move from my current experience with the great driver from maniacbug and start with the network layer...

1º question
How to define the type of node :

  • Base nodes
  • leaf nodes
  • Relay nodes
    I even don't know if this names should be used ..

Following the documentation

Octal Addressing
Each node must be assigned an 15-bit address by the administrator. This address exactly describes the position of the node within the tree. The address is an octal number. Each digit in the address represents a position in the tree further from the base.
Node 00 is the base node.
Nodes 01-05 are nodes whose parent is the base.
Node 021 is the second child of node 01.
Node 0321 is the third child of node 021, an so on.
The largest node address is 05555, so 3,125 nodes are allowed on a single channel.

is just based on the addressing ?

So if i set adresses like this:

unit name unit adress
base 00
UA 01
UB 011 <-- first child of node 01 (UA)

means that UB will always talk to UA to reach base ? or only if not in range ?

This means if i need a node as relay i will put all the nodes that can't reach the base as child of the node that reach the base ??

So with this there is no formal declaration of the leaf, relay, or base ?

i will always put on the network.write the final destination the network layer will find the way trough all the child's, correct ?

 RF24NetworkHeader header(/*to node*/ other_node);
 bool ok = network.write(header,hello,strlen(hello));

my header will always be the final destination, in this example the node 011 will always have the destination of the base and not the parent, correct ?

Maniacbug Thanks again for your great work

This library
http://maniacbug.github.com/RF24Network/index.html

Can I just clarify that by "RF24" you mean NRF24L01+ devices and not this: http://www.dspg.com/english/Product.aspx?CatalogId=733&CategoryID=12&SubCategoryID=20&ProductId=36

Hi maniacbug (Are you there)...
How to enable the serial debug i'm doing this

"#define SERIAL_DEBUG"
but still not all the debug is enabled i see in "RF24Network_config.h" this..

#undef SERIAL_DEBUG
#ifdef SERIAL_DEBUG
#define IF_SERIAL_DEBUG(x) ({x;})
#else
#define IF_SERIAL_DEBUG(x)
#endif

but don't understand on how to enable the full serial debug to see thinks like this:

IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Received on %u %s\n\r"),millis()

with my define only debug i see is this:

#ifdef SERIAL_DEBUG
  printf_P(PSTR("setup_address node=0%o mask=0%o parent=0%o pipe=0%o\n\r"),node_address,node_mask,parent_node,parent_pipe);
#endif
}

thanks

fca:
Hi i opened a new topic because these will be focused on the Network Layer for RF24 Radios ...

This library
http://maniacbug.github.com/RF24Network/index.html

Oh no! The network layer leaks out :open_mouth: I've intentionally not publicized RF24Network because I'm not totally sure it's ready for prime-time yet. That said, I have gobs o' nodes using it and it works great. Just be warned you're the first person other than me who has tried to put it to use, at least that I know of.

fca:

This means if i need a node as relay i will put all the nodes that can't reach the base as child of the node that reach the base ??

So with this there is no formal declaration of the leaf, relay, or base ?

You got it. If a node cannot reach base, but can reach node 01, then make it node 011. Or 021. Or 031, etc. "Relay" is purely a semantic notion as far as the library is concerned. It just means "A node that has both children and a parent."

EDIT: Just realized a problem with your diagram. "Node 012" in your diagram should be "Node 021". Node 021 is a child of Node 01, while Node 012 is a child of Node 02.

fca:
i will always put on the network.write the final destination the network layer will find the way trough all the child's, correct ?

Yup, that's the whole point. 'Write' to the node where you want the message ultimately delivered. The network will handle getting it there.

 RF24NetworkHeader header(/*to node*/ other_node);

bool ok = network.write(header,hello,strlen(hello));



my header will always be the final destination, in this example the node 011 will always have the destination of the base and not the parent, correct ?

How to enable the serial debug i'm doing this

"#define SERIAL_DEBUG"
but still not all the debug is enabled i see in "RF24Network_config.h" this..

Right, you need to change the "#undef SERIAL_DEBUG" to "#define SERIAL_DEBUG" in RF24Network_config.h. I've found the serial debug output to be absolutely critical in understanding what's going on. I just added a pile of unit tests, and absolutely would not have gotten it working without poring over the serial debug logs.

One thing to be careful of to not starve the network. RF24Network::update() needs to get called all the time, so don't block anywhere in delay() loops. Also, remember that the unit cannot both send and receive at the same time. So it's wise to chill for a little bit after every send.

fca:
Maniacbug Thanks again for your great work

Hey, yer welcome. Good luck with your project! It will not shock me if you run into bugs. You can go ahead and report them as issues on github.

Hi there so my network is almost finish i had to go +/- for a parent by floor like this

For the parents by floor I'm using a unit with antenna, but i must tell that i almost get the same range as the ones with my self made antenna...
And i have the same problem mixing the "normal " rf24l01+ and the ones with antenna (self made or professional made) ..

i mean my "child" send to the parent the parent receives it but the child never receive the ack of the parent so for the child it was like a failed transmit but in fact the parent has received the data...
Should i disable the ack ? why is that happening ? the parent has "strength " to receive the signal (better antenna) but the child can't catch the answer ?

fca:
Hi there so my network is almost finish i had to go +/- for a parent by floor like this

That's pretty cool. I hope you write that all up in a blog post when you're done! Or I can 'interview' you for mine :slight_smile:

fca:
but i must tell that i almost get the same range as the ones with my self made antenna...

Not surprising. Off-the-shelf antennas don't have any magic to them, so it seems reasonable you could get just as good of performance from your own, as long as you made it right.

fca:
i mean my "child" send to the parent the parent receives it but the child never receive the ack of the parent so for the child it was like a failed transmit but in fact the parent has received the data...
Should i disable the ack ? why is that happening ? the parent has "strength " to receive the signal (better antenna) but the child can't catch the answer ?

Hmm... Disabling the ack would be giving up :slight_smile: If it were me, I'd try to find the root cause, systematically working to isolate the problem. The thing to do here is strip back the layers and start from scratch. Can two nodes get the ACK from each other just using the pingpair example from RF24, sitting a few feet from each other? As you move them apart, is there a point at which the messages go through but the acks do not? Do those results change as you change the types of nodes?

Hmm... Disabling the ack would be giving up smiley If it were me, I'd try to find the root cause, systematically working to isolate the problem. The thing to do here is strip back the layers and start from scratch. Can two nodes get the ACK from each other just using the pingpair example from RF24, sitting a few feet from each other? As you move them apart, is there a point at which the messages go through but the acks do not? Do those results change as you change the types of nodes?

I will test with the ping pair between the parent and child ... but the ones that are failing are the ones at higher distances.... so i think without one of them with special antennas not even will talk....

I remember when i had with my home made antennas even at short distance the one with special antenna couldn't send... only receive..
will test and come back...

Yes I suggest you use SMA antennas regardless.
I also suggest to calculate the theoretical path loss and then validate your experimental data (ups my PhD just finished sorry!).
An example of calculation for a standard 2.4 Ghz Wifi router:
transmit power 125 mWatt = 21 dBm
receiver sensitivity -97 dBm
antenna gain 2.5 dBi

The attenuation is:
21 dBm – (-97 dBm) + 2.5 dBi + 2.5 dBi = 123 dB
(we add two antenna gain, because tx and rx)
In line-of-site conditions, every 6dB of link margin will double the transmission range. A radio with a link margin of 111
dB has 12 dB less link margin than the computed one, and thus it can only achieve a quarter of the range.

Then we have to consider the path loss:
Link Margin = Transmit Power – Receiver Sensitivity + Antenna Gain – Path Loss
Where the Free Space Loss is calculated with:
PathLoss= 20 Log_10(Mhz)+20 Log_10(distance)-147.55
In line-of-site conditions the path loss can be determined by using a mathematical formula (Friis transmission
equation). The path loss for a 2.4 GHz in free space is given for several distances in the table below.

10 meters 81dB
100 meters 101dB

Now let's assume that your antenna (like the one I have used for my Norduino) have a 3dBi, the nrf24l01+ has 1mWatt so is 0dBm.
The receiver sensitivity is:
-94dBm RX sensitivity a 250kbps
-82dBm RX sensitivity at 2Mbps
-85dBm RX sensitivity at 1Mbps

So the link margin is:
Link Margin = 0dBm – (-85dBm) + 3dBi + 3dBi = 91 dB
So the maximum distance that you can achieve at 91 dB is less than 30 meters.
This is what I measured in my test with Norduino outside on a street.

Of course then you have to consider multi path effects which will introduce further attenuation.
There are several studies about indoor RF propagation but then you go in the realm of simulations which is when you need some big computers.

I hope my computations will help you.
Keep my posted I'm really excited to sponsor your project.

hi robomotic and thanks fort your effort in explain me the radio theory.. i will have to read with time to try to understand it..
I'm not so sure about that sma antenna being the correct one mybe you can give your opinion...
This is what my antenna is inside.. just a straight copper wire.... very different from my other wifi antenas...


i just ordered a sma male connector 5dbi antenna from a trusted supplier to see if it get better ...

you can see the raw output i'm using from my base with a ethernet shield here...
Please don't abuse on the hits, the webserver http://tinyurl.com/6upa93h is the arduino ..

but some times i still loose signal from the far end units on floor 3 for long time ....

First i had the units retrying when failing the transmit but because this fake failing they are now sending and on fail retry once again and even if it fails again they go to sleep for 1 minute (on the final project i want to have 15 min interval)...
But i really wanted to solve this communications problem because on the future i want to controll the sensors remotely (things like sleep interval, address id on my network, scan for live sensors, etc) and i can only have this with real bidirectional communication...

thanks

Here it is the first sketch of what will be the interface on the iphone...
You can try it on the pc/mac but this all build for the mobile users, later when all the hardware components are 100% i will focus on Sw...
But now that sensors already giving data (i didn't resist) and used the fast and easy pachube for logging ... and start working on the mobile interface i will later decide if i keep pachube or go for my own logging mechanism....

here http://tinyurl.com/746oor8
[modify] it seems my free webhosting is checking the page :slight_smile:
so until then here is the :

screenshot

Regarding your mobile interface did you have a look at OpenRemote?

To increase the range you could use a modified nrf24l01+ module (PA + LNA) such as this:

It will give you +20dBm of additional power (do your maths and calculate the increase in range).

I have an old non plus version:


Nordic RF24L01PA U22 by epokh, on Flickr

Which worked pretty well and can fit your footprint whereas the plus version can fit also the Norduino header.

Hello fca!

If you need any help with smartphone interface, then I can help. I am doing network very similar to yours, but I am reading temperature, amount of light and last recieved IR code (IR for turning on and off light in room) plus turning on and off lights via webpage. Now I have only one clitent (in living room - 1st position: Salon), but you can look on source code here: http://77.252.80.15:8085/

PS, please do not turn on and off my light too often :stuck_out_tongue: (just joking, for external users I have only leds connected, not high voltage relays :wink:

This non + version will work at 250kbs ? i think i read it i only goes up to 1mbit.
I have to check if my current versions with antenna are the + version.
Hummm +20dbm clarify me on how to do the maths :grin:

robomotic:
Regarding your mobile interface did you have a look at OpenRemote?

To increase the range you could use a modified nrf24l01+ module (PA + LNA) such as this:

It will give you +20dBm of additional power (do your maths and calculate the increase in range).

I have an old non plus version:

Which worked pretty well and can fit your footprint whereas the plus version can fit also the Norduino header.

For the non plus version you can only select between 1 Mbps or 2 Mbps but not 256kbps.

Link Margin = 20dBm – (-85dBm) + 3dBi + 3dBi = 111 dB
which is more than 100 meters!

It looks like they are not the + version.

IIRC, the non-p variants, when 250Kbps mode is requested, silently falls back to 1Mbps mode. If you already are using this library, you can test by doing the following, which will return 'true' or 'false'.

radio.isPVariant() ;

Or you can determine what the hardware is currently configured for via:

radio.getDataRate() ;

which will return one of:

RF24_250KBPS, RF24_1MBPS, or RF24_2MBPS

The fallback logic occurs because 250Kbps is '10' bits. The non-p variants ignore the high bit (of the two bits, '1' of '10'), resulting in a single low bit '0' being latched to hardware. This is the same as requesting RF24_1MPBS. And given its the longest range, universal data rate, it seemingly makes for a good default.

Also as a minor nit, a 256Kbps mode is not available on the hardware. I'm guilty of this too. So to be clear, its a 250Kbps mode and NOT a 256Kbps mode. The distinction is important to remember because of the defined enums. Otherwise, you'll constantly mistype one of the enums.

Yes i have to change the library to maniacbug defaults , because i already changed a lot one of thinks was on that part... :wink:

Direk do you know javascript ?
im using this code to get current status from pachube :

 var xhrGet = dojo.xhrGet({
        url: "https://api.pachube.com/v2/feeds/42624/datastreams/1.json",
        handleAs: "json",
		headers: {
									"X-PachubeApiKey": "exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
       
			handle: function(response) {
            console.info(2,'response',response);                
            console.info(3,'xhrGet.results[0]',xhrGet.results[0])

			}

		 });

I getting the json correctly on the console but don't kow on how to work with the data on the html part, something like data.temp or similar

regards

direk:
Hello fca!

If you need any help with smartphone interface, then I can help. I am doing network very similar to yours, but I am reading temperature, amount of light and last recieved IR code (IR for turning on and off light in room) plus turning on and off lights via webpage. Now I have only one clitent (in living room - 1st position: Salon), but you can look on source code here: http://77.252.80.15:8085/

PS, please do not turn on and off my light too often :stuck_out_tongue: (just joking, for external users I have only leds connected, not high voltage relays :wink:

I can help, but please show me response from pachube - json structure (or just paste info from console). Then we can write some code to show values on webpage.

PS.
I prefer jquery, but dojo will do also.

---edit---
Ok, got it on my own... So, if your result is something like this:

"response" Object
      at: "2012-01-14T10:00:43.743942Z"
      current_value: "66"
      id: "1"
      max_value: "8280.0"
      min_value: "-7.0"
      tags: Array[1]
        0: "Humidade %"
        length: 1
...

You can do something like this to show values:

	handle: function(response) {
		alert(response.at);
		alert(response.current_value);
		alert(response.id);
		alert(response.max_value);
		alert(response.min_value);
		alert(response.tags[0]);
	}

response is your structure, after dot you have parameter name. if parameter is array (last alert) then you are using brackets to get array element (tags[0]).

To put those values into webpage just use:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.6.0/dojo/dojo.xd.js"></script>
        <script>
            dojo.ready(function(){
						var xhrGet = dojo.xhrGet({
							url: "https://api.pachube.com/v2/feeds/42624/datastreams/1.json",
							handleAs: "json",
							headers: {"X-PachubeApiKey": "xxxxxxxxxxxxxxxxxxxx" },
							handle: function(response) {
								dojo.byId("date_time").innerHTML = response.at;
								dojo.byId("curr_value").innerHTML = response.current_value;
								dojo.byId("id").innerHTML = response.id;
								dojo.byId("max_value").innerHTML = response.max_value;
								dojo.byId("min_value").innerHTML = response.min_value;
								dojo.byId("tag").innerHTML = response.tags[0];
							}
						});
            });
        </script>
    </head>
    <body>
		Date and time: <span id="date_time"></span>

		Current value: <span id="curr_value"></span>

		ID: <span id="id"></span>

		Max value: <span id="max_value"></span>

		Min value: <span id="min_value"></span>

		Tag: <span id="tag"></span>

    </body>
</html>

You will get result:

Date and time: 2012-01-14T10:00:43.743942Z
Current value: 66
ID: 1
Max value: 8280.0
Min value: -7.0
Tag: Humidade %

direk, thanks a million , it worked fine...

now would be possible to have that get as function so i don't need to repeat it for different feeds?

instead of the single datastream if i get the complete feed info:

{"status":"live","feed":"https://api.pachube.com/v2/feeds/42624.json","creator":"https://pachube.com/users/fcaeiro","location":{"domain":"physical","lon":-40.4296875,"lat":38.5481654230466},"datastreams":[{"min_value":"0.0","unit":{"symbol":"C","label":"C"},"at":"2012-01-17T13:25:33.766001Z","tags":["temperature"],"current_value":"15","max_value":"18453.0","id":"0"},{"min_value":"-7.0","unit":{"symbol":"H","label":"%"},"at":"2012-01-17T13:25:33.766001Z","tags":["Humidade %"],"current_value":"72","max_value":"8280.0","id":"1"},{"min_value":"0.0","unit":{"symbol":"mv","label":"mV"},"at":"2012-01-17T13:25:33.766001Z","tags":["Bvolt"],"current_value":"3966","max_value":"20053.0","id":"2"}],"title":"Sensor1","private":"false","id":42624,"description":"Quarto NANA","version":"1.0.0","updated":"2012-01-17T13:25:33.766001Z"}

and a function i could call in way like
" body>
Date and time:

in this case feedid=42624...

the function url will change based on my parameter "feedid"
https://api.pachube.com/v2/feeds/feedid.json

if i don't use a function i will have to create a entry like this for my 6 feeds (no so optimized)...

thanks for your help, (maybe we are starting to go offtopic)...

regards

"

Try something like this:

...
	function get_data(json_url) {
						var xhrGet = dojo.xhrGet({
							url: json_url,
							handleAs: "json",
							headers: {"X-PachubeApiKey": "xxxxxxxxxxxxxxxxxxxx" },
							handle: function(response) {
								dojo.byId("date_time").innerHTML = response.at;
								dojo.byId("curr_value").innerHTML = response.current_value;
								dojo.byId("id").innerHTML = response.id;
								dojo.byId("max_value").innerHTML = response.max_value;
								dojo.byId("min_value").innerHTML = response.min_value;
								dojo.byId("tag").innerHTML = response.tags[0];
							}
						});
	};


	get_data("https://api.pachube.com/v2/feeds/42624/datastreams/1.json");
	get_data("https://api.pachube.com/v2/feeds/42624/datastreams/2.json");
	get_data("https://api.pachube.com/v2/feeds/42624/datastreams/3.json");
...