Are we initializing the nRF24L01+ correctly?

  • Mod

    About a year ago I posted this issue on the forum.

    I never found out the cause of the problem, but kept running into known-good radios consistently failing every now and then. Judging from the forum posts, I'm not alone...

    Yesterday I was repeatedly hardware-resetting a sensor node and suddenly it stopped sending. It only reported fails on its serial interface. I did not move the sensor or the gateway inbetween.

    This means that sometimes after a reset of the Arduino, probably depending on the state of the nRF, the radio will not be initialized correctly. I searched the net for issues resetting the nRF and only really found this discussion, which could be the same issue I experienced.

    Anyway, opened the nRF's datasheet, and had a look at figure 4: Radio control state diagram. As the nRF cannot be reset from software, I was looking for a way to at least consistently bring the nRF back into a defined state during startup.
    Normally, after a reset of the Arduino, CE will be set 0 (in RF24::begin()) and state Standby-I should be entered, or we stay at Standby-II.
    This way we will not always start from the same state. Furthermore we may only hope that all those fake nRF chips lying around will follow the statemachine from a genuine nRF to the letter (I encountered this issue using a known fake nRF, btw).

    There is however a way to always bring the nRF back the same starting state. There is a state transition from every state to 'Power Down', by simply setting the PWR_UP flag to 0 (in the CONFIG register). PWR_UP will be set to 1 again, when calling powerUp() at the end of initialization.

    I compared the MySensors nRF driver to the current TMRh20 version (on which MySensors' driver is based) and found it always brings back the radio to state 'Power Down' before starting initialization (this line). The MySensors driver lacks this line of code....

    I added the same line to the MySensors driver, and retried the tests, but (ofcourse 😡 ) wasn't able to reproduce the issue again...

    So, could it be that in some rare sittuations we do not initialize the nRF24 correctly?
    If so, this might be a very simple fix for those issues, but we need to be able to reproduce it to make sure it fixes the issue.
    Did any of you guys experience somthing similar, or even know how to reproduce it?

  • Hero Member

    my g/w using a NRF24L01+ dies occasionally...
    I always suspect its due to movement of the pcb/radio as its mounted underneath a staircase.

    Ill have a go at making this change and see if the issue goes away.

  • Mod

    @gregl if my theory is correct, it will only happen when resetting the nRF, not during normal execution.

  • I've been suspicious of the order of operations in the begin() function of the RF24 driver.

    Specifically these lines:

      // Reset current status
      // Notice reset and flush is the last thing we do
      write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
      // Set up default configuration.  Callers can always change it later.
      // This channel should be universally safe and not bleed over into adjacent
      // spectrum.
      // Flush buffers
      powerUp(); //Power up by default when begin() is called
      // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp )
      // PTX should use only 22uA of power
      write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );

    Theoretically, I think it may be best to reset the IRQ flags and flush the buffers after powering up and entering standby, but the failures are a bit sporadic, so I haven't been able to verify if this will reduce/prevent issues on resetting. A larger user base or additional testing may be able to prove it one way or the other, so thought it worth mentioning.

  • Hmm... that's funny. I get the occasional fail on a particular motion sensor node/MQTT broker gateway I have as well. In my case, when I want to see the serial output of the MQTT broker that is connected to my Pi, I will picocom in with SSH and view the output, which resets the gateway. When that happens, I get the occasional fail message and have to unplug the Gateway to get it to read right again.

    Same thing goes with a motion sensor node I have. If watching the output via Serial in Arduino IDE, and I close/open the console window a few times, I can get the fail message to come up on startup. Again, unplug and full power down brings it back. The reset switch on the Arduino itself has never been dependable to fix it.

  • Have you guys been able to investigate a fix for this further? If you are looking for a Guinea Pig, I currently have two separate radios in this state. they both worked perfectly and then, sometime after a few hardware resets of the attached Arduino mini pro, they just stopped initializing ('radio init failed'). Would love to recover them if possible.

  • Admin

    @stevebus I'm doing a major RF24 lib refactoring to fully meet the nRF24L01+ specs.
    Please feel free to test it, feedbacks are appreciated.

  • Mod

    @tekka Good effort!
    I see you also start by setting PWR_UP flag to 0, as I suggested in this topic.
    I scanned your implementation and biggest changes compared to the current implementation (apart from the refactoring) are in the initialization code, correct?

  • Admin

    @Yveaux The current implementation does not initialize all registers properly, or modifies single bits (thus, the possibility of undefined conditions). The major changes are not necessarily in the init code, but rather in the pipe handling (all active RX pipes have now unique addresses) and less frequent register reading/writing.
    Over all, the library is faster, optimized to the specs and uses ~2kb less flash. However, this is still WIP and a few more pending changes before PR to dev.

  • Mod

    Awesome work @tekka !

  • Cool @tekka , I'll give it a try. Thanks for putting all the effort into it!

  • @tekka -- I downloaded the updated libraries and tried them. Still failed to initialize my "dead" radio..

    from serial monitor:
    Starting sensor (RNNNA-, 2.0.0-beta)
    Radio init failed. Check wiring.

    using MockSensor to test. Wiring is correct. It's certainly possible that the radio is truly 'dead', but I don't think so, as it was working fine before resets of the Arduino (and I have another in the same state.. and the same Arduino is currently being used in a sensor with a third radio).

    thoughts? I know you said it was a WIP, so it could be that it's not supposed to work yet. LMK.

  • Admin

    @stevebus If they fail with both library versions - I assume they're dead if you can exclude wiring problems or wrong Vcc.

  • thanks @tekka... I fear you are right. The main thing that sucks is I don't know what killed them. Oh well. Such is life.

  • @tekka Your rewrite actually fixed a problem I was having. For what ever reason I could not send messages from my ESP8266 based gateway to my test node. At the same time acknowledgement worked.
    Log of the original lib:

    0;255;3;0;9;send: 0-0-1-1 s=1,c=1,t=2,pt=4,l=4,sg=0,st=fail:1
    0;255;3;0;9;send: 0-0-1-1 s=1,c=1,t=2,pt=4,l=4,sg=0,st=fail:1
    0;255;3;0;9;send: 0-0-1-1 s=1,c=1,t=2,pt=4,l=4,sg=0,st=fail:1

    Same sketch with just your commit added:

    0;255;3;0;9;send: 0-0-1-1 s=1,c=1,t=2,pt=4,l=4,sg=0,st=ok:1
    0;255;3;0;9;send: 0-0-1-1 s=1,c=1,t=2,pt=4,l=4,sg=0,st=ok:1
    0;255;3;0;9;send: 0-0-1-1 s=1,c=1,t=2,pt=4,l=4,sg=0,st=ok:1

    Nothing else was changed.
    I didn't do any extensive testing. Just a quick check to see if your commit fixed my problem.

  • Admin