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,

    I am glad to hear that you figured it out.

    You are correct that calling nrf_pwr_mgmt_run() in the main loop will cause issues with the Zigbee scheduler. When using Zigbee in nRF5 SDK, you must use either zboss_main_loop() or zboss_main_loop_iteration() for the ZBOSS main loop, which will handle stack signals and ZCL callbacks. Calling nrf_pwr_mgmt_run() in the main loop will interfere with the ZBOSS main loop and, therefore, the Zigbee stack.
    However, nrf_pwr_mgmt_run() is called by the Zigbee stack when the Zigbee scheduler queue is empty, so there is no need to call this function yourself.

    Best regards,
    Marte

  • Hi. I updated the SDK version from 4.1.0 to 4.2.0. Now I see an increase again in the power consumption.

    I see a lot of 'spikes' from, I expect zigbee traffic. I also see this with the light bulb example. I didnt had this in sdk 4.1.0.

    Average consumption is now 451uA because of this.

    How can I reduce this traffic?

  • Hi,

    Can you capture a sniffer log and upload it here as a pcap file using Insert -> Image/video/file? With this, it is possible to see which Zigbee packets are being sent and how often. See nRF Sniffer for 802.15.4 for how to set up and use our 802.15.4 sniffer.

    You say that you started with the light switch example but also that you are using BLE. Did you add BLE functionality to the light switch example, or did you start with one of the multiprotocol examples for this?

    I would expect the light bulb example to have higher current consumption than the light bulb, as it is a router and not an end device. Have you tested with the out-of-the-box light switch example, or the multiprotocol BLE and Zigbee light switch example?

    I tested the multiprotocol light switch example in v4.2.0, and I got around 130-140 uA when the device was connected to the Zigbee network and advertising BLE, and around 50 uA after it had connected to the central.

    Best regards,
    Marte

  • Hi,

    See pcap attached.

    I tried to capture it a couple of times. One time, I saw after approx. 180seconds that all the traffic started to become "normal", as in that I saw it polling every 500ms (I set the poll time to 500ms).

    But then after I tried again I couldnt see this, it started to have this traffic for a longer period as you can see in the capture.

    What does this traffic mean? It finished steering by the way and is connected to the coordinator.wireshark_zigbee_capture2.pcapng

  • Hi,

    I am not able to decrypt the packets. Please share the network key so I can decrypt them, or capture a new sniffer where you start the sniffer before the coordinator creates the network so the sniffer has the network key.

    Best regards,

    Marte

Reply Children
Related