Zigbee power consumption

Hi,

I'm measuring the power consumption on our BLE+Zigbee device.

After the zigbee device is commsioned, it uses an average of 600uA of current, which seems pretty high. I already enabled the sleepy behavior like this:

    zb_set_rx_on_when_idle(ZB_FALSE);
     

#if ! defined DISABLE_POWER_CONSUMPTION_OPTIMIZATION
    /* If sleepy behaviour is enabled, power off unused RAM to save maximum energy */
    if (ZB_PIBCACHE_RX_ON_WHEN_IDLE() == ZB_TRUE)
    {
        zigbee_power_down_unused_ram();
    }

See below the power usage with sleepy behavior:

If I totally disable the Zigbee stack, it uses average of 4.65uA:

I assume this +/-600uA increase is not normal for Zigbee.

Can you please suggest how to lower this power consumption?

Parents
  • Hi,

    • Are you using nRF Connect SDK or nRF5 SDK for Thread and Zigbee?
    • Which version of the SDK do you use?
    • Which example/sample are you basing your code on?
    • Have you made modifications to the example?

    I would expect 600 uA to typically be caused by the HFCLK running and/or UART.

    Best regards,
    Jørgen

  • Hi,

    See answers below:

    • nRF5_SDK_for_Thread_and_Zigbee_v4.1.0
    • I'm using my own code. But I started with the light switch example, because this is a (sleepy) end device
    • Yes, it is my own code.

    UART is disabled. For current measurement I disabled all the logging by the way to exclude this factor.

    I understand it's hard for you to figure this out based on my own code which you didn't see, but that's why I tried to isolate the problem to Zigbee only, by disabling en enabling it. Just to make sure it's nothing else in my code which causes this, but it seems like the Zigbee stack is the problem. 

    When I use the light switch example I get much lower values, but as far as I know nothing else is happening there.

    This the code I use for zigbee init:

    static void zigbee_init(void)
    {
        uint64_t factoryAddress;
    
        /* Read long address from FICR. */
        factoryAddress  = (uint64_t)NRF_FICR->DEVICEID[0] << 32;
        factoryAddress |= NRF_FICR->DEVICEID[1];
        memcpy(m_ieee_addr, &factoryAddress, sizeof(factoryAddress));
    
        /* Set Zigbee stack logging level and traffic dump subsystem. */
        ZB_SET_TRACE_LEVEL(ZIGBEE_TRACE_LEVEL);
        ZB_SET_TRACE_MASK(ZIGBEE_TRACE_MASK);
        ZB_SET_TRAF_DUMP_OFF();
        /* Initialize Zigbee stack. */
        ZB_INIT("multiprotocol_template");
        /* Set device address to the value read from FICR registers. */
        zb_osif_get_ieee_eui64(m_ieee_addr);
        zb_set_long_address(m_ieee_addr);
        /* Set static long IEEE address. */
        zb_set_network_ed_role(ZB_TRANSCEIVER_ALL_CHANNELS_MASK);
        //zb_set_network_ed_role(IEEE_CHANNEL_MASK);
        
        zigbee_erase_persistent_storage(ERASE_PERSISTENT_CONFIG);
        zb_set_ed_timeout(ED_AGING_TIMEOUT_64MIN);
        zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000));
        sleepy_device_setup();
        UNUSED_RETURN_VALUE(ZB_MEMSET(&m_dev_ctx, 0, sizeof(m_dev_ctx)));
    
        ZB_AF_REGISTER_DEVICE_CTX(&device_ctx);
    
        // UNUSED_RETURN_VALUE(ZB_MEMSET(&on_off_switch_ctx, 0, sizeof(on_off_switch_ctx)));
    
        // ZB_AF_REGISTER_DEVICE_CTX(&on_off_switch_ctx);
    
        ZB_ZCL_REGISTER_DEVICE_CB(test_device_interface_cb);
    
        ZB_AF_SET_ENDPOINT_HANDLER(ZB_OUTPUT_ENDPOINT, zcl_specific_cluster_cmd_handler);
    
        window_covering_clusters_attr_init();
        power_config_battery_attr_init();
        /* Initialize application context structure. */
        //
        /* Register dimmer switch device context (endpoints). */
    
    
        /* Register callback for handling ZCL commands. */
        // ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);
    
        //test_device_attr_init();
    }

    This is the zboss_signal handler:

    void zboss_signal_handler(zb_bufid_t bufid)
    {
        /* Read signal description out of memory buffer. */
        zb_zdo_app_signal_hdr_t * p_sg_p      = NULL;
        zb_zdo_app_signal_type_t  sig         = zb_get_app_signal(bufid, &p_sg_p);
        zb_ret_t                  status      = ZB_GET_APP_SIGNAL_STATUS(bufid);
        zb_ret_t                  zb_err_code;
        zb_bool_t                 comm_status;
        zb_time_t                 timeout_bi;
    
        switch(sig)
        {
            case ZB_BDB_SIGNAL_DEVICE_REBOOT:
                // BDB initialization completed after device reboot, use NVRAM contents during initialization. Device joined/rejoined and started.
                if (status == RET_OK)
                {
                    if (ZIGBEE_MANUAL_STEERING == ZB_FALSE)
                    {
                        NRF_LOG_INFO("Start network steering");
                        comm_status = bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);
                        ZB_COMM_STATUS_CHECK(comm_status);
                    }
                    else
                    {
                        NRF_LOG_INFO("Coordinator restarted successfully");
                    }
                }
                else
                {
                    NRF_LOG_ERROR("Failed to initialize Zigbee stack using NVRAM data (status: %d)", status);
                }
                break;
    
            case ZB_BDB_SIGNAL_STEERING:
                if (status == RET_OK)
                {
                    if (ZIGBEE_PERMIT_LEGACY_DEVICES == ZB_TRUE)
                    {
                        NRF_LOG_INFO("Allow pre-Zigbee 3.0 devices to join the network");
                        zb_bdb_set_legacy_device_support(1);
                    }
    
                    /* Schedule an alarm to notify about the end of steering period */
                    NRF_LOG_INFO("Network steering started");
                    zb_err_code = ZB_SCHEDULE_APP_ALARM(steering_finished, 0, ZB_TIME_ONE_SECOND * ZB_ZGP_DEFAULT_COMMISSIONING_WINDOW);
                    ZB_ERROR_CHECK(zb_err_code);
                }
                break;
    
            case ZB_ZDO_SIGNAL_DEVICE_ANNCE:
                {
                    zb_zdo_signal_device_annce_params_t * dev_annce_params = ZB_ZDO_SIGNAL_GET_PARAMS(p_sg_p, zb_zdo_signal_device_annce_params_t);
                    NRF_LOG_INFO("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr);
    
                    zb_err_code = ZB_SCHEDULE_APP_ALARM_CANCEL(steering_finished, ZB_ALARM_ANY_PARAM);
                    if (zb_err_code == RET_OK)
                    {
                        NRF_LOG_INFO("Joining period extended.");
                        zb_err_code = ZB_SCHEDULE_APP_ALARM(steering_finished, 0, ZB_TIME_ONE_SECOND * ZB_ZGP_DEFAULT_COMMISSIONING_WINDOW);
                        ZB_ERROR_CHECK(zb_err_code);
                    }
            } break;
    
            case ZB_COMMON_SIGNAL_CAN_SLEEP: {
    
                    // zb_sleep_now();
            } break;
    
            default:
                    /* Call default signal handler. */
                    ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
                    break;
        }
    
        /* Update network status LED */
        if (ZB_JOINED() && (ZB_SCHEDULE_GET_ALARM_TIME(steering_finished, ZB_ALARM_ANY_PARAM, &timeout_bi) == RET_OK))
        {
            bsp_board_led_on(ZIGBEE_NETWORK_STATE_LED);
        }
        else
        {
            bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED);
        }
    
        /* All callbacks should either reuse or free passed buffers. If bufid == 0, the buffer is invalid (not passed) */
        if (bufid)
        {
            zb_buf_free(bufid);
        }
    }

    To start the zigbee stack:

    err_code = zboss_start_no_autostart();
    ZB_ERROR_CHECK(err_code);

    And in my main loop:

    zboss_main_loop_iteration();
    UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());

    I would expect 600 uA to typically be caused by the HFCLK running and/or UART.

    HFCLK could be, but as far as I know I'm not in control of the usage of when the Zigbee stack is used?

  • Hi,

    No, End Device Timeout Request is not the polling. The Data Request is the polling.

    End Device Timeout Requests are sent to inform the end device's parent of the end device's timeout requirements. This should only be sent once unless the end device does not receive an End Device Timeout Response from the parent. Here you can see the expected behavior when the end device joins the network. I have marked the request and response:

    Best regards,
    Marte

  • So it's more related to the coordinator that it doesn't send this response?

  • By the way, I gave you the filtered data, which I only filtered on a src.
    Now, when I look on all the data, I see that the coordinator sends an end device timeout response success to the device:

  • Hi,

    Please upload the sniffer log with the packets from both the coordinator and the end device.

    Best regards,
    Marte

Reply Children
  • Hi,

    According to the stack compliance revision in the coordinator's Node Descriptor Response, the coordinator is a Zigbee 2007 device and not a Zigbee Pro/Zigbee 3.0 device.

    In addition to the stack compliance revision, I also see that the commissioning process indicates that the coordinator is a Zigbee 2007 device, as it does not perform the Trust Center link key exchange.

    However, the coordinator responds with an End Device Timeout Response. End device timeout and aging mechanism were added in Zigbee Pro, so a Zigbee 2007 device should not support this and, therefore, not respond to an End Device Timeout Request.

    I believe this is causing the issues with the end device timeout and current consumption. Can you test with a Zigbee Pro coordinator instead? If you have an additional nRF52840 DK or dongle, or nRF52833 DK you can use the coordinator from our light control example or the CLI Agent example.

    Best regards,
    Marte

Related