Saturday, October 4, 2014

nRF24l01+ reloaded

Since writing my post on nrf24l01 control with 3 ATtiny85 pins, I've realized these modules are quite popular.  Of over a dozen posts on my blog, it has the most hits.  From the comments in the blog, I can see that despite a lot of online resources about these modules, there's still some not clearly documented problems that people run into.  So I'll go into some more detail on how they work, share some of my tips for testing & debugging, and more.

The biggest source of confusion seems to be with holding CE high.   Section 6.1.6 of the datasheet specifies a 10us high pulse to empty one level of the TX fifo (normal mode) or hold CE high to empty all levels of the TX fifo.  This is borne out in testing - CE can be held high for a transmitting device.

The above is a picture of a $1.50 wireless transmitter node I made.  Sorry about the poor focus - I don't have a good macro mode on my camera.  It's made with an ATtiny88-au glued and soldered with 30AWG wire to a nRF24l01+ module.  The pin arrangement is as follows:

ATtiny88 ------ nRF module
14 (PB2/SS) --- 4 (CSN)
15 (PB3/MO) --- 6 (MOSI)
16 (PB4/MI) --- 7 (MISO)
17 (PB5/SCK) -- 5 (SCK)
29 (PC6/RST) -- 3 (CE)

Connecting reset to CE keeps CE high when the AVR is running, and it also gives me an easy way to program the ATtiny88.  By connecting the CE pin to the RST pin of my programmer (a USBasp), the existing pins on the nRF module can be used as a programming header.  As long as CSN is not grounded, the nRF will not interfere with the communication on the SPI bus.  In my testing it worked with CSN floating, but it would probably be best to tie it high or connect a pullup resistor between CSN and Vcc.  A small 0603 15K chip resistor should work nicely for this.

The module is powered by a CR2032 cell in a holder on the back of the module.  When I wrote my post about Cheap battery-powered micro-controller projects, I hadn't done much experimenting with coin cells.  Although some CR2032 batteries can output 20mA continuous, the no-name cells I bought from DX certainly cannot.  I connected a 20uF electrolytic capacitor to provide enough voltage during transmits (around 12mA), and put the module in power-down mode the rest of the time.

While keeping CE high is fine for a device that is only transmitting or only receiving, you might run into a problem if you try to switch between the two.  The reason can be found in the state diagram from the datasheet: (contrast enhanced to make the state transitions easier to see)
The state diagram shows there is no way to go directly from Rx to Tx mode or the other way around.  The module must go into the standby-I state by setting CE low, or into the power down state by setting PWR_UP=0.  With CE held high, the only way to change between Rx and Tx mode is to go through power down mode.  Another option that doesn't require a separate pin for CE control is to connect CE to CSN.  This would allow you to use some nRF libraries that rely on CE toggling.  A potential drawback to this is if you want to keep the module in receive mode while polling the status (#7) register for incoming packets.  Each time CSN is brought low to poll the status, it will bring CE low as well, which will cause the module to drop out of Rx mode.  It only takes 130uS to return to Rx mode once CE goes high, so this may not be a concern for you.


Using a red LED in series with Vcc as my post on nrf24l01 control with 3 ATtiny85 pins makes it possible to quickly see how much power the module is using.  When in power down mode with CSN high, no light is visible from the LED due to the very low power use.  When powered up in Rx or Tx mode, the LED glows brightly, with 10-15mA of current.  By watching the power use I was able to tell that after the Rx fifo is full, the module stops receiving, causing the power consumption to drop.  The diagram in section 7.5.2 of the datasheet indicates that will happen if CE is low, but it still happens even with CE high.  Once a single packet is read out from the Rx fifo, it starts listening for packets again.

I also found connecting a LED to the IRQ pin (#8) helpful to see when the Rx or Tx IRQ fired.

Lastly, when testing connectivity, start with enhanced shockburst disabled (EN_AA = 0), and CRC off.  Then once you've confirmed connectivity, enable the features you want.  If you decide to use CRC, go with 2-byte CRC (EN_CRC and CRC0 in the CONFIG register) since a 1-byte CRC will miss 1 in every 256 bit errors vs 1 in 65,536 for a 2-byte CRC.

Undocumented registers

Register 6 (RF_SETUP) seems to be a 9-bit register.  Attempting to write 2 bytes to the register of all 1s (ff ff) followed by a read results in the following response:
0e ff 01
For other registers documented as being a single byte, attempts to read multiple bytes results in the same byte being repeated after the status byte.

There's also an undocumented multi-byte register at address 1e.  I found some code online that refers to this register as AGC_CONFIG, which implies it is for automatic gain control.  I could not find any documentation on how to use this register.  With my modules, the first three bytes of this register defaulted to 6d 66 05.  Reading them back after writing all 1s resulted in fd ff 07, so some bits are fixed at 0.


  1. Hi.. i find this technique of saving pins amazing, even more when we are speaking about for a micro controllers like the attiny 45/85.

    My idea was too use a nrf24l01 + attiny85 + ds18b20 + (later another sensor when possible ).

    here is my the circuit and how its connected on the link below

    its the circuit correctly connected?

    now on the code part

    the sketches that are on the picture is just to calculate the ping between the server and the client.

    the attiny85 is running as server and at 1 MHz

    the arduino uno i used as client to able to see on the serial monitor what is happening.

    but i don't know what is wrong.. it is giving me timeout on the serial monitor.

    could you help me?

    i would like too have communication between the arduino uno and the attiny85.

  2. I'm having a hard time understanding what you're asking. The link you gave is a small unreadable schematic on a page plastered with ads. If you have it in pdf or png I could look at it.
    Kyle Anderson used the CE tied high technique with a t85 in his equail project. It might help if you look at it too.

  3. Great article(s) !

    Any idea if this would work with an attiny13a?

    1. There's no USI or SPI hardware on the t13a, so you'd have to big-bang the communications. Other than that, you should be able to get it to work.

    2. thanks for reply, I noticed it didn't have the USI or SPI, but I wasn't sure if the technique you have needed either of those at a low level. As it turns out, I'm short a few GPIO, so I'm changing to an t44a or t88a.

      Also, any chance of a small writeup about your $1.50 nodes? My project is to make a cheap ibeacon, using the nrf24l01 + attiny and dmitry's bit bang BLE:

    3. I mentioned how I wired up the t88 to the nrf module, so I'm not sure what else there is to write about the $1.50 nodes I made. I've been looking at the ble beacon stuff too. I'm hoping to find nrf compatible modules that can transmit >32 bytes for full BLE compatibility. The SE8R01 turned out to be limited to 32 bytes like the nordic chip. Next I'll try a BK2423-based chip.

    4. Hi Ralph,
      thx for reply, the article above does have enough details, I somehow missed it the first time. For my purposes, the 32byte tx size might work out ok (just need rssi of beacon), but I am curious about one of the arduino libs having a receive function for the nrf24l01, I think it can only see other (similar) broadcasts.

      I was just looking at the SE8R01 as well, any chance of buying some of your spare parts? (se8r01, attiny88-au + breakout boards, etc). I'm in Toronto.

      thx, ttyl

    5. I've got enough to part with a few, and they're small enough I could probably send them cheaply in a first class envelope. Drop me an email and we can work something out.

  4. Hi Ralph,

    Did you have any luck with the NRF24L01 + BLE using Dmitry's code? I've tried it, plus some of the spinoff libraries, but no luck seeing the NRF24 on my android 4.4 phone. Trying to figure out if it's my setup and code, or some limitation in Android.

    1. Haven't tried it yet. Currently working on updating the Arduino RF24 lib to use the SPI transactions API added in Arduino 1.6.
      My plan is to try the BTLE lib instead of Dmitry's base code.

    2. I tried that one, plus Sandeep's revised version of Dmitry's code, but with no luck so far:"

    3. This comment has been removed by the author.

    4. followup: I got the ble transmit working with 2 other modules I received, not sure what I did to the first ones, look real (baite). Might have had them on 5v vcc briefly, oops.

      This post + tinySPI worked for me using attiny85 + nrf24l01

    5. Thanks for the suggestion, I tried lijun's code with a Pro Mini and 2 different nRF modules without any luck. My Moto G running 4.4.4 has picked up other devices with BLE scans, so I don't think it's a problem with my phone. I think I'll order a CC2540 BLE dongle and run the TI BLE sniffer to try to figure out what's going on.

  5. SE8R01 does have a RSSI indicator. Located in register 0x09, signed integer. Range from -100 to +10 dbm.

    1. I did notice that register, but had strange results with it. In my tests, it turned out to be much more accurate when checked on the TX node after getting back an ACK from the RX, instead of using it on the RX node like the docs mention. Could have been my code though.

  6. hello i have attiny24V can u plz tell me where can i find the board so i can program it 10x