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?

  • I just figured out that wireshark is not exporting the decrypted packages.

    The network key is:

    [Key: df159b023ed72c599a7f78dad6dc04d9]

  • Hi,

    The end device sends continuous End Device Timeout Requests to the coordinator. There are no packets from the coordinator in the sniffer log, so I cannot see whether it responds to the requests, but I would assume that it does not since the end device continues sending them.

    The request looks correct, so there should not be an issue there.

    What are you using as the coordinator? Can you also get a sniffer log that includes packets from the coordinator? Start the sniffer before the end device joins the network so you get the Node Descriptor Response from the coordinator in the sniffer log.

    Another thing you can try is to use the light coordinator or CLI agent as the coordinator and see if there is any difference in current consumption on the end device.

    Best regards,
    Marte

  • Hi,

    I think these End Device Timeout Requests is the polling (it's a sleepy end device) rate right? Because thats set at 500ms and I see that these requests are approx. 500ms delayed.

    But I think this extra traffic is generated by the Data Request packages on the IEEE 802.15.4 protocol. What does that mean?

  • 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?

Reply Children
Related