在本教程中,我们将学习如何构建一个Arduino无线网络,由多个NR24L01收发模块组成。你可以观看下面的视频或阅读下面的书面教程。
作为示例,我制作了5个节点的网络,并且它们中的每一个可以与网络中的任何节点通信,同时它们可以作为发射器和接收器的工作。实际上以一种方式设置了该示例,该方法解释了如何制作更大的网络,或者精确,我们可以在单个RF信道上共互相通信3125个模块。所以让我们来看看它是如何工作的。亚博88下载
在我以前的教程中,我们已经学过了如何进行无线通信使用NRF24L01模块和RF24库之间的两个Arduino板之间。现在除了这个图书馆,我们将使用RF24Network库,它允许以一种简单的方式构建Arduino无线网络,许多板之间进行通信。下面是网络拓扑结构的工作原理。
单个NRF24L01模块可以同时主动收听6个其他模块。
RF24Network库利用这种能力生成树形拓扑结构中的网络,其中一个节点是基本节点,所有其他节点都是该节点或另一个节点的子节点。每个节点最多可以有5个子节点,这可以深入到5层,这意味着我们可以创建一个总共有3125个节点的网络。每个节点都必须定义一个15位地址,它精确地描述了节点在树中的位置。
我们实际上可以用八进制格式定义节点的地址。因此,主节点或基节点的地址是00,基子节点地址是01到05,01节点子节点地址是011到051,以此类推。
注意,如果节点011想要与节点02通信,通信将必须通过节点01和基本节点00,因此这两个节点必须始终处于活动状态,以便通信能够成功。
使用Arduino无线伺服电机控制的rf24网络库
在我们解释本教程的主要示例之前,为了更好地理解库的工作方式,让我们做一个简单的例子,两个Arduino板相互通信。这是这个例子的电路图。
你可以从下面的链接获得这个Arduino教程所需的组件:
- NRF24L01收发器模块......... ..亚马逊/Banggood/阿里巴巴全球速卖通
- 伺服电机..........................................亚马逊/Banggood/阿里巴巴全球速卖通
- 电位计 ......................................亚马逊/Banggood/阿里巴巴全球速卖通
- Arduino纳米 ......................................亚马逊/Banggood/阿里巴巴全球速卖通
yaboAG娱乐城披露:这些是联盟链接。作为亚马逊助理,我从合格购买中获得。
用第一个Arduino上的电位器我们可以控制第二个Arduino上的伺服电机。现在让我们看一下源代码。
下面是电位器侧的代码:
/ * arduino无线网络 - 多个nrf24l01教程==示例01 - 伺服控制/节点00 - potentiomer == by dejan,www.www.kuaixg.com图书馆:nrf24 / rf24,https://gi亚搏手机版官方下载thub.com/nrf24/rf24 nrf24 /rf24network,https://github.com/nrf24/rf24network * / #include#include #include rf24收音机(10,9);// nRF24L01 (CE,CSN) RF24Network network(radio);//在网络中包含无线电const uint16_t this_node = 00;//该节点的地址八进制格式(04,031等)const uint16_t node01 = 01;void setup() {SPI.begin();radio.begin ();network.begin(90,this_node);//(通道,节点地址)} void循环(){network.update();unsigned long potvalue = analogread(a0);//读取电位计值无符号长角度=地图(Potvalue,0,1023,0,180); // Convert the value to 0-180 RF24NetworkHeader header(node01); // (Address where the data is going) bool ok = network.write(header, &angleValue, sizeof(angleValue)); // Send the data }
首先,我们需要包含两个库RF24和RF24Network,以及SPI库。然后,我们需要创建RF24对象,并将其包含到RF24Network对象中。在这里,我们需要以八进制格式定义节点的地址,或者这个节点为00,伺服端另一个节点为01。
在setup部分中,我们需要通过设置通道和该节点的地址来初始化网络。
在循环部分,我们需要不断地调用update()函数,网络中的所有操作都是通过这个函数发生的。然后读取电位器的值,将其转换为0到180之间的一个适合伺服控制的值。然后我们创建一个网络头,在那里我们分配数据要去的节点的地址。最后,使用write()函数将数据发送到另一个节点。因此,这里的第一个参数包含地址信息,第二个参数指定要发送的数据,第三个参数是数据的大小。
以下是伺服端的代码:
/ * Arduino无线网络 - 多个nrf24l01教程==示例01 - 伺服控制/节点01 - 伺服电机== * / #include#include #include #include <伺服。> RF24收音机(10,9);// nRF24L01 (CE,CSN) RF24Network network(radio);//在网络中包含无线电uint16_t this_node = 01;//以八进制格式(04,031,等)伺服myservo的节点的地址;//创建伺服对象以控制伺服void setup(){spi.begin();radio.begin ();network.begin(90,this_node);//(通道,节点地址)myservo.attach(3);//(伺服引脚)} void循环(){network.update();while(network.available()){//有任何传入数据? RF24NetworkHeader header; unsigned long incomingData; network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data myservo.write(incomingData); // tell servo to go to a particular angle } }
另一方面,在伺服电机上,我们需要像前面解释的那样定义库和对象。这个节点的八进制地址是01。定义好伺服电机后,在loop部分,我们使用while() loop和available()函数不断检查是否有传入数据。如果为true,则创建一个网络头,通过它数据将被接受,同时创建一个变量,数据将被存储在其中。然后使用read()函数读取数据,并将其存储到incomingData变量中。最后利用这些数据,根据另一个节点的电位器来移动伺服电机。
Arduino无线网络具有多个NRF24L01模块
在理解这个示例之后,我们可以继续学习本教程的主要示例,并构建一个由5个Arduinos相互通信的无线网络。下面是这个例子的框图。
从基地,使用电位器我们将控制节点01的伺服电机,与第二个电位器控制发光二极管022节点,使用按钮012年我们将在节点控制LED和LED底部将使用电位器控制节点02。我们也将使用节点012的红外传感器控制节点01的LED。因此,我们可以注意到,这个示例解释了如何同时传输和接收数据,以及如何与来自不同分支的节点通信。现在让我们看看Arduino代码。
基础00源代码
/ * Arduino无线网络——多个NRF24L01教程/主节点00 = = = =基地德扬,www.HowToMechatronics.com库:nRF24 / RF24, https://亚搏手机版官方下载github.com/nRF24/RF24 nRF24 / RF24Network, https://github.com/nRF24/RF24Network * / # include < RF24Network.h > # include < RF24.h > # include < SPI.h > #定义按钮2 # define领导3 RF24电台(10 9);// nRF24L01 (CE,CSN) RF24Network network(radio);//在网络中包含无线电const uint16_t this_node = 00;//该节点的地址八进制格式(04,031等)const uint16_t node01 = 01;//其他节点的地址在八进制格式const uint16_t node012 = 012;const uint16_t node022 = 022;void setup() {SPI.begin();radio.begin ();network.begin(90,this_node);//(信道,节点地址)radio.setDataRate(RF24_2MBPS); pinMode(button, INPUT_PULLUP); pinMode(led, OUTPUT); } void loop() { network.update(); //===== Receiving =====// while ( network.available() ) { // Is there any incoming data? RF24NetworkHeader header; unsigned long incomingData; network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data analogWrite(led, incomingData); // PWM output to LED 01 (dimming) } //===== Sending =====// // Servo control at Node 01 unsigned long potValue = analogRead(A0); unsigned long angleValue = map(potValue, 0, 1023, 0, 180); // Suitable for servo control RF24NetworkHeader header2(node01); // (Address where the data is going) bool ok = network.write(header2, &angleValue, sizeof(angleValue)); // Send the data // LED Control at Node 012 unsigned long buttonState = digitalRead(button); RF24NetworkHeader header4(node012); // (Address where the data is going) bool ok3 = network.write(header4, &buttonState, sizeof(buttonState)); // Send the data // LEDs control at Node 022 unsigned long pot2Value = analogRead(A1); RF24NetworkHeader header3(node022); // (Address where the data is going) bool ok2 = network.write(header3, &pot2Value, sizeof(pot2Value)); // Send the data }
因此,在基本节点或主节点上,我们需要像前面解释的那样定义库和对象,还需要定义主节点将向其发送数据的所有其他节点。在loop部分中,我们从不断检查是否有传入数据开始。如果是这样,我们读取数据,将其存储到传入的数据变量中,并使用它来控制LED亮度。这个数据实际上来自节点02的电位器。如果我们看一下它的代码,我们可以注意到设置几乎是一样的。重要的是为我们想要发送数据的地方分配正确的地址。在这种情况下,这是master 00。所以我们读取电位器的值,并将其转换为0到255的合适的PWM值,然后将这些数据发送给主机。我们可以注意到,我使用millis()函数以10毫秒的间隔发送数据。
节点02源代码
/ * arduino无线网络 - 多个nrf24l01教程==节点02(主节点00的子节点)== * / #include#include #include rf24收音机(10,9);// nRF24L01 (CE,CSN) RF24Network network(radio);//在网络中包含无线电umint16_t this_node = 02;//以八进制格式(04,031,等)的节点的地址(04,031,等)CONSS UINT16_T Master00 = 00;//以八进制格式的其他节点的地址const unsigned longal = 10;// MS //如何将数据发送到其他单位无符号LAND_SENT;//我们什么时候上次发送的?void setup() {SPI.begin();radio.begin (); network.begin(90, this_node); //(channel, node address) radio.setDataRate(RF24_2MBPS); } void loop() { network.update(); //===== Sending =====// unsigned long now = millis(); if (now - last_sent >= interval) { // If it's time to send a data, send it! last_sent = now; unsigned long potValue = analogRead(A0); unsigned long ledBrightness = map(potValue, 0, 1023, 0, 255); RF24NetworkHeader header(master00); // (Address where the data is going) bool ok = network.write(header, &ledBrightness, sizeof(ledBrightness)); // Send the data } }
接下来,从主设备,我们将电位器数据发送到节点01以控制伺服电机。
节点01源代码
/ * arduino无线网络 - 多个nrf24l01教程==节点02(主节点00的子节点)== * / #include#include #include #include #define LED 2 RF24收音机(10,9);// nRF24L01 (CE,CSN) RF24Network network(radio);//在网络中包含无线电uint16_t this_node = 01;//以八进制格式(04,031,等)的节点的地址(04,031,等)CONSS UINT16_T Master00 = 00;//八进制格式的其他节点的地址伺服myservo;//创建伺服对象以控制伺服void setup(){spi.begin();radio.begin ();network.begin(90,this_node);//(信道,节点地址)radio.setDataRate(RF24_2MBPS);myservo.attach(3); // (servo pin) pinMode(led, OUTPUT); } void loop() { network.update(); //===== Receiving =====// while ( network.available() ) { // Is there any incoming data? RF24NetworkHeader header; unsigned long incomingData; network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data if (header.from_node == 0) { // If data comes from Node 02 myservo.write(incomingData); // tell servo to go to a particular angle } if (header.from_node == 10) { // If data comes from Node 012 digitalWrite(led, !incomingData); // Turn on or off the LED 02 } } }
节点01实际上从两个不同的节点接收数据,一个用于伺服控制,另一个用于LED控制,该LED控制来自节点012的红外传感器。
Node 012源代码
/ * Arduino无线网络 - 多个NRF24L01教程==节点012(节点02的子节点)== * / #include#include #include #define LED 2 #defineIR 3 RF24收音机(10,9);// nRF24L01 (CE,CSN) RF24Network network(radio);//包括网络中的无线电常量uint16_t this_node = 012;//以八进制格式(04,031等)节点的地址(04,031等)CONSS UINT16_T NODE01 = 01;//以八进制格式的其他节点的地址void setup(){spi.begin();radio.begin ();network.begin(90,this_node);//(信道,节点地址)radio.setDataRate(RF24_2MBPS);pinMode(领导、输出); pinMode(IR, INPUT); } void loop() { network.update(); //===== Receiving =====// while ( network.available() ) { // Is there any incoming data? RF24NetworkHeader header; unsigned long buttonState; network.read(header, &buttonState, sizeof(buttonState)); // Read the incoming data digitalWrite(led, !buttonState); // Turn on or off the LED } //===== Sending =====// unsigned long irV = digitalRead(IR); // Read IR sensor RF24NetworkHeader header8(node01); bool ok = network.write(header8, &irV, sizeof(irV)); // Send the data }
在这种情况下,我们使用header.from_node属性来获取数据来自哪个节点的信息。如果输入数据来自主机,我们用它来控制伺服,如果输入数据来自节点012,我们用它来控制LED。
在012号节点,我们同时接收和发送信号。红外传感器控制前面提到的节点01上的LED,这里的LED是由主控制器上的按钮控制的。
节点022源代码
/ * Arduino无线网络 - 多个nrf24l01教程==节点022(节点02的子节点)== * / #include#include #include #define led1 2 #defineLED2 3 #DEFINE LED3 4 #define LED4 5 RF24收音机(10,9);// nRF24L01 (CE,CSN) RF24Network network(radio);//在网络中包含无线电uint16_t this_node = 022;//以八进制格式(04,031,等)的节点的地址(04,031,等)CONSS UINT16_T Master00 = 00;//以八进制格式的其他节点的地址void setup(){spi.begin();radio.begin ();network.begin(90,this_node);//(信道,节点地址)radio.setDataRate(RF24_2MBPS);Pinmode(LED1,输出); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); pinMode(led4, OUTPUT); } void loop() { network.update(); //===== Receiving =====// while ( network.available() ) { // Is there any incoming data? RF24NetworkHeader header; unsigned long potValue; network.read(header, &potValue, sizeof(potValue)); // Read the incoming data // Turn on the LEDs as depending on the incoming value from the potentiometer if (potValue > 240) { digitalWrite(led1, HIGH); } else { digitalWrite(led1, LOW); } if (potValue > 480) { digitalWrite(led2, HIGH); } else { digitalWrite(led2, LOW); } if (potValue > 720) { digitalWrite(led3, HIGH); } else { digitalWrite(led3, LOW); } if (potValue > 960) { digitalWrite(led4, HIGH); } else { digitalWrite(led4, LOW); } } }
最后,节点022处的led使用来自主电位器的另一个电位器的数据进行控制。
因此,总结一下,如果一切正常连接,并且所有节点一直处于活动状态,我们的作业归结为正好地解决节点,并且由令人难以置信的RF24Network库进行所有繁重的工作。
所以这就是全部,我希望你喜欢这个Arduino项目并学会了新的东西。随意询问以下意见部分中的任何问题。
你好,
这是一个有趣的项目。我有一个问题,为什么选择使用NRF24网络,而不是ESP模块和无线网络?
我计划一个相似的系统,主要用于控制(小载荷),我选择MQTT的主要协议,因为无线网络可用带宽,但是大多数的传感器可以做他们的工作通过发送几个整数和其他人可以使用蓝牙额外流(音频),所以我不需要无线网络,除了在用户界面节点,它将有一个web服务器控制和配置访问(可能是树莓派,在它的情况下,它将是以太网连接)。关于nRF的担忧是,除了作为确认的一部分的配对序列,并希望没有人能猜出有效载荷的内容和结构之外,没有那么多提高安全性的可用选择。
谢谢!嗯,这只是一个教程,解释如何使用nRF24网络,以防有人想使用它。我没有做过任何与其他方法的详细比较,所以我不能告诉你太多。
我认为使用NRF的最常见原因是它的功耗只有esp8266的十分之一,这在电池或太阳能设置中非常重要,只要你使用低功耗的微控制器。
你好,人们......是的 - 我想我必须同意...... 8266的功耗通过比较真的很大......
感谢Dejan ......我真的很感激你的努力......
请继续! !
嗨如何发布机制,首先,令人敬畏!
你能在7:40之前解释原因我们必须写出标题。从节点12接收信息吗?(我实际上有5个在船长中获得5个信息,但无法理解您使用的数字背后的逻辑)。
非常感谢你的视频,这太棒了!
嘿,谢谢!说实话,我不太确定为什么会这样。我的意思是,我看了一下代码,它是正确的,它应该是12,因为我们从那个节点接收数据。可能是打错了。
因为八进制的12是十进制的10
是的,我得到了它。谢谢!
if (header.from_node == 0){//如果数据来自节点02
“↑”应为节点00
if(header.from_node == 10){//如果数据来自节点012
10月12日= 12月10日
你好,
很好地完成了!我有一个问题,我需要做什么,以发送相同的信号到多个接收器在同一时间?
嘿,谢谢!您可以在基本的00示例代码中看到这种情况。您只需要创建具有特定地址的不同头文件,然后使用write函数向所有头文件发送相同的数据。
你好,我试图实现这个代码为我的项目。
我正在建造一个风能和太阳能的无线电表。使用2个发射机和1个接收器。我还没有完全理解代码。
但是您用于发送的代码可以用于从2个传感器发送数据?
一个传感器是安培,一个传感器是伏特?(两个都在同一个发射机上)
是的,你可以把两个传感器的数据发送到接收器。您只需要使用write函数两次,或者制作一个包含多个变量的数据包(在本例中是来自两个传感器的值)。检查我的DIY Arduino基于RC发射机看到这样的一个例子发送多个变量在一个单一的数据包。
这是一个很酷的项目。我实现了读取40个节点,效果很好。谢谢你!
你好卡洛斯,
据我所知,NRF24可以同时连接最多6个节点。您是否可以帮助分享您关于如何实施40个节点的经验?
您的网站非常好,解释非常细。感谢
谢谢!
嗨,德扬,
首先感谢这个网站,我学到了很多!我计划在一个项目,我可以控制两个RC车辆与一个控制器(非常像DIY Arduino RC发射器项目)。是否有一种方法通过使用物理开关在它们之间进行选择来单独与每个接收器对话?例如,当切换是一种方式,它与车辆A对话,当切换是另一种方式,它与车辆b对话,我仍然是一个新手,所以任何帮助将非常感谢
嘿,詹姆斯,谢谢!你可以这样做。通过本教程中介绍的方法,我们可以看到我们可以选择要讨论的节点,我们只需要设置适当的地址。是的,你可以用一个简单的开关来改变地址。例如:“switch”为“active”或“HIGH”时,请输入“address 01”;“switch”非“active”或“LOW”时,请输入“address 02”。
非常好的工作。由于我的残疾,我最近被迫退休,这些教程很棒。我手上有很多时间,我很欣赏你是如何把事情放在外面,易于遵循和精确。
就我个人而言,我很感激你。
达雷雷尔
我很高兴你觉得这些有用。享受学习新事物的乐趣!
德扬,
感谢您的教程。大量的信息和恰到好处的数量让你思考正在发生的事情。你的多重例子很适合我。然后我稍微修改了一下,很高兴地看到子节点没有充当从主节点到孙子节点的传递节点,而是重新传输,这允许您有效地扩展nRF24L01的范围。这将是特别有用的,因为我一直在寻找一种方法,将数据从我们的林地的一个角落传输到另一个…大约1公里的距离。此外,通过网络进行双向通信比旧的“openReadingPipe, stopplistening”等方法要简单得多。有趣的是,我发现我不能让I2C OLED (Adafruit库)在接收节点上工作,但I2C LED将工作正常。然而,同样的OLED在标准的nRF24L01应用程序中工作良好。
你好,
这是一个很酷的项目。良好的工作。谢谢你的所有教程。
我现在也尝试做同样的项目,而是用不同的传感器。传感器将安装在机器上,我想在我的电脑上创建一个GUI,我可以在工作时监视机器,并在其衡量的所有参数上显示所有参数。
所以我的问题是,如果我可以在相当快的时间内同时阅读和传输所有数据,以便我可以整个工作时间监控机器。
谢谢。
嘿,谢谢。好吧,我认为你应该能够做到这一点,尽管我不太确定你需要的速度以及你需要的速度。干杯!
佩德罗·伯克斯,
不错的工作,学习很多,祝你一切顺利,继续前进爱你的网站。