Any way to speed up Wifi Connection on ESP32?

Hi,

I have 6 DIY Multi-sensors around the house; motion, temperature, light and such. They’re all using a Wemos D1 Mini (ESP8266). Now though, I’ve been eyeing the new XIAO ESP32C3 from Seeed, they look really nice and like, you know, the perfect replacement. Smaller, more powerful and better WiFi (besides bluetooth).

For that purpose I’ve been fiddling around - with an ESP32 I already have - trying to create a replacement for my Multi-Sensor configuration, so I could have the ESP32 sleep most of the time and thus be more suitable for running of a battery.

I’m making progress, but I have a rather annoying and potential project-destroying issue: The ESP32 is proper slow to connect to WiFi after sleep. It can take 3 seconds, which is way too slow for a motion sensor to report in.

I’ve been reading up about it and use fast_connect together with manual IPs in ESPHome, but it’s still pretty slow. Some folks say that it’s caused by WPA2 and that’s it’s faster with WEP or an Open network. I do not want to use that on my network, so my question is: Is there any other way to speed things up?

Maybe I need to forgo ESPHome for this?

This is the code I have so far:

substitutions:
  device_name: test-sensor
  friendly_name: 'Test Sensor'
  led_pin: GPIO13
  pir_pin: GPIO26
  ldr_pin: GPIO36
  ldr_max_read: '3.12'
  ldr_min_read: '0.075'
  pir_delay_off: '5s'
  run_timeout_secs: '30'
  sleep_duration: 14min

esphome:
  name: $device_name
  friendly_name: $friendly_name
  on_boot:
    priority: 100
    then:
      - script.execute: timeout_script
          
esp32:
  board: wemos_d1_mini32
  framework:
    type: arduino

logger:
#  level: ERROR

ota:
  password: !secret ota_pass_test_sensor

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: true
  power_save_mode: none  
  manual_ip:
    static_ip: !secret ip_test_sensor
    gateway: !secret ip_gateway
    subnet: 255.255.255.0

mqtt:
  broker: !secret mqtt_broker
  username: !secret mqtt_user
  password: !secret mqtt_pass
  birth_message:
  will_message:

deep_sleep:
  id: deep_sleep_1
  wakeup_pin:
    number: $pir_pin
    mode: INPUT_PULLDOWN

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: false

globals:
  - id: run_timeout
    type: int
    restore_value: no
    initial_value: $run_timeout_secs

script:
  - id: timeout_script
    mode: single
    then:
      - while:
          condition:
            lambda: return ( id(run_timeout) > 0 );
          then:
            - delay: 1s
            - lambda: |-
                if ( !(id(pir_sensor).state || id(auto_light).current_values.is_on()) ) {
                  id(run_timeout) -= 1;
                  ESP_LOGD("debug", "Timeout: %d", id(run_timeout) );
                }
      - deep_sleep.enter: 
          id: deep_sleep_1
          sleep_duration: $sleep_duration   

output:
  - platform: gpio
    pin: $led_pin
    id: auto_light_out

light:
  - platform: binary
    name: 'Auto-Light'
    id: auto_light
    output: auto_light_out

binary_sensor:
  - platform: gpio
    name: 'Motion Sensor'
    id: pir_sensor
    device_class: motion
    pin:
      number: $pir_pin
      mode: INPUT_PULLDOWN 
    filters:
      delayed_off: $pir_delay_off
    on_release:
      then:
        - globals.set:
            id: run_timeout
            value: $run_timeout_secs

sensor:
  - platform: bme280
    address: $bme280_addr
    iir_filter: 4x
    temperature:
      name: 'Temperature'
      filters:
        - calibrate_linear:
          - 0.0 -> 0.0
          - 20.0 -> 18.0
      oversampling: 2x
    pressure:
      name: 'Pressure'
      oversampling: 2x
    humidity:
      name: 'Humidity'
      oversampling: 2x

  - platform: adc
    id: ldr_sensor
    pin: $ldr_pin
    on_value:
      - lambda: id(light_level).publish_state((x - $ldr_min_read) / ($ldr_max_read - $ldr_min_read) * 100.0);

  - platform: template
    name: 'Light Level'
    id: light_level
    update_interval: never
    icon: mdi:brightness-percent
    unit_of_measurement: '%'

I reckon you are unlikely to get satisfactory response times / latency for typical motion sensor applications (lights on if motion etc) by waking a sleeping esp. I would want 1sec or less total time lag for typical auto-lights application.

Do the D1 mini’s perform satisfactorily for you?

I don’t know the technical details about what kind of lower bound to aspire to, but I think there’s probably a reason why such devices are typically Zigbee/BLE/RF etc.

I could be wrong on this but that’s my 2 cents.

Thanks for the two cents :slight_smile:

I’ve managed to get the D1 Mini (ESP8266) to wake up in less than 500ms. Unfortunately the ESP8266 do not have support for a wake-up pin, so I cant use it for this project. The D1 Mini also have an onboard USB chip which can cause problems with deep sleep - if powered through USB connector.

If I could get the ESP32 down to 1sec, I would be fine with that, but 3 seconds is too long.

This thread seems to indicate that slow connection is caused by using the WPA2 protocol:

But yeah, maybe the best idea would be to wait for something like the new ESP32-C6 on a small form factor board and use ZigBee/Thread instead of WiFi.

1 Like

I was wondering why you said there is no hardware way to bring the esp8266 from deep sleep. Does this not work ? (see the part about external wake up)

or did you mean something else ?

They are referring to wakeup_pin:

Did you have any luck with this?

I have some low power projects that would benefit from minimising wake-up time.

Indeed :slight_smile:

I sort of gave up on it for a while, but I’ve now set up an Access Point with the WEP protocol instead of WPA2 and I got wake-up down to under 1 second. The AP is on a separate VLAN with no access to anything other than Home Assistant. I realize WEP isn’t secure, but hey ho…

1 Like