This example uses Acknowledgement (ACK) payloads attached to ACK packets to demonstrate how the nRF24L01's IRQ (Interrupt Request) pin can be configured to detect when data is received, or when data has transmitted successfully, or when data has failed to transmit.
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
3
4
5
6
16#include <SPI.h>
19
20
21#define IRQ_PIN 2
22volatile bool got_interrupt = false;
23volatile bool wait_for_event = false;
24
25#define CE_PIN 7
26#define CSN_PIN 8
27
28RF24 radio(CE_PIN, CSN_PIN);
29
30
31uint8_t address[][6] = { "1Node", "2Node" };
32
33
34
35
36
37bool radioNumber = 1;
38
39
40bool role = false;
41
42
43
44
45const uint8_t tx_pl_size = 5;
46const uint8_t ack_pl_size = 4;
47uint8_t pl_iterator = 0;
48
49char tx_payloads[][tx_pl_size + 1] = { "Ping ", "Pong ", "Radio", "1FAIL" };
50char ack_payloads[][ack_pl_size + 1] = { "Yak ", "Back", " ACK" };
51
52void interruptHandler();
53void printRxFifo();
54
55
56void setup() {
57 Serial.begin(115200);
58 while (!Serial) {
59
60 }
61
62
63 if (!radio.begin()) {
64 Serial.println(F("radio hardware is not responding!!"));
65 while (1) {}
66 }
67
68
69 Serial.println(F("RF24/examples/InterruptConfigure"));
70
71
72 Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
73 while (!Serial.available()) {
74
75 }
76 char input = Serial.parseInt();
77 radioNumber = input == 1;
78 Serial.print(F("radioNumber = "));
79 Serial.println((int)radioNumber);
80
81
82 Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
83
84
86 attachInterrupt(digitalPinToInterrupt(IRQ_PIN), interruptHandler, FALLING);
87
88
89
90
91
92
93
94
96
97
98
99
100 radio.enableDynamicPayloads();
101
102
103
104 radio.enableAckPayload();
105
106
107 radio.stopListening(address[radioNumber]);
108
109
110 radio.openReadingPipe(1, address[!radioNumber]);
111
112
113 if (!role) {
114
115
116
118
119
120
121 radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
122 radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
123 radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
124
125 radio.startListening();
126 }
127
128
129
130
131
132}
133
134void loop() {
135 if (got_interrupt) {
136 assessInterruptEvent();
137 }
138
139 if (role && !wait_for_event) {
140
141
142
143
144 if (pl_iterator == 0) {
145
146
147 Serial.println(F("\nConfiguring IRQ pin to ignore the 'data sent' event"));
149 Serial.println(F(" Pinging RX node for 'data ready' event..."));
150
151 } else if (pl_iterator == 1) {
152
153
154 Serial.println(F("\nConfiguring IRQ pin to ignore the 'data ready' event"));
156 Serial.println(F(" Pinging RX node for 'data sent' event..."));
157
158 } else if (pl_iterator == 2) {
159
160
161
162
163 radio.setStatusFlags();
164
165 Serial.println(F("\nSending 1 payload to fill RX node's FIFO. IRQ pin is neglected."));
166
167 if (radio.write(&tx_payloads[pl_iterator], tx_pl_size)) {
168 if (radio.rxFifoFull()) {
169 Serial.println(F("RX node's FIFO is full; it is not listening any more"));
170 } else {
171 Serial.println("Transmission successful, but the RX node might still be listening.");
172 }
173 } else {
174 Serial.println(F("Transmission failed or timed out. Continuing anyway."));
175 radio.flush_tx();
176 }
177
178 } else if (pl_iterator == 3) {
179
180
181 Serial.println(F("\nConfiguring IRQ pin to reflect all events"));
183 Serial.println(F(" Pinging inactive RX node for 'data fail' event..."));
184 }
185
186 if (pl_iterator < 4 && pl_iterator != 2) {
187
188
189
190 wait_for_event = true;
191
192
193
194 radio.startFastWrite(tx_payloads[pl_iterator++], tx_pl_size, false);
195
196
197
198
199
200 } else if (pl_iterator == 4) {
201
202
203
204 radio.stopListening();
205
206
207 printRxFifo();
208 pl_iterator++;
209
210
211
212 Serial.println(F("\n*** PRESS 'T' to restart the transmissions"));
213 Serial.println(F("*** PRESS 'R' to change to Receive role\n"));
214
215
216 } else if (pl_iterator == 2) {
217 pl_iterator++;
218 }
219
220 } else if (!role && radio.rxFifoFull()) {
221
222
223
225 radio.stopListening();
226 printRxFifo();
227
228
229
230 radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
231 radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
232 radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
233
235 radio.startListening();
236
237 }
238
239 if (Serial.available()) {
240
241
242 char c = toupper(Serial.read());
243 if (c == 'T') {
244
245 if (!role)
246 Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
247 else
248 Serial.println(F("*** RESTARTING IRQ PIN TEST ***"));
249
250 role = true;
251 wait_for_event = false;
252 pl_iterator = 0;
253 radio.flush_tx();
254
255
256
257 radio.stopListening();
258
259 } else if (c == 'R' && role) {
260
261 Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
262
263 role = false;
264
265
267
268
269
270 radio.flush_tx();
271 radio.flush_rx();
272 radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
273 radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
274 radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
275 radio.startListening();
276 }
277 }
278}
279
280
285void interruptHandler() {
286 got_interrupt = true;
287}
288
293void assessInterruptEvent() {
294
295
296 Serial.println(F("\tIRQ pin is actively LOW"));
298 uint8_t flags = radio.clearStatusFlags();
299
300
301
302
303 Serial.print(F("\tdata_sent: "));
305 Serial.print(F(", data_fail: "));
307 Serial.print(F(", data_ready: "));
309
311 radio.flush_tx();
312
313
314
315 if (pl_iterator <= 1) {
316 Serial.print(F(" 'Data Ready' event test "));
317 Serial.println(flags &
RF24_RX_DR ? F(
"passed") : F(
"failed"));
318 } else if (pl_iterator == 2) {
319 Serial.print(F(" 'Data Sent' event test "));
320 Serial.println(flags &
RF24_TX_DS ? F(
"passed") : F(
"failed"));
321 } else if (pl_iterator == 4) {
322 Serial.print(F(" 'Data Fail' event test "));
323 Serial.println(flags &
RF24_TX_DF ? F(
"passed") : F(
"failed"));
324 }
325 got_interrupt = false;
326 wait_for_event = false;
327}
328
333void printRxFifo() {
334 if (radio.available()) {
335
336
337 uint8_t pl_size = !role ? tx_pl_size : ack_pl_size;
338 char rx_fifo[pl_size * 3 + 1];
339 if (radio.rxFifoFull()) {
340 rx_fifo[pl_size * 3] = 0;
341 radio.read(&rx_fifo, pl_size * 3);
342 } else {
343 uint8_t i = 0;
344 while (radio.available()) {
345 radio.read(&rx_fifo + (i * pl_size), pl_size);
346 i++;
347 }
348 rx_fifo[i * pl_size] = 0;
349 }
350 Serial.print(F("Complete RX FIFO: "));
351 Serial.println(rx_fifo);
352 }
353}
Driver class for nRF24L01(+) 2.4GHz Wireless Transceiver.
#define pinMode(pin, direction)
#define delayMicroseconds(usec)
@ RF24_TX_DS
Represents an event where TX Data Sent successfully.
@ RF24_TX_DF
Represents an event where TX Data Failed to send.
@ RF24_RX_DR
Represents an event where RX Data is Ready to RF24::read().
@ RF24_IRQ_ALL
Equivalent to RF24_RX_DR | RF24_TX_DS | RF24_TX_DF.