does someone have a good example of a protocol implementation which simulates a syncronous bi-direction communication (like a serial communication via COM or bluetooth) using nRF24L01 devices?
In the end I want to simply dump a message to the other device, not caring about the current state of RX or TX. If the device is currently in sending mode, the message should get queued and send later.
Otherwise I'll start based on the very good existing libraries and develop it myself.
I started working on my own solution. Not all the features I requested in my initial post are in. But for my project it does the job. I'll extend it as needed by the project.
It is based on the getting started sketch.
What you can do with it:
One sketch for both arduinos/nodes.
Submitted messages get "injected" into the variable used for buffering the serial communication. So your sketch works with serial input the same way as with messages received via the NRF.
Submit T:xxx\n via serial to one arduino will submit a message (xxx) to the other one. (can trigger any function which can also be triggered by serial com)
Submit S:xxx\n via serial to one arduino will submit a message (xxx) to the other one and have him output the message via Serial.print.
Submit R\n via serial to one arduinowill perform a throughput test.
Submit T:R\n via serial to one arduino will request the other arduino to perform a throughput test.
Submit T:P\n via serial to one arduino will request the other arduino to perform send back "Pong".
Every input on improvements is welcome. If someone finds ways to reduce the size of the compiled sketch I would be glad too.
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(9,10);
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
//for Serial input
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
//NRF Packages
byte SendPackage[32];
byte ReceivePackage[32];
boolean sending=0;
void setup(void)
{
//
// Print preamble
//
Serial.begin(115200);
radio.begin();
// optionally, increase the delay between retries & # of retries
radio.setRetries(15,15);
radio.setPayloadSize(32);
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
radio.startListening();
//radio.printDetails();
}
void loop(void)
{
//check for NRF received
NRFreceive();
//check for Serial received (or filled by NRF)
Serialreceive();
}
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
}
byte NRFsend(String NRFPack = ""){
NRFPack.getBytes(SendPackage, 32);
radio.stopListening();
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
bool ok = radio.write(SendPackage,sizeof(SendPackage));
if (!ok) Serial.println("NRFerror");
radio.startListening();
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout )
if (millis() - started_waiting_at > 200 )
timeout = true;
if ( timeout )
{
Serial.println("NRFerror");
}
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
}
void NRFreceive(){
if ( radio.available() )
{
//byte ReceivePackage[32];
bool done = false;
while (!done)
{
done = radio.read( &ReceivePackage, sizeof(ReceivePackage) );
delay(5);
}
radio.stopListening();
inputString = ((char *)ReceivePackage);
stringComplete = true;
radio.write( "1", 1 );
radio.startListening();
}
}
void Serialreceive(){
if (stringComplete) {
if (inputString.startsWith("T:")) {
NRFsend(inputString.substring(2));
}
if (inputString.startsWith("S:")) {
Serial.print(inputString.substring(2));
}
// #### TEST FUNCTIONS ###
if (inputString == "P\n") {
Serial.println("Pong");
NRFsend("S:Pong\n");
}
if (inputString == "R\n"){
double starttest = millis();
int x = 1;
while ((millis()-starttest) < 1000){
NRFsend("11111111111111111111111111111111");
x++;
}
Serial.print("Packet test 1000 millis: ");
Serial.println(x);
NRFsend("S:Remote Test: Packet test ");
NRFsend("S:1000 millis: ");
NRFsend("S:" + String(x) + "\n");
}
// #### TEST FUNCTIONS - END ###
inputString = "";
stringComplete = false;
}
}
I'm looking for a protocol for send/recieve messages over Bluetooth. Atm I'm using Serial.read()/write(bytearray,lengt) to get/post messages and my scetch is working well but sometimes some bytes are twisted, different or just missing.
Does your scetch work with Bluetooth?
Or do you know any protocol which would solve my problem?
what I wrote is actually no protocol and it's only based on the nRF24L01 library someone else wrote. No, it doesn't work for bluetooth.
All it does is covered by the bluetooth protocol anyway.
It is actually a bit strange that you get bytes twisted as they get send serially. Maybe it is a resend issue on Bluetooth level.
What you can do is to send each byte converted as a string instead of the bytes alone. You add meta information like a serial number to the byte. The receiver can then sort the bytes by the serial number until the message is completely submitted (which is signaled by a byte you specify – e.g. 10).
I always used simple Serial.print to submit a String. Never had the problems you described.
No idea why it doesn't work. So I can't offer a solution.
You can try to lower the baud rate and see if the stability is better.
Also check the AT commands available for the module. Especially things like buffering and retransmitting.
robvoi:
I started working on my own solution. Not all the features I requested in my initial post are in. But for my project it does the job. I'll extend it as needed by the project.
It is based on the getting started sketch.
What you can do with it:
One sketch for both arduinos/nodes.
Submitted messages get "injected" into the variable used for buffering the serial communication. So your sketch works with serial input the same way as with messages received via the NRF.
Submit T:xxx\n via serial to one arduino will submit a message (xxx) to the other one. (can trigger any function which can also be triggered by serial com)
Submit S:xxx\n via serial to one arduino will submit a message (xxx) to the other one and have him output the message via Serial.print.
Submit R\n via serial to one arduinowill perform a throughput test.
Submit T:R\n via serial to one arduino will request the other arduino to perform a throughput test.
Submit T:P\n via serial to one arduino will request the other arduino to perform send back "Pong".
Every input on improvements is welcome. If someone finds ways to reduce the size of the compiled sketch I would be glad too.
This is good stuff man... just what I'm looking for...
I got the RF24 lib working fine with the GettingStarted examples and got very good range of out my wireless modules from inhaos.com ( they are 100% compatible with nRF24L01 modules )...
When I copy, compile & upload yr sketch on both my Arduino UNO with the correct SPI pins, nothing happened on the Serial Monitor... even the radio.printDetails() did not print out on the Serial monitor...
Any idea where should I start troubleshooting this ?
I've read the nRF24L01 datasheets and tested a few other Nordic RF24L01 libraries and found this RF24 libraries from maniacbug ( http://maniacbug.github.com/RF24/index.html ) one of the best lib for these low cost RF modules...
Go near a WIFI wouter and you should get some output. The output should look like in the example. When I first tried it I got 'W' stated in all fields of all chanels.
I don't remember though what the problem was. One NRF worked, the other didn't.
One you got this running you can start with the ping examples of the NRF library.
I mainly used it to steer a robot. I used one Arduino on the PC, and one on the robot.
The one on the PC acted as controller for the NRF. At the same time I can unhook the controller on the PC and can use physical control (joystick, buttons) to control the robot.
The communication was manly based on predefined message patterns. Like D:100 is: go forward 100cm. For the manual/physical control it's then a simple F: to go forward until the stop message arrives.
Hello,
I've tried this sketch on 2 Arduino with NRF but I lose most of my packets.
If I try to send 20 times the same packet, I receive it in the best case 1 time in 80% of the tests and 0 time in the other 20%.
I never receive all of my packets.
I don't understand why ...
Hi,robvoi...I have seen your code u have posted for 2 way communication whereby u combine the code together for both transmit and receive... So , are u uploading the same code to two different arduino ? Is it possible to seperate the code into two parts one for each arduino?