Close

Promising WiFi 6 Power Measurements with the ESP32-C6

A project log for YDrip

An open source water meter that detects leaks and measures usage

ydripydrip 10/07/2023 at 02:260 Comments

Tldr: YDrip V3 was designed to be footprint compatible with ESP32-C6, which supports WiFi 6. A key feature of WiFi 6 is the ability for devices to sleep for extended periods while remaining connected. This solves the issue of not being able to communicate with the ESP32 while it's in deep sleep.

Light Sleep

One of the misconceptions about the ESP32 is that they are capable of running on batteries for long periods of time. They are IoT devices after all right? Unfortunately, the details get complicated when you actually try building an application. Let's use the ESP32-S3 as an example:

The datasheet specifies a range of 7 to 240 microamps depending on the sleep state. However, you quickly learn that light sleep is the only possible mode if you plan on using WiFi (which is the main feature of ESP32). This is because the ESP has no way of saving the WiFi association information in deep sleep. In light sleep, the CPU powers down some components until the next beacon from the access point (100s of milliseconds). Here is an example of the C6 in light sleep mode.

You can see the ESP32 wakes up many times to stay associated with the AP and uses an average of 23mA. This is better than the 100 mA you can expect without light sleep, but this is not low enough to be battery powered for months.

Deep Sleep

The other approach, which is what I chose for YDrip, is to go into deep sleep until you have data to report back and re-associate every time. There are two trade offs here. The first is boot and WiFi association uses a lot of power. Here is an example from an earlier measurement I took with V2.

The ESP uses more than 150mA during boot for a few seconds. The total power consumption after establishments a connection is 100mA, but is highly dependent on how long the negotiation takes. The second down is you can't communicate with the device in deep sleep until it wakes. Not a great user experience if they need to change settings for example.

WiFi 6 Solution

Luckily, this isn't a problem that only affects the ESP32, which is why the WiFi Alliance has made some changes to the latest standard. Like I mentioned above, earlier versions of WiFi required devices to go into light sleep between beacons every few hundred milliseconds. WiFi 6 introduce the concept of Target Wake Time (TWT), which allows devices and access points to negotiate this sleep time instead. This means YDrip can sleep for extended periods of there is no water usage while still remaining connected.

V3 is footprint compatible with the ESP32-C6 so I decided to get a TP Link AX180 WiFi 6 router and test it out. Support of C6 in ESPHome is still a work in progress so I used the itwt example from the ESP-IDF. These are the settings I used to configure TWT.

    /* setup a trigger-based announce individual TWT agreement. */
    wifi_phy_mode_t phymode;
    wifi_config_t sta_cfg = { 0, };
    esp_wifi_get_config(WIFI_IF_STA, &sta_cfg);
    esp_wifi_sta_get_negotiated_phymode(&phymode);
    if (phymode == WIFI_PHY_MODE_HE20) {
        esp_err_t err = ESP_OK;
        wifi_twt_setup_config_t setup_config = {
            .setup_cmd = TWT_REQUEST,
            .flow_id = 0,
            .twt_id = CONFIG_EXAMPLE_ITWT_ID,
            .flow_type = flow_type_announced ? 0 : 1,
            .min_wake_dura = 255,
            .wake_duration_unit = 0,
            .wake_invl_expn = 10,
            .wake_invl_mant = 16384,
            .trigger = trigger_enabled,
            .timeout_time_ms = CONFIG_EXAMPLE_ITWT_SETUP_TIMEOUT_TIME_MS,
        };
        err = esp_wifi_sta_itwt_setup(&setup_config);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "itwt setup failed, err:0x%x", err);
        }
    } else {
        ESP_LOGE(TAG, "Must be in 11ax mode to support itwt");
    }

The plot above shows the device wakes up every 16 seconds and uses an average of 708uA while staying associated. This is a dramatic improvement over the 23mA we saw with light sleep. While it's not as low as the 50-100uA if we deep sleep until some water usage is detected, it's a great trade-off for users that want communicate with the device.

Discussions