nRF24L01 - Reading and Writing "at the same" time

Hi Guys!

I'm new to the forum, so welcome evryone!

I'm working on a prototype of greenhouse light controling system. Its consist of one central unit and four recivers controling multiple lamps. I used these small nrf modules and so far everything was working great. But i have to add a wireless light sensor to this sytem (four in future) to control light intesnity to the according sun light condition.

In this case it should look like this:

Central unit -----> Recivers

^---- Light meter

Anyone tried use nrf for collecting and sending data in one sketch? I studied documentation of library many times and it should work, but it doesn't. I've tried opening and closing pipes in probably every possible way and i'm stucked. Any help?

Have a look at this Simple nRF24L01+ Tutorial. The second example using the ackPayload feature is a simple way to collect data. There is also an example with one master and 2 slaves that could easily be extended to your 4 slaves.

...R

Ok! Finally i solved problem!

Central unit now primary working as a Master and communicate with Slaves (lamps) with adres "A". Ocassionaly it switches to Slave, read data from light sensor (B adress) and back to it's master role. Problem was with switching roles. Simply adding 50ms delay after calling "radio.startListening(); function solved problems with communication. I spend a lot of time working with theese modules, try a lot libraries and waste lot of time :wink: They are realy unreliable and probably this will be my last project with them. Its time to try LoRa :slight_smile:

Robin2, thanks for reply, i read a lot about this radio modules, but i haven't find your post earlier :slight_smile:

PS I love this

Two or three hours spent thinking and reading documentation solves most programming problems.

1 Like

MikeS:
They are realy unreliable

Nope. Used correctly they are rock solid.

Nope. Used correctly they are rock solid.

I'm pretty sure I use them corretly :slight_smile: But 100m range is a myth. Working With 20-25m range ofthen causes problems and its realy random...

MikeS:
I'm pretty sure I use them corretly :slight_smile:

Looking at your experiences I'm pretty shure you don't.

MikeS:
But 100m range is a myth. Working With 20-25m range ofthen causes problems and its realy random...

Where did you get the idea of 100m range? Are you using the high power modules with the external antenna?

I have had a pair of low power modules working at 110 metres out doors where interference from other devices was unlikely but I would not expect that performance where there are obstacles or other devices radiating at 2.4GHz.

It is possible, and wise, to design a program to make allowances for occasional transmission failures no matter what type of wireless device you are using.

Have you tried changing channels?

...R

Looking at your experiences I'm pretty shure you don't.

I belive we could continue this conversation all day. Yes, i build few devices using nRF24L01 and some of them are working without problems 24/7 over year long, but evrytime i have to code them i feel like fighting :slight_smile: In theory, according to library documentation evrything should work, like my last problem.

From lib documentation:

void RF24::startListening ( void )
Start listening on the pipes opened for reading.

Be sure to call openReadingPipe() first. Do not call write() while in this mode, without first calling stopListening(). Call isAvailable() to check for incoming traffic, and read() to get it.

So according to this, module should be able to read data just after calling function.

But chip datasheet says, its need 130us to switch betwen modes.... Probably this wasn't implemented to lib.

I can agree with you, nrf24l01 is quite good chip, but its support for arduino could be better :wink:

Where did you get the idea of 100m range? Are you using the high power modules with the external antenna?

I've tried both version, and antena one was the winner. In the same conditions i've randomly get issues with transmission. It's hard to catch wat is wrong, becouse they disapear as suddenly as they appear :slight_smile:

MikeS:
So according to this, module should be able to read data just after calling function.

Basically it is. A 100 µs delay once was in the library, but is commented out now.

You don't have to wait for the chip being fully switched to receive mode, you will not receive faster by doing so.

If you miss support for some features go ahead and make the library better or a better library.

Basically it is.

So why the hell it wasn't working :smiley: And after adding little delay evrything works perfect :smiley:

If you miss support for some features go ahead and make the library better or a better library.

I was sure, You'll say this :slight_smile: I choose Arduino platform, becouse its realy handy when you create single prototypes/devices. Simply its saves a lot of time for me. I realy appreciate amont of time and work puted in this library. But You have to agree it isn't perfect, or is it? Well, maybe i'am using old version? Maybe i'am wrong :slight_smile: So far it works, when it stops i'll be serching for futher solutions!

MikeS:
But You have to agree it isn't perfect, or is it?

What is ever perfect? It works as described, even unchanged on an ESP32.

I miss(ed) many functions, to name some

  • interrupt support
  • buffer management
  • callbacks
  • periodic autosends
  • pipe addresses in PROGMEM/EEPROM
  • data in PROGMEM/EEPROM
  • handling of AckPayload data
  • auto-role switch on sends if necessarySo I wrote such a beast, grown from the TMRh20 library (I did not yet make that run on the ESP32).

In that process I learned a lot about the chip and its behaviour and you can believe me, it works as advertised.

I did not experiment with channels/data rate/tx power and ranges.

So I wrote such a beast, grown from the TMRh20 library

Sounds like a useful contribution, especially if you corrected any errors you found!

Is it posted somewhere, or would you consider posting it? Thanks.

And please if you do post your updated version of the library please give it a new name so it is not easily confused with the TMRh20 and the ManiacBug versions :slight_smile:

...R

My code needs more documentation, a principles of operation document and more examples.
I named it NRF24, maybe that should also be changed before a real release.

If you want to have a look at it, I attach a snapshot.

The doxygen output makes it rather fat. :wink:

One of the examples that are included.

#include <OUtility.h>
#include <SimCommDefs.h>
#include <SPI.h>
#include <NRF24.h>

bool doAcks = true;  // two send modes

const byte addr[] PROGMEM =  "pipe0" "pipe1" "pipe2" "pipe3" "pipe4" "pipe5";

const byte tMsg[] PROGMEM = "****Test Message";

// SPI pins CE,CS,IRQ,Receive, State
NRF24 radio(9, 10, 2, procRcb, procEvent);

byte noOfPipes = 6;

void setup() {
  Serial.begin(115200);
  Serial.println(F("NRF24 minimum Ack/noAck six"));
  Serial.println(F("s - send, a - change Ack/noAck, p - pipes, ? - state"));

  // a table of 6 addresses, in PROGMEM and MSB format
  radio.addresses(addr, 6, dcInPM + dcLen5 + dcMSB);
  // listen on 6 pipes without suppressing acks
  radio.listenOn(0, aiFirst, 6, false);
  radio.begin(PRX);
  radio.printMode();
  radio.printPipes();
}

void loop() {
  radio.processEvents();
  serialHandler();
}

byte procRcb(RCB& rcb) {
  return rPrint;
}

byte procEvent(Event& e) {
  if (e.txAny()) {
    radio.printSendResult();
  }
  return 0;
}

void processCmd(char* buf) {
  switch (*buf) {
    // send the testmessage to a random address from the table
    case 's': radio.send(aiFirst + random(0, 6), &tMsg, sizeof(tMsg), !doAcks, dcInPM);
      break;
    case 'a': repFlipBool(PSTR("Acknowlege"), doAcks);
      break;
    case '?': radio.printState();
      break;
    case 'p': radio.printPipes();
      break;
    case 'I': if (*++buf) {
        nodeId(*buf);
      } else {
        printNode();
      }
  }
}

// Command line stuff

void pEqOnOff(bool val) {
  Serial.print(F(" = "));  Serial.print(val ? F("ON") : F("OFF"));
}

void repFlipBool(const char* named, bool& Val) {
  Val = !Val;
  repBool(named, Val);
}

void repBool(const char* named, bool Val) {
  pPS(named, Serial);
  pEqOnOff(Val);
  Serial.println();
}

void serialHandler() {
  const byte sCBMax = 30;
  static char sCBuffer[sCBMax];
  static byte buffIndex = 0;

  byte inChar;
  bool doCheck = false;

  while (Serial.available()) {
    inChar = Serial.read();
    if (inChar == 13) {
      doCheck = true;
    } else if (inChar != 10) {
      if ((buffIndex == 0) && isWhitespace(inChar)) {
        continue;
      }
      sCBuffer[buffIndex++] = inChar;
      doCheck = (buffIndex == (sCBMax - 1));
    }
    if (doCheck) {
      sCBuffer[buffIndex] = 0;
      doCheck = false;
      if (buffIndex != 0) {
        processCmd(sCBuffer);
        buffIndex = 0;
      } else {
        Serial.println();
      }
    }
  }
}

Are there really errors in the TMRh20 driver?
I can not remember real errors in it, some omissions maybe.

NRF24Plus.zip (1.13 MB)

Whandall:
I named it NRF24, maybe that should also be changed before a real release.

What about calling it WhandallRF24?

Seriously.

...R

The examples did not even compile, they missed some restructuring.

So here is an updated package.

NRF24Plus.zip (1.13 MB)