Optimized RF24Network Layer v2.0.0
2024 - Optimized RF24 Network Layer for NRF24L01 & NRF52x radios
Loading...
Searching...
No Matches
Network_Ping_Sleep.ino

Example: This is almost exactly the same as the Network_Ping example, but with use of the integrated sleep mode.

This example demonstrates how nodes on the network utilize sleep mode to conserve power. For example, the radio itself will draw about 13.5mA in receive mode. In sleep mode, it will use as little as 22ua (.000022mA) of power when not actively transmitting or receiving data. In addition, the Arduino is powered down as well, dropping network power consumption dramatically compared to previous capabilities.
Note: Sleeping nodes generate traffic that will wake other nodes up. This may be mitigated with further modifications. Sleep payloads are currently always routed to the master node, which will wake up intermediary nodes. Routing nodes can be configured to go back to sleep immediately. The displayed millis() count will give an indication of how much a node has been sleeping compared to the others, as millis() will not increment while a node sleeps.

#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include "printf.h"
#include <SPI.h>
#include <RF24.h>
#include <RF24Network.h>
/***********************************************************************
************* Set the Node Address *************************************
************************************************************************/
// These are the Octal addresses that will be assigned
const uint16_t node_address_set[10] = { 00, 02, 05, 012, 015, 022, 025, 032, 035, 045 };
// 0 = Master
// 1-2 (02, 05) = Children of Master(00)
// 3, 5 (012, 022) = Children of (02)
// 4, 6 (015, 025) = Children of (05)
// 7 (032) = Child of (02)
// 8, 9 (035, 045) = Children of (05)
uint8_t NODE_ADDRESS = 1; // Use numbers 0 through 9 to select an address from the array
/***********************************************************************/
/***********************************************************************/
RF24 radio(7, 8); // CE & CS pins to use (Using 7,8 on Uno,Nano)
RF24Network network(radio);
uint16_t this_node; // Our node address
const unsigned long interval = 1000; // Delay manager to send pings regularly (in ms). Because of sleepNode(), this is largely irrelevant.
unsigned long last_time_sent;
const short max_active_nodes = 10; // Array of nodes we are aware of
uint16_t active_nodes[max_active_nodes];
short num_active_nodes = 0;
short next_ping_node_index = 0;
bool send_T(uint16_t to); // Prototypes for functions to send & handle messages
bool send_N(uint16_t to);
void handle_T(RF24NetworkHeader& header);
void handle_N(RF24NetworkHeader& header);
void add_node(uint16_t node);
//This is for sleep mode. It is not really required, as users could just use the number 0 through 10
typedef enum { wdt_16ms = 0,
wdt_32ms,
wdt_64ms,
wdt_128ms,
wdt_250ms,
wdt_500ms,
wdt_1s,
wdt_2s,
wdt_4s,
wdt_8s } wdt_prescalar_e;
unsigned long awakeTime = 500; // How long in ms the radio will stay awake after leaving sleep mode
unsigned long sleepTimer = 0; // Used to keep track of how long the system has been awake
void setup() {
Serial.begin(115200);
printf_begin(); // needed for RF24* libs' internal printf() calls
while (!Serial) {
// some boards need this because of native USB capability
}
Serial.println(F("RF24Network/examples/meshping/"));
this_node = node_address_set[NODE_ADDRESS]; // Which node are we?
if (!radio.begin()) {
Serial.println(F("Radio hardware not responding!"));
while (1) {
// hold in infinite loop
}
}
radio.setPALevel(RF24_PA_HIGH);
radio.setChannel(100);
network.begin(/*node address*/ this_node);
/******************************** This is the configuration for sleep mode ***********************/
network.setup_watchdog(wdt_1s); //The watchdog timer will wake the MCU and radio every second to send a sleep payload, then go back to sleep
}
void loop() {
network.update(); // Pump the network regularly
while (network.available()) { // Is there anything ready for us?
RF24NetworkHeader header; // If so, take a look at it
network.peek(header);
switch (header.type) { // Dispatch the message to the correct handler.
case 'T':
handle_T(header);
break;
case 'N':
handle_N(header);
break;
/************* SLEEP MODE *********/
// Note: A 'sleep' header has been defined, and should only need to be ignored if a node is routing traffic to itself
// The header is defined as: RF24NetworkHeader sleepHeader(/*to node*/ 00, /*type*/ 'S' /*Sleep*/);
case 'S':
/*This is a sleep payload, do nothing*/
break;
default:
Serial.print(F("*** WARNING *** Unknown message type "));
Serial.println(header.type);
network.read(header, 0, 0);
break;
};
}
/***************************** CALLING THE NEW SLEEP FUNCTION ************************/
if (millis() - sleepTimer > awakeTime && NODE_ADDRESS) {
// Want to make sure the Arduino stays awake for a little while when data comes in.
// Do NOT sleep if master node.
Serial.println(F("Sleep"));
sleepTimer = millis(); // Reset the timer value
delay(100); // Give the Serial print some time to finish up
radio.stopListening(); // Switch to PTX mode. Payloads will be seen as ACK payloads, and the radio will wake up
network.sleepNode(8, 0); // Sleep the node for 8 cycles of 1second intervals
Serial.println(F("Awake"));
}
//Examples:
// network.sleepNode(cycles, interrupt-pin);
// network.sleepNode(0, 0); // The WDT is configured in this example to sleep in cycles of 1 second. This will sleep 1 second, or until a payload is received
// network.sleepNode(1, 255); // Sleep this node for 1 second. Do not wake up until then, even if a payload is received ( no interrupt ) Payloads will be lost.
/**** end sleep section ***/
unsigned long now = millis(); // Send a ping to the next node every 'interval' ms
if (now - last_time_sent >= interval) {
last_time_sent = now;
uint16_t to = 00; // Who should we send to? By default, send to base
if (num_active_nodes) { // Or if we have active nodes,
to = active_nodes[next_ping_node_index++]; // Send to the next active node
if (next_ping_node_index > num_active_nodes) { // Have we rolled over?
next_ping_node_index = 0; // Next time start at the beginning
to = 00; // This time, send to node 00.
}
}
bool ok;
if (this_node > 00 || to == 00) { // Normal nodes send a 'T' ping
ok = send_T(to);
} else { // Base node sends the current active nodes out
ok = send_N(to);
}
if (ok) { // Notify us of the result
Serial.print(millis());
Serial.println(F(": APP Send ok"));
} else {
Serial.print(millis());
Serial.println(F(": APP Send failed"));
last_time_sent -= 100; // Try sending at a different time next time
}
}
}
bool send_T(uint16_t to) {
RF24NetworkHeader header(/*to node*/ to, /*type*/ 'T' /*Time*/);
// The 'T' message that we send is just a ulong, containing the time
unsigned long message = millis();
Serial.println(F("---------------------------------"));
Serial.print(millis());
Serial.print(F(": APP Sending "));
Serial.print(message);
Serial.print(F(" to "));
Serial.print(to);
Serial.println(F("..."));
return network.write(header, &message, sizeof(unsigned long));
}
bool send_N(uint16_t to) {
RF24NetworkHeader header(/*to node*/ to, /*type*/ 'N' /*Time*/);
Serial.println(F("---------------------------------"));
Serial.print(millis());
Serial.print(F(": APP Sending active nodes to "));
Serial.print(to);
Serial.println(F("..."));
return network.write(header, active_nodes, sizeof(active_nodes));
}
void handle_T(RF24NetworkHeader& header) {
unsigned long message; // The 'T' message is just a ulong, containing the time
network.read(header, &message, sizeof(unsigned long));
Serial.print(millis());
Serial.print(F(": APP Received "));
Serial.print(message);
Serial.print(F(" from "));
Serial.print(header.from_node);
if (header.from_node != this_node || header.from_node > 00) // If this message is from ourselves or the base, don't bother adding it to the active nodes.
add_node(header.from_node);
}
void handle_N(RF24NetworkHeader& header) {
static uint16_t incoming_nodes[max_active_nodes];
network.read(header, &incoming_nodes, sizeof(incoming_nodes));
Serial.print(millis());
Serial.print(F(": APP Received nodes from "));
Serial.println(header.from_node);
int i = 0;
while (i < max_active_nodes && incoming_nodes[i] > 00)
add_node(incoming_nodes[i++]);
}
void add_node(uint16_t node) {
short i = num_active_nodes; // Do we already know about this node?
while (i--) {
if (active_nodes[i] == node)
break;
}
if (i == -1 && num_active_nodes < max_active_nodes) { // If not, add it to the table
active_nodes[num_active_nodes++] = node;
Serial.print(millis());
Serial.print(F(": APP Added "));
Serial.print(node);
Serial.print(F(" to list of active nodes."));
}
}
Definition RF24Network.h:384
Definition RF24Network.h:229
unsigned char type
Definition RF24Network.h:246
uint16_t from_node
Definition RF24Network.h:231