DigiMesh Power Management using Asynchronous Cyclic Sleep example for mbed XBeeLib By Digi

Dependencies:   XBeeLib mbed

Fork of XBeeZB_power_mngmnt_cyclic_sleep by Digi International Inc.

Description

This example characterizes a device that needs to be continuously joined to the coordinator so it doesn't lose any incoming packets. A fast response to packets is not required so radio can sleep for some time to save power while the coordinator buffers its packets.

The example configures the radio to poll its coordinator every 5 seconds if there is any packet for it.
If there is one or more, it awakes and send the packets to the mbed micro-controller.

Note that in DigiMesh modules, the polling mechanism required in this example is restricted to devices one hop away (Point to Multipoint delivery); it will not work fine across a DigiMesh network.

Setup

Network

You need to set up a coordinator in the network so it buffers the packets send to our local XBee device while it's sleeping.
A module configured as coordinator requires:

  • 'Coordinator Enable (CE)' parameter set to 1.
  • 'Cyclic Sleep Period (SP)' parameter set as the local XBee device.
    In the example it is set to 5000 which represent 5000 ms or 5 seconds.
    In the coordinator, when using X-CTU for configuration, the SP parameter has to be entered as the desired sleep time divided by 10 and in hexadecimal so to cope with the example it should be 5000 / 10 = 500 = 0x1F4 -> 1F4
  • 'Time Before Sleep (ST)' parameter set as the local XBee device; 500 ms = 0x1F4.
  • 'Transmit Options (TO)' parameter set to 0x40 so delivery method is Point to Multipoint.

Demo run

While it is running, send a packet to the device:

  • Go to the "Console" tab of the XCTU connected to the coordinator.
  • Press the "Add API frame to the list" button.
  • Press "Create using API Frame generator" button.
  • Select "DigiMesh" protocol and "0x10 Transmit Request" Frame Type.
  • Paste the Local XBee device 64-bit address in the "64-bit dest. address" text box. (You can copy it from the application banner).
  • In the "Options" text box, type 0x40 to select delivery method as Point To Multipoint (you can skip this if you configured atTO accordingly)
  • In the "RF data" text box, select the ASCII box and type "Hello XBee!".
  • Press OK, Add Frame.
  • Select the frame and press the "Send selected frame" button to send the frame ("Hello XBee!") to the XBee network.

Once the XBee device receives the frame, the radio will wake up to send it to mbed micro-controller, which will process and print the received data.

Verify that the XBee module has received the frame by accessing the serial console terminal. If it was successful, the "Hello XBee!" message will be displayed there.

After that, the radio will go to sleep again until new data is received.

Revision:
7:0b34ce30516a
Parent:
4:378daca584ef
Child:
8:f7fdee8c39a4
--- a/main.cpp	Thu Jul 28 10:20:16 2016 +0200
+++ b/main.cpp	Thu Jul 28 10:36:50 2016 +0000
@@ -31,11 +31,18 @@
 /* Configure Number of sleep periods */
 #define SLEEP_PERIOD_NUMBER 65535    /* High value so radio doesn't awake unnecessarily */
 
+#define REMOTE_NODE_ADDR64_MSB  ((uint32_t)0x0013A200)
+
+//#error "Replace next define with the LSB of the remote module's 64-bit address (SL parameter)"
+//#define REMOTE_NODE_ADDR64_LSB  ((uint32_t)0x01234567)
+#define REMOTE_NODE_ADDR64_LSB  ((uint32_t)0x40F86A88)
+
+#define REMOTE_NODE_ADDR64      UINT64(REMOTE_NODE_ADDR64_MSB, REMOTE_NODE_ADDR64_LSB)
 
 Serial *log_serial;
 
 /** Callback function, invoked at packet reception */
-static void receive_cb(const RemoteXBeeZB& remote, bool broadcast, const uint8_t *const data, uint16_t len)
+static void receive_cb(const RemoteXBeeDM& remote, bool broadcast, const uint8_t *const data, uint16_t len)
 {
     const uint64_t remote_addr64 = remote.get_addr64();
 
@@ -49,19 +56,21 @@
 {
     log_serial = new Serial(DEBUG_TX, DEBUG_RX);
     log_serial->baud(9600);
-    log_serial->printf("Sample application to demo cyclic sleep power management with the XBeeZB\r\n\r\n");
+    log_serial->printf("Sample application to demo cyclic sleep power management with the XBeeDM\r\n\r\n");
     log_serial->printf(XB_LIB_BANNER);
 
 #if defined(ENABLE_LOGGING)
     new DigiLoggerMbedSerial(log_serial, LogLevelInfo);
 #endif
 
-    XBeeZB xbee = XBeeZB(RADIO_TX, RADIO_RX, RADIO_RESET, NC, NC, 9600);
+    XBeeDM xbee = XBeeDM(RADIO_TX, RADIO_RX, RADIO_RESET, NC, NC, 9600);
+
+    const RemoteXBeeDM remoteDevice = RemoteXBeeDM(REMOTE_NODE_ADDR64);
 
     /* Register callbacks */
     xbee.register_receive_cb(&receive_cb);
 
-    RadioStatus const radioStatus = xbee.init();
+    RadioStatus radioStatus = xbee.init();
     MBED_ASSERT(radioStatus == Success);
 
     /* Configure sleep parameters */
@@ -69,38 +78,51 @@
 
     cmdresp = xbee.set_param("SO", (uint32_t)SLEEP_OPTIONS);
     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
-        log_serial->printf("SO Failed!!\r\n");
+        log_serial->printf("Setting SO Failed!!\r\n");
+        goto end;
     }
 
     cmdresp = xbee.set_param("SP", SLEEP_PERIOD_MS);
     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
-        log_serial->printf("SP Failed!!\r\n");
+        log_serial->printf("Setting SP Failed!!\r\n");
+        goto end;
     }
 
     cmdresp = xbee.set_param("ST", TIME_BEFORE_SLEEP_MS);
     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
-        log_serial->printf("ST Failed!!\r\n");
+        log_serial->printf("Setting ST Failed!!\r\n");
+        goto end;
     }
 
     cmdresp = xbee.set_param("SN", SLEEP_PERIOD_NUMBER);
     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
-        log_serial->printf("SN Failed!!\r\n");
+        log_serial->printf("Setting SN Failed!!\r\n");
+        goto end;
+    }
+
+    cmdresp = xbee.set_param("CE", 4);  /* Indirect Message Poller */
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        log_serial->printf("Setting CE Failed!!\r\n");
+        log_serial->printf("This example only works if both devices are S2C modules where asynchronous cyclic sleep is supported!!\r\n");
+        goto end;
+    }
+
+    /* Configure DH/DL with the address of the remoter device that acts 
+       as indirect message coordinator. Poll messages will be sent to this 
+       address each time the device awakes to check for pending messages */
+    radioStatus = xbee.config_poll_destination(remoteDevice);
+    if (radioStatus != Success) {
+        log_serial->printf("config_poll_destination Failed!!\r\n");
+        goto end;     
     }
 
     /* Configure Sleep mode */
     cmdresp = xbee.set_param("SM", 4);  /* Cyclic Sleep */
     if (cmdresp != AtCmdFrame::AtCmdRespOk) {
-        log_serial->printf("SM Failed!!\r\n");
+        log_serial->printf("Setting SM Failed!!\r\n");
+        goto end;
     }
 
-    /* Wait until the device has joined the network */
-    log_serial->printf("Waiting for device to join the network: ");
-    while (!xbee.is_joined()) {
-        wait_ms(1000);
-        log_serial->printf(".");
-    }
-    log_serial->printf("OK\r\n");
-
     /* Start processing frames */
     while (true) {
         xbee.process_rx_frames();
@@ -108,5 +130,6 @@
         log_serial->printf(".");
     }
 
+end:
     delete(log_serial);
 }