Search Microcontrollers

Monday, April 6, 2015

Stellaris Launchpad - NRF24L01 radio - Part 2

Ok, I had this one in draft for long enough now.
I still need to figure out a few things, so a part 3 will be needed in the future, also I initially had issues with Dynamic Payloads as I forgot to issue the FEATURE = EN_DPL command, hopefully shoudl work better now.


In a previous post we saw some basic concepts and functionality of the NRF24L01 chip.

We managed to establish a SPI communication between the Stellaris and the module, but we did not perform any data transmission across two nodes.
to achieve that we need to add a few functions to our library and decide some basic defaults for it.

I think this automatic ACK system (if you don't know what I am talking about, you really need to read my previous post) is pretty cool and I think it would be fair to use it by default, so the library will assume we are going to use it, should we have any issues with it later on, we might eventually change approach.

While supporting multiple RX pipes is indeed interesting, so I would rather keep that functionality in the library, we can assume that, by default, communication will be through pipe0.

The function nrf_enablePipes accepts a byte (bits 0:5 represent the 6 pipes) does 3 things :

1) Enables the selected pipes
2) Activates the AUTO ACK magic for them
3) configures them for dynamic payload

void nrf_enablePipes(unsigned char pipes)
{
  nrf_writeReg(EN_AA, pipes);     
         // enable AUTO ACK on pipes
  nrf_writeReg(EN_RXADDR, pipes); // enable pipes
  nrf_writeReg( FEATURE, 1<<EN_DPL ); //enable DPL
  nrf_writeReg(DYNPD, pipes); // dynamic payload for pipes
}

About dynamic payload (DPL), the Datasheet says :

(@Nordic)


Another default I picked is to use 5 byte addressing.

Now we need to be able to set the TX address and the various RX addresses for the RX pipes.

 /*
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
pipe : 0..5
 */
void nrf_setRXAddress(unsigned char pipe, unsigned char *addr)
{
 nrf_writeRegMulti(RX_ADDR_P0+pipe, addr, 5);
}

void nrf_setTXAddress(unsigned char *addr)
{
 nrf_writeRegMulti(TX_ADDR, addr, 5);
}

the writeRegMulti function works like the writeReg, but accepts a buffer and sends n bytes instead of a single one, we need it for setting the addresses since they are 5 bytes long.

As we discussed in the previous post, a node can be set up as PRX or PTX, this is done setting the lowest bit in the CONFIG register : 1 means PRX, 0 means PTX.
The same register is used to specifcy if a CRC is used, int hat case wether is it 1 or 2 byte long,m plus there are 3 bits used to mask the interrupts.

You can find more info on the CONFIG register here.

/**
 * Set crc = 0 to disable crc, 1 for 1 byte ,2 for 2 bytes
 */
void nrf_config(unsigned char maskRXirq, 
                unsigned char maskTXirq,
                unsigned char maskMAXirq,
unsigned char crc,
                unsigned char pwUp,
                unsigned char prx)
{
   unsigned char val = maskRXirq<<6 | 
                       maskTXirq<<5 | 
                       maskMAXirq <<4;
   if (crc>0) val |= 8; else crc--;
   val |= crc <<2 | pwUp<<1 | prx;
   nrf_writeReg(CONFIG,val);
}

When we need to initiate a transmission, we need to set up the node as PTX, to set the TX address to the address of the receiving module, plus the Pipe0 address equal to the TX one.

Additionally we might want to configure the number of transmission attempts (if Auto ACK fails) and the delay between them

/**
 * delay : 0 = 250us, 1=500us ... 15=4000us
 * count : 0..15 auto retransmit if AA fails
 */
void nrf_setRetransmit(unsigned char count, 
                       unsigned char rDelay)
{
 unsigned char val = ((rDelay&0x0f)<<4) | (count&0x0f);
 nrf_writeReg(SETUP_RETR,val);
}

In our experiment we will use node 1 with address "node1" (in ASCII) and node 2 with address "node2" and we will try to have them communicate  @2MBps on the channel 0x10.
Node 1 will try to send a payload containing the data "TEST1234" every 2 seconds and we will use the RGB leds on the two Launchpads to provide some feedback.

For this initial test we will do something simple, however I believe we still need to use two pipes.
The reason for this is that when the PTX sends data, it has to configure the RX pipe0 with the same address of the receiver, therefore it needs to be able to listen on a different pipe, with a unique address, in order to be contacted when it switches back to PRX.

Initially I was thinking to have one of the two nodes running on Arduino, to use a know library such as Mirf to minimize the debug, unfortunately I am not really sure if Mirf allows to be configured properly and if that is the case, I don't know how, while with my library at least I know all the settings.

Ok, I stopped here because I got lost with the DPL feature, as stated at the beginning, should work now, need to experiment a bit more (been doing other stuff for quite some time) and then hopefully a final Part 3 will be posted :)