亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

本教程将学习如何使用nRF24L01收发模块实现两块Arduino开发板间的无线通信。nRF24L01模块是Arduino无线通信的热门选择。

我已在多个Arduino项目中使用此模块,可在此查看部分项目:

  • DIY Arduino遥控发射器
  • Arduino遥控飞机 | 100% DIY
  • DIY Arduino气垫船
  • Arduino无线气象站项目

可观看以下视频或阅读下方图文教程。内容涵盖nRF24L01收发模块所有必知要点:模块引脚图、工作原理、接线及多个代码示例。

概览

为讲解无线通信,我们将做两个例子:第一个从一块Arduino向另一块发送简单的“Hello World”消息;第二个实现双向通信,第一块Arduino的摇杆控制第二块的舵机,反之第二块的按钮控制第一块的LED。

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

nRF24L01收发模块

近观NRF24L01收发模块。它使用2.4 GHz频段,波特率250 kbps至2 Mbps可选。开阔地低波特率下通信距离可达100米。

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

完整规格参数:

频率范围2.4 – 2.5GHz ISM频段
数据速率250Kbps / 1Mbps / 2Mbps
最大输出功率0dBm
工作电压1.9 – 3.6V
最大工作电流12.3mA
待机电流22µA
逻辑输入5V兼容
通信距离100米(开阔地)

工作原理

模块可用125个不同信道,意味着可在一地组建125个独立工作的调制解调器网络。每个信道最多6个地址,或每个单元可同时与最多6个其他单元通信。

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

模块发射时功耗约12mA,甚至低于单个LED。工作电压1.9-3.6V,好消息是其他引脚耐5V逻辑,可直接接Arduino无需电平转换。

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

三个引脚用于SPI通信,需接Arduino的SPI引脚,注意不同Arduino板SPI引脚不同。CSN和CE引脚可接任意数字引脚,用于设置模块待机/激活模式、切换发射/命令模式。最后一个是中断引脚,非必用。

模块变体

NRF24L01有多种变体。最流行的是板载天线版。体积更紧凑,但传输距离降至约100米。

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

第二种变体无板载天线,改为SMA接口,可接吸盘天线以获得更好传输距离。

第三种变体除吸盘天线外,还集成RFX2401C芯片,含PA(功率放大器)和LNA(低噪声放大器)。这放大NRF24L01信号,开阔地通信距离可达1000米。

nRF24L01模块引脚图

详细看NRF24L01引脚图,以及NRF24L01+ PA/LNA模块。

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

两款模块引脚图相同,接线方式一致。

如何将nRF24L01连接到Arduino

NRF24L01模块连接Arduino开发板的方式如下:

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

如前所述,不同Arduino板SPI引脚不同,接线时请注意。

ArduinoSCKMISOMOSISS
Uno13121110
Nano13121110
Mega52505153

本教程所需组件获取链接:

  • NRF24L01收发模块………
  • Arduino开发板……………………
  • 面包板和杜邦线……………

Arduino与nRF24L01代码

连接好NRF24L01模块到Arduino板后,准备编写发射端和接收端代码。

首先需下载安装RF24库简化编程。也可从Arduino IDE库管理器直接安装。搜索“rf24”,找到并安装TMRh20, Avamander维护的版本。

以下是无线通信的两个代码及其说明。

发射端代码

/* * Arduino无线通信教程 * 示例1 - 发射端代码 * * by Dejan Nedelkovski, www.HowToMechatronics.com * * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> RF24 radio(7, 8); // CE, CSN const byte address[6] = "00001"; void setup() { radio.begin(); radio.openWritingPipe(address); radio.setPALevel(RF24_PA_MIN); radio.stopListening(); } void loop() { const char text[] = "Hello World"; radio.write(&text, sizeof(text)); delay(1000); }

接收端代码

/* * Arduino无线通信教程 * 示例1 - 接收端代码 * * by Dejan Nedelkovski, www.HowToMechatronics.com * * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> RF24 radio(7, 8); // CE, CSN const byte address[6] = "00001"; void setup() { Serial.begin(9600); radio.begin(); radio.openReadingPipe(0, address); radio.setPALevel(RF24_PA_MIN); radio.startListening(); } void loop() { if (radio.available()) { char text[32] = ""; radio.read(&text, sizeof(text)); Serial.println(text); } }

代码解析

需包含基础SPI库和新安装的RF24库,创建RF24对象。两个参数为CSN和CE引脚。

RF24 radio(7, 8); // CE, CSN

接着创建字节数组作为地址(即两模块通信的管道)。

const byte address[6] = "00001";

可将此地址改为任意5字母字符串,以选择与哪个接收端通信。本例中发射端和接收端使用相同地址。

setup中初始化radio对象,用radio.openWritingPipe()设置接收端地址(即之前设定的5字母字符串)。

radio.openWritingPipe(address);

接收端用radio.openReadingPipe()设置相同地址,建立双向通信。

radio.openReadingPipe(0, address);

用radio.setPALevel()设置功率放大器级别,本例设为最低(模块距离很近)。

radio.setPALevel(RF24_PA_MIN);

注意:用高功率级别时,建议在模块GND和3.3V间并联旁路电容,以获得更稳定电压。

radio.stopListening()设置模块为发射模式,radio.startListening()设置为接收模式。

// 发射端 radio.stopListening();
// 接收端 radio.startListening();

loop中,发射端创建字符数组赋值“Hello World”,用radio.write()发送。第一参数为待发送变量。

void loop() { const char text[] = "Hello World"; radio.write(&text, sizeof(text)); delay(1000); }

变量名前的“&”表示取变量地址(存储待发数据的指针),第二参数设置取多少字节。此处sizeof()取字符串“text”全部字节。末尾加1秒延时。

radio.write()单次最多发送32字节。

接收端loop中,用radio.available()检查是否有数据可收。若真,先创建32元素数组“text”存储入站数据。

void loop() { if (radio.available()) { char text[32] = ""; radio.read(&text, sizeof(text)); Serial.println(text); } }

用radio.read()读取数据存入“text”变量。最后串口打印文本。上传两程序后,打开接收端串口监视器,每秒打印一次“Hello World”。

故障排查

值得注意的是,电源噪声是用NRF24L01通信时最常见问题。通常RF电路或射频信号对电源噪声敏感。因此,在电源线并联去耦电容总是好主意。电容可为10uF至100uF任意值。

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

另一常见问题:Arduino 3.3V引脚不总能给NRF24L01供足电。用外部电源供电也是好主意。

双向无线通信:双NRF24L01与Arduino

看第二个例子,两块Arduino双向无线通信。电路原理图:

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

所需组件获取链接:

  • NRF24L01收发模块…………
  • Arduino开发板……………………
  • 摇杆模块…………………………
  • 舵机………………………………
  • 按钮………………………………
  • LED………………………………

nRF24L01源代码

以下是两个代码及说明。

发射端代码

/* * Arduino无线通信教程 * 示例2 - 发射端代码 * * by Dejan Nedelkovski, www.HowToMechatronics.com * * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #define led 12 RF24 radio(7, 8); // CE, CSN const byte addresses[][6] = {"00001", "00002"}; boolean buttonState = 0; void setup() { pinMode(12, OUTPUT); radio.begin(); radio.openWritingPipe(addresses[1]); // 00002 radio.openReadingPipe(1, addresses[0]); // 00001 radio.setPALevel(RF24_PA_MIN); } void loop() { delay(5); radio.stopListening(); int potValue = analogRead(A0); int angleValue = map(potValue, 0, 1023, 0, 180); radio.write(&angleValue, sizeof(angleValue)); delay(5); radio.startListening(); while (!radio.available()); radio.read(&buttonState, sizeof(buttonState)); if (buttonState == HIGH) { digitalWrite(led, HIGH); } else { digitalWrite(led, LOW); } }

接收端代码

/* * Arduino无线通信教程 * 示例2 - 接收端代码 * * by Dejan Nedelkovski, www.HowToMechatronics.com * * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #include <Servo.h> #define button 4 RF24 radio(7, 8); // CE, CSN const byte addresses[][6] = {"00001", "00002"}; Servo myServo; boolean buttonState = 0; void setup() { pinMode(button, INPUT); myServo.attach(5); radio.begin(); radio.openWritingPipe(addresses[0]); // 00001 radio.openReadingPipe(1, addresses[1]); // 00002 radio.setPALevel(RF24_PA_MIN); } void loop() { delay(5); radio.startListening(); if ( radio.available()) { while (radio.available()) { int angleV = 0; radio.read(&angleV, sizeof(angleV)); myServo.write(angleV); } delay(5); radio.stopListening(); buttonState = digitalRead(button); radio.write(&buttonState, sizeof(buttonState)); } }

与前例不同之处:双向通信需创建两个管道/地址。

const byte addresses[][6] = {"00001", "00002"};

setup中需定义两个管道,注意:第一块Arduino的写地址必须是第二块的读地址,反之亦然——第一块的读地址是第二块的写地址。

// 发射端 radio.openWritingPipe(addresses[1]); // 00001 radio.openReadingPipe(1, addresses[0]); // 00002
// 接收端 radio.openWritingPipe(addresses[0]); // 00002 radio.openReadingPipe(1, addresses[1]); // 00001

loop中用radio.stopListening()设第一块Arduino为发射端,读取摇杆模拟值映射0-180,用radio.write()发送给接收端。

radio.stopListening(); int potValue = analogRead(A0); int angleValue = map(potValue, 0, 1023, 0, 180); radio.write(&angleValue, sizeof(angleValue));

另一端用radio.startListening()设第二块Arduino为接收端,检查是否有可用数据。有数据时循环读取,存入“angleV”变量并用该值旋转舵机。

radio.startListening(); if ( radio.available()) { while (radio.available()) { int angleV = 0; radio.read(&angleV, sizeof(angleV)); myServo.write(angleV); }

接着发射端设为接收模式,用空“while”循环等待第二块Arduino发回数据——即按钮按下状态。按钮按下则LED点亮。此过程持续循环,两块Arduino持续收发数据。

示例3——单包发送多变量

再看一个用NRF24L01模块的代码示例。除数据结构与发送方式外,其余不变。

发射端代码

/* Arduino无线通信教程 示例1 - 发射端代码 by Dejan Nedelkovski, www.HowToMechatronics.com Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> RF24 radio(7, 8); // CE, CSN const byte address[6] = "00001"; // 结构体最大32字节 - NRF24L01缓冲区限制 struct Data_Package { byte a = 0; byte b = 125; byte c = 255; int d = 1024; float e = 3.141592; String f = "Test"; }; Data_Package data; // 创建上述结构的变量 void setup() { radio.begin(); radio.openWritingPipe(address); radio.setPALevel(RF24_PA_MIN); radio.stopListening(); } void loop() { // 将结构体整个数据发送给接收端 radio.write(&data, sizeof(Data_Package)); delay(500); }

可创建struct(结构体),实际是多类型变量的集合。

// 结构体最大32字节 - NRF24L01缓冲区限制 struct Data_Package { byte a = 0; byte b = 125; byte c = 255; int d = 1024; float e = 3.141592; String f = "Test"; }; Data_Package data; // 创建上述结构的变量

注意结构体数据最大32字节。此处含三个byte变量、一个int(4字节)、一个float(4字节)、一个4字符String(4字节),共15字节。

接收端代码

/* Arduino无线通信教程 示例1 - 接收端代码 by Dejan Nedelkovski, www.HowToMechatronics.com Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> RF24 radio(7, 8); // CE, CSN const byte address[6] = "00001"; // 结构体最大32字节 - NRF24L01缓冲区限制 struct Data_Package { byte a = 0; byte b = 125; byte c = 255; int d = 1024; float e = 3.141592; String f = "Test"; }; Data_Package data; // 创建上述结构的变量 void setup() { Serial.begin(9600); radio.begin(); radio.openReadingPipe(0, address); radio.setPALevel(RF24_PA_MIN); radio.startListening(); } void loop() { // 检查是否有数据可接收 if (radio.available()) { radio.read(&data, sizeof(Data_Package)); // 读取整个数据并存入'data'结构体 } Serial.print("a: "); Serial.print(data.a); Serial.print(" b: "); Serial.print(data.b); Serial.print(" c: "); Serial.print(data.c); Serial.print(" d: "); Serial.print(data.d); Serial.print(" e: "); Serial.print(data.e); Serial.print(" f: "); Serial.println(data.f); }

接收端必须定义相同结构体才能接收数据。为测试无线通信是否正常,我在串口监视器打印每个变量。

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

结语

NRF24L01模块是Arduino项目需要无线通信时的绝佳选择。我已在许多Arduino项目中使用它。

列出所有用到该模块的项目/教程:

  • Arduino机器人小车无线控制:HC-05蓝牙、NRF24L01、HC-12收发模块
  • Arduino无线气象站项目
  • DIY Arduino遥控发射器
  • Arduino六足蚂蚁机器人
  • DIY Arduino气垫船
  • Arduino麦克纳姆轮机器人
  • DIY Arduino遥控接收机(用于遥控模型和Arduino项目)
  • Arduino遥控飞机 | 100% DIY

每个项目/教程都详细讲解如何使用NRF24L01模块,含电路图、改进代码实现等。

我最爱的项目是这个定制设计的Arduino遥控发射器。实际是14通道遥控器,可控制几乎任何Arduino项目。

掌握nRF24L01:无线通信、Arduino集成、电路与代码全攻略

本教程到此结束,希望你喜欢并学到新知识. 评论区欢迎提问。

制造工艺

  1. 使用 OpenSensors 监测空气质量:Arduino 与 Python 实战指南
  2. 用 Arduino 制作万能红外遥控器:分步指南
  3. DIY 数字身高仪:Arduino Nano + VL53L0X 激光测距 + OLED 显示
  4. JX 波形发生器 – 基于 Arduino 的 DDS 振荡器,带 OLED 显示屏
  5. DIY VR 滑板:用 Arduino、Google Cardboard 与蓝牙打造虚拟滑雪体验
  6. Arduino Mega 2560 接 NEO-6M GPS 模块完整教程
  7. 热敏电阻测温轻松上手:Arduino 分步实战教程
  8. Arduino 合成乐音:从零实现 88 键钢琴全音域
  9. Arduino Modbus 从机开发全攻略:基于 RS485 扩展板的分步实现指南
  10. ArduRadio 闹钟收音机:DIY Arduino FM 收音机与闹钟系统
  11. Arduino Due 望远镜自动导星系统 rDUINOScope:GPS、RTC、蓝牙、触控屏全集成
  12. 脑机接口:重连思维与行动