Antenna diversity (receive and transmit)

Utilize several nRF receiver modules in order to improve the reliability of wireless connections

Similar projects worth following
WIFI can provide antenna diversity but WIFI and TCP/IP are high latency in comparison to bluetooth and 2.4GHz radio control protocols. However, there are basically no bluetooth systems with realtime antenna diversity available, nor any other 2.4GHz low-cost, low-latency hardware with that feature. For now, this project lays out a concept for using receive diversity and transmit diversity based on Nordics low-cost, low-level nRF24/nRF52 protocol and provides use cases.
Many modules with NRF24 IC exist that can be controlled with Arduino. The nRF52 IC contains an MCU that can be programmed in various ways, such as the Arduino environment. In terms of low-level and low-cost I found nothing better suited than the nRF24/52 protocol and modules. This will become clear when looking in the details.

1. Receiving diversity: Multiple receivers, single transmitter
Instead of doing antenna diversity based on the signal strength, the data consistency is analyzed after receiving. This is receiver diversity. The receivers can be positioned with some distance to each other in order to compensate multipath or with various orientations of the antennas to compensate for misalignment of antenna orientation between transmitter and receiver. Or one can do both at the same time.
The nRF24 protocol is packet-based. A transmitted packet will be received by every receiver at almost the same time, if it is received at all of course. Auto acknowledgment and auto retransmit must be turned off. If lost packets are unacceptable, which is not the case for radio control and telemetry, must be managed at higher levels of your own communication protocol.

Case 1a. Checking for a packet with valid CRC
The nRF24 packets can contain a 2 bit packet identification (PID) field (sort of packet counter) as well as a 1 or 2 byte CRC field. By looking at PID and CRC from all the receiver modules, one can hope for at least one successful reception for every transmitted packet.

Case 1b. Comparing bytes
In the case 1a, if the CRC check fails for a transmitted packet in every receiver, no packet is presented at all, because packet with failed CRC are dismissed inside the nRF IC. Thus, discarding CRC-failed packet should be deactivated. This seems to be more comfortable with the nRF52.
Once discarding CRC-failed packets is deactivated, several receivers might present a packet with the CRC field of every packet being wrong. One can compare the bytes of those packets to each other in terms of which bytes are the same across all received packets and which ones differ. For those bytes that differ (could be all of them), a majority decision is made in the hope to construct a packet with valid CRC.

Example: For one single transmitted packet, the set of receivers provides 3 packets with the following bytes:
1. A B C D E F
2. A B G H E J
3. K L C H M J

The reconstructed packet would be:

Case 1c. Comparing bits
Same as 1b., but instead of bytes, the bits are compared. For the algorithm, please have a look into the executable specification file.

Case 1d. Distributed bit comparison (large scale, 60+ receivers)
Like 1c, but the data processing is distributed on several hierarchical levels. Lets investigate an example with 60 receiver, 32bytes/packet and a 1Mbps baud rate:

There shall be a hierarchy of 3 levels A,B,C

A. Total amount of data, if 60 modules are receiving: 60*1Mbps=60Mbps
B. Total amount of data, if 15 modules are receiving: 15*1Mbps=15Mbps
C. Total amount of data, if 3 modules are receiving: 3*1Mbps=3Mbps

Analysis of level C:
One MCU shall handle 3 receivers as follows:
Add up the data in terms of bit comparison. However, stop before deciding whether a bit of the resulting packet is 0 or 1. Instead, the sums of zeros for each bit and the number of packets is transmitted to a higher level in the hierarchy of MCUs.
Each sum of zeros can have a value between 0 and 3 (including). This can be encoded in 2bit. Thus, we can encode 4 bits in one byte.

Maximum incoming data/packet: 3modules*32byte*8bit=768bit=96Byte
Outgoing: 32byte*8bit*2Bits_per_Bit+8Bit(number_of_packets)=520Bit=65Byte

Analysis of level B:
5 of those 3x-levelC-groups are combined.
Maximum number of zeros: 15 -> encoded in 4 bit -> 2bits per byte
Incoming data: 5*65Byte=325Byte
Outgoing: 32byte*8bit*4Bits_per_Bit+8Bit(number_of_packets)=1032Bits=129Bytes

Analysis of level A:
4 of those 15x-levelB-groups are combined. Thus, the top MCU has to process 4*129Bytes=516Bytes per packet. However, if the top MCU were to process the data from 60 modules directly, that would be 60*32=1.920bytes per packet. The ratio of those two values is 1920/516=3.7. As a consequence, the top MCU does not require a SPI capability of 60Mbps, but only of 60/3.7=16Mbps!

What processing needs to be done in the top MCU (see executable specification...

Read more »

executable specification

Python script: bit comparison; crc; bit operations optimized for 32bit architectures

py - 5.59 kB - 06/22/2016 at 18:48


executable specification

Python script illustrating functional byte comparison and low-level bit comparison

py - 2.07 kB - 06/05/2016 at 16:07


  • 3 × Arduino PRIMO CORE

  • nRF24 triangulation?

    Lars R.06/06/2016 at 09:39 0 comments

    Could a widespread array of nRF24 receivers also be used to triangulate the position of the transmitter?

  • Howto simultaneously receive from 60 nRF24 with Cortex M3

    Lars R.06/06/2016 at 08:14 0 comments

    I added another case in the details section regarding on how to process the data from many receivers with low-cost MCUs.

    Please go to the project details and scroll down to

    "Case 1d. Distributed bit comparison (large scale, 60 receivers)"

  • Shockburst vs. Enhanced Shockburst, nRF24 vs. nRF5x

    Lars R.06/05/2016 at 08:18 0 comments

    In this Nordic blog entry, the differences between Shockburst (SB) and Enhanced Shockburst (ESB) and the differences between nRF24 and nRF5x implementations are explained. In particular, the difference between SB and ESB is the Packet Control Field (PCF), which contains payload length field (6 bit), packet ID (2 bits) and an acknowledge bit (1 bit). Regarding nRF24 and nRF5x, SB and ESB are implemented in hardware for the nRF24 series and in software for the nRF5x series.

    In this blog, [Yveaux] explains the differences between SB and ESB for nRF24L01+. He also explains how to receive ESB packets with a second receiver module that runs in SB mode without sending additional ACK packets. In detail, an ESB connection between two modules with CRC, ACK packets and resend data packets is listened to by a third module that is running in SB mode. Since this third module is running in SB mode, it does not interpret the ACK bit inside the PCF of the ESB packet and does not send ACK packets. Data packets with faulty CRC are accepted by the third module by disabling CRC interpretation (predenting that there is no CRC at all) and by counting the CRC data of the original packet to its own payload. This reduces the effectively usable payload length of the original packet by the number of CRC bytes, so that the third module sees both, the original payload and the original CRC, inside its own payload.

    When using multiple receiver modules, no more than one of those should send ACK packets. Otherwise, multiple ACK packets that are being send from various receivers at the same time, might cause interference on the radio channel(?) Now, ESB supports not to send ACK packets but this is currently (June 2016) coded inside the packet in the PCF (ACK bit). Thus, the transmitter either wants ACK packets or it does not. Thus, either ACK is disabled in the ESB packet, or every additional receiver works in SB mode without interpreting the ACK bit of the ESB packet.

    The nRF51 can receive SB packets with the Micro ESB library. However, this library was developed for SDK version 8 (SDK version 11 in June 2016) and is deprecated. Today (June 2016), it is suggested to use the nrf_esb library from the nRF5 SDK.

    Unfortunately, nrf_esb does not support SB, only ESB. This migration tutorial from March 2016 clearly states that "nrf_esb only support the Enhanced ShockBurst protocol. ShockBurst has been removed from nrf_esb". Thus, either all receivers are sending ACK-packets or none of them. In contrast to that, with nRF24 or the nRF51 micro esb, only one receiver could operate in ESB mode and send ACK packets, while all the other receivers were listening in SB mode without sending ACK packets (see [Yveaux]s blog entry).


    The nRF5x series have improved RF hardware in comparison to the nRF24 series. The nrf_esb implementation has advantages over the old nRF24 implementations like payload lengths larger than 32 bytes (up to 200+) as well as a payload to be send in ACK packets, which could be used to send control sequences to the transmitter. However, as long as the behavior regarding sending ACK packets cannot be overwritten inside the receiver, it is probably hard to use ACK with nrf_esb and multiple receivers due to radio interferences caused by multiple ACK packets being send out by multiple receivers. (Is it possible to override the ACK-behavior?)

    If exactly one of the receivers should send ACK packets (and the lack of an ACK packet should trigger resending a data packet), one has to go with the nRF51 micro ESB library (and probably an old version of the SDK) or use nRF24 modules.

    If ACK packets and retransmits are disabled in ESB mode, nrf_esb from the newest SDK should work with multiple nRF5xreceivers.

View all 3 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates