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
不管式傳送端還是接收端,開頭都一樣,
差別在傳送端與接收端的"代碼"要互相指定對方作配對
接收端的設定是:
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]);
}
}