- Mon Feb 16, 2009 9:37 pm
#66383
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
You can implement your own protocol, as well as set your own data rate and data width using my config functions.
Sender.c
(Set terminal font to Courier New for best results)
nrf2401.h
Code: Select all
nrf2401.c
/*
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 ... */
Code: Select all
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./*
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++;
}
}
You can implement your own protocol, as well as set your own data rate and data width using my config functions.
Sender.c
Code: Select all
Rcvr.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);
}
}
Code: Select all
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) :#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();
}
}
(Set terminal font to Courier New for best results)
Code: Select all
Remember to set the pins to however you have the avr and nRF2401 connected like this:
--------------------------------------------------------------------
| 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 |
--------------------------------------------------------------------
Code: Select all
Hope this helps somebody. Enjoy.nrf2401_pins.CE = ...
nrf2401_pins.CS = ...
nrf2401_pins.DR1=...
nrf2401_pins.CLK=...
nrf2401_pins.DATA=...