## NRF24L01 Channel scan

I used an NRF24L01+ attached to an Intel Galileo Gen2 to do an RF channel scan in an effort to identify a “good” choice for a channel that will best avoid interference. The program repeatedly changes channel and monitors the Received Power Detect Bit (Register 9). The program ran for and hour and counted up the number of times the RPD bit was 1 for each of the 128 channels and produced an output like this:

0 0 0 0 0 0 1 0 0 0 1 0 0 1 1 0
1 0 0 0 1 0 1 1 0 2 1 0 0 0 0 1
0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 0
0 0 1 0 0 1 3 6 3 2 4 9 4 7 12 5
4 7 2 3 7 5 1 3 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Each step across the output array represents a 1MHz step in frequency. The start frequency is 2400MHz. The value ’12’ occurs at a frequency of 2462MHz. This corresponds to Wifi Channel 11 – a fact confirmed by doing a Wifi Channel scan on my laptop which showed two Wifi access points operating at this frequency.
It is worth noticing that there is not much happening beyond 2471MHz. This is probably because Wifi stops around here (at least in Europe). So is this the answer – simply stay outside the Wifi bands? In Europe, the Wifi bands range from 2412MHz to 2472MHz so maybe the best NRF24L01 channels are less than 12 and greater than 72. Time will tell….

Code is below (node.js)

```
// NRF24L01+ demo in javascript for the Intel Galileo Gen 2
// Author: Frank Duignan.
// Updates posted on http://ioprog.com and http://eleceng.dit.ie/frank

var PAYLOAD_LENGTH=10
var SOURCE_ADDRESS=([8,0,5,8,6]);
var DESTINATION_ADDRESS=([0x0a,1,1,1,4]);
/******* Low level setup (configure I/O etc *******/
var m=require('mraa');
console.log('MRAA version: ' + m.getVersion());
// configure SPI for 1MHz operation
var SPI=new m.Spi(0);
SPI.frequency(1000000);
// Set up CE and CSN pins for the NRF24L01
// These will be directly controlled by software NOT the SPI hardware
var CEPin=new m.Gpio(9);
var CSNPin=new m.Gpio(8);
CEPin.dir(m.DIR_OUT);
CSNPin.dir(m.DIR_OUT);
CEPin.write(0);
CSNPin.write(1);
// Global variable that is updated during each SPI transaction
var NRFStatus;

// NRF Functions follow
function NRFinit()
{
NRFWriteRegister(0,0);			// Clear out config
NRFWriteRegister(1,3);			// enable auto ack in P0 and P1
NRFWriteRegister(4,0x24);		// 750us between retries, 4 retries
NRFWriteRegister(2,3);			// enable data pipe 0 and 1
NRFWriteRegister(3,3);			// 5 byte addressing
NRFWriteRegister(0x05,5); 		// select channel 5
NRFWriteRegister(0x06,0x06); 	// select 1Mbps, maximum power
NRFWriteRegister(0x07,0x70); 	// clear status flags
NRFWriteRegister(0x11,0);		// Auto ack in pipe 0
NRFWriteRegister(0x12,PAYLOAD_LENGTH);	// set payload length
NRFWriteCE(1);
NRFEnableRXMode();				// start listening
}
function delay(howlong)
{
howlong = howlong / 2; // yields approx 1us timebase
while(howlong > 0)
{
howlong = howlong -1 ;
}
}
function NRFWriteCE(Value)
{
if (Value)
CEPin.write(1)
else
CEPin.write(0)

}
function NRFWriteCSN(Value)
{
if (Value )
CSNPin.write(1);
else
CSNPin.write(0);
}

function transferSPI(data)
{
return SPI.writeByte(data);
}

function NRFReadRegister(RegNum)
{
var ReturnValue=0;
NRFWriteCSN(0);
if (RegNum < 0x20)
{
NRFStatus = transferSPI(RegNum); // update status after CSN goes low
ReturnValue = transferSPI(0xff); // Send dummy byte to generate clocks
}
else
{
ReturnValue = -1;
}
NRFWriteCSN(1);
return ReturnValue;
}

function NRFWriteRegister(RegNum, Value)
{
var ReturnValue=0;
NRFWriteCSN(0);
if (RegNum < 0x20)
{
NRFStatus = transferSPI(0x20+RegNum); // update status after CSN goes low
ReturnValue = transferSPI(Value);	  // Write byte to target
}
else
{
ReturnValue = -1;
}
NRFWriteCSN(1);
return ReturnValue;
}
function NRFFlushTX()
{
NRFWriteCSN(0);
NRFStatus = transferSPI(0xe1); // Send Flush TX command
NRFWriteCSN(1);
}
function NRFFlushRX()
{
NRFWriteCSN(0);
NRFStatus = transferSPI(0xe2); // Send Flush RX command
NRFWriteCSN(1);
}

function NRFSetRXAddress0(AddressLength, Address)
{
var index;
switch (AddressLength) {
case 3 : {
NRFWriteRegister(3,1); // 3 byte address length
break;
}
case 4 : {
NRFWriteRegister(3,2); // 4 byte address length
break;
}
case 5 : {
NRFWriteRegister(3,3); // 5 byte address length
break;
}
default: {
return -1; // invalid address length
}
}
NRFWriteCSN(0);
NRFStatus = transferSPI(0x20+0x0a); // start write to RX_P0_Pipe address
for (index = 0; index < AddressLength; index++)
{
NRFStatus = transferSPI(Address[index]);
}
NRFWriteCSN(1);
}
function NRFSetRXAddress1(AddressLength, Address)
{
var index;
switch (AddressLength) {
case 3 : {
NRFWriteRegister(3,1); // 3 byte address length
break;
}
case 4 : {
NRFWriteRegister(3,2); // 4 byte address length
break;
}
case 5 : {
NRFWriteRegister(3,3); // 5 byte address length
break;
}
default: {
return -1; // invalid address length
}
}
NRFWriteCSN(0);
NRFStatus = transferSPI(0x20+0x0b); // start write to RX_P1_Pipe address
for (index = 0; index < AddressLength; index++)
{
NRFStatus = transferSPI(Address[index]);
}
NRFWriteCSN(1);
}
function NRFGetRXAddress( MaxAddressLength,  Address)
{
var index;
var actual_length;
actual_length = NRFReadRegister(3);
actual_length = actual_length + 2;
if (actual_length > MaxAddressLength)
return -1;
NRFWriteCSN(0);
NRFStatus = transferSPI(0x0a); // start read from RX_P0_Pipe address
for (index = 0; index < actual_length; index++)
{
Address[index] = transferSPI(0xff);
}
NRFWriteCSN(1);
return(0);
}
function NRFSetTXAddress(AddressLength, Address)
{
var index;
switch (AddressLength) {
case 3 : {
NRFWriteRegister(3,1); // 3 byte address length
break;
}
case 4 : {
NRFWriteRegister(3,2); // 4 byte address length
break;
}
case 5 : {
NRFWriteRegister(3,3); // 5 byte address length
break;
}
default: {
return -1; // invalid address length
}
}
NRFWriteCSN(0);
NRFStatus = transferSPI(0x20+0x10); // start write to TX address
for (index = 0; index < AddressLength; index++)
{
transferSPI(Address[index]);
}
NRFWriteCSN(1);
return(0);
}

function NRFGetTXAddress(MaxAddressLength, Address)
{
var index;
var actual_length;
actual_length = NRFReadRegister(3);
actual_length = actual_length + 2;
if (actual_length > MaxAddressLength)
return -1;
NRFWriteCSN(0);
NRFStatus = transferSPI(0x10); // start read from TX address
for (index = 0; index < actual_length; index++)
{
Address[index] = transferSPI(0xff);
}
NRFWriteCSN(1);
return(0);
}
function NRFEnableTXMode()
{
NRFWriteRegister(0,0x0a); // enable CRC, power up
}
function NRFEnableRXMode()
{
NRFWriteRegister(0,0x0b); // enable CRC, power up, RX mode
}
function NRFWriteData(Length, Data)
{
var index;
if (Length > 32)
return -1; // too long
NRFWriteCE(0);
NRFWriteRegister(0x07,0x70); // clear RX_DR,TX_DS,MAX_RT bits
NRFEnableTXMode();
NRFWriteCSN(0);
NRFStatus = transferSPI(0xa0); // start write to TX buffer
for (index = 0; index < Length; index++)
{
transferSPI(Data[index]);
}
NRFWriteCSN(1);
NRFWriteCE(1);
console.log("Sending..");
NRFEnableRXMode();
}
function NRFReadData(MaxLength,Data)
{ // data is assumeed to be in data pipe 1
var available_bytes;
var index;
var Length;
available_bytes=NRFReadRegister(0x12); // find out how many bytes are available in P1
if (available_bytes == 0)
return 0;
NRFWriteCSN(0);
NRFStatus = transferSPI(0x61); // start read from RX buffer
if (available_bytes > MaxLength)
Length = MaxLength;
else
Length = available_bytes;
for (index = 0; index < Length; index++)
{
Data[index]=transferSPI(0xff);
}
NRFWriteCSN(1);
return Length;
}
function printRegisters()
{
var regnum;
for (regnum = 0;regnum < 0x20; regnum++)
{
var hexstring= NRFReadRegister(regnum).toString(16);
console.log(regnum.toString(16) + " : " + hexstring);
}
}
/* The main body of the program follows.
* The NRF is initialized with correct addresses etc and is periodically
* polled to see if there is any data available in the RX FIFO
* If there is data it is read and a byte is sent back
*/
var ChannelTraffic = new Buffer(128);
function poll()
{
// check to see if there is any received data
var cd=NRFReadRegister(0x09);
//console.log(Channel+":"+cd);
NRFWriteRegister(0x05,Channel); 		// select channel
NRFWriteCE(1);
NRFEnableRXMode();
NRFWriteCE(0);
if (cd)
ChannelTraffic[Channel] = ChannelTraffic[Channel]+1;
Channel++;
if (Channel > 127)
{
Channel = 1;
var row=0;
var column=0;
while(row < 8)
{
column = 0;
while(column < 16)
{
process.stdout.write(ChannelTraffic[row*16+column]+" ");
column++;
}
console.log(" ");
row++;

}
console.log("-----------------------------------------");
//console.log(ChannelTraffic);
}
setTimeout(poll,50);
}

var Channel=0;
while(Channel < 128)
{
ChannelTraffic[Channel]=0;
Channel++;
}
Channel = 0;
NRFinit();
NRFSetRXAddress0(5,DESTINATION_ADDRESS); // set auto ack address = destination
NRFSetTXAddress(5,DESTINATION_ADDRESS);	 // set destination address
NRFSetRXAddress1(5,SOURCE_ADDRESS);		 // set source address
console.log("Switching to RX mode");
NRFFlushTX();
NRFFlushRX();
NRFEnableRXMode();
NRFWriteRegister(0x05,Channel); 		// select channel
NRFWriteCE(1);
printRegisters();
poll();
```