Een robuust Arduino draadloos mesh-netwerk bouwen met NRF24L01-modules
In deze tutorial leer je hoe je een Arduino draadloos netwerk bouwt, samengesteld uit meerdere NRF24L01 transceiver-modules. Je kunt de volgende video bekijken of de geschreven tutorial hieronder lezen.
Overzicht
Als voorbeeld heb ik een netwerk van 5 knooppunten gemaakt en elk van hen kan communiceren met elk ander knooppunt in het netwerk en tegelijkertijd fungeren ze zowel als zender als ontvanger. Dit voorbeeld is eigenlijk zo opgezet dat het uitlegt hoe je een veel groter netwerk kunt maken, of om precies te zijn, we kunnen in totaal 3125 modules met elkaar laten communiceren op een enkele RF-kanaal. Laten we eens kijken hoe het werkt.

In mijn vorige tutorials hebben we al geleerd hoe je draadloze communicatie maakt tussen twee Arduino-boards met de NRF24L01-modules en de RF24-bibliotheek. Nu gaan we naast deze bibliotheek ook de RF24Network-bibliotheek gebruiken, die het op een eenvoudige manier mogelijk maakt om een Arduino draadloos netwerk te bouwen met veel boards die met elkaar communiceren. Hier is hoe de netwerktopologie werkt.
Communicatie met meerdere NRF24L01-modules
Een enkele NRF24L01-module kan actief luisteren naar maximaal 6 andere modules tegelijkertijd.

Deze mogelijkheid wordt door de RF24Network-bibliotheek benut om een netwerk te genereren in een boomtopologie, waarbij één knooppunt de basis is en alle andere knooppunten kinderen zijn van die basis of van een ander knooppunt. Elk knooppunt kan maximaal 5 kinderen hebben, en dit kan 5 dieptes diep gaan, wat betekent dat we een netwerk van in totaal 3125 knooppunten kunnen creëren. Elk knooppunt moet worden gedefinieerd met een 15-bits adres, wat de positie van het knooppunt in de boom precies beschrijft.

We kunnen de adressen van de knooppunten eigenlijk in octaal formaat definiëren. Het adres van de master of basis is 00, de kinderen van de basis hebben adressen 01 tot 05, de kinderen van knooppunt 01 hebben adressen 011 tot 051, enzovoort.
Let op dat als knooppunt 011 wil communiceren met knooppunt 02, de communicatie moet gaan via knooppunt 01 en de basisknooppunt 00, dus deze twee knooppunten moeten constant actief zijn voor succesvolle communicatie.

Arduino draadloze servomotor besturing met de RF24Network-bibliotheek
Voordat we het hoofdvoorbeeld van deze tutorial uitleggen, laten we voor een beter begrip van de bibliotheek eerst een eenvoudiger voorbeeld maken van twee Arduino-boards die met elkaar communiceren. Hier is het schakelschema voor dit voorbeeld.

Je kunt de benodigde componenten voor deze Arduino-tutorial via de onderstaande links verkrijgen:
- NRF24L01 Transceiver Module
- Servomotor
- Potentiometer
- Arduino Nano
Met de potentiometer aan de eerste Arduino zullen we de servomotor aan de tweede Arduino besturen. Laten we kijken naar de broncodes.
Code aan de potentiometer-kant (Knooppunt 00)
/* Arduino Draadloos Netwerk - Meerdere NRF24L01 Tutorial == Voorbeeld 01 - Servo Besturing / Knooppunt 00 - Potentiometer == by Dejan, www.HowToMechatronics.com Bibliotheken: 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); // Neem de radio op in het netwerk
const uint16_t this_node = 00; // Adres van dit knooppunt in Octaal formaat (04, 031, etc)
const uint16_t node01 = 01;
void setup() {
SPI.begin();
radio.begin();
network.begin(90, this_node); //(kanaal, knooppuntadres)
}
void loop() {
network.update();
unsigned long potValue = analogRead(A0); // Lees de potentiometerwaarde
unsigned long angleValue = map(potValue, 0, 1023, 0, 180); // Converteer naar 0-180 voor servo
RF24NetworkHeader header(node01); // (Adres waar de data naartoe gaat)
bool ok = network.write(header, &angleValue, sizeof(angleValue)); // Verstuur de data
}
Eerst moeten we beide bibliotheken RF24 en RF24Network includeren, evenals de SPI-bibliotheek. Vervolgens maken we het RF24-object en nemen we het op in het RF24Network-object. Hier definiëren we de adressen van de knooppunten in octaal formaat: 00 voor dit knooppunt en 01 voor het andere knooppunt aan de servo-kant.
In de setup initialiseren we het netwerk door het kanaal en het adres van dit knooppunt in te stellen.
In de loop roepen we constant de update()-functie aan, waardoor alle acties in het netwerk gebeuren. Vervolgens lezen we de potentiometerwaarde en converteren deze naar een waarde van 0 tot 180, geschikt voor servobesturing. Dan maken we een netwerkheader waar we het adres van het doelknooppunt toewijzen. Ten slotte versturen we de data met de write()-functie. De eerste parameter bevat de adresinformatie, de tweede wijst naar de te versturen data, en de derde is de grootte van de data.
Code aan de servo-kant (Knooppunt 01)
/* Arduino Draadloos Netwerk - Meerdere NRF24L01 Tutorial == Voorbeeld 01 - Servo Besturing / Knooppunt 01 - Servomotor == */
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>
#include <Servo.h>
RF24 radio(10, 9); // nRF24L01 (CE,CSN)
RF24Network network(radio); // Neem de radio op in het netwerk
const uint16_t this_node = 01; // Adres van ons knooppunt in Octaal formaat
Servo myservo; // Maak servo-object aan
void setup() {
SPI.begin();
radio.begin();
network.begin(90, this_node); //(kanaal, knooppuntadres)
myservo.attach(3); // (servo pin)
}
void loop() {
network.update();
while (network.available()) { // Is er binnenkomende data?
RF24NetworkHeader header;
unsigned long incomingData;
network.read(header, &incomingData, sizeof(incomingData)); // Lees binnenkomende data
myservo.write(incomingData); // Beweeg servo naar de hoek
}
}
Aan de servokant definiëren we de bibliotheken en objecten op dezelfde manier. Het adres van dit knooppunt in octaal formaat is 01. Na het definiëren van de servomotor controleren we in de loop met de while()-lus en de available()-functie constant of er binnenkomende data is. Als dat zo is, maken we een netwerkheader en een variabele om de data op te slaan. Met de read()-functie lezen we de data en slaan we deze op in incomingData. Ten slotte gebruiken we deze data om de servomotor te bewegen volgens de potentiometer van het andere knooppunt.
Arduino draadloos netwerk met meerdere NRF24L01-modules
Na dit voorbeeld te begrijpen, kunnen we verdergaan met het hoofdvoorbeeld en een draadloos netwerk van 5 Arduinos bouwen die met elkaar communiceren. Hier is een blokdiagram van het voorbeeld.

Vanaf de basis besturen we met een potentiometer de servomotor op knooppunt 01, met een tweede potentiometer de LEDs op knooppunt 022, met de knop de LED op knooppunt 012, en de LED op de basis wordt bestuurd door de potentiometer op knooppunt 02. Ook besturen we met de infraroodsensor op knooppunt 012 de LED op knooppunt 01. We zien dat dit voorbeeld laat zien hoe je tegelijkertijd kunt zenden en ontvangen, en hoe je kunt communiceren met knooppunten uit verschillende takken. Laten we kijken naar de Arduino-codes.
Gerelateerd: DIY Arduino RC-zender
Basis 00 broncode
/* Arduino Draadloos Netwerk - Meerdere NRF24L01 Tutorial == Basis/Master Knooppunt 00 == by Dejan, www.HowToMechatronics.com Bibliotheken: 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); // Neem de radio op in het netwerk
const uint16_t this_node = 00; // Adres van dit knooppunt in Octaal formaat
const uint16_t node01 = 01; // Adres van het andere knooppunt in Octaal formaat
const uint16_t node012 = 012;
const uint16_t node022 = 022;
void setup() {
SPI.begin();
radio.begin();
network.begin(90, this_node); //(kanaal, knooppuntadres)
radio.setDataRate(RF24_2MBPS);
pinMode(button, INPUT_PULLUP);
pinMode(led, OUTPUT);
}
void loop() {
network.update();
//===== Ontvangen =====//
while (network.available()) {
RF24NetworkHeader header;
unsigned long incomingData;
network.read(header, &incomingData, sizeof(incomingData));
analogWrite(led, incomingData); // PWM uitgang naar LED 01 (dimmen)
}
//===== Versturen =====//
// Servo besturing op Knooppunt 01
unsigned long potValue = analogRead(A0);
unsigned long angleValue = map(potValue, 0, 1023, 0, 180);
RF24NetworkHeader header2(node01);
bool ok = network.write(header2, &angleValue, sizeof(angleValue));
// LED besturing op Knooppunt 012
unsigned long buttonState = digitalRead(button);
RF24NetworkHeader header4(node012);
bool ok3 = network.write(header4, &buttonState, sizeof(buttonState));
// LEDs besturing op Knooppunt 022
unsigned long pot2Value = analogRead(A1);
RF24NetworkHeader header3(node022);
bool ok2 = network.write(header3, &pot2Value, sizeof(pot2Value));
}
Op de basis of master-knooppunt definiëren we de bibliotheken en objecten zoals uitgelegd, en ook alle andere knooppunten waarnaar de master data zal sturen. In de loop controleren we constant of er binnenkomende data is. Zo ja, lezen we de data en gebruiken we deze om de LED-helderheid te besturen. Deze data komt van de potentiometer van knooppunt 02. Als we naar de code van knooppunt 02 kijken, is de setup vrijwel hetzelfde. Het belangrijkte is het juiste adres toewijzen waar we data naartoe willen sturen, in dit geval de master 00. Na het lezen van de potentiometerwaarde en omzetten naar een geschikte PWM-waarde (0-255), sturen we deze naar de master. Let op dat ik de millis()-functie gebruik om de data op intervallen van 10 milliseconden te versturen.
Knooppunt 02 broncode
/* Arduino Draadloos Netwerk - Meerdere NRF24L01 Tutorial == Knooppunt 02 (Kind van Master knooppunt 00) == */
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
RF24 radio(10, 9); // nRF24L01 (CE,CSN)
RF24Network network(radio); // Neem de radio op in het netwerk
const uint16_t this_node = 02; // Adres van ons knooppunt in Octaal formaat
const uint16_t master00 = 00; // Adres van het andere knooppunt in Octaal formaat
const unsigned long interval = 10; //ms - Hoe vaak data versturen
unsigned long last_sent; // Wanneer hebben we laatst verstuurd?
void setup() {
SPI.begin();
radio.begin();
network.begin(90, this_node); //(kanaal, knooppuntadres)
radio.setDataRate(RF24_2MBPS);
}
void loop() {
network.update();
//===== Versturen =====//
unsigned long now = millis();
if (now - last_sent >= interval) {
last_sent = now;
unsigned long potValue = analogRead(A0);
unsigned long ledBrightness = map(potValue, 0, 1023, 0, 255);
RF24NetworkHeader header(master00);
bool ok = network.write(header, &ledBrightness, sizeof(ledBrightness));
}
}
Vanaf de master sturen we de potentiometerdata naar knooppunt 01 voor de servobesturing.
Knooppunt 01 broncode
/* Arduino Draadloos Netwerk - Meerdere NRF24L01 Tutorial == Knooppunt 01 (Kind van Master knooppunt 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);
const uint16_t this_node = 01;
const uint16_t master00 = 00;
Servo myservo;
void setup() {
SPI.begin();
radio.begin();
network.begin(90, this_node);
radio.setDataRate(RF24_2MBPS);
myservo.attach(3);
pinMode(led, OUTPUT);
}
void loop() {
network.update();
//===== Ontvangen =====//
while (network.available()) {
RF24NetworkHeader header;
unsigned long incomingData;
network.read(header, &incomingData, sizeof(incomingData));
if (header.from_node == 0) { // Data komt van Master (knooppunt 00)
myservo.write(incomingData);
}
if (header.from_node == 10) { // Data komt van Knooppunt 012 (octaal 012 = decimaal 10)
digitalWrite(led, !incomingData);
}
}
}
Knooppunt 01 ontvangt data van twee verschillende knooppunten: één voor servobesturing en de andere voor LED-besturing vanaf de infraroodsensor van knooppunt 012. We gebruiken het header.from_node-attribuut om te bepalen van welk knooppunt de data afkomstig is. Bij data van de master besturen we de servo, bij data van knooppunt 012 besturen we de LED.
Knooppunt 012 broncode
/* Arduino Draadloos Netwerk - Meerdere NRF24L01 Tutorial == Knooppunt 012 (kind van Knooppunt 01) == */
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#define led 2
#define IR 3
RF24 radio(10, 9);
RF24Network network(radio);
const uint16_t this_node = 012;
const uint16_t node01 = 01;
void setup() {
SPI.begin();
radio.begin();
network.begin(90, this_node);
radio.setDataRate(RF24_2MBPS);
pinMode(led, OUTPUT);
pinMode(IR, INPUT);
}
void loop() {
network.update();
//===== Ontvangen =====//
while (network.available()) {
RF24NetworkHeader header;
unsigned long buttonState;
network.read(header, &buttonState, sizeof(buttonState));
digitalWrite(led, !buttonState);
}
//===== Versturen =====//
unsigned long irV = digitalRead(IR);
RF24NetworkHeader header8(node01);
bool ok = network.write(header8, &irV, sizeof(irV));
}
Op knooppunt 012 zitten zowel zenden als ontvangen. De infraroodsensor bestuurt de LED op knooppunt 01 en de LED hier wordt bestuurd door de knop op de master.
Knooppunt 022 broncode
/* Arduino Draadloos Netwerk - Meerdere NRF24L01 Tutorial == Knooppunt 022 (kind van Knooppunt 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);
RF24Network network(radio);
const uint16_t this_node = 022;
const uint16_t master00 = 00;
void setup() {
SPI.begin();
radio.begin();
network.begin(90, this_node);
radio.setDataRate(RF24_2MBPS);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
}
void loop() {
network.update();
//===== Ontvangen =====//
while (network.available()) {
RF24NetworkHeader header;
unsigned long potValue;
network.read(header, &potValue, sizeof(potValue));
// Zet LEDs aan afhankelijk van inkomende waarde van 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);
}
}
Tot slot worden de LEDs op knooppunt 022 bestuurd met de data van de andere potentiometer op de master.
Kortom, als alles correct is aangesloten en alle knooppunten constant actief zijn, komt ons werk neer op het precies adresseren van de knooppunten; al het zware werk wordt gedaan door de geweldige RF24Network-bibliotheek.
Dat was het voor deze Arduino-tutorial. Ik hoop dat je ervan hebt genoten en iets nieuws hebt geleerd. Stel gerust vragen in de reacties hieronder.
Productieproces
- Een Betaalbaar Draadloos Sensornetwerk Bouwen voor Uw Huis
- Bouw een Raspberry Pi Cijferherkenner met TensorFlow en OpenCV
- Arduino Draadloze Magnetische Dataoverdracht met Infineon 3D-Sensor
- K30 CO2-sensor: Real-time binnenluchtkwaliteitmonitoring met Arduino
- Communicatie voor doofblinden vergemakkelijken met 1Sheeld en Arduino
- Slimme spaarpot bouwen: Muntenacceptor besturen met Arduino Nano
- Een LED bedienen via Bluetooth met Arduino – Eenvoudige DIY Handleiding
- Een DFRobot Capacitieve Vingerafdruksensor integreren met Arduino of ESP8266
- USB-BLE Draadloze MIDI Adapters – Naadloze Connectiviteit voor Musici
- Interactief Nextion HMI-weerstation met Arduino Mega en sensoren
- Arduino-gebaseerde 6-DoF Robotarm Gestoeerd met Wii Nunchuk