/* * See documentation at https://nRF24.github.io/RF24 * See License information at root directory of this library * Author: Brendan Doherty 2bndy5 */ /** * 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. */ #include #include "printf.h" #include "RF24.h" // instantiate an object for the nRF24L01 transceiver RF24 radio(7, 8); // using pin 7 for the CE pin, and pin 8 for the CSN pin // For this example, we'll be using 6 addresses; 1 for each TX node // It is very helpful to think of an address as a path instead of as // an identifying device destination // Notice that the last byte is the only byte that changes in the last 5 // addresses. This is a limitation of the nRF24L01 transceiver for pipes 2-5 // because they use the same first 4 bytes from pipe 1. uint64_t address[6] = {0x7878787878LL, 0xB3B4B5B6F1LL, 0xB3B4B5B6CDLL, 0xB3B4B5B6A3LL, 0xB3B4B5B60FLL, 0xB3B4B5B605LL }; // Because this example allow up to 6 nodes (specified by numbers 0-5) to // transmit and only 1 node to receive, we will use a negative value in our // role variable to signify this node is a receiver. // role variable is used to control whether this node is sending or receiving char role = 'R'; // 0-5 = TX node; any negative number = RX node // For this example, we'll be using a payload containing // a node ID number and a single integer number that will be incremented // on every successful transmission. // Make a data structure to use as a payload. struct PayloadStruct { unsigned long nodeID; unsigned long payloadID; }; PayloadStruct payload; // This example uses all 6 pipes to receive while TX nodes only use 2 pipes // To make this easier we'll use a function to manage the addresses, and the // payload's nodeID void setRole(); // declare a prototype; definition is found after the loop() void setup() { Serial.begin(115200); while (!Serial) { // some boards need to wait to ensure access to serial over USB } // initialize the transceiver on the SPI bus if (!radio.begin()) { Serial.println(F("radio hardware is not responding!!")); while (1) {} // hold in infinite loop } // print example's introductory prompt Serial.println(F("RF24/examples/MulticeiverDemo")); Serial.println(F("*** Enter a number between 0 and 5 (inclusive) to change")); Serial.println(F(" the identifying node number that transmits.")); // Set the PA Level low to try preventing power supply related problems // because these examples are likely run with nodes in close proximity of // each other. radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default. // save on transmission time by setting the radio to only transmit the // number of bytes we need to transmit a float radio.setPayloadSize(sizeof(payload)); // 2x int datatype occupy 8 bytes // Set the pipe addresses accordingly. This function additionally also // calls startListening() or stopListening() and sets the payload's nodeID setRole(); // For debugging info // printf_begin(); // needed only once for printing details // radio.printDetails(); // (smaller) function that prints raw register values // radio.printPrettyDetails(); // (larger) function that prints human readable data } // setup() void loop() { if (role <= 53) { // This device is a TX node unsigned long start_timer = micros(); // start the timer bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report unsigned long end_timer = micros(); // end the timer if (report) { // payload was delivered Serial.print(F("Transmission of payloadID ")); Serial.print(payload.payloadID); // print payloadID Serial.print(F(" as node ")); Serial.print(payload.nodeID); // print nodeID Serial.print(F(" successful!")); Serial.print(F(" Time to transmit: ")); Serial.print(end_timer - start_timer); // print the timer result Serial.println(F(" us")); } else { Serial.println(F("Transmission failed or timed out")); // payload was not delivered } payload.payloadID++; // increment payload number // to make this example readable in the serial monitor delay(500); // slow transmissions down by 1 second } else if (role == 'R') { // This device is the RX node uint8_t pipe; if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it uint8_t bytes = radio.getPayloadSize(); // get the size of the payload radio.read(&payload, bytes); // fetch payload from FIFO Serial.print(F("Received ")); Serial.print(bytes); // print the size of the payload Serial.print(F(" bytes on pipe ")); Serial.print(pipe); // print the pipe number Serial.print(F(" from node ")); Serial.print(payload.nodeID); // print the payload's origin Serial.print(F(". PayloadID: ")); Serial.println(payload.payloadID); // print the payload's number } } // role if (Serial.available()) { // change the role via the serial monitor char c = Serial.read(); if (toupper(c) == 'R' && role <= 53) { // Become the RX node role = 'R'; Serial.println(F("*** CHANGING ROLE TO RECEIVER ***")); Serial.println(F("--- Enter a number between 0 and 5 (inclusive) to act as")); Serial.println(F(" a unique node number that transmits to the RX node.")); setRole(); // change address on all pipes to TX nodes } else if (c >= 48 && c <= 53 && c != role) { // Become a TX node with identifier 'c' role = c - 48; Serial.print(F("*** CHANGING ROLE TO NODE ")); Serial.print(c); Serial.println(F(" ***")); Serial.println(F("--- Enter a number between 0 and 5 (inclusive) to change")); Serial.println(F(" the identifying node number that transmits.")); Serial.println(F("--- PRESS 'R' to act as the RX node.")); setRole(); // change address on pipe 0 to the RX node } } } // loop void setRole() { if (role == 'R') { // For the RX node // Set the addresses for all pipes to TX nodes for (uint8_t i = 0; i < 6; ++i) radio.openReadingPipe(i, address[i]); radio.startListening(); // put radio in RX mode } else { // For the TX node // set the payload's nodeID & reset the payload's identifying number payload.nodeID = role; payload.payloadID = 0; // Set the address on pipe 0 to the RX node. radio.stopListening(); // put radio in TX mode radio.openWritingPipe(address[role]); // According to the datasheet, the auto-retry features's delay value should // be "skewed" to allow the RX node to receive 1 transmission at a time. // So, use varying delay between retry attempts and 15 (at most) retry attempts radio.setRetries(((role * 3) % 12) + 3, 15); // maximum value is 15 for both args } } // setRole