RF24 nRF24L01 Serial Chat example

Hi all,

I wrote a nRF Serial Chat to the RF24 example...

If you have nothing to do, you can load this up to two UNO/PCs and wireless/RF chat with yourself.. :slight_smile:
If the radios are far away, you might even know which bytes are dropped... good exercise running back and forth..

Can you be modified to take in Serial input (GPS,etc) and send it across using the nRF to the other side..

Github repo :-
https://github.com/stanleyseow/RF24/blob/master/examples/nRF24_Serial_Chat/nRF24_Serial_Chat.ino

Source code :-

/*
nRF Serial Chat

Date : 22 Aug 2013
Author : Stanley Seow
e-mail : stanleyseow@gmail.com
Version : 0.90
Desc : 
I worte this simple interactive serial chat over nRF that can be used for both sender 
and receiver as I swapped the TX & RX addr during read/write operation.

It read input from Serial Monitor and display the output to the other side
Serial Monitor or 16x2 LCD (if available)... like a simple chat program.

Max payload is 32 bytes for radio but the serialEvent will chopped the entire buffer
for next payload to be sent out sequentially.

*/

#include <LiquidCrystal.h>
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

LiquidCrystal lcd(10, 7, 3, 4, 5, 6);

RF24 radio(8,9);

const uint64_t pipes[2] = { 0xDEDEDEDEE7LL, 0xDEDEDEDEE9LL };

boolean stringComplete = false;  // whether the string is complete
static int dataBufferIndex = 0;
boolean stringOverflow = false;
char charOverflow = 0;

char SendPayload[31] = "";
char RecvPayload[31] = "";
char serialBuffer[31] = "";

void setup(void) {
 
  Serial.begin(57600);
  lcd.begin(16,2);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("RF Chat V0.90");

  printf_begin();
  radio.begin();
  
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_MAX);
  radio.setChannel(70);
  
  radio.enableDynamicPayloads();
  radio.setRetries(15,15);
  radio.setCRCLength(RF24_CRC_16);

  radio.openWritingPipe(pipes[0]);
  radio.openReadingPipe(1,pipes[1]);  
  
  radio.startListening();
  radio.printDetails();

  Serial.println();
  Serial.println("RF Chat V0.90");    
  delay(500);
  lcd.clear();
}

void loop(void) {
  
  nRF_receive();
  serial_receive();
  
} // end loop()

void serialEvent() {
  while (Serial.available() > 0 ) {
      char incomingByte = Serial.read();
      
      if (stringOverflow) {
         serialBuffer[dataBufferIndex++] = charOverflow;  // Place saved overflow byte into buffer
         serialBuffer[dataBufferIndex++] = incomingByte;  // saved next byte into next buffer
         stringOverflow = false;                          // turn overflow flag off
      } else if (dataBufferIndex > 31) {
         stringComplete = true;        // Send this buffer out to radio
         stringOverflow = true;        // trigger the overflow flag
         charOverflow = incomingByte;  // Saved the overflow byte for next loop
         dataBufferIndex = 0;          // reset the bufferindex
         break; 
      } 
      else if(incomingByte=='\n'){
          serialBuffer[dataBufferIndex] = 0; 
          stringComplete = true;
      } else {
          serialBuffer[dataBufferIndex++] = incomingByte;
          serialBuffer[dataBufferIndex] = 0; 
      }          
  } // end while()
} // end serialEvent()

void nRF_receive(void) {
  int len = 0;
  if ( radio.available() ) {
      bool done = false;
      while ( !done ) {
        len = radio.getDynamicPayloadSize();
        done = radio.read(&RecvPayload,len);
        delay(5);
      }
  
    RecvPayload[len] = 0; // null terminate string
    
    lcd.setCursor(0,0);
    lcd.print("R:");
    Serial.print("R:");
    lcd.setCursor(2,0);
    lcd.print(RecvPayload);
    Serial.print(RecvPayload);
    Serial.println();
    RecvPayload[0] = 0;  // Clear the buffers
  }  

} // end nRF_receive()

void serial_receive(void){
  
  if (stringComplete) { 
        strcat(SendPayload,serialBuffer);      
        // swap TX & Rx addr for writing
        radio.openWritingPipe(pipes[1]);
        radio.openReadingPipe(0,pipes[0]);  
        radio.stopListening();
        bool ok = radio.write(&SendPayload,strlen(SendPayload));
        
        lcd.setCursor(0,1);
        lcd.print("S:");
        Serial.print("S:");
        lcd.setCursor(2,1);
        lcd.print(SendPayload);
        Serial.print(SendPayload);          
        Serial.println();
        stringComplete = false;

        // restore TX & Rx addr for reading       
        radio.openWritingPipe(pipes[0]);
        radio.openReadingPipe(1,pipes[1]); 
        radio.startListening();  
        SendPayload[0] = 0;
        dataBufferIndex = 0;
  } // endif
} // end serial_receive()

Thank you for the example. I would suggest modifying it to read one input pin to determine it's address number. Then the code doesn't have to be recompiled for both sides.

JohnHoward:
Thank you for the example. I would suggest modifying it to read one input pin to determine it's address number. Then the code doesn't have to be recompiled for both sides.

The program does not need to read any input pin, it swapped the Tx/Rx addr during the radio.write operation...

Oh, I see that now. I misunderstood.

How can i use this code to transmite GPS data?

For that, I wrote another program for it.. it fragment the GPS data into 3 fragments...

Hi, thank you for the example.
i use arduino mega, is it work fine on mega?
RF24 radio(8,9);
is 8 for csn pin & 9 ce?

Thanks

http://maniacbug.github.io/RF24/classRF24.html

No, RF24 radio(CE,CSN);

Hi

Thanks for the nice little chat-program, it will be a good start for me to understand wireless communication between 2 arduino with the rf24L01

Its "sort of" working for me. I cant seem to get the code to understand when i hit ENTER/RETURN
From this piece of code:

      else if(incomingByte=='\n'){
          serialBuffer[dataBufferIndex] = 0; 
          stringComplete = true;
      }

Do I understand it right, by when it gets the "char" \n, it will send whatever that has been written?
For me it looks like it never detects the \n, because it will only send when dataBufferIndex is above 31, like this code:

      } else if (dataBufferIndex > 31) {
         stringComplete = true;        // Send this buffer out to radio
         stringOverflow = true;        // trigger the overflow flag
         charOverflow = incomingByte;  // Saved the overflow byte for next loop
         dataBufferIndex = 0;          // reset the bufferindex
         break; 
      }

If I do change:

      else if(incomingByte=='\n'){

to

      else if(incomingByte=='<'){

I can type:
abcdefg< followed by ENTER to send it
So could it be that I'm on a mac with OSX and \n isn't what is being received when hitting ENTER?, However, I've tried with:

      else if(incomingByte=='\n' || incomingByte=='\r' || incomingByte=='\r\n' || incomingByte=='\n\r'){

with no success.

I'm confused.

Can anybody help me through this?

Best regards
Niclas

Hi Niclas

Try "newline" instead of "carriage return" in your serial window.
And then press Send...

;D

hi, try tmrh20 fork of maniac's rf24 library, it is more recent and actively developped
google for his blog and github repository
you probably do not have to change your sketch, just replace the library

thanks for sharing

Thank you for very simple and helping example. Greatly appreciated...

hi all

i'm trying to connect 2 arduino boards mega and uno with nrf24l01
it wroks, arduino uno as tranceiver and mega as receiver
now i'm trying to send reply ( well received for example ) from the receiver to the tranceiver but it didn't works
Can you help me on this
you will find the 2 program codes and the library used attached.
Thank you for your help

recepteur.ino (1.58 KB)

transmetteur.ino (1.69 KB)

recepteur.ino (1.58 KB)

transmetteur.ino (1.69 KB)

I copy the exacly code and i get this error :

chat_serial_monitor_transceiver.ino: In function 'void setup()':
chat_serial_monitor_transceiver:49: error: 'printf_begin' was not declared in this scope
'printf_begin' was not declared in this scope

do i need any library to solve the problem ?
can anyone help me ?

Hi, I am relevantly new to arduino and with the help of my friend I was trying to write a code for sending a string to the receiver which after receiving the string will send back another string to the transmitter. I am posting my code below. While compiling it shows no error but on serial monitor it shows no output... Can any one help me and tell me what it is that I am doing wrong. I have no experience of coding in arduino...Thanks in advance :slight_smile: :slight_smile: :slight_smile:

Here is the code:

Transmitter:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>

int msg[1];
int resp[1];
RF24 radio(9,10);
String theReply = "";

const uint64_t pipe1 = 0xE8E8F0F0E1LL;
const uint64_t pipe2 = 0xE8E8F0F0E3LL;

void setup(void) {
Serial.begin(9600);
radio.begin();
}

void loop(void) {
int role = 1;
String theMessage = "Is it working? :/";
int msgsize = theMessage.length();

if(role == 1)
{
radio.openWritingPipe(pipe1);

for(int i=0; i < msgsize; i++)
{
int charToSend[1];
charToSend[0] = theMessage.charAt(i);
radio.write(charToSend,1);
}

msg[0] = 2;
radio.write(msg, 1);
role+=1;
radio.powerDown();
delay(1000);
radio.powerUp();
}

if (role == 2)
{
radio.openReadingPipe(1, pipe2);
radio.startListening();
if (radio.available())
{
bool done = false;
done = radio.read(msg, 1);
char theChar = resp[0];
if (resp[0] != 2)
{
theReply.concat(theChar);
}
else
{
Serial.println(theReply);
theReply = "";
}
}
role = 1;
radio.powerDown();
radio.powerUp();
}
}

receiver:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>

int msg[1];
int resp[1];
RF24 radio(9,10);
String theMessage = "";

const uint64_t pipe1 = 0xE8E8F0F0E1LL;
const uint64_t pipe2 = 0xE8E8F0F0E3LL;
void setup(void) {
Serial.begin(9600);
radio.begin();
}

void loop(void) {
int role = 1;
String theReply = "Yes! It is indeed working!";
int msgsize = theReply.length();

if (role == 2)
{
radio.openReadingPipe(1, pipe1);
radio.startListening();
if (radio.available())
{
bool done = false;
done = radio.read(resp, 1);
char theChar = msg[0];
if (msg[0] != 2)
{
theMessage.concat(theChar);
}
else
{
Serial.println(theMessage);
theMessage = "";
}
}
role = role - 1;
radio.powerDown();
delay(1000);
radio.powerUp();
}

if(role == 1)
{
radio.openWritingPipe(pipe2);

for(int i=0; i < msgsize; i++)
{
int charToSend[1];
charToSend[0] = theReply.charAt(i);
radio.write(charToSend,1);
}

resp[0] = 2;
radio.write(resp, 1);
role = 2;
radio.powerDown();
radio.powerUp();
}

}

Hi Stanley,

Thanks a lot for the code.
I got this code running on two NRF24L01+ 's on Arduino Uno's; and it worked like a charm.
However, now I would like to run these using ATtiny84's, and just cannot get the code to compile. (serial was not declared in this scope).

What am I missing here?

Thanks!

Hi. Im new in all this stuff so Im having problems with your sketch, when I verify the code I got an error:
"fatal error: printf.h: No such file or directory
compilation terminated."

So, it seems I need a printf.h library? If thats the case I cant find anything but information about being obsolete, so I need to use something different, the answer is what?

Thanks.

printf.h

/*
 Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 version 2 as published by the Free Software Foundation.
 */
 /*  Galileo support from spaniakos <spaniakos@gmail.com> */

/**
 * @file printf.h
 *
 * Setup necessary to direct stdout to the Arduino Serial library, which
 * enables 'printf'
 */

#ifndef __PRINTF_H__
#define __PRINTF_H__

#if defined (ARDUINO) && !defined (__arm__) && !defined(__ARDUINO_X86__)

int serial_putc( char c, FILE * )
{
  Serial.write( c );

  return c;
}

void printf_begin(void)
{
  fdevopen( &serial_putc, 0 );
}

#elif defined (__arm__)

void printf_begin(void){}

#elif defined(__ARDUINO_X86__)
int serial_putc( char c, FILE * )
{
  Serial.write( c );

  return c;
}

void printf_begin(void)
{
  //JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port)
  stdout = freopen("/dev/ttyGS0","w",stdout);
  delay(500);
  printf("redirecting to Serial...");
  
  //JESUS -----------------------------------------------------------
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO

#endif // __PRINTF_H__

Stanley

I just copied and pasted your sketch from the original post On compiling I get these errors

D:\Arduino\serialChat\serialChat.ino: In function 'void nRF_receive()':

serialChat:111: error: void value not ignored as it ought to be

         done = radio.read(&RecvPayload,len);

              ^

D:\Arduino\serialChat\serialChat.ino: In function 'void serial_receive()':

D:\Arduino\serialChat\serialChat.ino:137:14: warning: unused variable 'ok' [-Wunused-variable]

         bool ok = radio.write(&SendPayload,strlen(SendPayload));

              ^

I can see what the second one (ok) is about but I can make neither head nor tail of the first one (done).
I am using Arduino 1.6.13 which may make a difference.

However, I am reluctant to start fiddling with the code if there's a simple answer (which you might see being the author). Can you suggest the solutions?

BTW: there is some really clever programming in this. Thanks

I found out, that I am getting ACK from nowhere. I turned off RPI3 and I still getting ACK messages. I have line
if (radio.available()) {

}
So I am having available data from somewhere?

So how I am getting ACK messages from nowhere? Maybe Aliens wants to contact with me? :smiley: