Sending data by NRF24L01'S - driving me insane

My old, fried 51yr old brain CANNOT figure this out.

I have a wireless link between a Mega 2560p and an Uno, using a pair of NRF24L01’s.

Used the demo code and wiring on this page:

Didn’t work as usual. Finally worked out that you need a 100uf across each NRF24L01. Why that isn’t mentioned anywhere on the page is maddening. But hey ho.

The transmitter code is:

 /*
    * Arduino Wireless Communication Tutorial
    *     Example 1 - Transmitter Code
    *                
    * by Dejan Nedelkovski, www.HowToMechatronics.com
    * 
    * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
    */
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    RF24 radio(7, 8); // CE, CSN
    const byte address[6] = "00001";
    void setup() {
      radio.begin();
      radio.openWritingPipe(address);
      radio.setPALevel(RF24_PA_MIN);
      radio.stopListening();
    }
    void loop() {
      const char text[] = "Hello World";
      radio.write(&text, sizeof(text));
      delay(1000);
    }

And the receiver code is:

 /*
    * Arduino Wireless Communication Tutorial
    *       Example 1 - Receiver Code
    *                
    * by Dejan Nedelkovski, www.HowToMechatronics.com
    * 
    * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
    */
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    RF24 radio(7, 8); // CE, CSN
    const byte address[6] = "00001";
    void setup() {
      Serial.begin(9600);
      radio.begin();
      radio.openReadingPipe(0, address);
      radio.setPALevel(RF24_PA_MIN);
      radio.startListening();
    }
    void loop() {
      if (radio.available()) {
        char text[32] = "";
        radio.read(&text, sizeof(text));
        Serial.println(text);
      }
    }

Now, it declares the ‘Hello world’ as: const char text = “Hello World”;

How do I re-write this code, so that I can change the contents of the message ‘text’?
No matter what I seem to try, it fails.

I did get some kind of horrific affair going using a string, but then everyone rolls their eyes at using those.

All I want to do is put line of varied line of text into the ‘text’ container whenever I need to and send it.

Why I can’t get my head around it I don’t know…

Take alook at Simple nRF24L01+ 2.4GHz transceiver demo for examples and advice that I know work

Thanks Bob. I had found that page.

Not much ‘commenting’ in the code, so it is still difficult to understand the principles.

Strings, strings, char, etc are just filling me with rage at the moment.

So…

if in setup you declare:

char dataToSend[12] = “Message 1”;

Then, later in the main loop you declare:

radio.write( &dataToSend, sizeof(dataToSend) ); // This sends the text correctly as defined the setup ‘Message 1’

Later in the loop, you enter:

char dataToSend[12] = “Message 2”;
radio.write( &dataToSend, sizeof(dataToSend) ); // This ends ‘Message 2’ correctly

But after this point, I cannot redeclare the contents of the message to say:

char dataToSend[12] = “Message 3”;
radio.write( &dataToSend, sizeof(dataToSend) );

Because this fires up the error:

redeclaration of 'char dataToSend [12]

How do you change the contents of the message?

Strings, strings, char, etc are just filling me with rage at the moment.

It sounds like you are lacking some basic knowledge of C

Have you tried the examples in Robin's topic ? If you follow the instructions then unless the hardware is defective they work.

Where are you stuck ?

You cannot change "const char text" because it is a constant declaration. You might want to read a basic tutorial on how c-strings work. You should forget all about the "String" class, it will introduce unwanted behaviour on Arduinos.

But I didn't think I was declaring it as a "const char text" in the example I typed in #2 above?

I don't want to use strings, but don't know/understand the other options.

Every example of sending text from A to B I have found, uses a piece of text that is declared in setup, and then never changes after that point.

I need to be able to change that text throughout the program and be able to send it.

But I didn't think I was declaring it as a "const char text" in the example I typed in #2 above?

That's what this does

char dataToSend[12] = "Message 1";

Try this as a simple test then apply it to your program

void setup()
{
  Serial.begin(115200);
  char dataToSend[20];  //an array to hold up to 19 characters plus termination
  strcpy(dataToSend, "message1"); //copy text to the array
  Serial.println(dataToSend);
  strcpy(dataToSend, "message2"); //copy different text to the array
  Serial.println(dataToSend);
}

void loop()
{
}

THANK YOU BOB

strcpy(dataToSend, "message1");

strcopy is the command I seem to have not been able to find in my hours of Googling

I know it seems obvious to you guys, but it's madly frustrating when you are close, but your lack of knowledge prevents you getting the result you need.

I don't understand it. But I am trying.

The bottom line is that you can send / receive any type of data that you want, as long as:

  1. That data occupies contiguous bytes in memory.
  2. Its size is less than or equal to 32 bytes.

Look at the prototype for the write() function:

bool write( const void* buf, uint8_t len );

It simply takes a pointer to your data and the number of bytes to send.

Likewise, the read() function:

void read( void* buf, uint8_t len );

Takes a pointer to where you want to put the data (i.e. a buffer, a struct, a variable) and the maximum number of bytes to put there (up to 32).

I am almost there with this now. All text etc wirelessly transmitting fine.

However, I have a variable to send 'mid' transmission and I cannot seem to work out the formatting.

I have a loop from the examples provided earlier set as the routine Transmit.

Example:

TXData = ("Test text 1");Transmit();
TXData = ("Test text 2");Transmit();
TXData = ("Test text 3");Transmit();

This will work fine.

However, I need to send a float to 3 decimal places as the second message. I have tried:

Test_val=100.002;

TXData = ("Test text 1");Transmit();
dtostrf(Test_val, 7, 3, TXData);Transmit();
TXData = ("Test text 3");Transmit();

Now this works once. The arriving message on the other will be as expected:

Test text 1
100.002
Test text 3

But after that initial correct data transfer, all the following messages are corrupted with the variable.

You then only ever receive:

100.002
100.002
Test text 3

What has happened to the first message?

Hard to tell without seeing your current, complete code.

How many bytes in total do you need to send ?
If less than 32 bytes then the easiest way in my experience is to put the data into a struct and send it in one hit. At the Rx end you put it into a struct and use it however you want/need

UKHeliBob:
How many bytes in total do you need to send ?
If less than 32 bytes then the easiest way in my experience is to put the data into a struct and send it in one hit. At the Rx end you put it into a struct and use it however you want/need

I mentioned that in Reply #8. Converting numbers to ASCII on the TX and then from ASCII at the RX is nuts.

But the receiver code is set up to receive data and print the results as text, using char.

So how is it going to know when print a variable. Surely it is easier to simply convert it and send it as a text file and then I don't need to 'adjust' the receiver code. 99% of what the receiver does is basically print the text it was sent.

I clearly don't understand this stuff. I will do as I always end up doing... randomly googling and stabbing code at it until it works.

I really don't understand why the dtostrf(Test_val, 7, 3, TXData);Transmit(); command changes after the first transmission, but hey ho

how is it going to know when print a variable

If the data is in a struct then each element of it has a separate data type and Serial.print() knows how to deal with each of them without conversion

You could try this, It complies ok.
It’s some code that I used that I know works and the only thing I’ve changed is the data in the struct instead of an int and byte I’ve changed it to a char and float.
I do like to test my code before posting as I don’t want to cause any confusion but I’m unable to test it as one of my NRF24L01 test boards is at work and I don’t have another one spare sorry.

TX Code:

 /*
    * Arduino Wireless Communication Tutorial
    *     Example 1 - Transmitter Code
    *                
    * by Dejan Nedelkovski, www.HowToMechatronics.com
    * 
    * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
    */
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    RF24 radio(7, 8); // CE, CSN
    const byte address[6] = "00001";
    // The sizeof this struct should not exceed 32 bytes
// This gives us up to 32 8 bits channals
struct MyData {
  char TXData1;
  float TXData2 ;
  char TXData3;

};

MyData data;
    void setup() {
      radio.begin();
      radio.openWritingPipe(address);
      radio.setPALevel(RF24_PA_MIN);
      radio.stopListening();
    }
    void loop() {
      data.TXData1 = ("TEST text1 ");
  data.TXData2 = 100.00;
  data.TXData3 = ("TEST text2 ");
  radio.write(&data, sizeof(MyData)); 
    }

RX code:

 /*
    * Arduino Wireless Communication Tutorial
    *       Example 1 - Receiver Code
    *                
    * by Dejan Nedelkovski, www.HowToMechatronics.com
    * 
    * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
    */
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    RF24 radio(7, 8); // CE, CSN
    const byte address[6] = "00001";
    unsigned long previousMillis = 0;        // will store last time LED was updated
const long interval = 1000;           // interval at which to blink (milliseconds)
unsigned long lastRecvTime = 0;
struct MyData {
  char RXData_in1;
  float RXData_in2;
  char RXData_in3;
  
};

MyData data;

void resetData()
{
  Serial.println("LOST DATA/CONNECTION");

}
    void setup() {
      Serial.begin(9600);
      radio.begin();
      radio.openReadingPipe(0, address);
      radio.setPALevel(RF24_PA_MIN);
      radio.startListening();
    }
    void recvData()
{
  while ( radio.available() ) {
    radio.read(&data, sizeof(MyData));
    lastRecvTime = millis();
  }
}
    void loop() {
      recvData();
  unsigned long now = millis();
  if ( now - lastRecvTime > 500 ) { //if data stops coming turn everything off with a half of second
    // signal lost? tunr it off
    resetData();
  }
  //# Print the data every second can be more)
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    //Print the Incoming data
    Serial.print("Test Data 1 in = ");
    Serial.print(data.RXData_in1);
    Serial.println("   ");
    Serial.print("Test Data 2 in = ");
    Serial.print(data.RXData_in2);
    Serial.println("   ");
    Serial.print("Test Data 3 in= ");
    Serial.print(data.RXData_in3);
    Serial.println("#######################   ");
    
  }
    }

Let us know how it goes and if it works

Steveiboy:
It's some code that I used that I know works and the only thing I've changed
is the data in the struct instead of an int and byte I've changed it to a char and float.

struct MyData {
  char TXData1;
  float TXData2 ;
  char TXData3;
};

  data.TXData1 = ("TEST text1 ");
  data.TXData3 = ("TEST text2 ");

The char fields are butchered, you created a very bad example.
If that code worked before, it does no longer.

Whandall:

struct MyData {

char TXData1;
  float TXData2 ;
  char TXData3;
};

data.TXData1 = ("TEST text1 ");
  data.TXData3 = ("TEST text2 ");



The char fields are butchered, you created a very bad example.
If that code worked before, it does no longer.

My bad then, I am unable to test. May be I should have not uploaded it.
I've not sent a char or float in my other code just a byte and int variable.

What would be the correct way then ?

once again sorry for the confusion .

steve

Thank you for all your assistance.
I have a working code. I would post the entire code, but it will quite literally get ripped apart by those who know better. I have posted code in here before and it didn't end well.

I can send text fine.

int TempTXData;                                                                                                                                    
char TXdata[30];
String Tosend;

I have a transmit routine:

void Transmit(){

   radio.stopListening();           // Sets RF module to transmit                                                                                                                
   delay(50);

   strcpy(TXdata, TempTXData);                   // Seed the string 'TXdata' with the contents of TempTXdata                                                                                                  

   radio.write(&TXdata, sizeof(TXdata));         // Send the data                                                                                               
   delay(50);


   radio.startListening();             // Sets RF module back to receive                                                                                                        
}

Fine.
Now to send my commands, I simply send:

TempTXData = ("Test text 1");Transmit();
TempTXData = ("Message has been sent");Transmit();

This all works as it should.

Further on in the code, I have a String command that is assembled from individual parts, and ends up as the String: 'Tosend' and that equals say "X+100"

I send that String using the following command:

Tosend.toCharArray(TempTXData,Tosend.length());Transmit();
TempTXData = ("Message has been sent");Transmit();

This will work once only. The receiving end will be:

X+100
Message has been sent

But, after that, the routine doesn't work any longer.

The above command will result in:

X+100
X+100

It ignores my request: TempTXData = ("Message has been sent");

So, do I need to clear the toCharArray command or something? I don't understand how it is printing the first transmission twice. The first String must be still stored somewhere.

Pretty sure this is messed up in more ways than one. Don't think TempTXData should be an int for a start