Friday 24 October 2014

NRF24L01+ and data whitening (arduino)

25.10.2014

The NRF24L01+ IC is a cheap and relatively versatile way to add radio transmission to a project, however this versatility comes at a price: Some features and controls are not included, such as modulation and encoding types, PLL and IF settings, RSSI adc, etc.

This post investigates if data whiting, which is included in some competitor's chips, would actually provide an improvement at longer range transmissions. Said missing data whitening could be implemented in software,  but the performance benefit must be present in order to make best use of available resources. There is also the possibility that whitening could have a negative effect. ( which turns out to be true)

Whitening works by attempting to break up long chains of zeroes and ones that may occur because of the particular data being sent. This is done by XORing the data to send with a known string of random numbers, and repeating the process at the receiving end with the same numbers.

Anyway, for the practical side of the test I used ( in the first tests) an arduino controlled mobile NRF tx and a similar static rx, with it's accompanying arduino connected to my PC for logging. The speed was set to 250k, no shockburst, 10 bytes payload of which the first and last were zero and soft crc respectively.

For measurement I have logged the percentage of received packets filled with repeating 8bit data. Each packet would be sent a number of times to find a receive rate. For this test I used approx 1000 packets for each value tested.

After doing this for every 8 bit number I hoped I will have a result of the possible effectiveness of data whitening. I had doubts about the effectiveness of this test, because 2.4 Ghz is very susceptable to multipath propagation. While running a test for several hours, things like people and cars moving make differences in reception. I used 2 alternating channels since the software already had that feature.


Each pink dot represents 100 packets.

In the above image a gap just before 128 can be seen, which implies it is caused by multiples ones.
A similar gap is present before 64, too. Also the above data is somewhat repeatable, but a lot of noise is masking a definable pattern, while also not excluding other, non whitening related mechanisms. For instance, the frequency modulation (GFSK) could be subject to different propagation or multiple paths, or interference from other devices  could be the cause ( jamming more ones, for example).

I decided it was probably interference , but I still tried some more tests. At this point I changed the amount of channels the NRF used in order to exclude some frequency related mechanisms. I figured 8 channels should be of benefit.


the highest light blue line is the sum of all channels. the 45 degree line is the binary number transmitted. There were probably 500000 packets sent for this ( measly) graph.

In the above graph "helped" by some image editing, it can be seen that the drop before 127 is still there. But you have to be very optimistic to see a pattern in this graph, and humans are known to see what they want to see, too.

Using 8 channels did not help much, in fact one channel was usually not receiving anything due to positioning, or swinging up and down adding noise to the graph. Anyway, i needed a better method since this is not repeatable, and drops in rf transmission add noise to the actual data needed.

Since using incremented values of payload did not work so well I changed to a different scheme, using random numbers instead as to mask the slow moving propagation changes.

The random number rx software needed a different method of counting packets and so i placed each received packet in a "bin" depending on it's value. I used 256 bins, and stopped the test when a bin reached 255, since arduino is somewhat low on memory. ( 255 was not transmitted due to the arduino random() function not including the top value)

The internal arduino number generator  is used ( c++ ) and as I understand it shouldn't have any problems dividing the data in between 8 channels, since 8 is a pretty low number.


As usual, I thought this wasn't good enough. I thought perhaps, using random numbers was not the best idea since they are basically white noise, hence adding noise to the graph. I didn't know it at the time, but differently arranged the graph makes quite a good point about the efficiency of data whitening.

Next, and last (at least for now) test involved replacing the random number generator with a " random sequence" 255 bytes long. I figured the sequence will reduce the noise overall, since each number will be transmitted the same amount of times as any other. The 255/ 8 channel combination is less then ideal, but at least it is not a multiple. Luckily the LFSR pseudo-random sequence generator can only generate 255 bytes long sequences instead of 256. Zero was not included this time, for a change.



The line type graph makes the data look a lot better, at least to me, an XY graph is actually not so different then the previous test . Of course, I have been staring at lists of binary numbers quite a lot lately, so I can hardly tell.
Arranging the data by number of ones can show exactly what is happening:



In the above graph the values are arranged in order of number of "ones" out of 8, ascending. It becomes clear that sending a lot of ones is a really bad idea. Sadly , for data whitening to work the same has to be true for zeroes, and that is not true here, at least for the settings used.



I originally thought that reception might be affected not only by one/zero ratio but by amount of consecutive ones ( or zeroes) . In the above (unlabeled) graph I plotted the same data arranged by number of consecutive ones, ascending  ( the ones are counted including neighbours ) . This is very similar to the previous graph. In case you can't tell, the linear regression line is at the same angle in both. To me this means the consecutive-ness of ones is not affecting reception much.

In the graphs there are some spikes that may imply a second influencing pattern. However, there is still a lot of noise, and people, I included, are very good at seeing patterns in random data that are not actually there. One such pattern seems to be 01010000 and it's shifted relatives.

In conclusion, the NRF24L01+ chip ( non fake / copy, etc) does not include data whitening because it would achieve not much. For my application , I decided to use RLL codes (  run length limited ) specifically a  GCR: (0,2) RLL code (inverted) that originally was used for magnetic media. I will probably implement them any day now. Since such codes are 4 to 5 encoding, and as such 8 to 10 they will require a slightly longer payload. That opens a whole new can of worms.