在本教程中,我们将学习如何构建由多个NR24L01收发器模块组成的Arduino无线网络。您可以观看以下视频或阅读下面的书面教程。
作为示例,我制作了5个节点的网络,并且它们中的每一个可以与网络中的任何节点通信,同时它们可以作为发射器和接收器的工作。实际上以一种方式设置了该示例,该方法解释了如何制作更大的网络,或者精确,我们可以在单个RF信道上共互相通信3125个模块。所以让我们来看看它是如何工作的。betway
在我以前的教程中,我们已经学过了如何进行无线通信使用NRF24L01模块和RF24库之间的两个Arduino板之间。现在除了这个图书馆,我们将使用RF24Network库,它可以以一种简单的方式构建一个Arduino无线网络,多个板相互通信。下面是网络拓扑结构的工作原理。
单个NRF24L01模块可以同时主动收听6个其他模块。
RF24Network库利用这种能力来生成排列在树状拓扑结构中的网络,其中一个节点是基础节点,而所有其他节点都是该节点或另一个节点的子节点。每个节点最多可以有5个子节点,这可以深入5层,这意味着我们可以创建一个总共3125个节点的网络。每个节点都必须定义一个15位地址,它精确地描述了节点在树中的位置。
我们实际上可以用八进制格式定义节点的地址。因此,主节点或基节点的地址是00,基子节点地址是01到05,01节点子节点地址是011到051,以此类推。
注意,如果节点011想要与节点02交谈,则通信必须通过节点01和基本节点00,因此这两个节点必须一直处于活动状态,以便进行通信成功。
Arduino无线伺服电机控制使用RF24Network库
在我们解释本教程的主要示例之前,为了更好地理解库的工作原理,让我们做一个简单的示例,两个Arduino板相互通信。这是这个例子的电路图。
您可以从下面的链接获取此Arduino教程所需的组件:
- NRF24L01收发器模块......... ..亚马逊/Banggood/阿里巴巴全球速卖通
- 伺服电机..........................................亚马逊/Banggood/阿里巴巴全球速卖通
- 电位计 ......................................亚马逊/Banggood/阿里巴巴全球速卖通
- Arduino纳米 ......................................亚马逊/Banggood/阿里巴巴全球速卖通
必威外围提钱披露:这些是联盟链接。作为亚马逊助理,我从合格购买中获得。
因此,在第一个Arduino使用电位器,我们将控制第二个Arduino的伺服电机。我们现在看看源代码。
这里是电位器端的代码:
/ * arduino无线网络 - 多个nrf24l01教程==示例01 - 伺服控制/节点00 - potentiomer == by dejan,www.www.mfxpo.com图书馆:nrf24 / rf24,https://gibet188官方网站thub.com/nrf24/rf24 nrf24 /rf24network,https://github.com/nrf24/rf24network * / #include#include #include rf24收音机(10,9);// NRF24L01(CE,CSN)RF24NETWORK网络(无线电);//在网络中包含无线电uint16_t this_node = 00;//以八进制格式(04,031,等)的此节点的地址(04,031,等)CONSS 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。
在设置部分中,我们需要通过设置通道和这个节点的地址来初始化网络。
在循环部分,我们需要不断地调用update()函数,网络中的所有动作都是通过这个函数发生的。然后读取电位器的值,将其转换为适合于伺服控制的0 ~ 180的值。然后我们创建一个网络报头,在那里我们分配数据要去的节点的地址。最后,使用write()函数将数据发送到另一个节点。所以这里第一个参数包含地址信息,第二个参数指出要发送哪些数据,第三个参数是数据的大小。
这是伺服端的代码:
/ * Arduino无线网络 - 多个nrf24l01教程==示例01 - 伺服控制/节点01 - 伺服电机== * / #include#include #include #include <伺服。> RF24收音机(10,9);// NRF24L01(CE,CSN)RF24NETWORK网络(无线电);//在网络中包含无线电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。定义伺服电机后,在回路部分,使用while()回路和available()函数不断检查是否有任何传入数据。如果为真,我们将创建一个网络报头,通过它接收数据,并创建一个变量存储数据。然后使用read()函数读取数据,并将其存储到incomingData变量中。最后,我们利用这些数据来根据电位器从另一个节点移动伺服电机。
Arduino无线网络具有多个NRF24L01模块
在理解了这个示例之后,我们可以继续学习本教程的主要示例,并构建一个由5个Arduinos相互通信的无线网络。这是这个例子的框图。
因此,使用电位器,使用电位器,我们将在节点01上控制伺服电机,用第二电位计我们将在节点022上控制LED,使用该按钮,我们将在节点012上控制LED,并在此处控制LED基座将在节点02处使用电位器控制。还使用节点012处的红外传感器,我们将在节点01上控制LED。因此,我们可以注意到该示例说明如何同时发送和接收数据,以及如何与来自不同分支的节点通信。让我们来看看Arduino代码。
基础00源代码
/ * Arduino无线网络 - 多个NRF24L01教程== Base / Master节点00 == by Dejan,www.www.mfxpo.com库:nrf24 /bet188官方网站 rf24,https://github.com/nrf24/rf24 nrf24 / rf24network,https://github.com/nrf24/rf24network * / #include#include #include #define按钮2 #define LED 3 RF24收音机(10,9);// NRF24L01(CE,CSN)RF24NETWORK网络(无线电);//在网络中包含无线电uint16_t this_node = 00;//以八进制格式(04,031,等)的此节点的地址(04,031,等)CONSS UINT16_T NODE01 = 01;//以八进制格式的其他节点的地址const16_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 }
因此,在基节点或主节点上,我们需要定义库和前面解释的对象,并定义主节点将向其发送数据的所有其他节点。在循环部分中,我们首先不断检查是否有任何传入的数据。如果是,我们读取数据,将其存储到传入的data变量中,并使用它来控制LED亮度。这个数据实际上来自于节点02的电位器。如果我们看一下它的代码,我们可以注意到设置几乎是相同的。重要的是给我们想要发送数据的地方分配正确的地址。在这种情况下,这是主00。所以读取电位器的值并将其转换为合适的0到255的PWM值后,我们将此数据发送给主机。我们可以注意到这里我使用了millis()函数以10毫秒为间隔发送数据。
节点02源代码
/ * arduino无线网络 - 多个nrf24l01教程==节点02(主节点00的子节点)== * / #include#include #include rf24收音机(10,9);// NRF24L01(CE,CSN)RF24NETWORK网络(无线电);//在网络中包含无线电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网络(无线电);//在网络中包含无线电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的红外传感器。
节点012源代码
/ * Arduino无线网络 - 多个NRF24L01教程==节点012(节点02的子节点)== * / #include#include #include #define LED 2 #defineIR 3 RF24收音机(10,9);// NRF24L01(CE,CSN)RF24NETWORK网络(无线电);//包括网络中的无线电常量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(LED,输出); 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网络(无线电);//在网络中包含无线电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的功率约为1/10,这在电池或太阳能设置中是重要的,只要您使用低功耗微控制器。
你好,人们......是的 - 我想我必须同意...... 8266的功耗通过比较真的很大......
感谢Dejan ......我真的很感激你的努力......
请继续! !
嗨如何发布机制,首先,令人敬畏!
你能在7:40之前解释原因我们必须写出标题。从节点12接收信息吗?(我实际上有5个在船长中获得5个信息,但无法理解您使用的数字背后的逻辑)。
非常感谢你的视频,这太棒了!
嘿,谢谢!老实说,我不太清楚为什么会这样。我看了一下代码,它应该是12,因为我们从那个节点接收数据。可能是打错字了。
因为八进制的12是十进制的10
是的,我得到了它。谢谢!
if (header.from_node == 0){//如果数据来自Node 02 . if (header.from_node == 0)
应该是节点00
if(header.from_node == 10){//如果数据来自节点012
12月12日= 12月10日
你好,
很好地完成了!我有一个问题,我需要做什么,才能在同一时间将同一个信号发送给多个接收器?
嘿,谢谢!您可以在Base 00示例代码中看到这种情况。您只需要创建具有特定地址的不同头文件,然后使用write函数将相同的数据发送到所有头文件。
你好,我正在尝试为我的项目实现这段代码。
我正在建立风和太阳能的无线能表。使用2个发射器和一个接收器。我不完全了解代码。
但是您用于发送的代码可以用于从2个传感器发送数据?
一个传感器表示安培一个传感器表示伏特?(在同一发射机上)
嘿,是的,您可以将数据从两个传感器发送到接收器。您只需使用写入功能两次,或者在这种情况下制作具有多个变量的数据包,两个传感器的值。检查我的DIY Arduino基RC发射器,以便在单个数据包中发送多个变量的这样的示例。
这是一个非常酷的项目。我实现它读取40个节点,它工作得很好。谢谢你!
你好卡洛斯,
据我所知,NRF24可以同时连接最多6个节点。您是否可以帮助分享您关于如何实施40个节点的经验?
您的网站非常好,解释非常细。谢谢
谢谢!
嗨,德扬,
首先感谢您的网站,我学到了这么多!我正在计划一个项目,我可以用一个控制器控制两个RC车辆(与DIY Arduino RC发射器项目相同)。有没有办法通过使用物理开关在它们之间进行选择,单独与每个接收器交谈?例如,当交换机是一种方式时,它与车辆A交谈时,当它交换到车辆B时,它仍然是一个新的新手,所以任何帮助都会非常感激
嘿,詹姆斯,谢谢!你可以这样做。使用本教程中解释的方法,我们可以选择要交谈的节点,我们只需要设置适当的地址。你可以用一个简单的开关来改变地址。例如,交换机主用或高用时,设置地址01;交换机非主用或低用时,设置地址02。
非常好的工作。由于我的残疾,我最近被迫退休,这些教程很棒。我手上有很多时间,我很欣赏你是如何把事情放在外面,易于遵循和精确。
我一个,欣赏你。
达雷雷尔
我很高兴你觉得它们有用。享受学习新事物的乐趣!
德州,
谢谢你的教程。大量的信息和恰到好处的数量让你思考正在发生的事情。你的多个例子对我来说非常有效。然后我稍微修改了一下,很高兴看到子节点不充当从主节点到孙子节点的传递节点,而是重新传输,允许您有效地扩展nRF24L01的范围。这将是特别有用的,因为我一直在寻找一种方式,以传输数据从我们的树林的一个角落到另一个大约1公里的距离。此外,通过网络进行双向通信比旧的“openReadingPipe, stopListening”等方法简单得多。有趣的是,我发现我不能让一个I2C OLED (Adafruit库)在接收节点上工作,但一个I2C LED可以工作。然而,同样的OLED在标准的nRF24L01应用程序中工作得很好。
你好,
这是一个非常酷的项目。良好的工作。谢谢你的所有教程。
我现在也尝试做同样的项目,而是用不同的传感器。传感器将安装在机器上,我想在我的电脑上创建一个GUI,我可以在工作时监视机器,并在其衡量的所有参数上显示所有参数。
所以我的问题是,如果我可以在相当快的时间内同时阅读和传输所有数据,以便我可以整个工作时间监控机器。
谢谢。
嘿,谢谢。好吧,我认为你应该能够做到这一点,尽管我不太确定你需要的速度以及你需要的速度。干杯!
佩德罗·伯克斯,
不错的工作,学习了很多,希望你继续前进,爱你的网站。