The two sketches I have published below have no real practical value except as a jumping-off point for further development. But the sketches have been thoroughly tested, nevertheless!
Hardware requirements:
- 2 Arduinos
- 2NRF24L01
- 2 LEDs
The two LEDs are connected to D5 and D6 pins of the Arduino with the receive sketch and the NRF24L01 modules are connected to pins D9 to D13 on each Arduino. The Arduino with the transmit sketch I will call the remote and it is battery powered, the receive(local) Arduino is connected to the computer by USB, as the Serial Monitor is required. Once both Arduinos are running, the LEDs should be flashing alternately twice per second.
This frequency can be altered by entering the millisecond delay (10 for really fast or 5000 for really slow) in the input field of the Serial Monitor. The input delay time in milliseconds will then be displayed on the Serial Monitor.
The receiver sketch:
#include <RF24.h> #include <RF24Network.h> #include <SPI.h> RF24 radio(10,9); // nRF24L01 (CE,CSN) RF24Network network(radio); // Include the radio in the network const uint16_t this_node = 01; // Address of our node in Octal format ( 04,031, etc) const uint16_t node00 = 00; void setup() { Serial.begin(9600); Serial.println("NRF24L01_receive.ino"); Serial.println("Input number of milliseconds delay for remote transmitter"); SPI.begin(); radio.begin(); network.begin(90, this_node); //(channel, node address) pinMode(5, OUTPUT); pinMode(6, OUTPUT); } void loop() { network.update(); while (network.available()) { // Is there any incoming data? RF24NetworkHeader header; int incomingData; network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data if(incomingData > 0){ digitalWrite(5, HIGH); digitalWrite(6, LOW); } else{ digitalWrite(5, LOW); digitalWrite(6, HIGH); } } if(Serial.available() != 0){ int mData = Serial.parseInt(); Serial.println(mData); sendMyData(mData); } } void sendMyData(int outgoingData){ RF24NetworkHeader header(node00); // (Address where the data is going) bool ok = network.write(header, &outgoingData, sizeof(outgoingData)); // Send the data }
The transmitter sketch:
#include <RF24.h> #include <RF24Network.h> #include <SPI.h> RF24 radio(10,9); // nRF24L01 (CE,CSN) RF24Network network(radio); // Include the radio in the network const uint16_t this_node = 00; // Address of this node in Octal format ( 04,031, etc) const uint16_t node01 = 01; unsigned long currentTime; unsigned long previousTime; unsigned long delayTime = 250; bool transmit = true; void setup() { Serial.begin(9600); Serial.println("NRF24L01_transmit.ino"); pinMode(LED_BUILTIN, OUTPUT); SPI.begin(); radio.begin(); network.begin(90, this_node); //(channel, node address) previousTime = millis(); } void loop() { network.update(); currentTime = millis(); if(currentTime >= previousTime + delayTime){ if(transmit){ sendMyData(255); transmit =!transmit; // set transmit to false }else{ sendMyData(-255); transmit =!transmit; // set transmit to true } previousTime = millis(); } while (network.available()) { // Is there any incoming data? RF24NetworkHeader header; int incomingData; network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data delayTime = incomingData; } } void sendMyData(int outgoingData){ RF24NetworkHeader header(node01); // (Address where the data is going) bool ok = network.write(header, &outgoingData, sizeof(outgoingData)); // Send the data }
I hope you have fun testing this out and adapting these sketches to your own needs!
Now here are the files for download:
Just out of curiosity, what's the difference between using radio or network to do the reading or writing? I've been experimenting with radio read/write previously, and it seems to work in quite a similar fashion.
What do you mean by "network"?
Ok, just to clarify... I've seen the use of different libraries, using similar code:
network.read/write(...) vs radio.read/write(...)
What exactly is the difference, when it appears (at least in my testing), that they look to offer the same outcome... what am I missing?
network.read/write(...) vs radio.read/write(...)
"network" and "radio" are just the names of the declared objects, found above the setup() loop
frogandtoad.write would be perfectly valid if "frogandtoad" was declared as the object.
And in the above code, "radio" is an object within the "network" object.
I also believe that the "radio" object inherits properties from the "network" object.
radio.begin(); network.begin(90, this_node); //(channel, node address)
Note that radio is initiated before network, if the order was reversed this would not work.
I hope that clears it up!!
Yes, I do understand they are objects... no problems there, and I have also seen that radio is passed to the network constructor, and this is what I wanted to know... are they essentially doing the same work, but just different libraries? Is there a case where one of these implementations should be used over the other? IOW... do they have different applications?
Is there a case where one of these implementations should be used over the other?
No, they are not interchangeable! Network object needs the radio object to function.
To understand this better you should take a look at the RF24.cpp and RF24Network.cpp files in the Arduino/libraries/RF24 & Arduino/libraries/RF24Network folders.
Thanks, I can look at the files, but that won't tell me when to use one library over the other. Like I said in my original post, I have been able to communicate with radio.read() and radio.write(), and quite successfully... However, I'm still not sure under which circumstances I would user network.read() or network.write(), because from the examples I've seen posted here so far, I don't see what one can do better than the other?
Does that make sense?
From what i read in the doc, the RF24Network (using the underlying "optimized" RF24) introduces an OSI Layer 3 with message acknowledgement and routing (equivalent of IP in the TCP/IP network stack) :
http://tmrh20.github.io/RF24Network/
So RadioA could send messages to RadioC via RadioB for example (see the RF24Mesh for much more complex examples, it is built on top of RF24Network which itself relies on "optimized" RF24)
Eric
I haven't used radio.read or radio.write in my code. In my code above, the radio object is initialised for use by the network object, and in the loop(), only the network object addressed. So if you have seen this usage, it may be in conjunction with other libraries.
All I know is that my code functions 100%, without radio.read or radio.write!
Thus, a comparison of these object.functions is a complete waste of time.
Ok, maybe not your code specifically, but some code you have helped with perhaps?. I wasn't questioning whether your code worked or not, but if you haven't used radio.read() or radio.write() to communicate with these transceivers before then that's fine.
A waste of time?... not if you want to learn!
Sorry, I missed this post earlier.
Ok, that makes some sense, if it offers more functionality, specifically for dealing with the OSI model.
Thanks for the information, I will read up on it further.
Just out of curiosity, what's the difference between using radio or network to do the reading or writing? I've been experimenting with radio read/write previously, and it seems to work in quite a similar fashion.
I think I have got the answer now.
Both are simplex communications but network does not have to be explicitly told that it is the transmitter or receiver during setup, whereas radio does need to be set to transmitter or receiver programmatically.
radio.stopListening(); & radio.startListening(); are not required by the network station to change its status.
Once set up:
RF24NetworkHeader header;
int incomingData;
network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data
is all that is required to receive data and:
RF24NetworkHeader header(node01); // (Address where the data is going)
bool ok = network.write(header, &outgoingData, sizeof(outgoingData)); // Send the data
is all that is required to send data.