Arduino无线网络具有多个NRF24L01模块

在本教程中,我们将学习如何构建一个Arduino无线网络,由多个NR24L01收发模块组成。你可以观看下面的视频或阅读下面的书面教程。

概述

作为示例,我制作了5个节点的网络,并且它们中的每一个可以与网络中的任何节点通信,同时它们可以作为发射器和接收器的工作。实际上以一种方式设置了该示例,该方法解释了如何制作更大的网络,或者精确,我们可以在单个RF信道上共互相通信3125个模块。所以让我们来看看它是如何工作的。亚博88下载

在我以前的教程中,我们已经学过了如何进行无线通信使用NRF24L01模块和RF24库之间的两个Arduino板之间。现在除了这个图书馆,我们将使用RF24Network库,它可以以一种简单的方式构建一个Arduino无线网络,多个板相互通信。下面是网络拓扑结构的工作原理。

一个NRF24L01模块可以同时主动侦听多达6个其他模块。

NRF24L01可以同时收听最多6个其他模块

RF24Network库利用这种能力来生成排列在树状拓扑结构中的网络,其中一个节点是基础节点,而所有其他节点都是该节点或另一个节点的子节点。每个节点最多可以有5个子节点,这可以深入5层,这意味着我们可以创建一个总共3125个节点的网络。每个节点都必须定义一个15位地址,它精确地描述了节点在树中的位置。

树状拓扑无线网络

我们实际上可以用八进制格式定义节点的地址。因此,主节点或基节点的地址是00,基子节点地址是01到05,01节点子节点地址是011到051,以此类推。

注意,如果节点011想要与节点02通信,则通信必须经过节点01和基本节点00,因此这两个节点必须一直处于活动状态,才能成功通信。

Arduino无线伺服电机控制使用rf24网络库

在我们解释本教程的主要示例之前,为了更好地理解库的工作原理,让我们做一个简单的示例,两个Arduino板相互通信。这是这个例子的电路图。

Arduino无线伺服电机控制电路图。png

你可以从下面的链接获得这个Arduino教程所需的组件:

yaboAG娱乐城披露:这些是联盟链接。作为亚马逊助理,我从合格购买中获得。

所以我们用第一个Arduino上的电位器来控制第二个Arduino上的伺服电机。现在让我们看一下源代码。

这里是电位器端的代码:

/ * Arduino无线网络——多个NRF24L01教程= =例子00 - 01 -伺服控制/节点电位计,德扬= = www.HowToMechatronics.com库:nRF24 / RF24, https://github.com/nRF24/RF24亚搏手机版官方下载 nRF24 / RF24Network, https://github.com/nRF24/RF24Network * / # include < RF24.h > # include < RF24Network.h > # include < SPI.h > RF24电台(10 9);// nRF24L01 (CE,CSN) RF24Network网络(无线);//在网络中包含广播const uint16_t this_node = 00;//该节点的八进制地址(04,031,etc) const uint16_t node01 = 01;void setup() {SPI.begin();radio.begin ();network.begin(90,this_node);//(channel, node address)} void loop() {network.update();无符号长potValue = analogRead(A0);//读取电位器的值unsigned long angleValue = map(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相互通信的无线网络。这是这个例子的框图。

Arduino-Wireless-Network-with-Multiple-NRF24L01-Modules

从基地,使用电位器我们将控制节点01的伺服电机,与第二个电位器控制发光二极管022节点,使用按钮012年我们将在节点控制LED和LED底部将使用电位器控制节点02。同样使用节点012的红外传感器,我们将控制节点01的LED。因此,我们可以注意到,这个示例解释了如何同时传输和接收数据,以及如何与来自不同分支的节点通信。现在我们来看看Arduino的代码。

有关的:DIY Arduino RC发射机

基数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网络(无线);//在网络中包含广播const uint16_t this_node = 00;//该节点的八进制地址(04,031,etc) 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 }

因此,在基节点或主节点上,我们需要定义库和前面解释的对象,并定义主节点将向其发送数据的所有其他节点。在循环部分中,我们首先不断检查是否有任何传入的数据。如果是,我们读取数据,将其存储到传入的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,etc) const 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,etc) const 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(领导、输出); 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 Wireless Network - Multiple NRF24L01 Tutorial ==节点022(节点02的子节点)== */ #include  #include  #include  #define led1 2 #define led2 3 #define led3 4 #define led4 5 RF24 radio(10, 9);// nRF24L01 (CE,CSN) RF24Network网络(无线);//在网络中包含广播const uint16_t this_node = 022;//我们的节点地址的八进制格式(04,031,etc) const uint16_t master00 = 00;//另一个节点的八进制地址void setup() {SPI.begin();radio.begin ();network.begin(90,this_node);//(信道,节点地址)radio.setDataRate(RF24_2MBPS);pinMode (led1、输出);pinMode (led2、输出); 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项目并学会了新的东西。随意询问以下意见部分中的任何问题。

25回应

  1. 莎莎Banovic

    你好,

    这是一个有趣的项目。我有个问题,为什么你选择使用nRF24网络,而不是ESP模块和无线网络?

    我计划一个相似的系统,主要用于控制(小载荷),我选择MQTT的主要协议,因为无线网络可用带宽,但是大多数的传感器可以做他们的工作通过发送几个整数和其他人可以使用蓝牙额外流(音频),所以我不需要无线网络,除非在用户界面节点上有一个web服务器控制和配置访问(可能是树莓派,在它的情况下,它将是以太网连接)。对nRF的担忧是,除了配对序列作为确认的一部分,并希望没有人能猜出有效载荷的内容和结构之外,没有那么多提高安全性的选择。

    回复
    • 德扬

      谢谢!这只是一个教程,解释如何使用nRF24网络,以防有人想使用它。我没有和其他方法做过任何详细的比较,所以我不能告诉你太多。

      回复
    • 安东尼球

      我认为使用NRF最常见的原因是,它使用的功率大约是esp8266的十分之一,这在电池或太阳能设置中是很重要的,只要你使用低功率的微控制器。

      回复
      • 斯宾塞

        大家好,我想我必须同意,相比之下,8266的能耗真的很大。
        谢谢- Dejan,我真的很感谢你的努力。
        请继续! !

  2. Alex Pasz.

    嗨如何发布机制,首先,令人敬畏!
    你能在7:40之前解释原因我们必须写出标题。从节点12接收信息吗?(我实际上有5个在船长中获得5个信息,但无法理解您使用的数字背后的逻辑)。
    非常感谢你的视频,这太棒了!

    回复
    • 德扬

      嘿,谢谢!老实说,我不太清楚为什么会这样。我看了一下代码,它应该是12,因为我们从那个节点接收数据。可能是打错字了。

      回复
    • 卡洛斯·阿尔贝托·法拉利·梅鲁西

      因为八进制的12是十进制的10

      回复
  3. 一个

    if (header.from_node == 0){//如果数据来自Node 02 . if (header.from_node == 0)

    应该是节点00

    if (header.from_node == 10){//如果数据来自节点012 . if (header.from_node == 10)

    10月12日

    回复
  4. Mettdrescher.

    你好,

    很好地完成了!我有一个问题,我需要做什么,才能在同一时间将同一个信号发送给多个接收器?

    回复
    • 德扬

      嘿,谢谢!您可以在Base 00示例代码中看到这种情况。您只需要创建具有特定地址的不同头文件,然后使用write函数将相同的数据发送到所有头文件。

      回复
  5. 西蒙

    你好,我正在尝试为我的项目实现这段代码。
    我正在为风能和太阳能做一个无线电能表。使用两个发射器和一个接收器。我还不完全懂代码。
    但是你用来发送的代码,可以用来发送2个传感器的数据吗?
    一个传感器表示安培一个传感器表示伏特?(在同一发射机上)

    回复
    • 德扬

      是的,你可以把两个传感器的数据发送到接收器上。你只需要两次使用write函数,或者制作一个有多个变量的数据包,在这种情况下,来自两个传感器的值。检查我的DIY Arduino基于RC发射器,看看这样一个例子发送多个变量在一个单一的数据包。

      回复
  6. 卡洛斯·阿尔贝托·法拉利·梅鲁西

    这是一个非常酷的项目。我实现它读取40个节点,它工作得很好。谢谢你!

    回复
    • Truong Ngoc Cuong

      你好,卡洛斯,

      据我所知,NRF24只能同时连接6个节点。能否分享一下你的经验,关于如何实现40个节点?

      回复
  7. 詹姆斯·达菲

    嗨,德扬,
    首先感谢这个网站,我学到了很多!我正在计划一个项目,我可以用一个控制器控制两个RC车辆(很像DIY Arduino RC发射器项目)。是否有一种方法可以通过使用物理开关在他们之间进行选择来分别与每个接收方交谈?例如,当切换到一种方式时,它与车辆A对话,当切换到另一种方式时,它与车辆b对话。我仍然是一个新手,所以任何帮助都将非常感谢

    回复
    • 德扬

      嘿,詹姆斯,谢谢!你可以这样做。使用本教程中解释的方法,我们可以选择要交谈的节点,我们只需要设置适当的地址。你可以用一个简单的开关来改变地址。例如,交换机主用或高用时,设置地址01;交换机非主用或低用时,设置地址02。

      回复
  8. Darrel

    非常好的工作。由于我的残疾,我最近被迫退休,这些教程很棒。我手上有很多时间,我很欣赏你是如何把事情放在外面,易于遵循和精确。
    就我个人而言,我很感激你。
    Darrel

    回复
  9. 约翰L

    德扬,
    谢谢你的教程。大量的信息和恰到好处的数量让你思考正在发生的事情。你的多个例子对我来说非常有效。然后我稍微修改了一下,很高兴看到子节点不充当从主节点到孙子节点的传递节点,而是重新传输,允许您有效地扩展nRF24L01的范围。这将是特别有用的,因为我一直在寻找一种方式,以传输数据从我们的树林的一个角落到另一个大约1公里的距离。此外,通过网络进行双向通信比旧的“openReadingPipe, stopListening”等方法简单得多。有趣的是,我发现我不能让一个I2C OLED (Adafruit库)在接收节点上工作,但一个I2C LED可以工作。然而,同样的OLED在标准的nRF24L01应用程序中工作得很好。

    回复
  10. Hassen Romene.

    你好,
    这是一个非常酷的项目。良好的工作。谢谢你所有的指导。
    我现在也在尝试做同样的项目,但是用不同的传感器。传感器将被安装在机器上,我想在我的计算机上创建一个GUI,我可以监控机器,而它的工作和可视化的所有参数,我测量。
    所以我的问题是,如果我可以在相当快的时间内同时阅读和传输所有数据,以便我可以整个工作时间监控机器。
    谢谢。

    回复
    • 德扬

      嘿,谢谢。好吧,我认为你应该能够做到这一点,尽管我不太确定你需要的速度以及你需要的速度。干杯!

      回复
  11. 佩德罗·博伊斯

    佩德罗·伯克斯,

    不错的工作,学习了很多,希望你继续前进,爱你的网站。

    回复

留下一个回复

您的电子邮件地址不会被公开。

推荐

2019年最佳入门级示波器初学者和爱好者

初学者和爱好者最好的示波器

推荐

2019年最佳Arduino入门套件

8个最好的arduino初学者工具包

推荐

最佳3D打印机为初学者和爱好者- 3D打印

最好的3d打印机为初学者和爱好者