Setting Up the nRF24L01 for Transmitting, and Receiving - Page 1
Forum section: electronics / projects

author: Kalcifer
author_rank: Regular Contributor
timestamp: May 11, 2021, 06:00:48 am
content: I have one of those nRF24L01 ~2.4GHz transmitter modules, as seen here:http://www.hobbyandyou.com/content/images/thumbs/0002081_nrf24l01-24ghz-wireless-transceiver-module-for-arduino.jpeg.I have been having some trouble getting it to work (data not being received), so I wanted to make sure that I am, at least, using the right method for configuring the device(s) for use; I want to make sure that I am understanding the datasheet correctly. So, my setup is as follows:Receiver:1. Enter RX mode by setting the PWR_UP bit and the PRIM_RX bit, and bringing the CE pin logic high.2. Default receive address is used at data pipe 0: 0xE7E7E7E7E72. Ensure that the data pipe 0 (using the default address that is used at reset) is enabled to receive 1 byte by writing 1 to RX_PW_P0.Transmitter:1. Go into standby-2 mode to wait for transmit data by setting the PWR_UP bit, clearing the PRIM_RX bit, and bringing the CE pin logic high.2. Default transmit address at reset is used: 0xE7E7E7E7E7Transmission:1. Write a byte of data to the transmit payload with 0b00000001 written to W_TX_PAYLOAD2. from my understanding, this should automatically start the transmission of data3. read the received data by reading from R_RX_PAYLOADPlease let me know if my configuration and usage method is correct.Thank you.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: May 11, 2021, 07:58:30 pm
content: My sincerest advise is tho throw the thing in the garbage bin and buy some better hardware.Years ago I bought a bunch of these things and wrote a driver library from a collection of a bunch of giants before me, but mostly from reading the datasheet about 20 times.The nRF24L01+ is another chip from the incompatible nRF24L01, and I found the whole thing just horrible.The designer of that chip had some very distorted ideas of what is useful in such a chip and what is not. They have some "6 pipe" model, which is either not enough or too much, and either way you have to find a way to work around it. It's doing a bunch of buffering and it's very hard to determine what is buffered where and when. I've had the thing lock up, and then after a complete power cyle have it receive messages from before the power cycle. The way their internal synchronization works is very yucky.I had a short moment to light my interest when I noticed that it had some signal strength measurement, but it's implemented so badly that it's completely useless.And on top of that. There are some clones on the market and these have some bugs and / or incompatibilities, so you never know what you're working with.So pay 50ct or a euro more for some other RF breakout board that has some decent hardware on it.The HopeRF RFM95 and RFM96 are probably much better chips. But probably anything is better than the nRF24 horror.If you're lucky you can get some "arduino" lib for it to work in 10 minutes or so, but that's because someone else has been banging their heads to the wall for days before you.

author: Kalcifer
author_rank: Regular Contributor
timestamp: May 12, 2021, 04:23:48 am
content: Quote from: Doctorandus_P on May 11, 2021, 07:58:30 pmPerhaps something like an ESP8266 would be good. Those are decently popular it seems. Although, I have looked into it before, and I'm not entirely sure how to go about programming them.Quote from: Doctorandus_P on May 11, 2021, 07:58:30 pmI don't have HopeRF chips but I do have a couple of those Semtech SX1278 LoRa module things lying around which seem to be similar in idea to the chips that you mentioned.

author: MarkF
author_rank: Super Contributor
timestamp: May 12, 2021, 11:22:01 am
content: Here is the general flow I use. I have the 'Plus' modules.There is an Arduino library for the nRF24L01+ (RF24 lib)//CHANGES TO POWER-ON DEFAULTS:nRF_CONFIG (00h) = nRF_CRC1|nRF_PwrDn|nRF_PRX (09h)nRF_SETUP_RETR (04h) = (ARD=500us, ARC=3 retries) (13h)nRF_RF_SETUP (06h) = nRF_1Mbps|nRF_PWR0 (06h)//RECEIVER SETUP:nRF_RX_ADDR_P0 (0Ah) = (E7E7E7E7E7h)nRF_RX_ADDR_P1 (0Bh) = (C2C2C2C2C2h)nRF_TX_ADDR (10h) = (E7E7E7E7E7h)nRF_RX_PW_P0 (11h) = 8nRF_RX_PW_P1 (12h) = 8// Start listening: Power-up and Receive modenRF_CONFIG (00h) = nRF_CRC1|nRF_PwrUp|nRF_PRX (0Bh)delay_us(130)// Set CE highCEpin = 1// Read FIFO statuswhile ((nFIFO_STATUS & 0x03) != 1) {// read payload, nRF_RD_RX_PL (61h)}//TRANSMITER SETUP:nRF_RX_ADDR_P0 (0Ah) = (C2C2C2C2C2h)nRF_RX_ADDR_P1 (0Bh) = (E7E7E7E7E7h)nRF_TX_ADDR (10h) = (C2C2C2C2C2h)nRF_RX_PW_P0 (11h) = 8nRF_RX_PW_P1 (12h) = 8// Write payload: Power-up and Transmit modenRF_CONFIG (00h) = nRF_CRC1|nRF_PwrUp|nRF_PTX (0Ah)delay_us(150)for (int i=0;i<8;i++) {// write payload, nRF_WR_TX_PL (A0h)}// Strobe CECEpin = 1delay_us(16)CEpin = 0

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 12, 2021, 05:15:18 pm
content: I've used the nRF24L01+ chip a few years ago, and I don't remember how close to the nRF24L01 it is, nor if your module doesn't actually contain a nRF24L01+, which I'm suspecting.Anyway, from what I remember, what MarkF showed looks correct to me. If you have any further problem, I may have to take a closer look at my project to give possible additional info.

author: janoc
author_rank: Super Contributor
timestamp: May 12, 2021, 06:01:52 pm
content: nRF24L01+ is the enhanced version of the original nRF24L01. nRF24L01+ can talk to both nRF24L01+ and nRF24L01 but the nRF24L01 doesn't support some data rates that nRF24L01+ does. The original (non-plus) version hasn't been sold for years, so it is unlikely you would find one in a new module these days.There is nothing wrong with these radios, no need to hate on them. They work, they are simple to use and widely deployed - e.g. many wireless keyboards/mice that use dongles are based on these chips, as are various cheap drones and toys needing remote control.However, that is assuming you get the genuine one and a good quality module. The stuff from AliExpress and wherever is a lottery.There are even fakes/clones of these Nordic radios around:https://hackaday.com/2015/02/23/nordic-nrf24l01-real-vs-fake/Oh and do make sure you don't accidentally damage them with 5V - there are 3.3V only (the data pins are 5V tolerant, AFAIK). I had a few of these damaged by a dodgy DC-DC converter module that was letting some voltage spikes in and then the radio was locking up, talking to the host but not transmitting and weird and wonderful stuff like that.Quote from: Kalcifer on May 12, 2021, 04:23:48 amIf you don't mind the roughly 10x power consumption and the need to configure wifi ...If you need low power (which is likely why you were looking at the nRF24L01+ in the first place), then nRF52 or nRF53 series could be a good fit - ARM Cortex core, radio that can handle Bluetooth Low Energy, Zigbee, ANT, Shockburst (the nRF24L01+ protocol) and many other things and still very low power consumption. E.g. the recently released Apple AirTags use nRF52 SoCs.

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 12, 2021, 09:30:04 pm
content: Agreed, those ICs are actually pretty good. Sure they are barebones - that's what they are meant to be. But yes they draw little power. The protocol is pretty raw. But you can implement your own protocol on top of that. I've seen a project implementing simple BLE with them. AFAIR, Nordic also provides a protocol that you can use with them: Gazell.I don't get why anyone would suggest using WiFi instead (unless you actually want to connect to an existing network). Talk about waste.You could otherwise consider BLE if you are after a low power solution with a more sophisticated protocol. TI chips, like the CC2640 (IIRC?) contain an ARM Cortex core and are very low power. I think you can implement something else than BLE with those as well if you're so inclined.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: May 12, 2021, 10:07:33 pm
content: Quote from: SiliconWizard on May 12, 2021, 09:30:04 pmNobody suggested to use WiFi.OP asked if that could be a good alternative.And I agree with the others. WiFi is power hungry.A part of the power hungryness is because of encryption and key exchange, which needs relatiely much data going to and fro.Apparerently you can get some decent battery life out of an ESP8266, if it sleeps 99.999% of it's time and does not much communicate in the time it's awake, but it will never be as low as those small radio's.

author: Kalcifer
author_rank: Regular Contributor
timestamp: May 12, 2021, 10:28:23 pm
content: Quote from: janoc on May 12, 2021, 06:01:52 pmCorrect, I need decently low power consumption, as well as a somewhat decent range. I need the modules to be able to communicate across a length of my yard (retrieving data from a sensor from about 30 or so meters away. Very little obstructions, only a very slight incline, some shrubs and a fence.). I also really don't want to go through the headache of designing my own antenna and whatnot (that bit of my schooling is a little fuzzy), so the premade module was a good fit for me. Also, I find that really cool that the air tags are using nordic semiconductor chips! I had no idea.

author: MarkF
author_rank: Super Contributor
timestamp: May 13, 2021, 12:39:29 am
content: I'm using the nRF24L01+ modules in my wireless model railroad throttles.There is no problem across my basement at 10 meters.My guess is you can go 20 meters, but 30+ meters is probably pushing their range for the PCB antenna.There is a high power version with a screw-on antenna that might get you the range you want.

author: Kalcifer
author_rank: Regular Contributor
timestamp: May 13, 2021, 04:05:39 am
content: Quote from: janoc on May 12, 2021, 06:01:52 pmIs the nRF24L01 obsolete? I took a look on nordic's website, and in the nRF24 section, it says "not recommended for new designs" and then lists the nRF52 series chips as alternatives. Would the nRF52 series chips have improvements in range? They use Bluetooth 5.2 bluetooth low energy. Not sure how that stacks up to the performance of the nRF24 series.

author: sleemanj
author_rank: Super Contributor
timestamp: May 13, 2021, 09:32:17 am
content: Quote from: MarkF on May 13, 2021, 12:39:29 amThe PCB antenna is limited as a transmitter, but as a receiver it's pretty decent.It's all about the antenna really you can do some very long distances if there's nothing in the way...https://www.youtube.com/c/iforce2d/search?query=NRF24L01%2B

author: janoc
author_rank: Super Contributor
timestamp: May 13, 2021, 09:56:10 am
content: Quote from: Kalcifer on May 13, 2021, 04:05:39 amnRF24 is not really obsolete (as in end of life/not made anymore) but they would want you to phase it out. It is likely going to be around for a long time, though, a lot of products use these radios.nRF52does not useBLE. nRF52is capableof running BLE but not only - it is a multiprotocol radio and with the exception of Bluetooth Classic and Wifi it can probably handle every common wireless protocol.Not sure what you mean by "performance of the nRF24 series". Bitrate? That's a function of the protocol, both SoCs have 2Mbps capable radios. Shockburst on nrf24L01+ is 250kbps-2Mbps (AFAIK). That's the same on nRF52.Power consumption? I had nRF52832 take about 6mA while running the full Bluetooth Low Energy/Bluetooth Mesh stack and actively advertising. When sleeping it is down in uA territory. nRF24L01+ takes about 12mA when transmitting. So that's comparable (the different protocol I have used prevents 1:1 comparison here).Plus nRF52x is has an ARM core with built-in flash you can run your own programs on, nRF24L01+ requires another micro to act as a host because the SoC isn't user programmable.

author: janoc
author_rank: Super Contributor
timestamp: May 13, 2021, 10:15:44 am
content: Quote from: SiliconWizard on May 12, 2021, 09:30:04 pmYou can run the same Shockburst protocol even on the nRF52, it is compatible and officially supported.nRF24can'trun BLE, the radio is "hardwired" and is unable to broadcast/receive data in the required format. It was only "abused" to send BLE advertisement packets with a bit of hackery, so it can act as e.g. the iBeacon style tag. Not much else.nRF52 can run the following (but not all models - the ones with smaller flash can't run everything due to the size of some of the sw stacks):- Bluetooth Low Energy- Bluetooth Mesh (based on BLE but not compatibile with it)- ZigBee- Thread (IPv6 based mesh network)- ANT (very low power protocol used mostly in fitness equipment)- IEEE 802.15.4 (low level protocol, basis for ZigBee, Thread, 6LoWPAN, SNAP, MiWi ...)- Shockburst and Enhanced Shockburst (same as nRF24L01+)- Gazell (proprietary Nordic thing)- NFC (has a separate antenna for it)Possibly more, because there are some other protocols that are built on top of Shockburst or IEEE 802.15.4 that can run on these SoCs. Some parts have also USB, so if you need to build a dongle to interface e.g. a mesh network to a PC, these are ideal parts for it (and, in fact, many BLE dongles contain them for this reason).If someone wants to mess with this, I would strongly recommend looking at the Zephyr project first instead of trying to work with the Nordic SDKs. It ismucheasier because you don't have to deal with the Nordic RTOS blob ("softdevice"). Zephyr is completely open source so if anything goes haywire (and it will, especially when implementing complex stuff like BLE or some mesh) it is much easier to debug than getting a hard fault from the softdevice and then wondering where in that binary blob it faulted and why.https://www.zephyrproject.org/

author: tonytruong
author_rank: Newbie
timestamp: February 15, 2024, 05:15:55 pm
content: Hello ...My name is Tony Truong. I am a beginner and trying to make 2 x nrf24L01+ to communicate with 2 UNO R3.I follow the code sequence of MarkF (in this forum) to set them up. They don't really work as I expected.Note: I write code in assembly and using SPInterface with CE on PORTD bit 7, CSN on PORTB bit 0On receiver side ...With CE = 0I set up all parameter and then cfg_reg to 0x0B and delay msThen CE = 1Looping on fifo_status (reg 0x17) .. checking bit 0 if RX is NOT empty ...Upload code to receiving UNOOn transmitter side ...With CE = 0 ...I set up all parameters and the cfg_reg to 0x0A ... delay msWriting W_TX_PAYLOAD ... then CE=1 ... delay ms then CE=0Upload code to transmitting UNOI saw the data is received by the receiver once.I did several experiments and observed these strange things:- Intended data sent to receiver EVEN I put a break before/in front CE=1 ... looks like nrf was in standby-2 mode but data was sent even before CSN de-asserted (W_TX_PAYLOAD writing sequence not completed yet)- Status reg (addr = 0x07) = 0x1F ... Max num transmit Interrupt ... TXFifo FULL ...- Fifo_status reg (addr - 0x17) = 0x21 ... TXFifo Full ... RXFifo Empty- On receiver side .. received all intended data that were sent from transmitter ... code read all received data out and print on terminal- Status reg content (addr 0x07) = 0x4E .. RX_DR=1- CE=0- Code write 1 to reset RX_DR .... but can not get reset to 0x0E- Receiver can not receive afterward as this bit is SETPlease help. I can copy and paste assembly code if needed.Thanks a lot and have a good day.Tony Truong

author: janoc
author_rank: Super Contributor
timestamp: February 15, 2024, 06:00:58 pm
content: Please don't necropost to 3 years old threads with a completely unrelated issue. Make a new post in the proper section.

author: MarkF
author_rank: Super Contributor
timestamp: February 15, 2024, 08:34:04 pm
content: Tony,I believe you're hanging up because you're not handling any errors.At this point, I'll just give you some code snippets from my PIC micro-controller and see if you can figure out the problem before I spend much time on it.This example code is assuming 8 byte transmit and receive payload data.nRF library headerCode:// 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 ACK// Prototypesuint8_t nrfRead(uint8_t *buf, uint8_t cnt);uint8_t nrfWrite(uint8_t *buf, uint8_t cnt);nRF library codeCode:/*------------------------------------------------------------*/#define WRITE(c, s) \PIR1bits.SSPIF = 0; \SSPBUF = c; \while ( !PIR1bits.SSPIF ) {} \s = SSPBUF#define READ(s) \PIR1bits.SSPIF = 0; \SSPBUF = 0; \while ( !PIR1bits.SSPIF ) {} \s = SSPBUF/*------------------------------------------------------------*/uint8_t nrfRead(uint8_t *buf, uint8_t cnt){uint8_t stat;nRF_CSNpin = 0;WRITE(buf, stat);for (int i=cnt-1;i>0;i--) {READ(buf);}nRF_CSNpin = 1;return(stat);}uint8_t nrfWrite(uint8_t *buf, uint8_t cnt){uint8_t stat;uint8_t tmp;nRF_CSNpin = 0;WRITE(buf, stat);for (int i=cnt-1;i>0;i--) {WRITE(buf, tmp);}nRF_CSNpin = 1;return(stat);}nRF functions and main loopCode:// Register readsuint8_t rfAddr= {nRF_RD_REGISTER|nRF_RX_ADDR_P0, 0, 0, 0, 0, 0};uint8_t rfAux= {nRF_RD_REGISTER|nRF_RX_ADDR_P1, 0, 0, 0, 0, 0};uint8_t rfCh= {nRF_RD_REGISTER|nRF_RF_CH, 0};uint8_t rfStatus= {nRF_RD_REGISTER|nRF_STATUS, 0};uint8_t rfObserve= {nRF_RD_REGISTER|nRF_OBSERVE_TX, 0};uint8_t rfFIFO= {nRF_RD_REGISTER|nRF_FIFO_STATUS, 0};//============================================================void nrfSetup(void){// Configure the radio// Set addressesuint8_t rfA0={nRF_WR_REGISTER|nRF_RX_ADDR_P0, 0xd6, 0xd6, 0xd6, 0xd6, 0x11};nrfWrite(rfA0,6);rfA0=nRF_WR_REGISTER|nRF_TX_ADDR;nrfWrite(rfA0,6);uint8_t rfA1={nRF_WR_REGISTER|nRF_RX_ADDR_P1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2};nrfWrite(rfA1,6);// Set payload widthuint8_t rfPW0={nRF_WR_REGISTER|nRF_RX_PW_P0, 8}; // transmit 8 bytesnrfWrite(rfPW0,2);uint8_t rfPW1={nRF_WR_REGISTER|nRF_RX_PW_P1, 8}; // receive 8 bytesnrfWrite(rfPW1,2);// Set Auto_Acknowledgementuint8_t rfAA={nRF_WR_REGISTER|nRF_EN_AA, 0x01};nrfWrite(rfAA,2);// Set RF data rate and power leveluint8_t rfSetup={nRF_WR_REGISTER|nRF_RF_SETUP, nRF_1Mbps|nRF_PWR12};nrfWrite(rfSetup,2);}//============================================================void powerUp(void){uint8_t rfConfig;rfConfig = nRF_RD_REGISTER|nRF_CONFIG;nrfRead(rfConfig,2);rfConfig = nRF_WR_REGISTER|nRF_CONFIG;rfConfig = rfConfig | nRF_PwrUp;nrfWrite(rfConfig,2);}//============================================================void powerDn(void){uint8_t rfConfig;rfConfig = nRF_RD_REGISTER|nRF_CONFIG;nrfRead(rfConfig,2);rfConfig = nRF_WR_REGISTER|nRF_CONFIG;rfConfig = rfConfig & (~nRF_PwrUp);nrfWrite(rfConfig,2);}//============================================================void startListening(void){// Set PwrUp and PRXuint8_t rfRcvMode={nRF_WR_REGISTER|nRF_CONFIG, nRF_CRC1|nRF_PwrUp|nRF_PRX};nrfWrite(rfRcvMode,2);// Clear RX_DR, TX_DS, MAX_RT bitsuint8_t rfClear={nRF_WR_REGISTER|nRF_STATUS, nRF_RX_DR|nRF_TX_DS|nRF_MAX_RT};nrfWrite(rfClear,2);// Set CE highnRF_CEpin=1;delay_us(130);}//============================================================void stopListening(void){// Set CE lownRF_CEpin=0;// Flush TX FIFOuint8_t rfFlush={nRF_FLUSH_TX};nrfWrite(&rfFlush,1);}//============================================================void writePayload(void){uint8_t stat,timeout;// Set PwrUp and PTXuint8_t rfXmtMode={nRF_WR_REGISTER|nRF_CONFIG, nRF_CRC1|nRF_PwrUp|nRF_PTX};nrfWrite(rfXmtMode,2);delay_us(150);// Fill payloaduint8_t rfPayload={nRF_WR_TX_PL};// TODO:: Fill in the 8 bytes of data to send here.// rfPayload thru rfPayload. . .// Send payloadnrfWrite(rfPayload,9);// Strobe CEnRF_CEpin=1;delay_us(16);nRF_CEpin=0;// Wait for completetimeout=100;do {delay_ms(1);stat = nrfRead(rfObserve,2);} while ( (stat & 0x30) == 0 && --timeout > 0 );RxReady = (stat >> 6) & 0x01; // RX_DRTxOkay = (stat >> 5) & 0x01; // TX_DSTxFail = (stat >> 4) & 0x01; // MAX_RT// Clear RX_DR, TX_DS, MAX_RT bitsuint8_t rfClear={nRF_WR_REGISTER|nRF_STATUS, nRF_RX_DR|nRF_TX_DS|nRF_MAX_RT};nrfWrite(rfClear,2);if (TxFail) {uint8_t rfFlush={nRF_FLUSH_TX};nrfWrite(&rfFlush,1);}}//============================================================void readPayload(void){uint8_t rfPayload={nRF_RD_RX_PL};nrfRead(rfPayload,9);// TODO:: Unpack the 8 bytes of data you received here.// rfPayload thru rfPayload. . .}//============================================================//============================================================void main(void){// InitializationnrfSetup();startListening();// Main loopwhile (1) {// Read FIFO status >>>>> Status <<<<<stat = nrfRead(rfFIFO,2);TxFIFO = (rfFIFO >> 4) & 0x03;RxFIFO = (rfFIFO) & 0x03;RxReady = (stat >> 6) & 0x01; // RX_DRTxOkay = (stat >> 5) & 0x01; // TX_DSTxFail = (stat >> 4) & 0x01; // MAX_RT// Read available payloads <<<<< Payload <<<<<while ( (rfFIFO & 0x01) != 1 ){readPayload(); // Get payloadnrfRead(rfFIFO,2); // Get FIFO status}// Write payload >>>>> Payload >>>>>if ( anything_to_send ){stopListening();writePayload(); // Send payloadstartListening();}// 10Hz processing loopdelay_ms(100);}}

author: tonytruong
author_rank: Newbie
timestamp: February 17, 2024, 05:33:49 pm
content: Thanks a lot MarkF.I am reading/working on your snippets and let you know how far I can achieve.I will have certainly to ask more for your helps along the way ... but right now have to digest your code skeleton and proceed.Thanks again and have a good day.Tony Truong

author: tonytruong
author_rank: Newbie
timestamp: February 19, 2024, 02:14:40 am
content: Hi MarkF ...I tried to follow your snippets but get stuck at these sequences:- In Write Payload ...do {delay_ms(1);stat = nrfRead(rfObserve,2);} while ( (stat & 0x30) == 0 && --timeout > 0 );RxReady = (stat >> 6) & 0x01; // RX_DR.TxOkay = (stat >> 5) & 0x01; // TX_DS.TxFail = (stat >> 4) & 0x01; // MAX_RT.// Clear RX_DR, TX_DS, MAX_RT bitsuint8_t rfClear={nRF_WR_REGISTER|nRF_STATUS, nRF_RX_DR|nRF_TX_DS|nRF_MAX_RT};nrfWrite(rfClear,2);ANDIn main loop ...// Main loopwhile (1) {// Read FIFO status >>>>> Status <<<<<stat = nrfRead(rfFIFO,2);TxFIFO = (rfFIFO >> 4) & 0x03;RxFIFO = (rfFIFO) & 0x03;RxReady = (stat >> 6) & 0x01; // RX_DR.TxOkay = (stat >> 5) & 0x01; // TX_DS.TxFail = (stat >> 4) & 0x01; // MAX_RT.// Read available payloads <<<<< Payload <<<<<while ( (rfFIFO & 0x01) != 1 ){readPayload(); // Get payloadnrfRead(rfFIFO,2); // Get FIFO status}What are these variables and where in the code they are used/called RxReady, TXOkay, TxFIFO, and RxFIFO?I thought nRF_Status register has these bits RX_DR, TX_DS, and MAX_RT, not in _Observe one.Also, I have not seen where the receiver "Clear" the RX_Dr (Status @ 0x07) bit in the code in the "main loop".Could you please provide more info on these? I really appreciate your insights and helps.Thanks a lot MarkF. Have a nice day.Tony Truong

author: MarkF
author_rank: Super Contributor
timestamp: February 19, 2024, 08:51:14 pm
content: Quote from: tonytruong on February 19, 2024, 02:14:40 amThe comments tell the story here. The variable names are only meaningful in the program I pulled this code from. They are not used in communicating with the nRF24L01+ transceiver. This code was pulled from wireless hand-held throttles for my model railroad. The variable are used as radio status indicators at the top of my display. Hard to see in this photo but they are the five dots at the very top of the screen:The nRF status register is returned for ALL command words.You don't have to explicitly read the status register.QuoteI'm not sure I understand your question. I don't reset/clear anything in the main loop that I know of.The only time I clear anything is at the end of the 'Write Payload' function. In this case after the transfer is complete, I clear all the status bits. I'm not sure it needs to be done for the nRF to function. More so, just to get a status for display on the screen and they need to be cleared before the next transmission. During my initial design, it was hard to determine what was going on with the nRF. Just leftover debugging that's mostly used to see if the nRF is hungup.As far as clearing the RX_DR when doing the transmission, I just cleared everything at the same time. The code generally depends on the state in the FIFO status register instead of the RX_DR status bit when determining if data is available.

author: MarkF
author_rank: Super Contributor
timestamp: February 19, 2024, 09:25:42 pm
content: As I mentioned, some of the code relates to debugging.You will reach a point where you will want to know how many message transfers fail.Even with the Enhanced ShockBurst™, you will have some level of packet loss.It's hard to determine this packet loss. In some of my critical messages, I added a sequence number.Therefore, I recommend thinking about debugging and eventual having some kind of status/health display of the nRF nodes.

author: tonytruong
author_rank: Newbie
timestamp: February 20, 2024, 03:46:19 pm
content: Great thanks to MarkF.I have rewrote/corrected my assembly code based on your guidance and luckily it is working, just for now, with a simple "1-way" repeated message.You were right on nRF's Status returns automatically when UNO's SPI clocks out the command, either for a Read or a Write.You are really a great teacher. I will certainly continue my own experiments and appreciate your helps in the future.I live in Austin, TX and if possible I really want to meet and learn from you.Thanks again and have a great day.Tony Truong

author: MarkF
author_rank: Super Contributor
timestamp: February 20, 2024, 04:18:53 pm
content: Glad I could help.One additional thing that may be useful in your design:I'm actually using one pipe with 'EN_AA Enhanced ShockBurst™' enabled and another that is not enabled.The enabled pipe will re-transmit the set number of times when packet loss is detected (think TCP/IP in a network connection). The other pipe doesn't not even try to detect packet loss (think UDP).What this does is that that the ShockBurst™' pipe would be your critical pipe. While the other pipe can 'broadcast' to multiple nRF transceivers. In my model railroad scenario, my laptop receives the throttle position from multiple wireless units (i.e. the ShockBurst™' pipe) trying to error correct each message for dropped packets. In turn, the laptop transmits on the other pipe to all the units info needed by each without the need to specifically send the same message multiple times. That is because there is no response from the receiver when ShockBurst™' is turned off.

author: tonytruong
author_rank: Newbie
timestamp: March 04, 2024, 05:06:46 pm
content: Good morning MarkF.I have been using a very simple code from How to Mechatronics "Dejan Nedelkovski,www.HowToMechatronics.com"I have tried for more than 2 weeks, with a lots of combinations, to make 2 x nRF24L01 transceivers to communicate both way without success.It only works in 1-way direction and a very specific way.After having interchanged nRFs and it did NOT work, I bought another UNO(3). Same result.Note1: My laptop assigned automatically COM(x) to UNO(y) at the first time plugged in and keep the same COMx when re-plugged in for usedNote2: Thinking it might be the nRF so I have interchanged nRFs but the result was the same.It sounds like the transmission is only working with the elder UNO. The younger UNO in nRF pair can only receive.Below is the truth table:Combination TableUNO-1 UNO-2 UNO-3 TX-Code in RX-Code in ResultsCOM-3 COM-4 No-used UNO-1 on COM-3 UNO-2 on COM-4 Working fineCOM-3 COM-4 No-used UNO-2 on COM-4 UNO-1 on COM-3 Not workingCOM-3 No-used COM-5 UNO-1 on COM-3 UNO-3 on COM-5 Working fineCOM-3 No-used COM-5 UNO-3 on COM-5 UNO-1 on COM-3 Not workingNo-used COM-4 COM-5 UNO-2 on COM-4 UNO-3 on COM-5 Working fineNo-used COM-4 COM-5 UNO-3 on COM-5 UNO-2 on COM-4 Not workingNot sure what I have missed. I don't think USB/COM ports have effects on UNO-nRF code and functions but really I have no clue here.Hoping you can shed the light on this.Thanks a lotTony Truong

author: MarkF
author_rank: Super Contributor
timestamp: March 04, 2024, 08:05:24 pm
content: The Arduino ports are not that important as long as you can upload your program to the Uno and see the serial monitor.What is of particular interest is how you configured each nRF.Of particular interest are registers (leaving the rest at their defaults):- EN_AA Enhanced ShockBurst (01h)- EN_RXADDR (02h)- SETUP_AW (03h)- RX_ADDR_P0 (0Ah)- RX_ADDR_P1 (0Bh)- TX_ADDR (10h)- RX_PW_P0 (11h)- RX_PW_P1 (12h)Pay close attention to the byte order of the address registers. I had mine reversed for a while.Also, have you looked at the RF24 library and its examples for the Arduino:https://github.com/nRF24/RF24Beyond that, you will need to show me some code. By that I mean 'pseudo code' !!!I stopped doing assembly code back in the '80s and I don't do it anymore except for very very special cases where it's required.IMHO it's just too hard to read and maintain across all the various platforms and processors.(Please use the forum code tag)

author: tonytruong
author_rank: Newbie
timestamp: March 04, 2024, 09:48:34 pm
content: Thanks for a quick reply MarkF.As had trouble to make it to work with my assembly code, I have restarted to test with the simple code from "How to Mechatronis" from Mr. Dejan Nedelkovski's code to verify/understand the reason why.Unfortunately it behaves the same way, only in direction from elder UNO to younger UNO as I have described in the previous post.Here is the code ...Note: Mr. Dejean Nedelkovski uses "Arduino Mega + nRF24L01" and "Arduino UNO/Nano + nRF24L01". I think the code is common in all platform.Thank as lot.Tony Truong======Transmitter Code/** Arduino Wireless Communication Tutorial* Example 1 - Transmitter Code** by Dejan Nedelkovski,www.HowToMechatronics.com** Library: TMRh20/RF24,https://github.com/tmrh20/RF24/*/#include <SPI.h>#include <nRF24L01.h>#include <RF24.h>RF24 radio(7,; // CE, CSNconst byte address = "00001";void setup() {radio.begin();radio.openWritingPipe(address);radio.setPALevel(RF24_PA_MIN);radio.stopListening();}void loop() {const char text[] = "Hello World";radio.write(&text, sizeof(text));delay(1000);}=====Receiver Code/** Arduino Wireless Communication Tutorial* Example 1 - Receiver Code** by Dejan Nedelkovski,www.HowToMechatronics.com** Library: TMRh20/RF24,https://github.com/tmrh20/RF24/*/#include <SPI.h>#include <nRF24L01.h>#include <RF24.h>RF24 radio(7,; // CE, CSNconst byte address = "00001";void setup() {Serial.begin(9600);radio.begin();radio.openReadingPipe(0, address);radio.setPALevel(RF24_PA_MIN);radio.startListening();}void loop() {if (radio.available()) {char text = "";radio.read(&text, sizeof(text));Serial.println(text);}}Code language: Arduino (arduino)=====

author: MarkF
author_rank: Super Contributor
timestamp: March 04, 2024, 11:18:44 pm
content: What I have done is at a much lower level talking to the nRF transceiver directlywithoutany libraries.I leave it to you to debug Mr. Nedelkovski's code.At a glance, I wouldn't think the address for both radios should be the same( i.e.const byte address = "00001";)I would start with the 'GettingStarted.ino' example in the RF24 example section.I spent a lot of time with the RF24 library and never really figured out how they did their addressing.The nRF24L01 expects pipe #0 receive address and the transmit address toalwaysbe the same.I then used pipe #1 as the receive of the other transceiver. For example:nRF #1RX_ADDR_P0 = E7E7E7E7E7hRX_ADDR_P1 = C2C2C2C2C2hTX_ADDR = E7E7E7E7E7hnRF #2RX_ADDR_P0 = C2C2C2C2C2hRX_ADDR_P1 = E7E7E7E7E7hTX_ADDR = C2C2C2C2C2hThe Arduino RF24 library hides the real addressing from you.P.S. Please use the code tag when posting code (i.e. the '#' button above the edit box.)Or enclose your code within the html like "code", "/code" within square brackets.

author: tonytruong
author_rank: Newbie
timestamp: March 07, 2024, 01:23:02 pm
content: Good morning MarkF.Thank you very much for your helps.I have followed your suggestions and I have successfully made 2 x nRFs talk to each other with "assembly code" now.I really appreciate your insights and your "open mind" to help out people.Have a good day.Tony Truong

author: MarkF
author_rank: Super Contributor
timestamp: March 07, 2024, 06:31:48 pm
content: I've been doing a little experimenting myself.I was wrong about the addressing needing to be different.Two nRF24L01+ transceivers addressed and configured exactly the same will communicate with each other using pipe 0.