nRF24L01

nRF24L01是個透過SPI介面(至少5條線)傳送資料的單向雙工無線模組,

(單向雙工是指 A傳送時B接收 或A接收時B傳送(類似對講機),無法與手機一樣同時邊講邊聽

優點是傳送速度很快,配對速度很快,傳送距離遠,官方數據是空曠處1100公尺

穿透力實測:帶天線版,可穿透可穿透三面水泥牆,極限是四面牆

非常適合作遙控車船飛機等連線模組

缺點是無法由APP Inventor2 透過app作控制,占用MCU的腳位較多

對於傳送資料方式的程式較進階

13 SCK

12 MISO

11 MOSI

8 CE

7 CSN (?)

2 IRQ (?)

【參考資料】

曹永忠 - 邁入『物聯網』的第一步:如何使用無線傳輸:基本篇

http://tmrh20.github.io/RF24/GettingStarted_8ino-example.html

官方硬體資料(密碼:wireless)

Arduino 連接 nRF24L01 (附件)

不管式傳送端還是接收端,開頭都一樣,

差別在傳送端與接收端的"代碼"要互相指定對方作配對

接收端的設定是:

Mirf.setRADDR((byte *)"A"); //讀取

Mirf.setTADDR((byte *)"B"); //傳送

傳送端的設定是:

Mirf.setRADDR((byte *)"B"); //讀取

Mirf.setTADDR((byte *)"A"); //傳送

#include <SPI.h>

#include <Mirf.h>

#include <nRF24L01.h>

#include <MirfHardwareSpiDriver.h>

#define ledpin 7

byte recvdata ;

void setup() {

Serial.begin(9600);

Mirf.spi = &MirfHardwareSpi;

Mirf.init();

Mirf.setRADDR((byte *)"bruce");

Mirf.setTADDR((byte *)"UNO");

Mirf.payload =1; //一次傳一個位元的資料

Mirf.config();

Serial.println("Listening...");

pinMode(ledpin,OUTPUT) ;

}

傳送端 接收端

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2);

#include <SPI.h>

#include <Mirf.h>

#include <nRF24L01.h>

#include <MirfHardwareSpiDriver.h>

#define ledpin 7

byte recvdata ;

byte num = 0 ;

byte num1 = 0 ;

void setup() {

Serial.begin(9600);

lcd.init();

lcd.backlight();

Mirf.spi = &MirfHardwareSpi;

Mirf.init();

Mirf.payload = 1;

Mirf.config();

Mirf.setTADDR((byte *)"bruce");

Mirf.setRADDR((byte *)"UNO");

pinMode(ledpin,OUTPUT) ;

}

void loop(){

unsigned long time = millis();

if (num >= 255)

num = 0 ;

transmit((char)num) ;

lcd.setCursor(0,0) ;

lcd.print("TX=") ;

lcd.print(num) ;

lcd.print(" ");

num ++ ;

if (!Mirf.isSending() && Mirf.dataReady()) {

Mirf.getData((byte *) &num1);

lcd.setCursor(0,1) ;

lcd.print("RX=") ;

lcd.print(num1) ;

lcd.print(" ");

}

}

void transmit(char st){

byte c;

c = st;

Mirf.send(&c);

while( Mirf.isSending() ) ;

}

void transmit( float v){

byte c;

char buf[10];

dtostrf(v,9,3,buf);

for( int i=0 ; i<8 ; i++ ){

c = buf[i];

Mirf.send(&c);

while( Mirf.isSending() ) ;

}

}

void transmit(const char *string){

byte c;

for( int i=0 ; string[i]!=0x00 ; i++ ){

c = string[i];

Mirf.send(&c);

while( Mirf.isSending() ) ;

}

}

void transmitlf(void){

byte c;

c = '\r';

Mirf.send(&c);

while( Mirf.isSending() ) ;

c = '\n';

Mirf.send(&c);

while( Mirf.isSending() ) ;

}

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

#include <SPI.h>

#include <Mirf.h>

#include <nRF24L01.h>

#include <MirfHardwareSpiDriver.h>

#define ledpin 7

byte recvdata ;

byte num = 0 ;

byte num1 = 0 ;

void setup() {

Serial.begin(9600);

lcd.init();

lcd.backlight();

Mirf.spi = &MirfHardwareSpi;

Mirf.init();

Mirf.setRADDR((byte *)"bruce");

Mirf.setTADDR((byte *)"UNO");

Mirf.payload =1;

Mirf.config();

pinMode(ledpin,OUTPUT) ;

}

void loop(){

if (!Mirf.isSending() && Mirf.dataReady()) {

Mirf.getData(&recvdata);

lcd.setCursor(0, 0) ;

lcd.print("RX=") ;

lcd.print(recvdata) ;

lcd.print(" ");

}

if (num >= 255)

num = 0 ;

transmit((char)num) ;

lcd.setCursor(0,1) ;

lcd.print("TX=") ;

lcd.print(num) ;

lcd.print(" ");

num ++ ;

}

void transmit(char st){

byte c;

c = st;

Mirf.send(&c);

while( Mirf.isSending() ) ;

}

void transmit( float v){

byte c;

char buf[10];

dtostrf(v,9,3,buf);

for( int i=0 ; i<8 ; i++ ){

c = buf[i];

Mirf.send(&c);

while( Mirf.isSending() ) ;

}

}

void transmit(const char *string){

byte c;

for( int i=0 ; string[i]!=0x00 ; i++ ){

c = string[i];

Mirf.send(&c);

while( Mirf.isSending() ) ;

}

}

void transmitlf(void){

byte c;

c = '\r';

Mirf.send(&c);

while( Mirf.isSending() ) ;

c = '\n';

Mirf.send(&c);

while( Mirf.isSending() ) ;

}

/*

nRF24L01 Arduino发送端

引脚接法:

nRF24L01 Arduino UNO

VCC <-> 3.3V

GND <-> GND

CE <-> D9

CSN <-> D10

MOSI<-> D11

MISO<-> D12

SCK <-> D13

IRQ <-> 不接

*/

#include <SPI.h>

#include <Mirf.h>

#include <nRF24L01.h>

#include <MirfHardwareSpiDriver.h>

void setup()

{

Serial.begin(9600);

Mirf.cePin = 9; //设置CE引脚为D9

Mirf.csnPin = 10; //设置CE引脚为D10

Mirf.spi = &MirfHardwareSpi;

Mirf.init(); //初始化nRF24L01

//设置接收标识符"Sen01"

Mirf.setRADDR((byte *)"Sen01");

//设置一次收发的字节数,这里发一个整数,写sizeof(unsigned int),实际等于2字节

Mirf.payload = sizeof(unsigned int);

//发送通道,可以填0~128,收发必须一致。

Mirf.channel = 3;

Mirf.config();

//注意一个Arduino写Sender.ino,另一个写Receiver.ino。

//这里标识写入了Sender.ino

Serial.println("I'm Sender...");

}

unsigned int adata = 0;

void loop()

{

//读取A0值到adata

adata = analogRead(A0);

//由于nRF24L01只能以byte单字节数组形式发送Mirf.payload个数据,

//所以必须将所有需要传输的数据拆成byte。

//下面定义byte数组,存放待发数据,因为Mirf.payload = sizeof(unsigned int);

//实际下面等于byte data[2];

byte data[Mirf.payload];

//adata是unsigned int双字节数据,必须拆开。

//将adata高低八位拆分:

data[0] = adata & 0xFF; //低八位给data[0],

data[1] = adata >> 8; //高八位给data[1]。

//设置向"serv1"发送数据

Mirf.setTADDR((byte *)"Rec01");

Mirf.send(data);

//while死循环等待发送完毕,才能进行下一步操作。

while(Mirf.isSending()) {}

delay(20);

}

/*

nRF24L01 Arduino Receiver接收端

引脚接法:

nRF24L01 Arduino UNO

VCC <-> 3.3V

GND <-> GND

CE <-> D9

CSN <-> D10

MOSI<-> D11

MISO<-> D12

SCK <-> D13

IRQ <-> 不接

*/

#include <SPI.h>

#include <Mirf.h>

#include <nRF24L01.h>

#include <MirfHardwareSpiDriver.h>

//定义一个变量adata存储最终结果,oldadata存储旧结果,防止相同结果刷屏。

unsigned int adata = 0, oldadata = 0;

void setup()

{

Serial.begin(9600);

//---------初始化部分,不可随时修改---------

Mirf.cePin = 9; //设置CE引脚为D9

Mirf.csnPin = 10; //设置CE引脚为D10

Mirf.spi = &MirfHardwareSpi;

Mirf.init(); //初始化nRF24L01

//---------配置部分,可以随时修改---------

//设置接收标识符"Rev01"

Mirf.setRADDR((byte *)"Rec01");

//设置一次收发的字节数,这里发一个整数,

//写sizeof(unsigned int),实际等于2字节

Mirf.payload = sizeof(unsigned int);

//发送通道,可以填0~128,收发必须一致。

Mirf.channel = 3;

Mirf.config();

//注意一个Arduino写Sender.ino,另一个写Receiver.ino。

//这里用来辨别写入了Receiver.ino程序

Serial.println("I'm Receiver...");

}

void loop()

{

//定义一个暂存数组,大小为Mirf.payload。

byte data[Mirf.payload];

if(Mirf.dataReady()) //等待接收数据准备好

{

Mirf.getData(data); //接收数据到data数组

//data[1]<左移8位与data[0]并,重组数据。

adata = (unsigned int)((data[1] << 8) | data[0]);

//与上一次结果比较,避免相同结果刷屏,降低串口流量

if(adata != oldadata)

{

oldadata = adata; //本次结果作为历史结果。

//Serial.print输出数据

Serial.print("A0=");

Serial.println(adata);

//也可以输出双字节数据

//Serial.write(data[1]);

//Serial.write(data[0]);

}

}

}

/*

nRF24L01 Arduino发送端

引脚接法:

nRF24L01 Arduino UNO

VCC <-> 3.3V

GND <-> GND

CE <-> D9

CSN <-> D10

MOSI<-> D11

MISO<-> D12

SCK <-> D13

IRQ <-> 不接

*/

#include <SPI.h>

#include <Mirf.h>

#include <nRF24L01.h>

#include <MirfHardwareSpiDriver.h>

void setup()

{

Serial.begin(9600);

Mirf.cePin = 9; //设置CE引脚为D9

Mirf.csnPin = 10; //设置CE引脚为D10

Mirf.spi = &MirfHardwareSpi;

Mirf.init(); //初始化nRF24L01

//设置接收标识符"Sen01"

Mirf.setRADDR((byte *)"Sen01");

//设置一次收发的字节数,这里发一个整数,写sizeof(unsigned int),实际等于2字节

Mirf.payload = sizeof(unsigned int);

//发送通道,可以填0~128,收发必须一致。

Mirf.channel = 3;

Mirf.config();

//注意一个Arduino写Sender.ino,另一个写Receiver.ino。

//这里标识写入了Sender.ino

Serial.println("I'm Sender...");

}

unsigned int adata = 0;

void loop()

{

//读取A0值到adata

adata = analogRead(A0);

//由于nRF24L01只能以byte单字节数组形式发送Mirf.payload个数据,

//所以必须将所有需要传输的数据拆成byte。

//下面定义byte数组,存放待发数据,因为Mirf.payload = sizeof(unsigned int);

//实际下面等于byte data[2];

byte data[Mirf.payload];

//adata是unsigned int双字节数据,必须拆开。

//将adata高低八位拆分:

data[0] = adata & 0xFF; //低八位给data[0],

data[1] = adata >> 8; //高八位给data[1]。

//设置向"serv1"发送数据

Mirf.setTADDR((byte *)"Rec01");

Mirf.send(data);

//while死循环等待发送完毕,才能进行下一步操作。

while(Mirf.isSending()) {}

delay(20);

}

/*

nRF24L01 Arduino Receiver接收端

图表输出版本

引脚接法:

nRF24L01 Arduino UNO

VCC <-> 3.3V

GND <-> GND

CE <-> D9

CSN <-> D10

MOSI<-> D11

MISO<-> D12

SCK <-> D13

IRQ <-> 不接

*/

#include <SPI.h>

#include <Mirf.h>

#include <nRF24L01.h>

#include <MirfHardwareSpiDriver.h>

//定义一个变量adata存储最终结果。

unsigned int adata = 0;

void setup()

{

Serial.begin(9600);

//---------初始化部分,不可随时修改---------

Mirf.cePin = 9; //设置CE引脚为D9

Mirf.csnPin = 10; //设置CE引脚为D10

Mirf.spi = &MirfHardwareSpi;

Mirf.init(); //初始化nRF24L01

//---------配置部分,可以随时修改---------

//设置接收标识符"Rev01"

Mirf.setRADDR((byte *)"Rec01");

//设置一次收发的字节数,这里发一个整数,

//写sizeof(unsigned int),实际等于2字节

Mirf.payload = sizeof(unsigned int);

//发送通道,可以填0~128,收发必须一致。

Mirf.channel = 3;

Mirf.config();

//注意一个Arduino写Sender.ino,另一个写Receiver.ino。

//这里用来辨别写入了Receiver.ino程序

Serial.println("I'm Receiver...");

}

void loop()

{

//定义一个暂存数组,大小为Mirf.payload。

byte data[Mirf.payload];

if(Mirf.dataReady()) //等待接收数据准备好

{

Mirf.getData(data); //接收数据到data数组

//data[1]<左移8位与data[0]并,重组数据。

adata = (unsigned int)((data[1] << 8) | data[0]);

//输出双字节数据

Serial.write(data[0]);

Serial.write(data[1]);

}

}