Arduino教程学习A16-Arduino连接nRF24L01无线收发模块

Arduino连接nRF24L01无线收发模块



nRF24L01是一款工作在 2.4~2.5GHz 世界通用ISM频段的单片无线收发器芯片,输出功率、频道选择和协议的设置可以通过SPI接口进行设置。有极低的电流消耗,当工作在发射模式下发射功率为-6dBm时电流消耗为9.0mA,接收模式时为12.3mA。掉电模式和待机模式下电流消耗更低。

nRF24L01参考数据:供电电压:1.9 V~3.6V;最大发射功率:0 dBm;最大数据传输率:2000 kbps;发射模式下电流消耗(0dBm时):11.3 mA;接收模式下电流消耗(2000kbps):12.3 mA;接收模式数据传输率为1000kbps下的灵敏度:-85 dBm;掉电模式下电流消耗:900 nA。



淘宝上面有两种nRF24L01模块,一种是单纯的nRF24L01模块,号称传输距离250m的,几块钱就有交易;另外一种是NRF24L01+PA+LNA模块,包含放大,号称可以传输1000m,价格几十块。实际距离视地形和障碍物而定,是否够远只能通过试用确定。



下面用廉价的第一种单纯nRF24L01模块做示例:


nrf24l01.jpg

2015-3-8 00:24 上传
(290.73 KB)





一、nRF24L01硬件连接:

此模块是使用SPI方式连接,在标准SPI口基础增加CE和CSN引脚:

nRF24L01 Arduino UNO

VCC <-> 3.3V

GND <-> GND

CE <-> D9

CSN <-> D10

MOSI<-> D11

MISO<-> D12

SCK <-> D13

IRQ <-> 不接



还有就是nRF24L01属于对传模块。每块芯片既是发射器,也是接收器。所以一般来说,要使用两块nRF24L01+两块Arduino才能进行测试。



二、应用例子

实验1:

将Sender机A0的AD转换值无线发送到Receiver机



原理图:



Sender机(A0端与电源两端接一个电位器,阻值随意,一般1k~100k均可):

Sender.png

2015-3-8 00:24 上传
(22.67 KB)


Sender.jpg

2015-3-8 00:59 上传
(223.22 KB)



Receiver机:

Receiver.png

2015-3-8 00:24 上传
(20.36 KB)


Receiver.jpg

2015-3-8 00:59 上传
(175.1 KB)



代码:



首先需要安装Mirf库,可以在http://playground.arduino.cc/InterfacingWithHardware/Nrf24L01下载或者本文附件下载。



Sender机:

ARDUINO 代码复制打印下载

/nRF24L01 Arduino发送端Ansifa2015/3/7引脚接法:nRF24L01 Arduino UNOVCC  <->  3.3VGND  <->  GNDCE  <->  D9CSN  <->  D10MOSI<->  D11MISO<->  D12SCK  <->  D13IRQ  <->  不接/#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[] = adata & 0xFF;      //低八位给data[


Receiver机:
ARDUINO 代码复制打印下载
/*nRF24L01 Arduino Receiver接收端Ansifa2015/3/7引脚接法:nRF24L01 Arduino UNOVCC <-> 3.3VGND <-> GNDCE<-> D9CSN <-> D10MOSI<-> D11MISO<-> D12SCK <-> D13IRQ <-> 不接*/#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 Receiver接收端

Ansifa
2015/3/7

引脚接法:
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]);
}

}
}


实验2:
将上述的数据绘图表。

修改一下输出格式,然后用现成的串口图表软件显示出来。

原理图:
与实验1一样。
代码:
发射端代码与原来一样。
接收端新代码:
ARDUINO 代码复制打印下载
/*nRF24L01 Arduino Receiver接收端图表输出版本Ansifa2015/3/7引脚接法:nRF24L01 Arduino UNOVCC <-> 3.3VGND <-> GNDCE<-> D9CSN <-> D10MOSI<-> D11MISO<-> D12SCK <-> D13IRQ <-> 不接*/#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]);  }}
/*
nRF24L01 Arduino Receiver接收端
图表输出版本

Ansifa
2015/3/7

引脚接法:
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]);
}
}


上位机:
直接用现成软件比如这个串口猎人。
配置如图。依照图片顺序配置成截图一样即可。

串口猎人1.png

2015-3-8 00:51 上传
(44.76 KB)


串口猎人2.png

2015-3-8 00:51 上传
(62.31 KB)


串口猎人3.png

2015-3-8 01:40 上传
(47.87 KB)


串口猎人4.png

2015-3-8 00:51 上传
(28.25 KB)









下面是PDF版本文章与源代码

Arduino连接NRF24L01无线收发模块.zip

(3.25 MB, 下载次数: 661)

2015-3-8 01:42 上传
点击文件名下载附件







via - 极客工坊

标签: Arduino教程