Setting up NRF24L01 devices - Page 1
Forum section: electronics / beginners

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: March 10, 2025, 08:54:10 pm
content: Hello!I am working on a school project involving a Raspberry Pi Pico sending information to a Raspberry Pi 4. I don't need anything fast or fancy, this is just handling data from a weather station that I am building.The raspberry pi 4 us running ubuntu 22.04. Since I don't have much experience with linux I was hoping on being able to just hard program sending data and register settings using a generic SPI library. I have been able to read and write the registers on the NRF, but I have not been able send or receive data yet.Before troubleshooting my radio setup, is this something that is reasonable to do? I know there are nrf24 libraries out there, but they all seem a bit complicated, especially since I don't need 2Mbps or even auto acknowledge for that matter.

author: MarkF
author_rank: Super Contributor
timestamp: March 10, 2025, 09:59:49 pm
content: What you want to do is very reasonable depending on the distance between the transmitter and receiver. My experience for range is about 25 ft. with the power level reduced (-12 dBm) for better battery life. I use several nrf24L01+ transceivers for multiple wireless hand throttles on my HO scale model railroad.I must say that the nrf24L01+ is about the hardest interface to learn and use that I've programmed. The nRF arduino library is probably the best reference.Have a look at another discussion on the forum where I've posted basically my entire library. It can be easily ported to the PI with just changes ported to the PI hardware SPI registers.https://www.eevblog.com/forum/projects/looking-for-help-with-an-old-nrf2410l-chip/msg5721681/#msg5721681Note: I set my data rate to 1Mbps because I didn't need a high data throughput and intuition tells me it would be less susceptible to rf noise. Do expect some pack transmission loss.

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: March 11, 2025, 12:22:23 am
content: Thanks for the input MarkI bought the NRF modules with the external power amp and SMA antenna, since the signal has to travel some distance.I have a pretty good grasp of hoe SPI works, I just need to figure out what format the NRF wants data in. Page 65 of the datasheet for the NRF24L01 has an example, which I hope I can use as a guide. The only part that I don't understand from that example is where it says to send the NRF the transmit and the data payload. Where do you put the address? I assume it needs a command at the start, but which one?

author: MarkF
author_rank: Super Contributor
timestamp: March 11, 2025, 03:25:51 am
content: Question: Do you have a nrf14L01 or a nrf24L01+? The plus version is the newer version and most available.NOTE: EVERYTHING I'M TELLING YOU IS FOR THE PLUS VERSION.In order the send a message pipe 0 receive address and the transmit address must be the same. In your case you will only need pipe 0 and you can set both nrf24L01+ addresses the same. (You can leave them at their default power up addressed.Registers nRF_RX_ADDR_P0 and nRF_TX_ADDR.The other things you need to set are: The payload width for pipe 0. This is the number to bytes you wish to send (1 to 32 bytes). You can make the payload width variable (Dynamic Payload) but it's best to just pick a width. Note the width determines the time it take to transmit and does impact other timeout variables in the nRF24L01+.Register nRF_RX_PW_P0.You also should change the data rate to 1Mbps. The default is 250Kbps.Register nRF_RF_SETUP.If you use 1Mbps or 2Mbps, you can leave the re-transmisson timeouts at their default.You read and write configuration data via thenRF_RD_REGISTER and nRF_WR_REGISTERcommands.You transmit data by writing the data via theW_TX_PAYLOADcommand.And receive data by reading via theR_RX_PAYLOADcommand.The data is in any format you like. The nRF does NOT do anything with it.Control of each transmission is via thenRF_CONFIG, nRF_STATUS and nRF_FIFO_STATUSregisters.Here is a link to myreadPayload()andwritePayload()referenced in my previous link to my sample code:https://www.eevblog.com/forum/projects/looking-for-help-with-an-old-nrf2410l-chip/msg5721465/#msg5721465To summarize the minimum nRF initialization changes from their default values:- Set nRF_RX_ADDR_P0 and nRF_TX_ADDR addresses only if you want other than default or more than two nRF tranceivers.- Set nRF_RX_PW_P0 payload width.- Set nRF_RF_SETUP to nRF_1Mbps (recommend to start).This is all you need to do a pseudo broadcast of data.If you want to do an auto-acknowledge and re-transmit, there is more to setup.Then follow my code example to start sending data.Here is my nRF header file with #defines for the registers and commands used in my code:Code:// nRF24L01+ Commands#define nRF_RD_REGISTER 0x00#define nRF_WR_REGISTER 0x20#define nRF_RD_RX_PL_WID 0x60#define nRF_RD_RX_PL 0x61#define nRF_WR_TX_PL 0xA0#define nRF_WR_ACK_PL 0xA8#define nRF_W_TX_PL_NOACK 0xB0#define nRF_FLUSH_TX 0xE1#define nRF_FLUSH_RX 0xE2#define nRF_REUSE_TX_PL 0xE3#define nRF_NOP 0xFF// nRF24L01+ Registers#define nRF_CONFIG 0x00 // Configuration Register#define nRF_EN_AA 0x01 // Enable Auto_Acknowledgement#define nRF_EN_RXADDR 0x02 // Enable RX Addresses#define nRF_SETUP_AW 0x03 // Setup Address Width#define nRF_SETUP_RETR 0x04 // Setup Automatic Retransmission#define nRF_RF_CH 0x05 // RF Channel#define nRF_RF_SETUP 0x06 // RF Setup Register#define nRF_STATUS 0x07 // Status Register#define nRF_OBSERVE_TX 0x08 // Transmit Observe Register#define nRF_RPD 0x09 // Receiver Power Detector#define nRF_RX_ADDR_P0 0x0A // Receive Address#define nRF_RX_ADDR_P1 0x0B#define nRF_RX_ADDR_P2 0x0C#define nRF_RX_ADDR_P3 0x0D#define nRF_RX_ADDR_P4 0x0E#define nRF_RX_ADDR_P5 0x0F#define nRF_TX_ADDR 0x10 // Transmit Address#define nRF_RX_PW_P0 0x11 // Payload Length#define nRF_RX_PW_P1 0x12#define nRF_RX_PW_P2 0x13#define nRF_RX_PW_P3 0x14#define nRF_RX_PW_P4 0x15#define nRF_RX_PW_P5 0x16#define nRF_FIFO_STATUS 0x17 // FIFO Status Register#define nRF_DYNPD 0x1C // Enable Dynamic Payload Length#define nRF_FEATURE 0x1D // Feature Register// nRF24L01+ Bits// Configuration Bits#define nRF_CRC0 0x00 // CRC Off#define nRF_CRC1 0x08 // CRC 1 Byte#define nRF_CRC2 0x0C // CRC 2 Bytes#define nRF_PwrUp 0x02 // Power Up#define nRF_PwrDn 0x00 // Power Down#define nRF_PRX 0x01 // RX Mode#define nRF_PTX 0x00 // TX Mode// Address Width Bits#define nRF_AW3 0x01 // 3 Byte Address#define nRF_AW4 0x02 // 4 Byte Address#define nRF_AW5 0x03 // 5 Byte Address// RF Setup Bits#define nRF_250Kbps 0x20 // Data Rate 250 Kbps#define nRF_1Mbps 0x00 // 1 Mbps#define nRF_2Mbps 0x08 // 2 Mbps#define nRF_PWR18 0x00 // -18 dBm#define nRF_PWR12 0x02 // -12 dBm#define nRF_PWR6 0x04 // -6 dBm#define nRF_PWR0 0x06 // 0 dBm// Status Bits#define nRF_RX_DR 0x40 // Data Ready#define nRF_TX_DS 0x20 // Data Sent#define nRF_MAX_RT 0x10 // Max ReTransmit#define nRF_RX_P_NO 0x0E // RX Pipe Number#define nRF_TX_FIFO 0x01 // TX FIFO Full// FIFO Status Bits#define nRF_TX_REUSE 0x40#define nRF_TX_FULL 0x20#define nRF_TX_EMPTY 0x10#define nRF_RX_FULL 0x02#define nRF_RX_EMPTY 0x01// Feature Bits#define nRF_EN_DPL 0x04 // Enable Dynamic Payload Length#define nRF_EN_ACK_PAY 0x02 // Enable Payload with ACK#define nRF_EN_DYN_ACK 0x01 // Enable Dynamic ACKAttached is the nRF24L01+ datasheet and an interface summary PDF I put together.

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: March 18, 2025, 04:10:16 pm
content: Its been a bit, but I have made some progress, I apologize for no response to the last post.I can now receive data, but not consistentlyWhat happens is the RX will receive some number of packets, then it will fail to receive three times, after which the TX sets the TX_FIFO full flag. Perhaps this is a acknowledge problem, but I am not sure how to determine which end the problem is on.from what I can tell, micropython being somewhat difficult to write/ SPI commands, the address are set right. My next troubleshooting step is to disable auto ack and see what happens with the default power-up address.

author: MarkF
author_rank: Super Contributor
timestamp: March 18, 2025, 06:40:51 pm
content: Not knowing how you have the nRF's configured, a few things come to mind:- Remember the nRF transmit and receive FIFO's are only 3 payloads deep.- There are 3 bits in the STATUS register that the user must clear. I do this in the 'StartListening()' function.MAX_RT bit:Maximum number of TX retransmits interruptWrite 1 to clear bit.If MAX_RT is asserted it must be cleared toenable further communication.Your transmitting nRF may need to go through the receive mode even though it's not expecting any data.At a minimum, clearing the interrupt bits in the STATUS register prior to each transmission.Your main transmit loop if never receiving anything should be:while (1) {nrfStopListening();writePayload();nrfStartListening();delay(1000);}

author: RoGeorge
author_rank: Super Contributor
timestamp: March 18, 2025, 06:51:03 pm
content: Vaguely remember some strange problems for nRF24L01 when high Tx power levels are used.To check if this is the case, try setting the Tx power at minimum, and increase power level only if the receiver can't hear the transmitter. Don't use more power than needed.

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: March 18, 2025, 07:46:27 pm
content: Thanks for the info Mark and George, I will try a couple of things and report back.

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: March 24, 2025, 06:09:56 pm
content: Here is an update.I tried changing power levels, it did not seem to make a difference.I have not tried the mode switching thing yet, other code seems to do it as well so there is something here. I also noticed that in the data sheet that it states the NRF24 should not be in TX mode for more than 4ms at a time (page 23 of 78) can somebody explain why this is?The thing that doesn't make sense to me is that the transmission and ACK will succeed several times before failing, sometimes it will succeed 3 times, and sometimes it will succeed 15 times. I am not sure how to determine weather the failure is on the RX side or the TX side, either the RX is not getting the packets, or the TX is not getting the ACK. Either way the fact that the number of successes is variable leads me to believe that there is a problem with the radio signal, rather then software config, but please give your thoughts on this.Thanks!Alex

author: KimLum
author_rank: Contributor
timestamp: March 24, 2025, 06:39:17 pm
content: If you insist on operating the nRF24 radios whithout using a library, I would suggest you look at some code for a RF24 library in order to see how the radios are operated.I have made a weather station using an ATmega328P barebone chip, a BME280 sensor and a nRF24L01+ radio to transmit data every 10 minutes. The data is received by a Raspberry Pi 4 which then stores a copy of the data locally before transmitting it to the internet. On the Pi, i am using the rather oldlib_nrf24python library which works perfectly for what I need. You can look into the code of that library (file name: lib_nrf24.py) which should give you a pretty nice impression on how to operate the radios using SPI. If you are more into C(++), you could look at theArduino library(there are multiple, this is the one I use) used to operate the radios.

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: March 24, 2025, 07:39:50 pm
content: Thank you kim for the tip on that python library, It looks way simpler than the others that I found previously, I will give it a shot.I did not use a library before because as someone who does not have a very firm grasp on python and especially the syntax of libraries it was much easier to approach the problem by just bit-banging essentially. This method got me pretty far, but is flawed and clunky I am sure.

author: MarkF
author_rank: Super Contributor
timestamp: March 24, 2025, 11:37:38 pm
content: A few things:If you look at the bottom of mywritePayload()function, I check if the transmit failed.If the nRF is in Enhanced ShockBurst mode, the nRF will never be in TX mode for more than 4ms.If you're just doing the pseudo broadcast, you will notice that my code writes the payload and immediately returns to RX mode in thestartListening()function.I have not tried the mode switching thing yet, other code seems to do it as well so there is something here.- THIS IS MORE IMPORTANT THAN ANYTHING ELSE. This handles errors, FIFO flushing, and nRF resetting.Follow the example mainloop in my last post.The code I gave you is almost line-for-line what's in the Arduino nRF24 library for the Arduino.The bulk of the Arduino library I did not need and is not included.I don't do Python but I think we will soon need to see some code.I believe I said this earlier:YouWILLget transmission failures.Your codeNEEDSto be able to handle those errors or the nRFWILLstop sending your payloads.

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: March 26, 2025, 03:55:46 pm
content: I am currently reworking the transmitter code on the raspberry pi pico, but I tried the library suggested earlier for the pi4.Unfortunately that library does not seem to work, it has not been updated since 2015 so that may be partly why. when I ran one of the example programs it was reading that status register incorrectly, I couldn't figure out why.

author: RoGeorge
author_rank: Super Contributor
timestamp: March 26, 2025, 04:52:32 pm
content: A couple of years ago there was a major change in the way Linux kernel is accessing the I/O pins (since kernel v6.1.~19 or so, the device tree is mandatory). As a side effect, many old style ways of accessing I/O pins won't work with the recent versions of kernel (in any Linux machine, not just the RPi).For Raspbian, I think the most recent using old style I/O access is "Bullseye Debian 11".From their OS download page the Raspbian name seems to be "Raspberry Pi OS (Legacy)"https://www.raspberrypi.com/software/operating-systems/If you have a spare SD card, a quick test to see if this is the cause why the Python lib on RPi4 is not working would be to install the "Raspberry Pi OS (Legacy)", and make sure the OS does NOT auto update to the latest, then to try on it that Python library for nRF24.However, porting code from the old I/O access style to the new one is not trivial, would be probably easier to just rewrite the whole thing for the current Raspberry PI OS. Or to search for another nRF24L01+ Python library that can work with the recent RPi4 OS.

author: KimLum
author_rank: Contributor
timestamp: March 27, 2025, 10:39:24 am
content: I'm am running the latest "Raspberry Pi OS Lite" (Bookworm, 64bit, kernel 6.6) on a Pi 4, and the library I linked to earlier works without problems, the library uses "RPi.GPIO" in BCM-mode and an instance of "spidev.SpiDev()" to communicate with the radio module. The library does not work on a Pico-Pi, you would need to find a different library for that, you couldlook at this one.

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: March 28, 2025, 03:33:33 pm
content: I feel like I am getting very close at this point, but am running into reliability issues.Using a logic analyzer I discovered that the Rpi Pico's program was not writing some data correctly, having fixed that I can now successfully read/clear status and clear the TX fifo, which I could not do before.Now with the transmitter sending a packet once every second or so, 90% are not received by the RX. Of the 10% that are received, an ACK packet makes it back to the transmitter only about half the time. Is it possible that this is caused by a problem with the program? perhaps timing?To me it looks like there is a problem with the RF radio link, but that would be down to physical hardware, which seems unlikely unless the nrf modules I bought on amazon have faulty/fake power amplifiers on them.

author: MarkF
author_rank: Super Contributor
timestamp: March 28, 2025, 06:04:53 pm
content: How do you have the nRF's configured?Specifically:CONFIG - Configuration RegisterSETUP_AW - Setup of Address WidthsSETUP_RETR - Setup of Automatic RetransmissionRF_SETUP - RF Setup RegisterFrom my questions, you can probably determine if your configuration meets allthe timing requirements to perform Enhanced ShockBurst™ ‘Auto Acknowledgment’

author: KimLum
author_rank: Contributor
timestamp: March 28, 2025, 06:28:31 pm
content: Du you have at least an 10uF (at most 100uF) capacitor on VCC & GND as close as possible to the radio modules? This is used both for decoupling and stabilization of the power source and may improve stability by a lot on some modules - especially the long range / high power ones. If you are using long range modules, you may have issues if they are placed to close to each other so increasing the distance between the modules may also solve some issues. The modules can be setup to retry to send a message multiple times with a delay until an ACK is received (SETUP_RETR as already mentioned by MarkF), you may look into that.I would strongly encourage you to try to use libraries that are known to be good in order to test your setup and thereby eliminating hardware issues as being the problem.

author: MarkF
author_rank: Super Contributor
timestamp: March 28, 2025, 09:27:56 pm
content: Quote from: KimLum on March 28, 2025, 06:28:31 pmI have had that issue when testing on a breadboard.Adding a 1µF electrolytic capacitor solved the problem for me.In my case without the decoupling capacitor in place, the SPI channel communication would fail.The payload transfer loss may be as high as 1% during my normal operation using three nRF modules.Nothing near 90%.I have never seen the problem with the RF power being too high (PCB antenna).Even with two nRF's right next to each other at max power levels.

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: March 30, 2025, 07:17:43 pm
content: I have the registers configured in the following manner.config: 0x0A (power up, PTX)setup_aw: 0x03 (5 bytes, default)setup_retr: 0x1F (500us delay, up to 15 retransmit)rf_setup: 0x00 (1Mbps, -18dbm power output)I tested different power settings already, the TX and RX are only about two feet apart at the moment. From my understanding retransmit delay only becomes problematic with slower data rates?If I could find libraries that just worked I would use them, believe me! I have looked at several and have copied the general format, which is where I am now. My code can load a payload, transmit, wait for ack or max_rt, and finally reset the status and flush TX.I will add a capacitor as soon as I get a chance, then I will update.

author: KimLum
author_rank: Contributor
timestamp: March 31, 2025, 05:51:10 pm
content: It is unclear to me which programming language(s) you are using for RasPi and PicoPi? Could you link to the libraries (for both ends/devices) that did not work for you?EDIT: A schematic of the wiring could also be useful.

author: Alex_Baker
author_rank: Frequent Contributor
timestamp: April 01, 2025, 09:30:53 pm
content: Adding a large electrolytic capacitor seems to have solved all the problems, I sat and watched the NRF send a payload 100 times without a max_rt failureI was aware that the NRF boards needed a decent bypass cap but I didn't realize how bad the problem was. Both the RX and TX have ceramic bypass caps, 1uF or so. There must be a design flaw intrinsic to the NRF module that causes this problem.

author: KimLum
author_rank: Contributor
timestamp: April 02, 2025, 09:52:48 am
content: Quote from: Alex_Baker on April 01, 2025, 09:30:53 pmNo, it is a power supply issue.. Great that you got it working, though!