ZigBee Power Management using Cyclic Sleep example for mbed XBeeLib By Digi

Dependencies:   XBeeLib mbed

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 the 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 to check if there is any packet for it. If there is one or more, it awakes and send the packets to the mbed micro-controller.

Setup

Firmware

In S2B modules, router firmware will not work for this example, because routers don't support sleep modes.
Make sure the XBee module has end-device firmware.
To flash new firmware into an XBee module, you need to use the XCTU software.

Network

Make sure the coordinator has at Cyclic Sleep Period (SP) option a value greater than XBee module.
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
On a router or coordinator, SP determines the transmission timeout when sending to a sleeping end device. SP also determines how long the parent will buffer a message for a sleeping child.

Demo run

While it is running, go to the "Console" tab of the X-CTU connected to the coordinator. Press the "Add API frame to the list" and paste following bytes that create a new broadcast transmit request packet:

7E 00 19 10 01 00 00 00 00 00 00 FF FF FF FE 00 00 48 65 6C 6C 6F 20 58 42 65 65 21 5A

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.

main.cpp

Committer:
hbujanda
Date:
2016-07-29
Revision:
7:fe3aee4d263a
Parent:
4:378daca584ef

File content as of revision 7:fe3aee4d263a:

/**
 * Copyright (c) 2015 Digi International Inc.,
 * All rights not expressly granted are reserved.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 * =======================================================================
 */

#include "mbed.h"
#include "XBeeLib.h"
#if defined(ENABLE_LOGGING)
#include "DigiLoggerMbedSerial.h"
using namespace DigiLog;
#endif

using namespace XBeeLib;

/* Configure Sleep Options */
#define SLEEP_OPTIONS 0      /* Short Sleep */

/* Configure Sleep Period in mS */
#define SLEEP_PERIOD_MS (5000 / 10)   /* 5000 mS */

/* Configure Time before sleep */
#define TIME_BEFORE_SLEEP_MS 500    /* 500 mS */

/* Configure Number of sleep periods */
#define SLEEP_PERIOD_NUMBER 65535    /* High value so radio doesn't awake unnecessarily */


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)
{
    const uint64_t remote_addr64 = remote.get_addr64();

    log_serial->printf("\r\nGot a %s RX packet [%08x:%08x|%04x], len %d\r\nData: ", broadcast ? "BROADCAST" : "UNICAST",
                                      UINT64_HI32(remote_addr64), UINT64_LO32(remote_addr64), remote.get_addr16(), len);

    log_serial->printf("%.*s\r\n\r\n", len, data);
}

int main()
{
    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(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);

    /* Register callbacks */
    xbee.register_receive_cb(&receive_cb);

    RadioStatus const radioStatus = xbee.init();
    MBED_ASSERT(radioStatus == Success);

    /* Configure sleep parameters */
    AtCmdFrame::AtCmdResp cmdresp;

    cmdresp = xbee.set_param("SO", (uint32_t)SLEEP_OPTIONS);
    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
        log_serial->printf("SO Failed!!\r\n");
    }

    cmdresp = xbee.set_param("SP", SLEEP_PERIOD_MS);
    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
        log_serial->printf("SP Failed!!\r\n");
    }

    cmdresp = xbee.set_param("ST", TIME_BEFORE_SLEEP_MS);
    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
        log_serial->printf("ST Failed!!\r\n");
    }

    cmdresp = xbee.set_param("SN", SLEEP_PERIOD_NUMBER);
    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
        log_serial->printf("SN Failed!!\r\n");
    }

    /* Configure Sleep mode */
    cmdresp = xbee.set_param("SM", 4);  /* Cyclic Sleep */
    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
        log_serial->printf("SM Failed!!\r\n");
    }

    /* 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();
        wait_ms(100);
        log_serial->printf(".");
    }

    delete(log_serial);
}