Arduino and nRF2401A

I created an Arduino NRF2401 library which is ready to plug-n-play. Put the .h and .c files in hardware\libraries\nRF2401.

nrf2401.h

/*
Arduino based NRF2401 Header File
Created by Sam Berro -- samberro(at)gmail.com
*/

#ifndef NRF2401_H
#define NRF2401_H

#include "WConstants.h"

#ifdef __cplusplus
extern "C" {
#endif


#define RX true
#define TX false

#define kbps240 false
#define kbps1000 true

#define SHOCKBURST true
#define DIRECT false

typedef struct {
    uint8_t CE;
    uint8_t CS;
    uint8_t DR1;
    uint8_t CLK;    
    uint8_t DATA;
} nrf2401_pins_t;

extern nrf2401_pins_t nrf2401_pins; 

/* ---- nrf2401_config_t struct was adopted from Timothy Willman's implementation ---- */
typedef struct {
    uint8_t data2w;
    uint8_t data1w;
    uint8_t addr2[5];
    uint8_t addr1[5];
    
    uint8_t addrw_crc;  /* addr_w:6 crc_l:1 crc_en:1 (hi-lo) */
    uint8_t misc;        /*  rx2_en:1 cm:1 rfdr_sb:1 xo_f:3 rf_pwr:2 (hi-lo) */
    uint8_t rf_ch_rxen;  /* rf_ch:7 rxen:1 (hi-lo) */
} nrf2401_config_t;

extern nrf2401_config_t nrf2401_config;
extern nrf2401_pins_t nrf2401_pins;

/*--------- MAIN FUNCTIONS: Call these functions ----------*/
void nrf2401_Init();
boolean nrf2401_available();
void nrf2401_getPacket(uint8_t*);
void nrf2401_sendPacket(const uint8_t*, const uint8_t*);
boolean nrf2401_getOpMode();
void nrf2401_setOpMode(boolean);

/* ---------- Functions to set the config word. Need to call nrf2401_Init for changes to take effect -------*/
void nrf2401_setRX(boolean);
void nrf2401_setChnl(uint8_t);
void nrf2401_setPow(uint8_t);
void nrf2401_setFreq(uint8_t);
void nrf2401_setDRate(boolean);
void nrf2401_setCM(boolean);
void nrf2401_setRX2EN(boolean);
void nrf2401_setCRCEN(boolean);
void nrf2401_setCRC16(boolean);
void nrf2401_setADDRW(uint8_t);
void nrf2401_setADDR1(const uint8_t*);
void nrf2401_setADDR2(const uint8_t*);
void nrf2401_setData1W(uint8_t);
void nrf2401_setData2W(uint8_t);

/* ------ Helper Functions -------*/
void nrf2401_toggleByte(const uint8_t);



#ifdef __cplusplus
};
#endif

#endif /* #ifndef NRF2401_H ... */

nrf2401.c

/*
Arduino based NRF2401 Header File
Created by Sam Berro -- samberro(at)gmail.com
*/

#include "nrf2401.h"

nrf2401_config_t nrf2401_config = {0x20,0x08,{0x11,0x22,0x33,0x44,0xE7},{0x11,0x22,0x33,0x44,0xE7},0xA3,0x4F,0x20};
nrf2401_pins_t nrf2401_pins = {8,9,7,10,11};

void nrf2401_setOpMode(boolean b){
  //TX = FALSE, RX= TRUE
  uint8_t i = 8;
  pinMode(nrf2401_pins.DATA,OUTPUT);
  digitalWrite(nrf2401_pins.DATA,LOW);
  digitalWrite(nrf2401_pins.CE,LOW);
  digitalWrite(nrf2401_pins.CS,HIGH);
  delayMicroseconds(500);//Tcs2data
  if(b) nrf2401_config.rf_ch_rxen |= 0x01;
  else nrf2401_config.rf_ch_rxen &= 0xFE;
  for(i=8;i>0;i--){
    digitalWrite(nrf2401_pins.DATA,((nrf2401_config.rf_ch_rxen>>(i-1)) & (0x01)));
    delayMicroseconds(1);
    digitalWrite(nrf2401_pins.CLK,HIGH);
    delayMicroseconds(1);
    digitalWrite(nrf2401_pins.CLK, LOW);
  }
  if(b == RX) pinMode(nrf2401_pins.DATA,INPUT);
  digitalWrite(nrf2401_pins.DATA,LOW);
  digitalWrite(nrf2401_pins.CLK,LOW);
  digitalWrite(nrf2401_pins.CS,LOW);
  if(b==RX) digitalWrite(nrf2401_pins.CE,HIGH);
} //setOpMode

boolean nrf2401_getOpMode(){
  return (nrf2401_config.rf_ch_rxen & 0x01);
}

void nrf2401_setRX(boolean b){
  if(b) nrf2401_config.rf_ch_rxen |= 0x01;
  else nrf2401_config.rf_ch_rxen &= 0xFE;
}

void nrf2401_setChnl(uint8_t c){
  boolean rxen =  nrf2401_config.rf_ch_rxen &= 0x01;
  nrf2401_config.rf_ch_rxen = c<<1;
  if(rxen) nrf2401_setRX(rxen);
}

void nrf2401_setPow(uint8_t p){
  nrf2401_config.misc |= (p & 0x03);
  nrf2401_config.misc &= (p | 0xFC);
}

void nrf2401_setFreq(uint8_t f){
  nrf2401_config.misc |= (f<<2 & 0x1C);
  nrf2401_config.misc &= (f<<2 | ~0x1C);
}

void nrf2401_setDRate(boolean r){
 if(r == kbps1000) nrf2401_config.misc |= 0x20;
  else nrf2401_config.misc &= ~0x20;
}

void snrf2401_setCM(boolean m){
  if(m == SHOCKBURST) nrf2401_config.misc |= 0x40;
  else nrf2401_config.misc &= ~0x40;
}

void nrf2401_setRX2EN(boolean e){
if(e) nrf2401_config.misc |= 0x80;
  else nrf2401_config.misc &= ~0x80;
}

void nrf2401_setCRCEN(boolean e){
  if(e) nrf2401_config.addrw_crc |= 0x01;
  else nrf2401_config.addrw_crc &= ~0x01;
}

void nrf2401_setCRC16(boolean c){
  if(c) nrf2401_config.addrw_crc |= 0x02;
  else nrf2401_config.addrw_crc &= ~0x02;
}

void nrf2401_setADDRW(uint8_t a){
  nrf2401_config.addrw_crc |= (a<<2 & 0xFC);
  nrf2401_config.addrw_crc &= (a<<2 | ~0xFC);
}

void nrf2401_setADDR1(const uint8_t* a1){
  uint8_t i = 0;
  for(i=0;i<5;i++){
    nrf2401_config.addr1[i] = a1[i];
  }
}

void nrf2401_setADDR2(const uint8_t* a2){
  uint8_t i = 0;
  for(i=0;i<5;i++){
    nrf2401_config.addr2[i] = a2[i];
  }
}

void nrf2401_setData1W(uint8_t w){
  nrf2401_config.data1w = w;
}

void nrf2401_setData2W(uint8_t w){
  nrf2401_config.data2w = w;
}

void nrf2401_toggleByte(uint8_t b){
  pinMode(nrf2401_pins.CLK, OUTPUT);
  pinMode(nrf2401_pins.DATA, OUTPUT);
  
  uint8_t i =0;
  for(i=0;i<8;i++){
    digitalWrite(nrf2401_pins.DATA, b & 0x80>>i);
	delayMicroseconds(1);
	digitalWrite(nrf2401_pins.CLK, HIGH);
	delayMicroseconds(1);
	digitalWrite(nrf2401_pins.CLK, LOW);
  }
}


void nrf2401_Init(){
  uint8_t i = 0;
  uint8_t arr [15] = {nrf2401_config.data2w, nrf2401_config.data1w, nrf2401_config.addr2[0], nrf2401_config.addr2[1], nrf2401_config.addr2[2],
				nrf2401_config.addr2[3], nrf2401_config.addr2[4], nrf2401_config.addr1[0], nrf2401_config.addr1[1], nrf2401_config.addr1[2],
				nrf2401_config.addr1[3], nrf2401_config.addr1[4], nrf2401_config.addrw_crc, nrf2401_config.misc, nrf2401_config.rf_ch_rxen};
  pinMode(nrf2401_pins.CLK, OUTPUT);
  pinMode(nrf2401_pins.CE, OUTPUT);
  pinMode(nrf2401_pins.CS, OUTPUT);
  pinMode(nrf2401_pins.DATA, OUTPUT);
  pinMode(nrf2401_pins.DR1,INPUT);
  
  digitalWrite(nrf2401_pins.CE,LOW);
  digitalWrite(nrf2401_pins.CS,HIGH);
  delay(3);
  for(i=0;i<15;i++){
    nrf2401_toggleByte(arr[i]);
  }
  digitalWrite(nrf2401_pins.CS,LOW);
  digitalWrite(nrf2401_pins.DATA,LOW);
  digitalWrite(nrf2401_pins.CLK,LOW);
  digitalWrite(nrf2401_pins.CE,LOW);
  if(nrf2401_config.rf_ch_rxen & 0x01){
    digitalWrite(nrf2401_pins.CE, HIGH); 
	pinMode(nrf2401_pins.DATA, INPUT);
  }
}

void nrf2401_sendPacket(const uint8_t *a, const uint8_t *d){
  if(nrf2401_getOpMode() == RX) nrf2401_setOpMode(TX);
  uint8_t i =0;
  uint8_t dlength = nrf2401_config.data1w >> 3; //length in bytes
  uint8_t alength = ((nrf2401_config.addrw_crc >> 2)&0x3F)>>3;//length in bytes
  digitalWrite(nrf2401_pins.CE, HIGH);
  delayMicroseconds(5);
  for(i=0;i<alength;i++){
    nrf2401_toggleByte(a[i]);
  }
  for(i=0;i<dlength;i++){
    nrf2401_toggleByte(d[i]);
  }
  digitalWrite(nrf2401_pins.CE,LOW);
  delayMicroseconds(200); //Tsby2rx/tx
  nrf2401_setOpMode(RX);
}

boolean nrf2401_available(){
  if(nrf2401_getOpMode() == TX) nrf2401_setOpMode(RX);
  return digitalRead(nrf2401_pins.DR1);
}

void nrf2401_getPacket(uint8_t *b){
  if(nrf2401_getOpMode() == TX) nrf2401_setOpMode(RX);
  uint8_t i = 0;
  while(nrf2401_available()){
    b[i/8] <<= 1;
	if(digitalRead(nrf2401_pins.DATA)) b[i/8] |= 0x01;
	digitalWrite(nrf2401_pins.CLK, HIGH);
    delayMicroseconds(1);
    digitalWrite(nrf2401_pins.CLK, LOW);
    delayMicroseconds(1);  
	i++;
  }
}

For test purposes I have coded a sender and a receiver. The sender operates at 1Mbps with 20Bytes payload, 5Bytes addr and 16bit CRC. The sender sends 20 byte packets stamped with a frame ID. The receiver sends an ACK once it receives a frame. This protocol insures no missed frames, and if the sender misses the ACK and resends, the rcvr knows its a resend and simply drops the frame. In my example the frame ID is simply a counter.

You can implement your own protocol, as well as set your own data rate and data width using my config functions.

Sender.c

#include <nrf2401.h>

byte count = 0x00;
const int dataw = 20;
byte addr [] = {0x11,0x22,0x33,0x44,0xE7};

boolean getAck(unsigned long t){
  //t=time in ms
  byte ack[dataw] = {0};
  nrf2401_setOpMode(RX);
  unsigned long entry = millis();
  while(!nrf2401_available() && millis()<entry+t) delay(1);
  if(!nrf2401_available()) return false;
  else {
    nrf2401_getPacket(ack);
    if(ack[0] == ((count-1)&0xFF))   return true;
  }
  return false;
}

void setup() {
 nrf2401_setData1W(dataw<<3);
 nrf2401_setDRate(kbps1000);
 nrf2401_Init();
 Serial.begin(19200);
}
void loop (){
  byte pl   [] = {   count++,count<<1,
                0xE7,0x11,0x22,0x33,0x44,0x55,
                0xE7,0x11,0x22,0x33,0x44,0x55,
                0xE7,0x11,0x22,0x33,0x44,0x55};
  nrf2401_sendPacket(addr,pl);
  while(!getAck(100)){
    nrf2401_sendPacket(addr,pl);
  }
}

Rcvr.c

#include <nrf2401.h>

byte temp_b_l = 0x00;
unsigned long temp = 0;
int count = 0;
int count2 = 0;
double rate = 0;
unsigned long BEST = 1000000000;
const int dataw = 20;
byte addr [] = {0x11,0x22,0x33,0x44,0xE7};

void setup(){
  Serial.begin(19200);
 nrf2401_setRX(true);
 nrf2401_setDRate(kbps1000);
 nrf2401_setData1W(dataw<<3);
 nrf2401_Init();
  pinMode(13, OUTPUT);
  pinMode(2,OUTPUT);
  temp = millis();
  
}
void loop(){
  byte temp_b[dataw] = {0};
  if(nrf2401_available()) {
    digitalWrite(13,HIGH);
    nrf2401_getPacket(temp_b);
    nrf2401_sendPacket(addr, temp_b);
    if(temp_b[0] != temp_b_l){
      //Serial.print(" 0x");
      //if(temp_b[0]<0x10) Serial.print("0");
      //Serial.print(temp_b[0], HEX);
      //Serial.print(temp_b[1], HEX);
      temp_b_l = temp_b[0];
      count++;
    }
    else {count2++;}
  }  

  if(temp_b[0] == 0xFF && count > 1){
    temp = millis()-temp;
    rate = 100*((float)(temp_b[0]-count+1)/(float)(temp_b[0]));
    if(temp < BEST){
      BEST = temp;
    }
    
    Serial.println("");
    Serial.println("--------------------------------------------------------------------");
    Serial.println("|  Sent  |  Rcvd  | Missed (Err%) | Repeated | Best Run | Last Run |");
    Serial.println("--------------------------------------------------------------------");
    Serial.print("|  ");Serial.print(temp_b[0]+1, DEC);Serial.print("   |");
    Serial.print("  ");Serial.print(count, DEC);Serial.print("   |");
    Serial.print("  ");Serial.print(temp_b[0]+1-count, DEC);Serial.print("     (");
    Serial.print(rate, DEC);Serial.print("%)   |");
    Serial.print("    ");Serial.print(count2, DEC);Serial.print("     |");
    Serial.print("  ");Serial.print(BEST, DEC);Serial.print("ms  |");
    Serial.print("  ");Serial.print(temp, DEC);Serial.println("ms  |");
    Serial.println("--------------------------------------------------------------------");
    count2=0;
    count = 0;
    temp = millis();
  }
}

The rcvr code connects to a serial term and outputs performance info. This is what I’m getting at my current settings (20 bytes data, 1Mbps) :

(Set terminal font to Courier New for best results)

--------------------------------------------------------------------
|  Sent  |  Rcvd  | Missed (Err%) | Repeated | Best Run | Last Run |
--------------------------------------------------------------------
|  256   |  256   |  0     (0%)   |    1     |  4186ms  |  4397ms  |
--------------------------------------------------------------------

--------------------------------------------------------------------
|  Sent  |  Rcvd  | Missed (Err%) | Repeated | Best Run | Last Run |
--------------------------------------------------------------------
|  256   |  256   |  0     (0%)   |    2     |  4186ms  |  4398ms  |
--------------------------------------------------------------------

--------------------------------------------------------------------
|  Sent  |  Rcvd  | Missed (Err%) | Repeated | Best Run | Last Run |
--------------------------------------------------------------------
|  256   |  256   |  0     (0%)   |    4     |  4186ms  |  4606ms  |
--------------------------------------------------------------------

--------------------------------------------------------------------
|  Sent  |  Rcvd  | Missed (Err%) | Repeated | Best Run | Last Run |
--------------------------------------------------------------------
|  256   |  256   |  0     (0%)   |    1     |  4186ms  |  4291ms  |
--------------------------------------------------------------------

--------------------------------------------------------------------
|  Sent  |  Rcvd  | Missed (Err%) | Repeated | Best Run | Last Run |
--------------------------------------------------------------------
|  256   |  256   |  0     (0%)   |    0     |  4186ms  |  4186ms  |
--------------------------------------------------------------------

--------------------------------------------------------------------
|  Sent  |  Rcvd  | Missed (Err%) | Repeated | Best Run | Last Run |
--------------------------------------------------------------------
|  256   |  256   |  0     (0%)   |    2     |  4186ms  |  4397ms  |
--------------------------------------------------------------------

--------------------------------------------------------------------
|  Sent  |  Rcvd  | Missed (Err%) | Repeated | Best Run | Last Run |
--------------------------------------------------------------------
|  256   |  256   |  0     (0%)   |    2     |  4186ms  |  4606ms  |
--------------------------------------------------------------------

--------------------------------------------------------------------
|  Sent  |  Rcvd  | Missed (Err%) | Repeated | Best Run | Last Run |
--------------------------------------------------------------------
|  256   |  256   |  0     (0%)   |    2     |  4186ms  |  4502ms  |
--------------------------------------------------------------------

Remember to set the pins to however you have the avr and nRF2401 connected like this:

nrf2401_pins.CE = ...
nrf2401_pins.CS = ...
nrf2401_pins.DR1=...
nrf2401_pins.CLK=...
nrf2401_pins.DATA=...

Hope this helps somebody. Enjoy.

Sharkbits - Thanks for the files - I am about to start using it. Are there any updates or corrections?

Fingers crossed - I will let you know how I get on.

r55boy:
Sharkbits - Thanks for the files - I am about to start using it. Are there any updates or corrections?

Fingers crossed - I will let you know how I get on.

These files and example sketches should get you started. They were developed and tested using Arduino 0011 (which I still use). It was brought to my attention that compiling these sketches on 0014 fails at compile time, although an object file gets generated from the library.

As far as updates, I have added a lot since my last post, mainly utility functions and such. A pair of nice functions I added are a sendWithReply() and a getWithReply() which perform ACKing to make sure a packet was received on the other end. This is similar to the latest nordic wireless transceiver which implements it in hardware. Let me know if you’re interested I’ll be happy to provide my latest version.

Good luck.

I found out there was a typo in the original code post so here are my latest .h/.c files for nrf2401:

nrf2401.h

/*
Arduino based NRF2401 Header File
Created by Sam Berro -- samberro(at)gmail.com
-------------------------------------------------------
March 09 2009:
  - added new send/rcv functions that do handshaking 
  - changed default pin assignment
  - kbps240 is now kbps250
-------------------------------------------------------
*/

#ifndef NRF2401_H
#define NRF2401_H

#include "WConstants.h"

#ifdef __cplusplus
extern "C" {
#endif


#define RX true
#define TX false

#define kbps250 false
#define kbps1000 true

#define SHOCKBURST true
#define DIRECT false

typedef struct {
    uint8_t CE;
    uint8_t CS;
    uint8_t DR1;
    uint8_t CLK;    
    uint8_t DATA;
} nrf2401_pins_t;

extern nrf2401_pins_t nrf2401_pins; 

/* ---- nrf2401_config_t struct was adopted from Timothy Willman's implementation ---- */
typedef struct {
    uint8_t data2w;
    uint8_t data1w;
    uint8_t addr2[5];
    uint8_t addr1[5];
    
    uint8_t addrw_crc;  /* addr_w:6 crc_l:1 crc_en:1 (hi-lo) */
    uint8_t misc;        /*  rx2_en:1 cm:1 rfdr_sb:1 xo_f:3 rf_pwr:2 (hi-lo) */
    uint8_t rf_ch_rxen;  /* rf_ch:7 rxen:1 (hi-lo) */
} nrf2401_config_t;

extern nrf2401_config_t nrf2401_config;

/*--------- MAIN FUNCTIONS: Call these functions ----------*/
void nrf2401_Init();
boolean nrf2401_available();
void nrf2401_getPacket(uint8_t*);
void nrf2401_getPacketWithReply(uint8_t*);
void nrf2401_sendPacket(const uint8_t*, const uint8_t*);
boolean nrf2401_sendPacketWithReply(const uint8_t*, const uint8_t*,unsigned long);
boolean nrf2401_getOpMode();
void nrf2401_setOpMode(boolean);

/* ---------- Functions to set the config word. Need to call nrf2401_Init for changes to take effect -------*/
void nrf2401_setRX(boolean);
void nrf2401_setChnl(uint8_t);
void nrf2401_setPow(uint8_t);
void nrf2401_setFreq(uint8_t);
void nrf2401_setDRate(boolean);
void nrf2401_setCM(boolean);
void nrf2401_setRX2EN(boolean);
void nrf2401_setCRCEN(boolean);
void nrf2401_setCRC16(boolean);
void nrf2401_setADDRW(uint8_t);
void nrf2401_setADDR1(const uint8_t*);
void nrf2401_setADDR2(const uint8_t*);
void nrf2401_setData1W(uint8_t);
void nrf2401_setData2W(uint8_t);

/* ------ Helper Functions -------*/
void nrf2401_toggleByte(const uint8_t);



#ifdef __cplusplus
};
#endif

#endif /* #ifndef NRF2401_H ... */

nrf2401.c

/*
Arduino based NRF2401 Header File
Created by Sam Berro -- samberro(at)gmail.com
-------------------------------------------------------
March 09 2009:
  - added new send/rcv functions that do handshaking 
  - changed default pin assignment
  - fixed typo (srf2401_setCM > nrf2401_setCM)
  - kbps240 is now kbps250
-------------------------------------------------------
*/

#include "nrf2401.h"

nrf2401_config_t nrf2401_config = {0x20,0x08,{0x11,0x22,0x33,0x44,0xE7},{0x11,0x22,0x33,0x44,0xE7},0xA3,0x4F,0x20};
nrf2401_pins_t nrf2401_pins = {7,6,5,4,3};

void nrf2401_setOpMode(boolean b){
  //TX = FALSE, RX= TRUE
  uint8_t i = 8;
  pinMode(nrf2401_pins.DATA,OUTPUT);
  digitalWrite(nrf2401_pins.DATA,LOW);
  digitalWrite(nrf2401_pins.CE,LOW);
  digitalWrite(nrf2401_pins.CS,HIGH);
  delayMicroseconds(500);//Tcs2data
  if(b) nrf2401_config.rf_ch_rxen |= 0x01;
  else nrf2401_config.rf_ch_rxen &= 0xFE;
  for(i=8;i>0;i--){
    digitalWrite(nrf2401_pins.DATA,((nrf2401_config.rf_ch_rxen>>(i-1)) & (0x01)));
    delayMicroseconds(1);
    digitalWrite(nrf2401_pins.CLK,HIGH);
    delayMicroseconds(1);
    digitalWrite(nrf2401_pins.CLK, LOW);
  }
  if(b == RX) pinMode(nrf2401_pins.DATA,INPUT);
  digitalWrite(nrf2401_pins.DATA,LOW);
  digitalWrite(nrf2401_pins.CLK,LOW);
  digitalWrite(nrf2401_pins.CS,LOW);
  if(b==RX) digitalWrite(nrf2401_pins.CE,HIGH);
  //delayMicroseconds(500); sometimes this seemed to save the day !!
} //setOpMode

boolean nrf2401_getOpMode(){
  return (nrf2401_config.rf_ch_rxen & 0x01);
}

void nrf2401_setRX(boolean b){
  if(b) nrf2401_config.rf_ch_rxen |= 0x01;
  else nrf2401_config.rf_ch_rxen &= 0xFE;
}

void nrf2401_setChnl(uint8_t c){
  boolean rxen =  nrf2401_config.rf_ch_rxen &= 0x01;
  nrf2401_config.rf_ch_rxen = c<<1;
  if(rxen) nrf2401_setRX(rxen);
}

void nrf2401_setPow(uint8_t p){
  nrf2401_config.misc |= (p & 0x03);
  nrf2401_config.misc &= (p | 0xFC);
}

void nrf2401_setFreq(uint8_t f){
  nrf2401_config.misc |= (f<<2 & 0x1C);
  nrf2401_config.misc &= (f<<2 | ~0x1C);
}

void nrf2401_setDRate(boolean r){
 if(r == kbps1000) nrf2401_config.misc |= 0x20;
  else nrf2401_config.misc &= ~0x20;
}

void nrf2401_setCM(boolean m){
  if(m == SHOCKBURST) nrf2401_config.misc |= 0x40;
  else nrf2401_config.misc &= ~0x40;
}

void nrf2401_setRX2EN(boolean e){
if(e) nrf2401_config.misc |= 0x80;
  else nrf2401_config.misc &= ~0x80;
}

void nrf2401_setCRCEN(boolean e){
  if(e) nrf2401_config.addrw_crc |= 0x01;
  else nrf2401_config.addrw_crc &= ~0x01;
}

void nrf2401_setCRC16(boolean c){
  if(c) nrf2401_config.addrw_crc |= 0x02;
  else nrf2401_config.addrw_crc &= ~0x02;
}

void nrf2401_setADDRW(uint8_t a){
  nrf2401_config.addrw_crc |= (a<<2 & 0xFC);
  nrf2401_config.addrw_crc &= (a<<2 | ~0xFC);
}

void nrf2401_setADDR1(const uint8_t* a1){
  uint8_t i = 0;
  for(i=0;i<5;i++){
    nrf2401_config.addr1[i] = a1[i];
  }
}

void nrf2401_setADDR2(const uint8_t* a2){
  uint8_t i = 0;
  for(i=0;i<5;i++){
    nrf2401_config.addr2[i] = a2[i];
  }
}

void nrf2401_setData1W(uint8_t w){
  nrf2401_config.data1w = w;
}

void nrf2401_setData2W(uint8_t w){
  nrf2401_config.data2w = w;
}

void nrf2401_toggleByte(uint8_t b){
  pinMode(nrf2401_pins.CLK, OUTPUT);
  pinMode(nrf2401_pins.DATA, OUTPUT);
  
  uint8_t i =0;
  for(i=0;i<8;i++){
    digitalWrite(nrf2401_pins.DATA, b & 0x80>>i);
	delayMicroseconds(1);
	digitalWrite(nrf2401_pins.CLK, HIGH);
	delayMicroseconds(1);
	digitalWrite(nrf2401_pins.CLK, LOW);
  }
}


void nrf2401_Init(){
  uint8_t i = 0;
  uint8_t arr [15] = {nrf2401_config.data2w, nrf2401_config.data1w, nrf2401_config.addr2[0], nrf2401_config.addr2[1], nrf2401_config.addr2[2],
				nrf2401_config.addr2[3], nrf2401_config.addr2[4], nrf2401_config.addr1[0], nrf2401_config.addr1[1], nrf2401_config.addr1[2],
				nrf2401_config.addr1[3], nrf2401_config.addr1[4], nrf2401_config.addrw_crc, nrf2401_config.misc, nrf2401_config.rf_ch_rxen};
  pinMode(nrf2401_pins.CLK, OUTPUT);
  pinMode(nrf2401_pins.CE, OUTPUT);
  pinMode(nrf2401_pins.CS, OUTPUT);
  pinMode(nrf2401_pins.DATA, OUTPUT);
  pinMode(nrf2401_pins.DR1,INPUT);
  
  digitalWrite(nrf2401_pins.CE,LOW);
  digitalWrite(nrf2401_pins.CS,HIGH);
  delay(3);
  for(i=0;i<15;i++){
    nrf2401_toggleByte(arr[i]);
  }
  digitalWrite(nrf2401_pins.CS,LOW);
  digitalWrite(nrf2401_pins.DATA,LOW);
  digitalWrite(nrf2401_pins.CLK,LOW);
  digitalWrite(nrf2401_pins.CE,LOW);
  if(nrf2401_config.rf_ch_rxen & 0x01){
    digitalWrite(nrf2401_pins.CE, HIGH); 
	pinMode(nrf2401_pins.DATA, INPUT);
  }
}

void nrf2401_sendPacket(const uint8_t *a, const uint8_t *d){
  if(nrf2401_getOpMode() == RX) nrf2401_setOpMode(TX);
  uint8_t i =0;
  uint8_t dlength = nrf2401_config.data1w >> 3; //length in bytes
  uint8_t alength = ((nrf2401_config.addrw_crc >> 2)&0x3F)>>3;//length in bytes
  digitalWrite(nrf2401_pins.CE, HIGH);
  delayMicroseconds(5);
  for(i=0;i<alength;i++){
    nrf2401_toggleByte(a[i]);
  }
  for(i=0;i<dlength;i++){
    nrf2401_toggleByte(d[i]);
  }
  digitalWrite(nrf2401_pins.CE,LOW);
  delayMicroseconds(300); //Tsby2rx/tx + toa
  nrf2401_setOpMode(RX);
}

boolean nrf2401_sendPacketWithReply(const uint8_t*a, const uint8_t*d,unsigned long t){
  byte ackByte = d[0];
  byte ack[20] = {0};
  nrf2401_sendPacket(a,d);
  unsigned long entry = millis();
  while(!nrf2401_available() && millis() <entry+t) {delay(1);}
  if(!nrf2401_available()) return false;
  else {
    nrf2401_getPacket(ack);
    if(ack[0] == ackByte)   return true;
  }
  return false;
}

boolean nrf2401_available(){
  if(nrf2401_getOpMode() == TX) return false;
  return digitalRead(nrf2401_pins.DR1);
}

void nrf2401_getPacket(uint8_t *b){
  if(nrf2401_getOpMode() == TX) nrf2401_setOpMode(RX);
  uint8_t i = 0;
  while(nrf2401_available()){
    b[i/8] <<= 1;
	if(digitalRead(nrf2401_pins.DATA)) b[i/8] |= 0x01;
	digitalWrite(nrf2401_pins.CLK, HIGH);
    delayMicroseconds(1);
    digitalWrite(nrf2401_pins.CLK, LOW);
    delayMicroseconds(1);  
	i++;
  }
}

void nrf2401_getPacketWithReply(uint8_t *b){
  nrf2401_getPacket(b);
  nrf2401_sendPacket(nrf2401_config.addr1, b);
}

Known issues:

  • DirectMode has not been tested (may work). There are no plans to fix it - use ShockBurst only.

  • Send functions use the data1w field to determine how many bytes to send.

A note about sendPacketWithReply() and getPacketWithReply():

In all my protocols I use a frameID as the first byte of the packet, which has to be different for the following packet (I use a simple counter). When you use getPacketWithReply the receiver will send an ACK packet with the same FID as the one it received. SendPacketWithReply will be waiting for a packet with that same FID. In case the ACK packet itself gets missed by the xmitter, it can simply retransmit and the receiver will drop a second packet with the same FID as the previous one. This protocol sacrifices transmission time for robustness (kinda like TCP). A raw xmit/rcv can be achieved using sendPacket and get Packet.

Thanks Sharkbits - I am working on this now.

One related question - in your project how did you interface the arduino and the trf-2.4g since one is 5v and one 3.3?

I am currently using 10k resistors on the arduino outputs, and a pair of transistors on the data line (which is bi-directional). I need to prove this setup yet before I start on the code side. Did you do something similar?

It would be very useful to add your library to the [Arduino Playgound. That way other users could easily find it.](http://www.arduino.cc/playground/Main/InterfacingWithHardware#Communication)

r55boy:
Thanks Sharkbits - I am working on this now.

One related question - in your project how did you interface the arduino and the trf-2.4g since one is 5v and one 3.3?

I am currently using 10k resistors on the arduino outputs, and a pair of transistors on the data line (which is bi-directional). I need to prove this setup yet before I start on the code side. Did you do something similar?

I used 5 BSS138 MOSFETS and a 3.3 voltage regulator for Vcc and Gnd. Actually I created a board that is more like an Arduino shield (plugs on top). To pull this off connect each gate to 3.3v, sources to nrf2401 i/o, and drains to 5v Arduino I/Os. I cannot see how transistors will work for a bi-directional setup.

I use this board to interface with any 3.3v device it works perfectly. I lost my Eagle schematics for this but I’m planning on creating an enhanced version soon.

Goodluck.

etracer:
It would be very useful to add your library to the [Arduino Playgound. That way other users could easily find it.[/quote]

I tried but after about an hour and a half of editing the wiki and documenting my code, I hit preview and it took me to the login screen, after which all my work disappeared !!! :cry:](http://www.arduino.cc/playground/Main/InterfacingWithHardware#Communication)

Sharkbits - got it working! and found a neat solution for bidirectional 3.3v to 5v interfacing too - see link below.

http://www.hagtech.com/pdf/translator.pdf

Also found a solution to the compile error that I logged above - add the #include <WProgram.h>.

But - I have a problem. I have built a transmitter and a reciever and its working ok at first sending a packet every second. But after 5-60 seconds the receiver stops receiving (ie: the DR line no longer goes high). Any idea why it might work perfectly for a little time then stop?

If I reset the receiver then the problem clears and it works again for a while.

Help!

Problem solved - I added the line back in…

//delayMicroseconds(500); sometimes this seemed to save the day !!

and its working! Clearly the Seeduino works differently than my Nano - one seems to need this extra delay, the other is happy with or without it.

Great library Sharkbits - thankyou so much.

Hello,

I am planning on buying 2 http://www.sparkfun.com/commerce/produc … cts_id=691 Nordic trancievers. I want to buy the nRF24L01+ because of the extra range, not because of the other features.

I have searched the web but could not find a library for Arduino. Do you think the library for this tranciever will be very different from the NRF2401 library? if so then I maybe need to buy the NRF2401 tranciever using your library.

Thanks in advance.

r55boy:
Sharkbits - got it working! and found a neat solution for bidirectional 3.3v to 5v interfacing too - see link below.

http://www.hagtech.com/pdf/translator.pdf

That should work but you need two transistors and two resistors for each bidirectional bus line. Using an enhancement mode MOSFET you only need one for each bus line (I use five for DATA, DR1, CLK, CE, and CS)..

r55boy:
Also found a solution to the compile error that I logged above - add the #include <WProgram.h>.

Nice I have to give that a shot. I am still using Arduino 0011 because it seems to generate the smallest hex file from sketches.

r55boy:
Problem solved - I added the line back in…

//delayMicroseconds(500); sometimes this seemed to save the day !!

and its working!

I remember having that same problem (which led me to add the extra delay line at the time). The delay seems to be a "workaround" for the issue but not the fix. As you see I commented it out after I figured out what was wrong. I cannot for the life of me;however, remember what was causing that now. Check your power source to Nordic.. It is definitely not the Arduino/Seeduino/Nano (or at least I dont remember that it was).

Sparkles:
Hello,

I am planning on buying 2 http://www.sparkfun.com/commerce/produc … cts_id=691 Nordic trancievers. I want to buy the nRF24L01+ because of the extra range, not because of the other features.

I have searched the web but could not find a library for Arduino. Do you think the library for this tranciever will be very different from the NRF2401 library? if so then I maybe need to buy the NRF2401 tranciever using your library.

Thanks in advance.

Hi Sparkles,

No this library will not work for nrf24L01 modules. The newer modules use a SPI interface instead of a two-wire like on nrf2401 (data+clk). You will have to create a new library from scratch because the data structures are different - nrf2401 uses a long config word while the nrf24L01 is register based being a SPI device.

Hi Sharkbits,

Thanks for your reply. I have found this code on the internet:

http://www.seeedstudio.com/depot/images … F24l01.rar (SeeedStudio).

http://www.seeedstudio.com/depot/24g-rf … p-214.html

I don’t know if this code also works with the Sparkfun module (I have no programming experience)?

Maybe it can be modified?

Best regards :slight_smile:

Sparkles:
Hi Sharkbits,

Thanks for your reply. I have found this code on the internet:

http://www.seeedstudio.com/depot/images … F24l01.rar (SeeedStudio).

http://www.seeedstudio.com/depot/24g-rf … p-214.html

I don’t know if this code also works with the Sparkfun module (I have no programming experience)?

Maybe it can be modified?

Best regards :slight_smile:

The Sparkfun module uses the same Nordic chip so the code should work. However, this code is more of a “demo” code to show that the device is alive than a functional set of APIs that you can use for your own purposes.

Sharkbits, I have a wireless project using some cheap 433mhz modules to communicate and I got a pair of those TRF-2.4G to replace. I found your code here and got your demo working on the first try. Great job!

I was trying to get 2 home-made arduino to work with 3.3v and 8mhz, but then I gave up after some problems and used the exactly same setup you did with the mosfets. I used 2N7000 transistors when testing on a breadboard, and BSS138 on sort of a shield too. I also had problems compiling with 0014, so I’m using 0011.

So, thanks a lot for doing this and making it available… do you or anyone else have any more practical examples for real-world applications using your library? My circuit and code using those other modules was very straightforward and now I’m kinda lost on the best way to change it to these.

Any idea if this library will work with the nRF24L01+. This uses the SPI interface so I’m guessing it wont?

Also I cant find how to connect the nRF24L01+ to the Arduino?

Connect it to the SPI interface.

Leon

pjwerneck:
Sharkbits, I also had problems compiling with 0014, so I’m using 0011.

I think somebody already figured out what the problem with 0014 and how to get around it earlier in this same thread. I haven't tried it cause 0011 works well for me.

pjwerneck:
do you or anyone else have any more practical examples for real-world applications using your library?

Well I tried making the library functions as generic as possible in such a way they can be used in any kind of application. Are you asking for project ideas? If so then just do a google search for wireless project or similar and pick what you like.

Hope this helps. And thanks for the props it didnt go unnoticed :slight_smile:

r55boy:
Any idea if this library will work with the nRF24L01+. This uses the SPI interface so I’m guessing it wont?

Nop sry it wont without major modifications. The top level functions group can be used as is but all low level ones have to be re-implemented.

r55boy:
Also I cant find how to connect the nRF24L01+ to the Arduino?

As Leon already mentioned, the easiest way is to use the SPI interface on your Arduino/ATMega.