Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zigbee: Improve the sleep sketch with regard to energy requirements #10746

Closed
1 task done
michapr opened this issue Dec 17, 2024 · 79 comments · Fixed by #11123
Closed
1 task done

Zigbee: Improve the sleep sketch with regard to energy requirements #10746

michapr opened this issue Dec 17, 2024 · 79 comments · Fixed by #11123
Assignees
Labels
Area: Libraries Issue is related to Library support. Area: Zigbee Issues and Feature Request about Zigbee Status: Pending Merge Pull Request is ready to be merged

Comments

@michapr
Copy link

michapr commented Dec 17, 2024

Board

ESP32H2

Device Description

Devboard, Supermini

Hardware Configuration

nothing connected

Version

latest development Release Candidate (RC-X)

IDE Name

Arduino IDE

Operating System

Windows 11

Flash frequency

80MHz

PSRAM enabled

no

Upload speed

921600

Description

The device require too much energy in active and sleeping mode.
ppk-20241217T194851

  1. not clear, why there are so many peaks with 100mA
  2. sleeping current is in my case about 450uA - too much. Any idea how to minimize it for ESP32H2?
    • maybe other request - provide a light sleep example without needed rejoin

Sketch

A bit modified sleeping sketch:
----------------------------------

#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"
#include <rom/rtc.h>

#define BOOT_PIN                  9  //Boot button for C6/H2
/* Zigbee temperature + humidity sensor configuration */
#define TEMP_SENSOR_ENDPOINT_NUMBER 10

#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  55         /* Sleep for 55s will + 5s delay for establishing connection => data reported every 1 minute */

uint8_t button = BOOT_PIN;

ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER);

/************************ Temp sensor *****************************/
void meausureAndSleep() {
  // Measure temperature sensor value
  float temperature = temperatureRead();

  // Use temperature value as humidity value to demonstrate both temperature and humidity
  float humidity = temperature;

  // Update temperature and humidity values in Temperature sensor EP
  zbTempSensor.setTemperature(temperature);
  zbTempSensor.setHumidity(humidity);

  // Report temperature and humidity values
  zbTempSensor.reportTemperature();
  //delay(100);
  zbTempSensor.reportHumidity();
 
  Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%\r\n", temperature, humidity);

  // Put device to deep sleep
  Serial.println("Going to sleep now");
  delay(100);
}

/********************* Arduino functions **************************/
void setup() {
  Serial.begin(115200);

  // Init button switch
  pinMode(button, INPUT_PULLUP);

  // Configure the wake up source and set to wake up every 5 seconds
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

  // Optional: set Zigbee device name and model
  zbTempSensor.setManufacturerAndModel("Espressif", "SleepyZigbeeTempSensorTest");

  // Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement)
  zbTempSensor.setMinMaxValue(10, 50);

  // Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C)
  zbTempSensor.setTolerance(1);

  // Set power source to battery and set battery percentage to measured value (now 100% for demonstration)
  // The value can be also updated by calling zbTempSensor.setBatteryPercentage(percentage) anytime
  zbTempSensor.setPowerSource(ZB_POWER_SOURCE_BATTERY, 100);

  // Add humidity cluster to the temperature sensor device with min, max and tolerance values
  zbTempSensor.addHumiditySensor(0, 100, 1);

  // Add endpoint to Zigbee Core
  Zigbee.addEndpoint(&zbTempSensor);

  // Create a custom Zigbee configuration for End Device with keep alive 10s to avoid interference with reporting data
  esp_zb_cfg_t zigbeeConfig = ZIGBEE_DEFAULT_ED_CONFIG();
  zigbeeConfig.nwk_cfg.zed_cfg.keep_alive = 10000;

  // When all EPs are registered, start Zigbee in End Device mode
  if (!Zigbee.begin(&zigbeeConfig, false)) {
    Serial.println("Zigbee failed to start!");
    Serial.println("Rebooting...");
    ESP.restart();
  }
  Serial.println("Connecting to network");
  while (!Zigbee.connected()) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();
  Serial.println("Successfully connected to Zigbee network");

  // Delay approx 1s (may be adjusted) to allow establishing proper connection with coordinator, needed for sleepy devices
   if ( (int)rtc_get_reset_reason(0) != 5 )  { // =  SW_CPU_RESET=12  // POWERON_RESET=1 //DEEPSLEEP_RESET=5
     delay(20000);
   }
}

void loop() {
  // Checking button for factory reset
  if (digitalRead(button) == LOW) {  // Push button pressed
    // Key debounce handling
    delay(100);
    int startTime = millis();
    while (digitalRead(button) == LOW) {
      delay(50);
      if ((millis() - startTime) > 3000) {
        // If key pressed for more than 3secs, factory reset Zigbee and reboot
        Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
        delay(1000);
        Zigbee.factoryReset();
      }
    }
  }

  // Call the function to measure temperature and put the device to sleep
  meausureAndSleep();
}

Debug Message

No errors in debug

Other Steps to Reproduce

disabled USB CDC, debugging for saving energy.
Have removed the internal temperature procedure and replaced with random value.

Have used Nordic Power Profiler Kit II for measurements with 3.3V power

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@michapr michapr added the Status: Awaiting triage Issue is waiting for triage label Dec 17, 2024
@michapr
Copy link
Author

michapr commented Dec 18, 2024

Have added before Zigbee.begin (because was thinking about scanning):
Zigbee.setPrimaryChannelMask(0x800);
but no change. (channel 11 in my case)

@P-R-O-C-H-Y
Copy link
Member

I will be able to test the consumption at the start of new year again to check if there is anything that can help.
But I can tell that if you are willing to do the LightSleep you have to switch to use the esp-zigbee-sdk directly. They have the light sleep example there. For Arduino it's not possible now, as there need to be a tickles RTOS config set, which we won't have anytime soon, as it may bring unexpected behavior.

@P-R-O-C-H-Y
Copy link
Member

Have added before Zigbee.begin (because was thinking about scanning): Zigbee.setPrimaryChannelMask(0x800); but no change. (channel 11 in my case)

What you can do that can help with optimizing stuff is to provide a pcap file from Wireshark, to see what is happening at that time. If there are some transmissions going on in the peaks. Otherwise for now there is nothing you can set/select to make it more power efficient.

@P-R-O-C-H-Y P-R-O-C-H-Y added Area: Libraries Issue is related to Library support. and removed Status: Awaiting triage Issue is waiting for triage labels Dec 18, 2024
@P-R-O-C-H-Y
Copy link
Member

Btw the energy consumption in the deep sleep is probably related to the board design. I can't tell what board I used if it was C6 or H2 Espressifs devout, but in deep sleep the power consumption was 9,8 uA. That's a big difference.

@michapr
Copy link
Author

michapr commented Dec 18, 2024

My Wireshark setup is not working, haven't found time to find out what happen...

About spikes: what I see in the Gateway logs is, that looks like a routing problem after rejoin (get messages like ezspIncomingNetworkStatusHandler(): callback called with: [errorCode=ROUTE_ERROR_TREE_LINK_FAILURE], [target=12084] ).
Same effect in ZHA (other log lines in debug mode) and in Zigbee2MQTT

Otherwise for now there is nothing you can set/select to make it more power efficient.

Why it is not possible to save all session information in RTC RAM and use it after reboot from deep sleep mode (if valid)?
Same was realized for ESP32 Lora modules and is working fine.

I can't tell what board I used if it was C6 or H2 Espressifs devout, but in deep sleep the power consumption was 9,8 uA. That's a big difference.

without any additional settings? like pin setting to analog input or disable anything?
Something like Zigbee.end() is not needed to switch off the modem part?

@P-R-O-C-H-Y
Copy link
Member

without any additional settings? like pin setting to analog input or disable anything?
Something like Zigbee.end() is not needed to switch off the modem part?

No additional settings, I am just using the sleepy example how its written.
In Deep-sleep mode, the CPUs, most of the RAM, and all digital peripherals that are clocked from APB_CLK are powered off. The only parts of the chip that remain powered on are:

  • RTC controller
  • ULP coprocessor
  • RTC FAST memory

So there is no need for Zigbee.end()

Why it is not possible to save all session information in RTC RAM and use it after reboot from deep sleep mode (if valid)?
Same was realized for ESP32 Lora modules and is working fine.

I will need to investigate this, if there is anything that can help. But the stuff is saved in Zigbee partitions, and it should be recalled. But the device still has to reconnect to the network.

My Wireshark setup is not working, haven't found time to find out what happen...

If you have some time, would b nice to have the logs from the Wireshark.

About spikes: what I see in the Gateway logs is, that looks like a routing problem after rejoin (get messages like ezspIncomingNetworkStatusHandler(): callback called with: [errorCode=ROUTE_ERROR_TREE_LINK_FAILURE], [target=12084] ).
Same effect in ZHA (other log lines in debug mode) and in Zigbee2MQTT

I can ask about this, but for sure more informations would be needed (WireShark traffic).

@michapr
Copy link
Author

michapr commented Dec 18, 2024

I will need to investigate this, if there is anything that can help. But the stuff is saved in Zigbee partitions, and it should be recalled. But the device still has to reconnect to the network.

But the "rejoin process" should be other and much faster.
If you compare with commercial temperature sensors - the online time is here < 1second (if taken the logs from Zigbee gateway to compare it)
Device will be recognized without a real rejoin.

@michapr
Copy link
Author

michapr commented Dec 21, 2024

About spikes: what I see in the Gateway logs is, that looks like a routing problem after rejoin (get messages like ezspIncomingNetworkStatusHandler(): callback called with: [errorCode=ROUTE_ERROR_TREE_LINK_FAILURE], [target=12084] ).
Same effect in ZHA (other log lines in debug mode) and in Zigbee2MQTT

I can ask about this, but for sure more informations would be needed (WireShark traffic).

Cannot confirm my thoughts.... the routing errors was something else...

In Wireshark see only short Zigbee time. So the other code before need so much time for "something"...

grafik
and
grafik

This difference is interesting, but not the top important thing....

@SuGlider SuGlider added the Area: Zigbee Issues and Feature Request about Zigbee label Dec 29, 2024
@P-R-O-C-H-Y
Copy link
Member

I will need to investigate this, if there is anything that can help. But the stuff is saved in Zigbee partitions, and it should be recalled. But the device still has to reconnect to the network.

But the "rejoin process" should be other and much faster. If you compare with commercial temperature sensors - the online time is here < 1second (if taken the logs from Zigbee gateway to compare it) Device will be recognized without a real rejoin.

The difference is probably the deep sleep (we use) vs light sleep (they use).
If you need to make it more power efficient you should move to use esp-idf and the zigbee-sdk directly and use the light sleep mode there. I will keep track on this and if I have any news, I will post an update if there is any improvement.

@michapr
Copy link
Author

michapr commented Jan 6, 2025

@P-R-O-C-H-Y Light sleep is not a solution for ESP32 - too high sleeping current.
What I really do not understand is - what happen all the time after wakeup and first Zigbee packet.
Zigbee live time is ok, wakeup time also - but if you look to debug log, you see that a long time "nothing" happen (ZBOSS), only the spikes are visible. This is the most time of all the process.

@P-R-O-C-H-Y
Copy link
Member

@P-R-O-C-H-Y Light sleep is not a solution for ESP32 - too high sleeping current. What I really do not understand is - what happen all the time after wakeup and first Zigbee packet. Zigbee live time is ok, wakeup time also - but if you look to debug log, you see that a long time "nothing" happen (ZBOSS), only the spikes are visible. This is the most time of all the process.

@michapr Would you be able to do some timeline (I can do it also, but it would help a lot if you can) to see the times from debug log and the packets from Wireshark to have them side by side to really see, the "nothing" happen in any of those logs and the spikes(peaks) are there? I can then report it and discuss more deeply with the Zigbee team. Don't forget to select the Zigbee ED debug libs :)

@michapr
Copy link
Author

michapr commented Jan 6, 2025

Used the sample sketch above.

Debug log:

=========== Before Setup Start ===========
Chip Info:
------------------------------------------
  Model             : ESP32-H2
  Package           : 0
  Revision          : 0.01
  Cores             : 1
  CPU Frequency     : 96 MHz
  XTAL Frequency    : 32 MHz
  Features Bitfield : 0x00000050
  Embedded Flash    : No
  Embedded PSRAM    : No
  2.4GHz WiFi       : No
  Classic BT        : No
  BT Low Energy     : Yes
  IEEE 802.15.4     : Yes
------------------------------------------
INTERNAL Memory Info:
------------------------------------------
  Total Size        :   235808 B ( 230.3 KB)
  Free Bytes        :   202452 B ( 197.7 KB)
  Allocated Bytes   :    28204 B (  27.5 KB)
  Minimum Free Bytes:   197640 B ( 193.0 KB)
  Largest Free Block:   184308 B ( 180.0 KB)
------------------------------------------
Flash Info:
------------------------------------------
  Chip Size         :  4194304 B (4 MB)
  Block Size        :    65536 B (  64.0 KB)
  Sector Size       :     4096 B (   4.0 KB)
  Page Size         :      256 B (   0.2 KB)
  Bus Speed         : 64 MHz
  Bus Mode          : QIO
------------------------------------------
Partitions Info:
------------------------------------------
                nvs : addr: 0x00009000, size:    20.0 KB, type: DATA, subtype: NVS
            otadata : addr: 0x0000E000, size:     8.0 KB, type: DATA, subtype: OTA
               app0 : addr: 0x00010000, size:  1280.0 KB, type:  APP, subtype: OTA_0
               app1 : addr: 0x00150000, size:  1280.0 KB, type:  APP, subtype: OTA_1
             spiffs : addr: 0x00290000, size:  1388.0 KB, type: DATA, subtype: SPIFFS
         zb_storage : addr: 0x003EB000, size:    16.0 KB, type: DATA, subtype: FAT
             zb_fct : addr: 0x003EF000, size:     4.0 KB, type: DATA, subtype: FAT
           coredump : addr: 0x003F0000, size:    64.0 KB, type: DATA, subtype: COREDUMP
------------------------------------------
Software Info:
------------------------------------------
  Compile Date/Time : Jan  6 2025 11:29:50
  Compile Host OS   : windows
  ESP-IDF Version   : v5.3.2-174-g083aad99cf-dirty
  Arduino Version   : 3.1.0
------------------------------------------
Board Info:
------------------------------------------
  Arduino Board     : ESP32H2_DEV
  Arduino Variant   : esp32h2
  Arduino FQBN      : esp32:esp32:esp32h2:UploadSpeed=921600,CDCOnBoot=cdc,FlashFreq=64,FlashMode=qio,FlashSize=4M,PartitionScheme=zigbee,DebugLevel=verbose,EraseFlash=all,JTAGAdapter=default,ZigbeeMode=ed_debug
============ Before Setup End ============
[   990][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 26 already has type USB_DM (38) with bus 0x408114d4
[   991][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 27 already has type USB_DP (39) with bus 0x408114d4
[   992][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type GPIO (1) successfully set to 0x42003c24
[   993][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 9 successfully set to type GPIO (1) with bus 0xa
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x42 attr_value 0x4081a44c
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 10
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x42 attr_value 0x4081a468
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 27
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x29 attr_value 0x4081edfc
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 2
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x29 attr_value 0x4081edfe
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 2
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x21 attr_value 0x4081edfe
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 2
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x30 attr_value 0x4081edfc
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 1
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x20 attr_value 0x4081edfb
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 1
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x21 attr_value 0x4081edee
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 2
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x21 attr_value 0x4081ede8
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 2
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x21 attr_value 0x4081edea
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 2
ZBOSS: zcl/zcl_common.c:215   >> zb_zcl_get_attribute_size: attr_type 0x21 attr_value 0x4081edec
ZBOSS: zcl/zcl_common.c:348   << zb_zcl_get_attribute_size: result 2
[  1009][D][ZigbeeCore.cpp:84] addEndpoint(): Endpoint: 10, Device ID: 0x0302
[  1010][D][ZigbeeCore.cpp:123] zigbeeInit(): Initialize Zigbee stack
ZBOSS: common/zb_init_default.c:181   ED build
ZBOSS: common/zb_init_default.c:187   sizes: g_zb 7576 sched 224 bpool 16 nwk 912 aps 3040 addr 284 zdo 840
ZBOSS: common/zb_init_default.c:196   sec 2
ZBOSS: common/zb_init_default.c:198   zcl 768
ZBOSS: common/zb_init_default.c:201   zll 960
ZBOSS: common/zb_init_default.c:207   nvram 140
ZBOSS: common/zb_init_default.c:210   buttons 200
ZBOSS: common/zb_init_default.c:212   err_ind 4
ZBOSS: common/zb_init_default.c:218   scheduler q size 80
ZBOSS: common/zb_init_default.c:221   g_mac 816 g_imac 28
ZBOSS: common/zb_init_default.c:225   Configurable mem build, use ZBOSS lib defaults = 0
ZBOSS: common/zb_init_default.c:231   ZB_IOBUF_POOL_SIZE 80 ZB_NWK_IN_Q_SIZE 40 ZB_MAC_PENDING_QUEUE_SIZE 20 ZB_APS_DST_BINDING_TABLE_SIZE 16 ZB_APS_BIND_TRANS_TABLE_SIZE 20 ZB_N_APS_RETRANS_ENTRIES 27
ZBOSS: common/zb_init_default.c:261   ZB_N_APS_KEY_PAIR_ARR_MAX_SIZE 8 ZB_IEEE_ADDR_TABLE_SIZE 64 ZB_NEIGHBOR_TABLE_SIZE 64 ZB_NWK_ROUTING_TABLE_SIZE 0 ZB_APS_DUPS_TABLE_SIZE 32
[  1035][D][ZigbeeCore.cpp:130] zigbeeInit(): Register all Zigbee EPs in list
ZBOSS: zdo/af_descriptor.c:357   ep_count 1
[  1039][I][ZigbeeCore.cpp:138] zigbeeInit(): List of registered Zigbee EPs:
[  1039][I][ZigbeeCore.cpp:140] zigbeeInit(): Device type: Temperature Sensor, Endpoint: 10, Device ID: 0x0302
ZBOSS: common/zb_nvram.c:3190   ds_ver == 2
ZBOSS: zdo/zdo_app_prod_conf.c:144   no production config block found
ZBOSS: zdo/zdo_app_prod_conf.c:781   no valid production configuration found, signaling to application
[  1057][V][ZigbeeCore.cpp:339] esp_zb_app_signal_handler(): ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL
[  1058][I][ZigbeeCore.cpp:219] esp_zb_app_signal_handler(): Zigbee stack initialized
ZBOSS: commissioning/bdb/zdo_commissioning_bdb.c:349   dev type 2, joined 1, ext_pan_id 1, authenticated 1, tclk_valid 1
ZBOSS: nwk/nwk_join.c:186   low lqi 0
ZBOSS: nwk/nwk_join.c:186   low lqi 0
ZBOSS: nwk/nwk_join.c:186   low lqi 0
ZBOSS: zdo/zdo_app_join.c:771   CONGRATULATIONS! joined status 0, addr 0xe059, iface_id 0, ch 11, rejoin 1
ZBOSS: zdo/zdo_app_join.c:773   xpanid 3a:63:5d:94:1c:56:10:7e
ZBOSS: commissioning/bdb/zdo_commissioning_bdb.c:549   COMMISSIONING_STOP: app signal 6 comm status 0
[  3440][I][ZigbeeCore.cpp:225] esp_zb_app_signal_handler(): Device started up in non factory-reset mode
[  3441][I][ZigbeeCore.cpp:238] esp_zb_app_signal_handler(): Device rebooted
[  3442][D][ZigbeeCore.cpp:466] searchBindings(): Requesting binding table for address 0xe059
[  3445][D][ZigbeeCore.cpp:406] bindingTableCb(): Binding table callback for address 0xe059 with status 0
[  3446][D][ZigbeeCore.cpp:409] bindingTableCb(): Binding table info: total 3, index 0, count 3
[  3447][D][ZigbeeCore.cpp:419] bindingTableCb(): Binding table record: src_endp 10, dst_endp 1, cluster_id 0x0402, dst_addr_mode 3
[  3448][D][ZigbeeCore.cpp:436] bindingTableCb(): Device bound to EP 10 -> device endpoint: 1, short addr: 0x0000, ieee addr: 94:34:69:FF:FE:0D:65:A9
[  3450][D][ZigbeeCore.cpp:419] bindingTableCb(): Binding table record: src_endp 10, dst_endp 1, cluster_id 0x0001, dst_addr_mode 3
[  3451][D][ZigbeeCore.cpp:436] bindingTableCb(): Device bound to EP 10 -> device endpoint: 1, short addr: 0x0000, ieee addr: 94:34:69:FF:FE:0D:65:A9
[  3452][D][ZigbeeCore.cpp:419] bindingTableCb(): Binding table record: src_endp 10, dst_endp 1, cluster_id 0x0405, dst_addr_mode 3
[  3453][D][ZigbeeCore.cpp:436] bindingTableCb(): Device bound to EP 10 -> device endpoint: 1, short addr: 0x0000, ieee addr: 94:34:69:FF:FE:0D:65:A9
[  3454][D][ZigbeeCore.cpp:457] bindingTableCb(): Filling bounded devices finished
Connecting to network

Successfully connected to Zigbee network
=========== After Setup Start ============
INTERNAL Memory Info:
------------------------------------------
  Total Size        :   235808 B ( 230.3 KB)
  Free Bytes        :   175104 B ( 171.0 KB)
  Allocated Bytes   :    54608 B (  53.3 KB)
  Minimum Free Bytes:   175096 B ( 171.0 KB)
  Largest Free Block:   163828 B ( 160.0 KB)
------------------------------------------
GPIO Info:
------------------------------------------
  GPIO : BUS_TYPE[bus/unit][chan]
  --------------------------------------  
     9 : GPIO
    23 : UART_RX[0]
    24 : UART_TX[0]
    26 : USB_DM
    27 : USB_DP
============ After Setup End =============
[  3496][V][ZigbeeTempSensor.cpp:71] setTemperature(): Updating temperature sensor value...
[  3498][D][ZigbeeTempSensor.cpp:73] setTemperature(): Setting temperature to 2000
[  3499][V][ZigbeeTempSensor.cpp:112] setHumidity(): Updating humidity sensor value...
[  3501][D][ZigbeeTempSensor.cpp:114] setHumidity(): Setting humidity to 2000
[  3506][V][ZigbeeTempSensor.cpp:93] reportTemperature(): Temperature report sent
[  3512][V][ZigbeeTempSensor.cpp:135] reportHumidity(): Humidity report sent
Reported temperature: 20.00°C, Humidity: 20.00%
Going to sleep now

[  3700][V][ZigbeeHandlers.cpp:134] zb_cmd_default_resp_handler(): Received default response: from address(0x0), src_endpoint(1) to dst_endpoint(10), cluster(0x402) with status 0x0
[  3717][V][ZigbeeHandlers.cpp:134] zb_cmd_default_resp_handler(): Received default response: from address(0x0), src_endpoint(1) to dst_endpoint(10), cluster(0x405) with status 0x0

Wireshark:

Wireshark

Data from Nordic Power Profiler v4.2.1
ppk2_H2_zigbee

Zigbee online time:
ppk2_H2_zigbee_1

Over all:
Power_profile_H2_Zigbee

@michapr
Copy link
Author

michapr commented Jan 23, 2025

@P-R-O-C-H-Y Are here any news about the ZBOSS procedure? What happens here during this time?

Thanks!

@P-R-O-C-H-Y
Copy link
Member

P-R-O-C-H-Y commented Jan 28, 2025

@michapr No news yet, once I have anything I will let you know :)

Just thinking out loud, possible solution would be to add support for light sleep to the library and then use the Arduino as a component in IDF or build custom libs, where the freertos tickless mode would be enabled.
And see how it goes. Compare deep sleep vs light sleep power consumption/start up time.

@psi-4ward
Copy link

I'd a cheap temp sensor a while ago and it mostly chooses a bulb as router but the bulb was not reachable for some months. Zigbee2mqtt map showed that the sensor uses another router after some time but the battery drained every 2 months. After powering the bulb again the battery holds a year.

So long story short, could it be the case the device has to find another router after wakeup?

@def1149
Copy link

def1149 commented Feb 23, 2025

I've played around with this Zigbee example and determined that there's some kind of quirk (bug?) when calling esp_deep_sleep_start(); from a function. I see the same high current behavior you reported. I moved esp_deep_sleep_start(); to the main loop and I see the expected about 19 uA during deep sleep. I also made a few other changes to optimize deep sleep power saving.

It works pretty well

But, I have a few open issues to solve:

  1. If I power off and reconnect I have to remove the device from Home Assistant and re-enroll it unless I wait a while to reconnect then it works without re-enrolling???.
  2. There are a couple of errors in the log I need to sort out.

During operation

09:53:06.303 -> [   954][D][ZigbeeCore.cpp:84] addEndpoint(): Endpoint: 10, Device ID: 0x0302
09:53:06.303 -> [   955][D][ZigbeeCore.cpp:123] zigbeeInit(): Initialize Zigbee stack
09:53:06.303 -> [   978][D][ZigbeeCore.cpp:130] zigbeeInit(): Register all Zigbee EPs in list
09:53:06.303 -> [   980][I][ZigbeeCore.cpp:138] zigbeeInit(): List of registered Zigbee EPs:
09:53:06.303 -> [   981][I][ZigbeeCore.cpp:140] zigbeeInit(): Device type: Temperature Sensor, Endpoint: 10, Device ID: 0x0302
ERROR >>>> 09:53:06.335 -> [   996][V][ZigbeeCore.cpp:352] esp_zb_app_signal_handler(): ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL
09:53:06.335 -> [   998][I][ZigbeeCore.cpp:219] esp_zb_app_signal_handler(): Zigbee stack initialized
09:53:08.674 -> [  3356][I][ZigbeeCore.cpp:225] esp_zb_app_signal_handler(): Device started up in non factory-reset mode
09:53:08.674 -> [  3357][I][ZigbeeCore.cpp:238] esp_zb_app_signal_handler(): Device rebooted
09:53:08.674 -> [  3358][D][ZigbeeCore.cpp:479] searchBindings(): Requesting binding table for address 0x20d8
09:53:08.674 -> [  3360][D][ZigbeeCore.cpp:419] bindingTableCb(): Binding table callback for address 0x20d8 with status 0
09:53:08.674 -> [  3361][D][ZigbeeCore.cpp:422] bindingTableCb(): Binding table info: total 2, index 0, count 2
09:53:08.718 -> [  3362][D][ZigbeeCore.cpp:432] bindingTableCb(): Binding table record: src_endp 10, dst_endp 1, cluster_id 0x0402, dst_addr_mode 3
09:53:08.718 -> [  3363][D][ZigbeeCore.cpp:449] bindingTableCb(): Device bound to EP 10 -> device endpoint: 1, short addr: 0x0000, ieee addr: F0:82:C0:FF:FE:6B:DB:EC
09:53:08.718 -> [  3365][D][ZigbeeCore.cpp:432] bindingTableCb(): Binding table record: src_endp 10, dst_endp 1, cluster_id 0x0001, dst_addr_mode 3
09:53:08.718 -> [  3366][D][ZigbeeCore.cpp:449] bindingTableCb(): Device bound to EP 10 -> device endpoint: 1, short addr: 0x0000, ieee addr: F0:82:C0:FF:FE:6B:DB:EC
09:53:08.718 -> [  3368][D][ZigbeeCore.cpp:470] bindingTableCb(): Filling bounded devices finished
09:53:08.718 -> Connecting to network
09:53:08.718 -> 
09:53:08.718 -> Successfully connected to Zigbee network
09:53:08.923 -> [  3570][V][ZigbeeEP.cpp:97] setBatteryPercentage(): Battery percentage updated
09:53:08.923 -> [  3571][V][ZigbeeTempSensor.cpp:58] setTemperature(): Updating temperature sensor value...
09:53:08.923 -> [  3573][D][ZigbeeTempSensor.cpp:60] setTemperature(): Setting temperature to 900
09:53:08.923 -> [  3574][V][ZigbeeEP.cpp:112] reportBatteryPercentage(): Battery percentage reported
09:53:08.923 -> [  3578][V][ZigbeeTempSensor.cpp:80] reportTemperature(): Temperature report sent
09:53:08.923 -> Reported temperature: 9.00°C, Battery Pct: 51%
09:53:09.095 -> Going to sleep now

During enrollment:

0:10:53.804 -> [   802][D][ZigbeeCore.cpp:84] addEndpoint(): Endpoint: 10, Device ID: 0x0302
10:10:53.804 -> [   803][D][ZigbeeCore.cpp:123] zigbeeInit(): Initialize Zigbee stack
10:10:53.837 -> [   877][D][ZigbeeCore.cpp:130] zigbeeInit(): Register all Zigbee EPs in list
10:10:53.882 -> [   879][I][ZigbeeCore.cpp:138] zigbeeInit(): List of registered Zigbee EPs:
10:10:53.882 -> [   880][I][ZigbeeCore.cpp:140] zigbeeInit(): Device type: Temperature Sensor, Endpoint: 10, Device ID: 0x0302
10:10:53.882 -> [   898][V][ZigbeeCore.cpp:352] esp_zb_app_signal_handler(): ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL
10:10:53.882 -> [   900][I][ZigbeeCore.cpp:219] esp_zb_app_signal_handler(): Zigbee stack initialized
10:10:56.268 -> [  3264][I][ZigbeeCore.cpp:225] esp_zb_app_signal_handler(): Device started up in non factory-reset mode
10:10:56.268 -> [  3265][I][ZigbeeCore.cpp:238] esp_zb_app_signal_handler(): Device rebooted
10:10:56.268 -> [  3266][D][ZigbeeCore.cpp:479] searchBindings(): Requesting binding table for address 0x20d8
10:10:56.268 -> [  3268][D][ZigbeeCore.cpp:419] bindingTableCb(): Binding table callback for address 0x20d8 with status 0
10:10:56.268 -> [  3269][D][ZigbeeCore.cpp:422] bindingTableCb(): Binding table info: total 2, index 0, count 2
10:10:56.268 -> [  3270][D][ZigbeeCore.cpp:432] bindingTableCb(): Binding table record: src_endp 10, dst_endp 1, cluster_id 0x0402, dst_addr_mode 3
10:10:56.268 -> [  3271][D][ZigbeeCore.cpp:449] bindingTableCb(): Device bound to EP 10 -> device endpoint: 1, short addr: 0x0000, ieee addr: F0:82:C0:FF:FE:6B:DB:EC
10:10:56.268 -> [  3273][D][ZigbeeCore.cpp:432] bindingTableCb(): Binding table record: src_endp 10, dst_endp 1, cluster_id 0x0001, dst_addr_mode 3
10:10:56.268 -> [  3274][D][ZigbeeCore.cpp:449] bindingTableCb(): Device bound to EP 10 -> device endpoint: 1, short addr: 0x0000, ieee addr: F0:82:C0:FF:FE:6B:DB:EC
10:10:56.268 -> [  3275][D][ZigbeeCore.cpp:470] bindingTableCb(): Filling bounded devices finished
10:10:56.268 -> Connecting to network
10:10:56.268 -> 
10:10:56.268 -> Successfully connected to Zigbee network
10:10:56.438 -> [  3478][V][ZigbeeEP.cpp:97] setBatteryPercentage(): Battery percentage updated
10:10:56.480 -> [  3480][V][ZigbeeTempSensor.cpp:58] setTemperature(): Updating temperature sensor value...
10:10:56.480 -> [  3481][D][ZigbeeTempSensor.cpp:60] setTemperature(): Setting temperature to 700
10:10:56.480 -> [  3483][V][ZigbeeEP.cpp:112] reportBatteryPercentage(): Battery percentage reported
10:10:56.480 -> [  3492][V][ZigbeeTempSensor.cpp:80] reportTemperature(): Temperature report sent
10:10:56.480 -> Reported temperature: 7.00°C, Battery Pct: 45%

 ERROR >>>> 10:10:56.778 -> [  3817][W][ZigbeeHandlers.cpp:24] zb_action_handler(): Receive unhandled Zigbee action(0x12) callback

My version

/// Low Power Zigbee TemperatureSensor with Deep Sleep 
/// ---------------------------------------------------
///  H/W: ESP32-C6 (Adafruit Feather ESP32-C6)
///       Clock: 80 Mhz
///
///       Sleeps at about 19 uA
///       One hour average about 1 mA         with report conditions set as follows
///         #define TIME_TO_SLEEP  60         // Sleep time in seconds between wakeup fortemperature check
///         #define TEMP_DELTA 1.9            // Temp Delta: If temperature changes by more than this report 
///         #define MAX_CYCLES 19             // Maximum number of temperature read cycles without reporting 
///
///
///   Occam
///   02/23/2025 

#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"
#include <rom/rtc.h>

#define BOOT_PIN                  9  //Boot button for C6/H2
/* Zigbee temperature sensor configuration */
#define TEMP_SENSOR_ENDPOINT_NUMBER 10

#define uS_TO_S_FACTOR 1000000ULL // Conversion factor for micro seconds to seconds 
#define TIME_TO_SLEEP  60         // Sleep time in seconds between wakeup fortemperature check
#define TEMP_DELTA 1.9            // Temp Delta: If temperature changes by more than this report 
#define MAX_CYCLES 19             // Maximum number of temperature read cycles without reporting 

uint8_t button = BOOT_PIN;

// Store in RTC memory to persist across sleep cycles
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR float temperature  = 0.0;

ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER);

void report()
{
  long battery_pct;

 //newTemp = temperature/100.; // RTC 
 Serial.printf("New temperature = %d\r\n",temperature);
 //Serial.printf("newTemp     = %.2f\r\n",newTemp);
 battery_pct = random(5,95);

 // Optional: set Zigbee device name and model
  zbTempSensor.setManufacturerAndModel("Occam", "DeepSleepZigbeeTempSensorTest");
 // Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement)
 zbTempSensor.setMinMaxValue(-10,50);   // NB. The C6 CPU temp reports values less than 10 and is low by about 7C 
                                        //     If the temperature value is lower than the set minimum, a garbage of -327.7222 is reported
 // Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C)
 zbTempSensor.setTolerance(0.1);
 zbTempSensor.setPowerSource(ZB_POWER_SOURCE_BATTERY, 100);
 
 // Add endpoint to Zigbee Core
 Zigbee.addEndpoint(&zbTempSensor);

 // Create a custom Zigbee configuration for End Device with keep alive 10s to avoid interference with reporting data
 esp_zb_cfg_t zigbeeConfig = ZIGBEE_DEFAULT_ED_CONFIG();
 zigbeeConfig.nwk_cfg.zed_cfg.keep_alive = 10000;

 // When all EPs are registered, start Zigbee in End Device mode
 if (!Zigbee.begin(&zigbeeConfig, false)) {
   Serial.println("Zigbee failed to start!");
   Serial.println("Rebooting...");
   ESP.restart(); 
 }
 Serial.println("Connecting to network");
 while (!Zigbee.connected()) {
   Serial.print(".");
   delay(50);
 }
 Serial.println();
 Serial.println("Successfully connected to Zigbee network");
 delay(200); 

 zbTempSensor.setBatteryPercentage(battery_pct);
 zbTempSensor.setTemperature(temperature);

 // Report temperature and battery pct
 zbTempSensor.reportBatteryPercentage();
 zbTempSensor.reportTemperature();
                                                                                               
 Serial.printf("Reported temperature: %.2f°C, Battery Pct: %d%%\r\n", temperature, battery_pct);

 // Delay approx 1s (may be adjusted) to allow establishing proper connection with coordinator, needed for sleepy devices
 if ( (int)rtc_get_reset_reason(0) != 5 )  { // =  SW_CPU_RESET=12  // POWERON_RESET=1 //DEEPSLEEP_RESET=5
   delay(20000);
 }
 //temperature = (int) newTemp*100; 
 bootCount = 0;
 delay(200); // Allow time for update. Needed? Is there a "delivered"  status that can be checked in loop? 
}

/************************ Temp sensor *****************************/
void checkTemp() {
 // Measure temperature sensor value and report data if warranted 
  float newTemp = temperatureRead();
  float tempDelta = abs(newTemp-temperature);
  log_v("New Temp  = %.2f\r\n",newTemp);
  log_v("Last Temp  = %.2f\r\n",temperature);
  log_v("Temp Delta = %.2f\r\n",tempDelta);
  log_v("Boot Count = %d\r\n",bootCount );
  // Report  temp if temp change > than maximum difference  or number of checks exceeds maximum 
  if((tempDelta > TEMP_DELTA) || (bootCount > MAX_CYCLES)) {
    // Save new temp in RTC memory
    temperature = newTemp;
    report();
  } 
}

/********************* Arduino functions **************************/
void setup() {

 Serial.begin(115200);
 randomSeed(analogRead(0)); // Battery VDC is not being read reseed the PRNG 

 //Init button switch
 pinMode(button, INPUT_PULLUP);
 // Configure the wake up source and set to wake up every 5 seconds
 esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
 bootCount++; // Bump the read cycle counbt
}

void loop() {
 
 // Checking button for factory reset
 if (digitalRead(button) == LOW) {  // Push button pressed
   // Key debounce handling
   delay(100);
   int startTime = millis();
   while (digitalRead(button) == LOW) {
     delay(50);
     if ((millis() - startTime) > 3000) {
       // If key pressed for more than 3secs, factory reset Zigbee and reboot
       //ESP_LOGV("Resetting Zigbee to factory and rebooting in 1s.");
       delay(1000);
       Zigbee.factoryReset();
     }
   }
 }
 // Read temp and report if warranted 
 checkTemp();
 // Put device to deep sleep
 Serial.println("Going to sleep now");
 //delay(100);
 esp_deep_sleep_start();
}

Sleep Power Consumption

Image

One-hour Average

Image

Home Assistant Zigbee device page

Image

@michapr
Copy link
Author

michapr commented Feb 24, 2025

@def1149 - can you please show the power usage (chart from PPK) for the active process for your device?

Would be interesting to compare it to my H2

@def1149
Copy link

def1149 commented Feb 24, 2025

I'm using the Adafruit Feather ESP32-C6 which has a MAX17048 battery charger/monitor chip that I'm now using to measure the battery voltage and percent remaining since my previous post. https://www.adafruit.com/product/5933
I'll next be substituting a real temperature sensor for the very inaccurate CPU_temp sensor. I haven't decided on which one.
I have Log_V (verbose) enabled in the settings
CDC on boot enabled
Clock 80 MHz

Wake-up temp check cycle without a Zigbee connection.

Image

Wake-up temp check cycle with a Zigbee connection

Image

@michapr
Copy link
Author

michapr commented Feb 25, 2025

It's the same what I got with C6.
Main problem (in my opinion) is the ZBOSS function - it take too much time/energy in this process.
Would be really interesting what happen here in this time frame - and how to optimize it (see above).

about sensor - any good low power I2C sensor will be fine...

@P-R-O-C-H-Y - still no answer from ZBOSS team? Does it make sense for me to contact them - will I get an answer?
As far as I understand this is a special version for Espressif, isn't it?

@def1149
Copy link

def1149 commented Feb 25, 2025

I'm using the TMP36 analog temperature sensor or a DS18B20 depending on the use case. The DS18B20 is better if you need a long connection lead.

I found out why I had to re-join network after making changes. I had set erase flash before upload. It seems that the Arduino Zigbee library functions save some network configuration on the data partion it creates. If that gets erased, you have to rejoin the network. I erase flash the first time I program a device then I reset not to erase flash. Now I don't have to keep rejoining after making changes.

Image

Image

@michapr
Copy link
Author

michapr commented Feb 25, 2025

@def1149 - about erase flash - it is well known that you have to do it this way. You can often read about it here ;)
without this it will not work, onlc if you will not change Zigbee endpoints etc. it can work again.

About sensor - DS18B20 is only good for long distance, but it take too much time (and energy) in most cases for battery devices. And the accuracy is not so good either...

@def1149
Copy link

def1149 commented Feb 26, 2025

After setting Core Debug to None I've minimized power use.
The active time is now about 2.5 seconds shorter for both temperature a check w/o making a Zigbee connection and for a Zigbee
report reducing power consumption

Wake up for a temperature check w/o making a Zigbee connection: 0.31 seconds vs 2.48 seconds

Image

Wake up and report over Zigbee: 3.23 seconds vs 5.48 seconds

Image

@michapr
Copy link
Author

michapr commented Feb 26, 2025

yes,... it's the same about as for my devices (I get about 2850ms)

In this discussion we are looking for the spikes before Zigbee communication - see here: #10746 (comment)
This is inside the ZBOSS module.

@xieqinan
Copy link

xieqinan commented Feb 27, 2025

Hi @michapr,

What I really do not understand is - what happen all the time after wakeup and first Zigbee packet.

Regarding this issue, if the device is not factory reset, it will register its ZCL model with the stack, restore network information from NVRAM, and scan the network based on the channelmask to locate its parent for rejoining. If a parent is found, the device will initiate a rejoin request to attempt to rejoin the network.

From the figure above, the peaks suggest that the stack is scanning channels 11 to 26—a total of 16 times—which matches the number of peaks. Could you double-check this? If you have access to esp_ieee802154_set_channel(), you can print which channels are being scanned when the device attempts to rejoin.

I will also confirm this issue simultaneously, and any updates will be shared here.

@michapr
Copy link
Author

michapr commented Feb 27, 2025

@xieqinan Thank you for taking the time to find a solution here!

Where I can find the esp_ieee802154_set_channel() ?

I also was thinking about the rejoin and scanning channels, but I didn't receive packets in my Zigbee packet sniffer.
And - I have defined the channel to use before, so a scan must not be done (at least that's what I had hoped/thought...)
Using void setPrimaryChannelMask(uint32_t mask); have not changed anything.

If it really is the channel scanning, maybe the selected channel mask is not taken into account?

Thanks again!

@Jason2866 Jason2866 added the Status: Awaiting Response awaiting a response from the author label Mar 13, 2025
@michapr
Copy link
Author

michapr commented Mar 13, 2025

@xieqinan @P-R-O-C-H-Y
Should I open a new issue for this, or are you working on this issue?

Typically, a Zigbee network does not change its channel. When a device rejoins, it should scan only the known and available channels instead of all channels, which is more efficient and consumes less energy, right?

Can the above suggestion be realized to save the channel used during the join and then use it during the rejoin - and thus save energy?

If you remember, the problem is, that after wakeup from deep sleep the device will scan all channels for the rejoin - and consumes a lot of energy

@P-R-O-C-H-Y
Copy link
Member

@michapr Lets keep this open, I will be testing currently the scanning after rejoin, if that works as expected and link this issue to the PR with the changes :)

@P-R-O-C-H-Y
Copy link
Member

If anyone can give the linked PR a try. and give feedback I would appreciate that :)

@michapr
Copy link
Author

michapr commented Mar 14, 2025

@P-R-O-C-H-Y Can confirm that it is working fine! Thank you for your work!

If somebody else want to confirm, would be nice.
(line with channel definition in sketch above must be removed)

@P-R-O-C-H-Y
Copy link
Member

@P-R-O-C-H-Y Can confirm that it is working fine! Thank you for your work!

If somebody else want to confirm, would be nice.
(line with channel definition in sketch above must be removed)

Just to clarify, any example can be used to test that :) just hit the reset button to see the "fast" reconnection

@def1149
Copy link

def1149 commented Mar 14, 2025

I have confirmed the PR works. During initial enrollment, all 16 channels are scanned. On restart, or power off and power on, only one channel is scanned.

What happens if the channel on the controller is changed? Will the ED perform a full scan?

I changed the channel on the controller and the ED will repeatedly scan try to connect on the saved channel and never connect. Commercial Zibee devices will rescan reconnect after a channel change. I confirmed reconnecting on channel change with a Lumi temperature sensor, Third Reality Mains Switch, and Third Reality Door Sensor. Is there a function call to reinitiate a full scan if a connected attempt fails on the current saved channel? Maybe a call to erase the saved channel information. Would that force a new full channel scan ?

@Jason2866 Jason2866 added Status: Pending Merge Pull Request is ready to be merged and removed Resolution: Awaiting response Waiting for response of author Status: Awaiting Response awaiting a response from the author labels Mar 14, 2025
@P-R-O-C-H-Y
Copy link
Member

I have confirmed the PR works. During initial enrollment, all 16 channels are scanned. On restart, or power off and power on, only one channel is scanned.

What happens if the channel on the controller is changed? Will the ED perform a full scan?

I changed the channel on the controller and the ED will repeatedly scan and never connect. Commercial Zibee devices will rescan reconnect after a channel change. I confirmed reconnecting on channel change with a Lumi temperature sensor, Third Reality Mains Switch, and Third Reality Door Sensor. Is there a function call to reinitiate a full scan if a connected attempt fails on the current saved channel? Maybe a call to erase the saved channel information. Would that force a new full channel scan ?

Thank you for additional info and testing :) I did not cover this scenario. I was testing only if the device gets factory reset, this scenario works. I will take a look and add some function or check if there is any callback available that channel was changed.

@michapr
Copy link
Author

michapr commented Mar 14, 2025

I wanted to write about the same just now :))

as @xieqinan wrote:

If the channel changes (i.e., the network configuration changes), the device should leave the current network, scan the channels specified by the primary channel mask, and select the appropriate network to join, rather than simply deleting the memorized channel (which would be insecure).

Would be nice to realize this too.

@def1149
Copy link

def1149 commented Mar 14, 2025

If a device fails to connect it should clear the current channel and rescan for a new channel on the same controller, NOT bind to any controller. That would be secure,

@michapr
Copy link
Author

michapr commented Mar 14, 2025

If a device fails to connect

I think there should be a definable timeout so that a full scan is not carried out immediately after the first connection problems. Or a definable number of failed attempts...

@P-R-O-C-H-Y
Copy link
Member

P-R-O-C-H-Y commented Mar 14, 2025

If a device fails to connect

I think there should be a definable timeout so that a full scan is not carried out immediately after the first connection problems. Or a definable number of failed attempts...

I agree. Do you think this will be good to handle in user code in check if(!Zigbee.begin())? You can simply add a number of tries + I will add a API to reset the channel scan mask.

@def1149
Copy link

def1149 commented Mar 14, 2025

Yes, that works for me. Perfect!

" if(!Zigbee.begin())" ?? Wouldn't resetting the channel mask be something that you do after N Zigbee.connected() fails?

@P-R-O-C-H-Y
Copy link
Member

Yes, that works for me. Perfect!

" if(!Zigbee.begin())" ?? Wouldn't resetting the channel mask be something that you do after N Zigbee.connected() fails?

I will check the proper place for sure. Was writing on the phone just the main idea :) but I think the begin is the right place (will check to be sure).

@michapr
Copy link
Author

michapr commented Mar 14, 2025

Yes, that works for me. Perfect!

Same for me - good idea!

@def1149
Copy link

def1149 commented Mar 15, 2025

Update on power use. I got an Olimex ESP32-H2 DevKit-LIPO board . If you don't need Wi-Fi and you run on battery then the the H2 is the way to go. I didn't modify the board to remove the regulator and it sleeps at 9.8 uA and sends at 34.2 mA Avg for 565 mS. That time included reading 12-bit analog results from TMP36 temperature 5 times @ 10 mS and averaging the result. You can see the dead time at the end of the report-in is due to waiting to make sure data was delivered before going to sleep. The last 200 mS of activity occurred during the hard-coded 200 mS delay just prior to going to sleep. About 90 mS of delay can be removed if there's some kind of completion status that can be polled before sleeping. Note: The small power peaks @ one minute are the device waking up checking for a temperature change and going back to sleep if the change is less than the defined delta. That strategy saves a lot of power by only reporting when there is a significant change in a sensor value

Image

@michapr
Copy link
Author

michapr commented Mar 15, 2025

@def1149 as @Jason2866 said,:

Please open a discussion about how to implement / build a low energy device. Thx
Github issues is not ment for. It is hard to follow here if the original issue is now solved or not.

Please use this only for the discussed issue - it is better for reading and understanding the progress about solving the issue ;)

@P-R-O-C-H-Y
Copy link
Member

P-R-O-C-H-Y commented Mar 18, 2025

Hi @michapr @def1149, I have updated the PR and now it's all working perfectly for me. When I change the network channel, after time outing the Zigbee.Begin() it resets the channel mask to default (all channels) and after reboot it scans all channels. When it joins again it will save the new channel mask, so next reboot it will scan again the "active" channel.

Few logs added, so you can track the mask in the logs when testing this:

[V][ZigbeeCore.cpp:516] setNVRAMChannelMask(): Channel mask set to 0x00400000
[V][ZigbeeCore.cpp:509] resetNVRAMChannelMask(): Channel mask reset to all channels

Can you please test it out again :) With changing the channels in your system to prove its working fine :) Thank you

And added a new function that needs to be called before Zigbee.begin(), which is:
Zigbee.setTimeout(uint32_t timeout); //in ms
So by that you can specify how long will the timeout be, by default is 30s. I have updated the sleepy example with this setting also :)

@def1149
Copy link

def1149 commented Mar 18, 2025

Did you update the public repo?

@P-R-O-C-H-Y
Copy link
Member

Did you update the public repo?

@def1149 its still a Pull Request. Please checkout the PR or copy the changes. Depends if you use manual version of installation.

@def1149
Copy link

def1149 commented Mar 18, 2025

Ahh.yes ... of course

@def1149
Copy link

def1149 commented Mar 18, 2025

It looks like this PR was implemented on top of other PRs making the editing of the RC2 base a bit complicated and it's unknown if there may be any dependencies on those previous PRs that are not in the RC2 base. I'll perform the edits and see what happens. Look like we need RC3 🤣

@P-R-O-C-H-Y
Copy link
Member

No need for RC-3 ;) I have tested the stuff properly and its working great :) so it would be perfect to have it for 3.2.0 release.
I just wanted to get additional feedback from you folks.

@michapr
Copy link
Author

michapr commented Mar 18, 2025

@P-R-O-C-H-Y I'm not available for testing in this time ;) ... until begin of next week

@def1149
Copy link

def1149 commented Mar 18, 2025

OK ... I downloaded the PR, replaced the Zigbee files in the local library with PR files, and recompiled my app.
I'm testing on the Olimex ESP32-H2 board

I ran several cycles of switching back and forth between channel 11 and channel 13 and watched the power use using the Nordic PPK2. I can see the full scan take place after a channel change and then settle down to a single-channel scan until I change the Zigbee channel again on the controller. Looks good. Thank you @P-R-O-C-H-Y

NB: the 3.2.0 update breaks stuff in the Adafruit library (MAX17043)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Libraries Issue is related to Library support. Area: Zigbee Issues and Feature Request about Zigbee Status: Pending Merge Pull Request is ready to be merged
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants