Optimized high speed nRF24L01+ driver class documentation v1.4.8
TMRh20 2020 - Optimized fork of the nRF24L01+ driver
Loading...
Searching...
No Matches
examples/MulticeiverDemo/MulticeiverDemo.ino

Written by 2bndy5 in 2020

A simple example of sending data from as many as 6 nRF24L01 transceivers to 1 receiving transceiver. This technique is trademarked by Nordic Semiconductors as "MultiCeiver".

This example was written to be used on up to 6 devices acting as TX nodes & only 1 device acting as the RX node (that's a maximum of 7 devices). Use the Serial Monitor to change each node's behavior.

1/*
2 * See documentation at https://nRF24.github.io/RF24
3 * See License information at root directory of this library
4 * Author: Brendan Doherty 2bndy5
5 */
6
16#include <SPI.h>
17#include "printf.h"
18#include "RF24.h"
19
20#define CE_PIN 7
21#define CSN_PIN 8
22// instantiate an object for the nRF24L01 transceiver
23RF24 radio(CE_PIN, CSN_PIN);
24
25// For this example, we'll be using 6 addresses; 1 for each TX node
26// It is very helpful to think of an address as a path instead of as
27// an identifying device destination
28// Notice that the last byte is the only byte that changes in the last 5
29// addresses. This is a limitation of the nRF24L01 transceiver for pipes 2-5
30// because they use the same first 4 bytes from pipe 1.
31uint64_t address[6] = { 0x7878787878LL,
32 0xB3B4B5B6F1LL,
33 0xB3B4B5B6CDLL,
34 0xB3B4B5B6A3LL,
35 0xB3B4B5B60FLL,
36 0xB3B4B5B605LL };
37
38// Because this example allow up to 6 nodes (specified by numbers 0-5) to
39// transmit and only 1 node to receive, we will use a negative value in our
40// role variable to signify this node is a receiver.
41// role variable is used to control whether this node is sending or receiving
42char role = 'R'; // integers 0-5 = TX node; character 'R' or integer 82 = RX node
43
44// For this example, we'll be using a payload containing
45// a node ID number and a single integer number that will be incremented
46// on every successful transmission.
47// Make a data structure to use as a payload.
48struct PayloadStruct {
49 unsigned long nodeID;
50 unsigned long payloadID;
51};
52PayloadStruct payload;
53
54// This example uses all 6 pipes to receive while TX nodes only use 2 pipes
55// To make this easier we'll use a function to manage the addresses, and the
56// payload's nodeID
57void setRole(); // declare a prototype; definition is found after the loop()
58
59void setup() {
60
61 Serial.begin(115200);
62 while (!Serial) {
63 // some boards need to wait to ensure access to serial over USB
64 }
65
66 // initialize the transceiver on the SPI bus
67 if (!radio.begin()) {
68 Serial.println(F("radio hardware is not responding!!"));
69 while (1) {} // hold in infinite loop
70 }
71
72 // print example's introductory prompt
73 Serial.println(F("RF24/examples/MulticeiverDemo"));
74 Serial.println(F("*** Enter a number between 0 and 5 (inclusive) to change"));
75 Serial.println(F(" the identifying node number that transmits."));
76
77 // Set the PA Level low to try preventing power supply related problems
78 // because these examples are likely run with nodes in close proximity of
79 // each other.
80 radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
81
82 // save on transmission time by setting the radio to only transmit the
83 // number of bytes we need to transmit a float
84 radio.setPayloadSize(sizeof(payload)); // 2x int datatype occupy 8 bytes
85
86 // Set the pipe addresses accordingly. This function additionally also
87 // calls startListening() or stopListening() and sets the payload's nodeID
88 setRole();
89
90 // For debugging info
91 // printf_begin(); // needed only once for printing details
92 // radio.printDetails(); // (smaller) function that prints raw register values
93 // radio.printPrettyDetails(); // (larger) function that prints human readable data
94
95} // setup()
96
97void loop() {
98
99 if (role <= 53) {
100 // This device is a TX node
101
102 unsigned long start_timer = micros(); // start the timer
103 bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report
104 unsigned long end_timer = micros(); // end the timer
105
106 if (report) {
107 // payload was delivered
108
109 Serial.print(F("Transmission of payloadID "));
110 Serial.print(payload.payloadID); // print payloadID
111 Serial.print(F(" as node "));
112 Serial.print(payload.nodeID); // print nodeID
113 Serial.print(F(" successful!"));
114 Serial.print(F(" Time to transmit: "));
115 Serial.print(end_timer - start_timer); // print the timer result
116 Serial.println(F(" us"));
117 } else {
118 Serial.println(F("Transmission failed or timed out")); // payload was not delivered
119 }
120 payload.payloadID++; // increment payload number
121
122 // to make this example readable in the serial monitor
123 delay(1000); // slow transmissions down by 1 second
124
125 } else if (role == 'R') {
126 // This device is the RX node
127
128 uint8_t pipe;
129 if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
130 uint8_t bytes = radio.getPayloadSize(); // get the size of the payload
131 radio.read(&payload, bytes); // fetch payload from FIFO
132 Serial.print(F("Received "));
133 Serial.print(bytes); // print the size of the payload
134 Serial.print(F(" bytes on pipe "));
135 Serial.print(pipe); // print the pipe number
136 Serial.print(F(" from node "));
137 Serial.print(payload.nodeID); // print the payload's origin
138 Serial.print(F(". PayloadID: "));
139 Serial.println(payload.payloadID); // print the payload's number
140 }
141 } // role
142
143 if (Serial.available()) {
144 // change the role via the serial monitor
145
146 char c = Serial.read();
147 if (toupper(c) == 'R' && role <= 53) {
148 // Become the RX node
149
150 role = 'R';
151 Serial.println(F("*** CHANGING ROLE TO RECEIVER ***"));
152 Serial.println(F("--- Enter a number between 0 and 5 (inclusive) to act as"));
153 Serial.println(F(" a unique node number that transmits to the RX node."));
154 setRole(); // change address on all pipes to TX nodes
155
156 } else if (c >= 48 && c <= 53 && c != role) {
157 // Become a TX node with identifier 'c'
158
159 role = c - 48;
160 Serial.print(F("*** CHANGING ROLE TO NODE "));
161 Serial.print(c);
162 Serial.println(F(" ***"));
163 Serial.println(F("--- Enter a number between 0 and 5 (inclusive) to change"));
164 Serial.println(F(" the identifying node number that transmits."));
165 Serial.println(F("--- PRESS 'R' to act as the RX node."));
166 setRole(); // change address on pipe 0 to the RX node
167 }
168 }
169
170} // loop
171
172void setRole() {
173 if (role == 'R') {
174 // For the RX node
175
176 // Set the addresses for all pipes to TX nodes
177 for (uint8_t i = 0; i < 6; ++i)
178 radio.openReadingPipe(i, address[i]);
179
180 radio.startListening(); // put radio in RX mode
181
182 } else {
183 // For the TX node
184
185 // set the payload's nodeID & reset the payload's identifying number
186 payload.nodeID = role;
187 payload.payloadID = 0;
188
189 // Set the address on pipe 0 to the RX node.
190 radio.stopListening(); // put radio in TX mode
191 radio.openWritingPipe(address[role]);
192
193 // According to the datasheet, the auto-retry features's delay value should
194 // be "skewed" to allow the RX node to receive 1 transmission at a time.
195 // So, use varying delay between retry attempts and 15 (at most) retry attempts
196 radio.setRetries(((role * 3) % 12) + 3, 15); // maximum value is 15 for both args
197 }
198} // setRole
Driver class for nRF24L01(+) 2.4GHz Wireless Transceiver.
Definition: RF24.h:116
@ RF24_PA_LOW
Definition: RF24.h:50
#define delay(milisec)