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

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

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

概览

作为一个例子,我制作了一个由 5 个节点组成的网络,每个节点都可以与网络中的任何节点通信,同时它们可以作为发送器和接收器工作。这个例子实际上是为了解释如何建立一个更大的网络,或者更准确地说,我们可以让总共 3125 个模块在一个 RF 通道上相互通信。那么让我们来看看它是如何工作的。

在我之前的教程中,我们已经学习了如何使用 NRF24L01 模块和 RF24 库在两个 Arduino 板之间进行无线通信。现在除了这个库之外,我们将使用 RF24Network 库,它可以轻松地构建一个 Arduino 无线网络,其中许多板相互通信。以下是网络拓扑的工作原理。

多个NRF24L01模块通信

单个NRF24L01模块最多可以同时主动监听6个其他模块。

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

我们实际上可以用八进制格式定义节点的地址。所以,master或base的地址是00,base children的地址是01到05,01节点的children地址是011到051等等。

请注意,如果节点011要与节点02通信,则必须通过节点01和基础节点00进行通信,因此这两个节点必须始终处于活动状态才能通信成功。

使用 RF24Network 库的 Arduino 无线伺服电机控制

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

您可以从以下链接获取本 Arduino 教程所需的组件:

  • NRF24L01 收发模块…………..
  • 伺服电机……………………………………
  • 电位器………………………………..
  • Arduino Nano………………………………..

因此,使用第一个 Arduino 上的电位器,我们将控制第二个 Arduino 上的伺服电机。现在让我们看一下源代码。

这是电位器端的代码:

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
 == Example 01 - Servo Control / Node 00 - Potentiometer ==
  by Dejan, www.HowToMechatronics.com
  Libraries:
  nRF24/RF24, https://github.com/nRF24/RF24
  nRF24/RF24Network, https://github.com/nRF24/RF24Network
*/
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 00;   // Address of this node in Octal format ( 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();
  unsigned long potValue = analogRead(A0);  // Read the potentiometer value
  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
}Code language: Arduino (arduino)

首先,我们需要包括库 RF24 和 RF24Network,以及 SPI 库。然后我们需要创建 RF24 对象,并将其包含到 RF24Network 对象中。这里我们需要用八进制格式定义节点的地址,或者00代表这个节点,01代表伺服侧的另一个节点。

在设置部分我们需要初始化网络,通过设置这个节点的通道和地址。

在循环部分,我们经常需要调用 update() 函数,网络中的所有动作都通过该函数发生。然后我们读取电位器的值并将其转换为适合伺服控制的 0 到 180 的值。然后我们创建一个网络头,我们在其中分配数据要去的节点的地址。最后,我们使用 write() 函数将数据发送到另一个节点。所以这里第一个参数包含地址信息,第二个参数指向要发送的数据,第三个参数是数据的大小。

伺服端的代码如下:

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
  == Example 01 - Servo Control / Node 01 - Servo motor ==
*/
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>
#include <Servo.h>

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 01;   // Address of our node in Octal format ( 04,031, etc)

Servo myservo;  // create servo object to control a servo

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node); //(channel, node address)
  myservo.attach(3);   // (servo pin)
}

void loop() {
  network.update();
  while ( network.available() ) {     // Is there any incoming data?
    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
  }
}Code language: Arduino (arduino)

另一方面,在伺服电机上,我们需要以与前面解释相同的方式定义库和对象。这里这个节点的八进制地址是01。在定义了伺服电机之后,在循环部分,使用while()循环和available()函数我们不断检查是否有任何传入数据。如果为真,我们将创建一个网络标头,通过该标头接受数据,以及一个用于存储数据的变量。然后使用 read() 函数读取数据,并将其存储到incomingData 变量中。最后我们使用这些数据根据来自另一个节点的电位器移动伺服电机。

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

在理解了这个例子之后,我们可以继续本教程的主要例子,并建立一个由 5 个 Arduino 相互通信的无线网络。这是示例的框图。

因此,从基础开始,使用电位器控制节点 01 处的伺服电机,使用第二个电位器控制节点 022 处的 LED,使用按钮控制节点 012 处的 LED,此处的 LED 位于基座将使用节点 02 处的电位器进行控制。同样使用节点 012 处的红外传感器,我们将控制节点 01 处的 LED。因此我们可以注意到,此示例说明了如何同时发送和接收数据,以及如何与来自不同分支的节点进行通信。现在让我们看一下Arduino代码。

相关:DIY Arduino RC 发射器

Base 00 源代码

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
          == Base/ Master Node 00==
  by Dejan, www.HowToMechatronics.com
  Libraries:
  nRF24/RF24, https://github.com/nRF24/RF24
  nRF24/RF24Network, https://github.com/nRF24/RF24Network
*/

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

#define button 2
#define led 3

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 00;   // Address of this node in Octal format ( 04,031, etc)
const uint16_t node01 = 01;      // Address of the other node in Octal format
const uint16_t node012 = 012;
const uint16_t node022 = 022;

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);  //(channel, node address)
  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
}Code language: Arduino (arduino)

因此,在基础节点或主节点上,我们需要定义库和对象,如前所述,并定义主节点将向其发送数据的所有其他节点。在循环部分,我们首先不断检查是否有任何传入数据。如果是这样,我们读取数据,将其存储到incomingData 变量中并使用它来控制LED 亮度。该数据实际上来自节点 02 的电位器。如果我们看一下它的代码,我们会发现设置几乎相同。重要的是为我们要发送数据的地方分配正确的地址。在这种情况下,就是主机 00。所以在读取电位器值并将其转换为 0 到 255 的合适 PWM 值后,我们将这个数据发送给主机。我们可以注意到这里我使用了millis()函数以10毫秒的间隔发送数据。

节点02源码

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
        == Node 02 (Child of Master node 00) ==    
*/

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 02;   // Address of our node in Octal format ( 04,031, etc)
const uint16_t master00 = 00;    // Address of the other node in Octal format

const unsigned long interval = 10;  //ms  // How often to send data to the other unit
unsigned long last_sent;            // When did we last send?

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
  }
}Code language: Arduino (arduino)

接下来,从主控端,我们将电位器数据发送到节点01,用于控制伺服电机。

节点01源码

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
        == Node 02 (Child of Master node 00) ==
*/

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <Servo.h>

#define led 2

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 01;   // Address of our node in Octal format ( 04,031, etc)
const uint16_t master00 = 00;    // Address of the other node in Octal format

Servo myservo;  // create servo object to control a servo

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node); //(channel, node address)
  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
    }
  }
}Code language: Arduino (arduino)

节点01实际上是从两个不同的节点接收数据,一个用于伺服控制,另一个用于LED控制,来自节点012的红外传感器。

节点012源代码

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
            == Node 012 (child of Node 02)==    
*/

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

#define led 2
#define IR 3

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 012;  // Address of our node in Octal format ( 04,031, etc)
const uint16_t node01 = 01;    // Address of the other node in Octal format

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);  //(channel, node address)
  radio.setDataRate(RF24_2MBPS);
  pinMode(led, OUTPUT);
  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
}Code language: Arduino (arduino)

在这种情况下,我们使用 header.from_node 属性来获取数据来自哪个节点的信息。如果传入的数据来自master,我们用它来控制舵机,如果传入的数据来自节点012,我们用它来控制LED。

在节点 012,我们既有发送又有接收。红外传感器控制前面提到的节点 01 的 LED,这里的 LED 是通过主机上的按钮控制的。

节点022源码

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
            == Node 022 (child of Node 02)==    
*/

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

#define led1 2
#define led2 3
#define led3 4
#define led4 5

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 022;  // Address of our node in Octal format ( 04,031, etc)
const uint16_t master00 = 00;    // Address of the other node in Octal format

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);  //(channel, node address)
  radio.setDataRate(RF24_2MBPS);
  pinMode(led1, OUTPUT);
  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);
    }
  }
}Code language: Arduino (arduino)

最后,节点 022 的 LED 使用来自主机上另一个电位器的数据进行控制。

因此,总而言之,如果一切都正确连接,并且所有节点始终处于活动状态,我们的工作归结为精确寻址节点,所有繁重的工作都由令人难以置信的 RF24Network 库执行。

这就是全部,我希望你喜欢这个 Arduino 项目并学到新的东西。欢迎在下方评论区提出任何问题。


制造工艺

  1. 在家中构建无线传感器网络
  2. 使用 PiCamera 进行 AI 数字识别
  3. 无线磁性数据传输
  4. 使用 K30 传感器监测二氧化碳
  5. 聋盲通信与 1Sheeld/Arduino
  6. 使用 Arduino 控制硬币接收器
  7. Arduino 带蓝牙控制 LED!
  8. 带有 Arduino 或 ESP8266 的电容式指纹传感器
  9. USB-BLE 无线 MIDI 适配器
  10. 玩 Nextion Display
  11. Nunchuk 控制机械臂(使用 Arduino)
  12. 无线灯开关操纵器