nRF24L01 Network

Hi! im building a nrf24l01 network iot to display realtime charts with sensor's data, so im having trouble because i dont know what the best way to do this might be.
I need a group of sensors sending data to a base pc, and in the base pc it stamps the time when received, because it would be a mess to add time modules to each sensor's point, then all the data is sent at once, so it is received at once, not byte by byte sending.
Here is my first problem.
My approach to the solution was making a string so

String data;
data = "[";
for (int i=0; i < nsensors; i++){
  if(i != nsensors-1) {
data += analogRead(i) + ",";
 else { 
 data += analogRead(i) + "]"
 }
}

In this way the format of the data can be received as [data,data,data] at the base pc, making it easier for me to format this in a list (python), as well as debug any wrong sent data, if i dont have "[", "]" this would be easy to know. Now the problem that i have is that i cannot send this as a string directly on the rf24Network library (GitHub - nRF24/RF24Network: OSI Layer 3 Networking for nRF24L01(+) Radios on Arduino and Raspberry Pi), not that i know at least.
So i can send a char array, but my problem with this would be transforming a non static size of that string, given that sensors values could change between 2 digits or 1 even to 3 or even 4, so char array would have variable size.

This is what i got know on the sender side

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

int nsensors = 4;
String id = 1;

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 01;   // Address of this node in Octal format ( 04,031, etc)
const uint16_t node00 = 00;      
String data;

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);  //(canal, dirección del nodo)
}

void loop() {
  network.update();
  
  data = "[" + id + ",";
  for (int i=0; i<nsensores; i++){
    if (i != nsensores-1){
      data += analogRead(i) + ",";
    } else {
      data += analogRead(i) + "]";
      }
    }
//METHOD TO CONVERT VARIABLE STRING SIZE TO CHAR ARRAY (now data would be char array)

  RF24NetworkHeader header(node00);     // (Address where the data is going)
  bool ok = network.write(header, &data, strlen(data)); // Send the data
}

and this on the receiver side

#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 our node in Octal format ( 04,031, etc)

void setup() {
  Serial.begin(9600);
  radio.begin();
  network.begin(90, this_node); //(channel, node address)
}

void loop() {
  network.update();
  while ( network.available() ) {     // Is there any incoming data?
    RF24NetworkHeader header;
    len = network.getDyanamicPayloadSize();
    char incomingData[len]; //or something like that, not sure tho
    network.read(header, &incomingData, len); // Read the incoming data
    Serial.println(incomingData);
    }
}

Thank you for helping, if you want to know more info about the nrf24Network library here i read chunks of code. Would love to know the optimal way that you think how this should be done.

at the receiver you could use strtok() or equivalent to parse the incomming string, e.g.

#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="[23,7,234,5678]";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str,"[,]");
  while (pch != NULL)
  {
    int x=999;
    printf ("string found %s\n",pch);
    x=atoi(pch);
    printf("integer = %d\n", x);
     pch = strtok (NULL, "[,");
  }
  return 0;
}

gives

Splitting string "[23,7,234,5678]" into tokens:
string found 23
integer = 23
string found 7
integer = 7
string found 234
integer = 234
string found 5678]
integer = 5678

NRF24 packet sizes are limited to a maximum of 32 bytes. In my opinion you are asking for trouble using an ASCII data format.

First of all by not packing the data efficiently you waste bandwidth. Secondly when multiple packets become necessary you have no easy way to tell if any packets have been lost.

I would send and receive data in binary format OTA. There’s nothing stopping you expanding out that OTA format into ASCII at the receiver if you need something human readable for the Python script to receive.

felipein:
I need a group of sensors sending data to a base pc,

I presume that means that the sensors are sending data to a base Arduino which then passes the data to the PC.

What is the longest distance between a sensor and the base Arduino? Maybe there is no need for the complication of the Network system?

...R
Simple nRF24L01+ Tutorial

wow thanks for the fast replies guys, i'll give my best trying to answer

horace:
at the receiver you could use strtok() or equivalent to parse the incomming string

Im having trouble on the sender and on the receiver, cause i dont know how to pack the data yet.

pcbbc:
NRF24 packet sizes are limited to a maximum of 32 bytes. In my opinion you are asking for trouble using an ASCII data format.

First of all by not packing the data efficiently you waste bandwidth. Secondly when multiple packets become necessary you have no easy way to tell if any packets have been lost.

I would send and receive data in binary format OTA. There’s nothing stopping you expanding out that OTA format into ASCII at the receiver if you need something human readable for the Python script to receive.

this sound quite right, i dont know how to use binary format, will look into it, any guide on a quick example? that would be awesome. If the main problem of sending an array with the data at once is achievable this might be an awesome solution. So its no such a big deal if a package of data is lost, the problem is if it is not received together, so i need at one moment in time the full data of all sensors to have a correct timestamp, that is the reason why i need to send 1 big array (im trying to use 7 sensors, lol i hope i can make it (it's for my undergraduate thesis LOLOL)

Robin2:
I presume that means that the sensors are sending data to a base Arduino which then passes the data to the PC.

What is the longest distance between a sensor and the base Arduino? Maybe there is no need for the complication of the Network system?

...R
Simple nRF24L01+ Tutorial

You are right on the first one, im on a harshful terrain, so getting the system wired is not impossible but highly undesirable, and i need multiple data points so this doesnt scale too good imo.

OTA = Over The Air
As opposed to...
OTW = Over The Wire

It refers to how the data is physically transmitted, not any one particular data format.

First you need to decide how much data, and of what type (bits, bytes, etc) you need to send. Only then can you devise a suitable OTA format. You need to keep in mind your messages will probably require extra fields to indicate which sensor the data came from, and maybe a message sequence number, etc, in addition to the actual payload.

Say you have more than 32 bytes worth of data total, then you must devise a multi-packet format which allows the receiver to piece back together the received packets and detect dropped packets such that it can reject the entire message and wait for the next transmission.

pcbbc:
Say you have more than 32 bytes worth of data total, then you must devise a multi-packet format which allows the receiver to piece back together the received packets and detect dropped packets such that it can reject the entire message and wait for the next transmission.

auch, im not quite sure if 7 analog sensors could fit 32 bytes, from 0 to 1023 each could that fit on that size? i think so, but how would you decompose that and make 1 sendable/readable payload?

1023 can be written in 2 bytes(on binary i guess), then i could have a byte to split values like 00000000 7 times, so that would be 21 bytes if i dont suck that much at this? haha

A basic error you have is

  String data;

  bool ok = network.write(header, &data, strlen(data)); // Send the data

This code will send the String descriptor (a pointer and a length) and not the String content.

felipein:
auch, im not quite sure if 7 analog sensors could fit 32 bytes, from 0 to 1023 each could that fit on that size? i think so, but how would you decompose that and make 1 sendable/readable payload?

1023 can be written in 2 bytes(on binary i guess), then i could have a byte to split values like 00000000 7 times, so that would be 21 bytes if i dont suck that much at this? haha

That will work, assuming all 7 sensors at the same location.

2 bytes per reading and 7 readings is 14 bytes total, not 21.

It is very easy to define an array for the values and send them...

uint16_t data[7];

network.write(header, data, sizeof(data));

felipein:
and i need multiple data points so this doesnt scale too good imo.

You can have as many data points as you want communicating directly with a base unit if the distance is suitable but you did not answer my question about the distance.

...R

Robin2:
You can have as many data points as you want communicating directly with a base unit if the distance is suitable but you did not answer my question about the distance.

...R

is in the order of hundreds of meters, actually is for an underground mine, so wiring that thing is not something that they will just let me, rf was accepted tho

pcbbc:
That will work, assuming all 7 sensors at the same location.

2 bytes per reading and 7 readings is 14 bytes total, not 21.

It is very easy to define an array for the values and send them...

uint16_t data[7];

network.write(header, data, sizeof(data));

This seems right on, i was thinking on putting a byte in between to separate the values, but seems that isnt neccesary! (14+7 gave me 21 lol)
Gonna test it, thanks!

felipein:
is in the order of hundreds of meters, actually is for an underground mine, so wiring that thing is not something that they will just let me, rf was accepted tho

You won't get much range from any 2.4GHz wireless underground. The signal will just be absorbed by the ground.

I suspect wireless underground is a specialised technology.

...R

Robin2:
You won't get much range from any 2.4GHz wireless underground. The signal will just be absorbed by the ground.

I suspect wireless underground is a specialised technology.

...R

yeah, is not too good but i have straight sight in a lot of places, so i dont need too much repetition points.

Its proof of concept more than anything

Any clue on how to use the dynamic payload on the network?
this line

uint8_t len = network.getDynamicPayloadSize();
network.read(header, &incomingData, len);

gives me this error

'class RF24Network' has no member named 'getDynamicPayloadSize'

or

uint16_t incomingData[7];
network.read(header, &incomingData, sizeof(incomingData));

should do it?
Its almost done! thankyou everyone for your good will