How to reduce zigbee power consumption when endpoint is searching network

We have a multiprotocol project running BLE and Zigbee Stacks. The device always operate on BLE, but Zigbee is optional. The project is developed using NCS with zephyr revision v2.4.99-ncs2. Zigbee can be enabled or disabled writing to a BLE characteristic. The device is configured as a Zigbee Endpoint

Zigbee stack is started with those lines of code:

	zb_af_register_device_ctx(&device_context);

	zb_set_ed_timeout(ED_AGING_TIMEOUT_64MIN);
	zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000));
	zb_set_rx_on_when_idle(ZB_FALSE);

	zigbee_enable();

When zigbee stack is searching network, the device is consuming around 15 mA, and after successful steering it lows down to 100 uA. If Zigbee is enabled, consumption is OK, but when Zigbee is disabled, and no network is available, the device keeps consuming 15 mA forever.

My questions are:

¿How can I disable the Zigbee stack on runtime, and avoid the consumption part due to zigbee functions?

alternatively

¿Is there a way to simulate a network join, without having a real network, so that the Zigbee EP thinks it is connected and the consumption keeps on 100 uA?

Even if we decide not to execute zigbee_enable at start up, the fact of having CONFIG_ZIGBEE=y consumes around 1 mA. So that not enabling zigbee at start up, is not an option.

Any help will be appreciated, thanks,

Jordi

  • Hi Andreas,

    The following zboss_signal_handler implementation works:

    void zboss_signal_handler(zb_bufid_t bufid)
    {
    	ZigbeeDeviceContext* instance = ZigbeeDeviceContext::getInstance();
    
    	zb_zdo_app_signal_hdr_t* p_sg_p = nullptr;
    	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 ret_code = RET_OK;
    
    	if(sig == ZB_BDB_SIGNAL_STEERING && status != RET_OK) { /**< Avoid start_network_rejoin */
    		instance->joinedUnsuccessful();
    		LOG_INF("Network steering was not successful (status: %d)", status);
    	} 
    	else if(sig == ZB_BDB_SIGNAL_DEVICE_REBOOT && status != RET_OK) { /**< Stored PAN-ID not found, avoid start_network_rejoin */
    		instance->joinedUnsuccessful();
    		LOG_INF("Unable to join the network (status: %d", status);
    	}
    	else {
    		ret_code = zigbee_default_signal_handler(bufid);
    	}
    
    	if(ret_code == RET_OK) {
    		if(sig == ZB_BDB_SIGNAL_STEERING || sig == ZB_BDB_SIGNAL_DEVICE_REBOOT) {
    			if(status == RET_OK) {
    				instance->joinedSuccessful();
    			}
    		} else if(sig == ZB_COMMON_SIGNAL_CAN_SLEEP) {
    			if(instance->isJoined() == true) {
    				zb_sleep_now();
    			}
    		}
    	}
    
    	/* All callbacks should either reuse or free passed buffers.
    	 * If bufid == 0, the buffer is invalid (not passed).
    	 */
    	if(bufid) {
    		zb_buf_free(bufid);
    	}
    }
    

    On the other hand, my application requires enabling and disabling Zigbee via a BLE smartphone APP, but it is tough using actual zboss api, without compromising power consumption. There is neither zigbee_disable function nor anything suitable for that purpose. Until now, the only solution which I don't like, is to reboot system at every enable / disable change.

    Should you have  any idea or example of how to enable/disable Zigbee at runtime, without compromising sleepy mode and power consumption, it will be much appreciated.

    Thanks,

    Jordi 

  • Hi Jordi,

    Glad to hear that you have managed to get it to work, although with a somewhat hacky-solution!

    A couple of questions back at you:

    1) I have been right in assuming that the application you are developing is for an end device? It has not been explicitly stated so far, only implied through you working with the light switch sample.

    2) Did you read the multiprotocol documentation supplied and to what degree did you follow it? I'll be glad to help you further with questions regarding this if there was anything you did not understand in this resource! 

    Jorcis said:
    Should you have  any idea or example of how to enable/disable Zigbee at runtime, without compromising sleepy mode and power consumption, it will be much appreciated.

    There are currently no "easy" solution for enabling/disabling ZigBee at runtime, as has been stated by both me and you several times, but the multiprotocol sample and documentation I have supplied contains a solution that handles the issues you're struggling with in a different way. The only other hacky solution is what you've started with by overriding the signal handler or forcing the device to leave the network, and after this don't do anything more ZigBee-related unless told so. By default it will try to rejoin the network, which will cause the power consumption spike mentioned earlier, so you will need to disable this as well. If you manage to remove this "auto-rejoin-feature" it should be possible to implement something that triggers the enabling/rejoining whenever you send a signal over BLE on command.

    But I must add that I can not guarantee that we will be able to support your own custom multiprotocol solution in the future if it deviates far from our own supported multiprotocol solution, so keep that in mind to some degree!

    Kind regards,
    Andreas

  • Hi Andreas

    1) I have been right in assuming that the application you are developing is for an end device? It has not been explicitly stated so far, only implied through you working with the light switch sample.

    Yes you are right, I am developing for an end device. Sorry about that, now I realize I wrote down endpoint where I wanted to say end device.

    2) Did you read the multiprotocol documentation supplied and to what degree did you follow it? I'll be glad to help you further with questions regarding this if there was anything you did not understand in this resource!

    Yes, I have read the supplied documentation but, I have not entered into detail. I have taken some interesting pics about it, like the zigbee_configure_sleepy_behavior(true). You have done great job about the multiprotocol feature, congrats. I would like to understand a bit more about that, but there's some pressure about releasing an MVP, and I am not able to spend time with a deep reading and investigation. I tend to focus on the most practical aspects, being a mere user of the SDK API, although I don't discard to get into more detail in the future, I will let you know If I have further questions.

    We don't use BLE NUS as in the light_switch example, on the contrary our device is a peripheral BLE with a GATT table, with connection and disconnection from another central device. I would like to note than when we introduced Zigbee and multiprotocol, it worked without significant modifications, so that was amazing, and in some kind magic!

    Also, on the other hand, in the light_switch example I have observed pairing callbacks, and I wonder how it works in BLE:

    	.pairing_confirm = pairing_confirm,
    	.pairing_complete = pairing_complete,
    	.pairing_failed = pairing_failed
    

    I wonder if it would be possible to pair BLE peripheral and central device, automatically when they get closer one another. There's a possibly general misunderstanding in our department that pairing is only possible between two legacy traditional bluetooth devices but not between low energy ones.

    Anyway, many thanks for you kind help and support.

    Jordi.

  • Hi Jordi,

    1) and 2): Great! Then we're on the same page! It is easy to focus on the practical aspects about something, and not spend enough time on reading and understanding the theory/API and I must admit I really know the feeling of prioritizing one over the other!..

    Jorcis said:
    I wonder if it would be possible to pair BLE peripheral and central device, automatically when they get closer one another.

    Yes, this is possible, and it can be done by modifying the peripheral_uart and central_uart filters. The BLE scan API should give you a headstart on how to do this together with those two samples. What you want to do is to limit the scanning of devices with a filter such that the peripheral only advertises a given filter (it could be UUID or a name in form of a string), and that the central and peripheral should only connect to each other if that filter criteria is met

    You could get started with this documentation and the two samples, and I'll see if I can put together a small sample illustrating this tomorrow!

    Kind regards,
    Andreas

  • Hi again, following up from yesterdays post

    Jorcis said:
    There's a possibly general misunderstanding in our department that pairing is only possible between two legacy traditional bluetooth devices but not between low energy ones.

    Yes, this is a misunderstanding. Both bonding and pairing can be done with both legacy Bluetooth protocol and newer Low Energy protocols. I said I was going to create a small sample to illustrate this, but I think the peripheral_bms sample which uses the Bluetooth LE bond module or the central and peripheral hrs, sample which scans for peripherals with the heart rate service defined, explains this far better. Here you may also see how the pairing callback structs are done line 128 in the main file in peripheral_bms as well as 202 in central_and_peripheral_hrs with with their respective 

    I hope this answers the missing details from my reply yesterday!

    Kind regards,
    Andreas

Related