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

Written by 2bndy5 in 2020

A simple example of sending data from 1 nRF24L01 transceiver to another with manually transmitted (non-automatic) Acknowledgement (ACK) payloads. This example still uses ACK packets, but they have no payloads. Instead the acknowledging response is sent with write(). This tactic allows for more updated acknowledgement payload data, where actual ACK payloads' data are outdated by 1 transmission because they have to loaded before receiving a transmission.

This example was written to be used on 2 devices acting as "nodes". 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
19#include <SPI.h>
20#include "printf.h"
21#include "RF24.h"
22
23#define CE_PIN 7
24#define CSN_PIN 8
25// instantiate an object for the nRF24L01 transceiver
26RF24 radio(CE_PIN, CSN_PIN);
27
28// Let these addresses be used for the pair
29uint8_t address[][6] = { "1Node", "2Node" };
30// It is very helpful to think of an address as a path instead of as
31// an identifying device destination
32
33// to use different addresses on a pair of radios, we need a variable to
34// uniquely identify which address this radio will use to transmit
35bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
36
37// Used to control whether this node is sending or receiving
38bool role = false; // true = TX node, false = RX node
39
40// For this example, we'll be using a payload containing
41// a string & an integer number that will be incremented
42// on every successful transmission.
43// Make a data structure to store the entire payload of different datatypes
44struct PayloadStruct {
45 char message[7]; // only using 6 characters for TX & RX payloads
46 uint8_t counter;
47};
48PayloadStruct payload;
49
50void setup() {
51
52 // append a NULL terminating character for printing as a c-string
53 payload.message[6] = 0;
54
55 Serial.begin(115200);
56 while (!Serial) {
57 // some boards need to wait to ensure access to serial over USB
58 }
59
60 // initialize the transceiver on the SPI bus
61 if (!radio.begin()) {
62 Serial.println(F("radio hardware is not responding!!"));
63 while (1) {} // hold in infinite loop
64 }
65
66 // print example's introductory prompt
67 Serial.println(F("RF24/examples/ManualAcknowledgements"));
68
69 // To set the radioNumber via the Serial monitor on startup
70 Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
71 while (!Serial.available()) {
72 // wait for user input
73 }
74 char input = Serial.parseInt();
75 radioNumber = input == 1;
76 Serial.print(F("radioNumber = "));
77 Serial.println((int)radioNumber);
78
79 // role variable is hardcoded to RX behavior, inform the user of this
80 Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
81
82 // Set the PA Level low to try preventing power supply related problems
83 // because these examples are likely run with nodes in close proximity to
84 // each other.
85 radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
86
87 // save on transmission time by setting the radio to only transmit the
88 // number of bytes we need to transmit a float
89 radio.setPayloadSize(sizeof(payload)); // char[7] & uint8_t datatypes occupy 8 bytes
90
91 // set the TX address of the RX node into the TX pipe
92 radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
93
94 // set the RX address of the TX node into a RX pipe
95 radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
96
97 if (role) {
98 // setup the TX node
99
100 memcpy(payload.message, "Hello ", 6); // set the outgoing message
101 radio.stopListening(); // put radio in TX mode
102 } else {
103 // setup the RX node
104
105 memcpy(payload.message, "World ", 6); // set the outgoing message
106 radio.startListening(); // put radio in RX mode
107 }
108
109 // For debugging info
110 // printf_begin(); // needed only once for printing details
111 // radio.printDetails(); // (smaller) function that prints raw register values
112 // radio.printPrettyDetails(); // (larger) function that prints human readable data
113
114} // setup()
115
116void loop() {
117
118 if (role) {
119 // This device is a TX node
120
121 unsigned long start_timer = micros(); // start the timer
122 bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report
123
124 if (report) {
125 // transmission successful; wait for response and print results
126
127 radio.startListening(); // put in RX mode
128 unsigned long start_timeout = millis(); // timer to detect timeout
129 while (!radio.available()) { // wait for response
130 if (millis() - start_timeout > 200) // only wait 200 ms
131 break;
132 }
133 unsigned long end_timer = micros(); // end the timer
134 radio.stopListening(); // put back in TX mode
135
136 // print summary of transactions
137 Serial.print(F("Transmission successful!")); // payload was delivered
138 uint8_t pipe;
139 if (radio.available(&pipe)) { // is there a payload received
140 Serial.print(F(" Round-trip delay: "));
141 Serial.print(end_timer - start_timer); // print the timer result
142 Serial.print(F(" us. Sent: "));
143 Serial.print(payload.message); // print the outgoing payload's message
144 Serial.print(payload.counter); // print outgoing payload's counter
145 PayloadStruct received;
146 radio.read(&received, sizeof(received)); // get payload from RX FIFO
147 Serial.print(F(" Received "));
148 Serial.print(radio.getPayloadSize()); // print the size of the payload
149 Serial.print(F(" bytes on pipe "));
150 Serial.print(pipe); // print the pipe number
151 Serial.print(F(": "));
152 Serial.print(received.message); // print the incoming payload's message
153 Serial.println(received.counter); // print the incoming payload's counter
154 payload.counter = received.counter; // save incoming counter for next outgoing counter
155 } else {
156 Serial.println(F(" Recieved no response.")); // no response received
157 }
158 } else {
159 Serial.println(F("Transmission failed or timed out")); // payload was not delivered
160 } // report
161
162 // to make this example readable in the serial monitor
163 delay(1000); // slow transmissions down by 1 second
164
165 } else {
166 // This device is a RX node
167
168 uint8_t pipe;
169 if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
170 PayloadStruct received;
171 radio.read(&received, sizeof(received)); // get incoming payload
172 payload.counter = received.counter + 1; // increment incoming counter for next outgoing response
173
174 // transmit response & save result to `report`
175 radio.stopListening(); // put in TX mode
176
177 radio.writeFast(&payload, sizeof(payload)); // load response to TX FIFO
178 bool report = radio.txStandBy(150); // keep retrying for 150 ms
179
180 radio.startListening(); // put back in RX mode
181
182 // print summary of transactions
183 Serial.print(F("Received "));
184 Serial.print(radio.getPayloadSize()); // print the size of the payload
185 Serial.print(F(" bytes on pipe "));
186 Serial.print(pipe); // print the pipe number
187 Serial.print(F(": "));
188 Serial.print(received.message); // print incoming message
189 Serial.print(received.counter); // print incoming counter
190
191 if (report) {
192 Serial.print(F(" Sent: "));
193 Serial.print(payload.message); // print outgoing message
194 Serial.println(payload.counter); // print outgoing counter
195 } else {
196 Serial.println(" Response failed."); // failed to send response
197 }
198 }
199 } // role
200
201 if (Serial.available()) {
202 // change the role via the serial monitor
203
204 char c = toupper(Serial.read());
205 if (c == 'T' && !role) {
206 // Become the TX node
207
208 role = true;
209 memcpy(payload.message, "Hello ", 6); // set the outgoing message
210 Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
211 radio.stopListening(); // put in TX mode
212
213 } else if (c == 'R' && role) {
214 // Become the RX node
215
216 role = false;
217 memcpy(payload.message, "World ", 6); // set the response message
218 Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
219 radio.startListening(); // put in RX mode
220 }
221 }
222} // loop
Driver class for nRF24L01(+) 2.4GHz Wireless Transceiver.
Definition: RF24.h:116
@ RF24_PA_LOW
Definition: RF24.h:50
#define delay(milisec)
#define millis()