ESP32-S3: Android 13+ Hotspot Wi-Fi Disconnect With BLE

Alex Johnson
-
ESP32-S3: Android 13+ Hotspot Wi-Fi Disconnect With BLE

Ever hit a snag with your ESP32-S3 project where your device connects to Wi-Fi just fine with some access points, but then throws a tantrum when you try to connect to a newer Android phone's hotspot, especially when Bluetooth Low Energy (BLE) is also active? You're not alone! This peculiar issue, often seen with Android 13 and later versions, has been a headache for many developers. The ESP32-S3, a powerful microcontroller with integrated Wi-Fi and BLE, is fantastic for creating connected devices, but sometimes, the way it handles the coexistence of these two wireless technologies can lead to unexpected disconnects. Specifically, a WIFI_REASON_CONNECTION_FAIL (205) error, often accompanied by a log message like wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy, suggests that the device's internal logic for managing Wi-Fi and BLE traffic is getting confused. This problem seems to be more prevalent with certain Android phone models, particularly those running Android 13, 14, or 15, and it only occurs when BLE is active. Turn off BLE, and suddenly, the Wi-Fi connection to that same Android hotspot becomes rock solid. This points to a complex interaction between the ESP-IDF's Wi-Fi driver, the BLE controller, and the specific radio frequency (RF) behavior of newer Android hotspots. Let's dive into why this might be happening and what we can do about it.

Understanding the Core Problem: Wi-Fi and BLE Coexistence

The ESP32-S3 is designed to juggle both Wi-Fi and BLE communications simultaneously, a feature known as coexistence. This is crucial for many applications, such as using BLE for device provisioning (like sending Wi-Fi credentials) and then maintaining a Wi-Fi connection for regular data transfer. The ESP-IDF (Espressif IoT Development Framework) provides mechanisms to manage this, including the esp_coex_preference_set() function, which allows developers to tell the system whether to prioritize Wi-Fi or BLE during times of contention. When you're setting up your ESP32-S3 for provisioning using wifi_prov_mgr, the device typically first establishes a BLE connection to your mobile app. Once the credentials are exchanged, it attempts to connect to your Wi-Fi network, often a phone's hotspot. The issue arises because, on specific newer Android versions (13+), the way these phones manage their Wi-Fi hotspots, combined with the timing of BLE activity on the ESP32-S3, can trigger a premature Wi-Fi disconnection. The logs often show a disconnect reason 0x5A0 or WIFI_REASON_CONNECTION_FAIL, which is a generic failure code, but the accompanying coexistence message gives us a vital clue: Wi-Fi connect fail, apply reconnect coex policy. This means the ESP32's Wi-Fi driver detected a problem during the connection process and decided to disconnect, attributing it to a coexistence policy. It's interesting to note that this problem doesn't appear with all Android devices or even with iPhones. This suggests that the specific implementation of Wi-Fi drivers and RF management in newer Android versions might be interacting differently with the ESP32-S3's coexistence logic. Older Android versions (11/12) and iPhones seem to handle this interaction more gracefully, allowing the ESP32-S3 to complete its Wi-Fi connection even while BLE is active. The fact that disabling the BLE controller entirely resolves the issue for Android 13+ hotspots is a definitive indicator that the problem lies squarely within the Wi-Fi and BLE coexistence management.

Why Newer Android Hotspots are Different

Newer Android hotspots (Android 13+) seem to be the critical factor in this ESP32-S3 connectivity issue. When your ESP32-S3 is trying to connect to a Wi-Fi network, it goes through a series of steps: scanning for available networks, authenticating with the access point (your phone's hotspot), associating with it, and finally completing the 4-way handshake to establish a secure connection. The problem occurs during this connection phase when BLE is also active on the ESP32-S3. It's theorized that newer Android versions might have more aggressive power-saving features or different timing protocols for their Wi-Fi hotspots. These might cause the hotspot to intermittently drop packets or change its beacon timing in a way that the ESP32-S3's Wi-Fi driver interprets as a connection failure, especially when the BLE controller is also trying to use the shared radio resources. The coexistence logic within the ESP-IDF aims to arbitrate access to the radio, but it seems that in this specific scenario, it's overly cautious. It might be reacting to perceived interference or timing discrepancies caused by BLE activity, leading it to prematurely enforce a disconnection policy. This is further supported by the fact that forcing the Wi-Fi protocol to 11b/g/n and using a 20 MHz bandwidth (WIFI_BW_HT20) can sometimes help, as these configurations are less demanding on the radio and might reduce the likelihood of conflicts. Disabling Wi-Fi power save (WIFI_PS_NONE) and setting listen_interval to 0 (meaning the ESP32 listens for every beacon from the AP) are also common troubleshooting steps that aim to keep the Wi-Fi connection more stable and responsive. However, even with these optimizations, the issue persists with newer Android hotspots when BLE is active, indicating a deeper conflict that needs careful management by the coexistence arbiter.

Debugging the ESP32-S3 Disconnect Issue

When you encounter the ESP32-S3 disconnecting with the WIFI_REASON_CONNECTION_FAIL (205) error on newer Android 13+ hotspots while BLE is active, systematic debugging is key. The provided logs give us a clear starting point. Notice the sequence: the device successfully receives Wi-Fi credentials via BLE, attempts to connect to the specified SSID, but after several seconds (around 4-6 seconds in the example log), it fails with the coexistence error. The log clearly shows the ESP32 attempting to connect in "NORMAL mode" (meaning both BLE and Wi-Fi are active), then switching to "PREFER_WIFI" for the connection window. Despite this preference, the connection fails, and the device logs wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy. This pattern repeats up to 10 times, preventing the device from ever reaching the WIFI_EVENT_STA_CONNECTED or IP_EVENT_STA_GOT_IP states. The crucial test here is disabling the BLE controller (esp_bt_controller_disable()) before attempting the Wi-Fi connection. When this is done, the ESP32-S3 connects flawlessly to the exact same Android hotspot. This definitively isolates the problem to the interaction between Wi-Fi and BLE coexistence. The diagnostic report you've provided, with its detailed logs and configuration information, is invaluable. It shows the specific ESP-IDF version (v5.2.6), the SoC revision, the build process (command line with idf.py), and the custom board setup. This level of detail helps rule out environmental factors and points towards a software-level issue within the ESP-IDF's networking or coexistence stack. By examining the coexistence preferences set (ESP_COEX_PREFER_BALANCE during scanning and ESP_COEX_PREFER_WIFI during connection), we can see an attempt to optimize the connection. However, it appears that the default coexistence policies might not be sufficient or might be misinterpreting the signals from newer Android Wi-Fi hotspots when BLE is also active.

Analyzing the Log Output

The log output you shared is incredibly helpful in pinpointing the issue. Let's break down some key parts:

  • I (30728) [PROV/MGR]: /wifi RECEIVE: 37 bytes - {"ssid":"Joji","password":"4r3e2w1q"}: This shows the Wi-Fi credentials being successfully received over BLE through the provisioning manager.
  • I (31688) [PROV/MGR]: /wifi: Attempt 1/10 - Mode: NORMAL (BLE+WiFi): This clearly indicates that the ESP32 is operating in its dual-mode, with both BLE and Wi-Fi active.
  • I (31688) [PROV/MGR]: /wifi: Switching coexistence to PREFER_WIFI for connection window: The system is trying to give Wi-Fi priority during the critical connection phase.
  • I (36528) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy: This is the smoking gun. The Wi-Fi driver detects a problem during the connection attempt and triggers a disconnection based on the coexistence policy.
  • W (36538) [PROV/MGR]: [COEX] Connection failed/timeout - failure count: 1: This confirms that the coexistence mechanism is involved in the failure.
  • I (36548) [PROV/MGR]: /wifi: Reverting coexistence to BALANCE for next attempt: After a failure, the system resets and tries again, going back to a balanced coexistence mode before attempting Wi-Fi connection again.

The repetition of these attempts (up to 10) until a timeout or explicit stop highlights the persistent nature of the problem. The fact that disabling BLE (esp_bt_controller_disable()) allows the connection to succeed on the same Android 13+ hotspot underscores that the coexistence logic, when faced with the combined load of Wi-Fi connection and active BLE, is failing to manage the radio resources effectively for these specific APs. This isn't necessarily a bug in the provisioning manager itself, but rather in how the underlying Wi-Fi and BLE drivers, and their coexistence arbitration, behave under specific RF conditions presented by newer Android hotspots.

Potential Solutions and Workarounds

While a definitive fix often requires Espressif to adjust the coexistence algorithms in a future ESP-IDF release, there are several workarounds and configurations you can explore to mitigate this ESP32-S3 Wi-Fi disconnect issue. Since the problem is specifically tied to the coexistence of Wi-Fi and BLE on Android 13+ hotspots, our efforts should focus on optimizing this interaction.

One of the most promising avenues is to fine-tune the coexistence preferences. Instead of just setting ESP_COEX_PREFER_WIFI during the connection window, you might experiment with other esp_coex_preference_t values or even more granular control if available in newer ESP-IDF versions. Sometimes, a slightly less aggressive Wi-Fi preference might allow the BLE transmissions to occur at critical moments without disrupting the Wi-Fi association handshake. Another approach involves adjusting Wi-Fi parameters to reduce potential interference. You've already tried setting the bandwidth to WIFI_BW_HT20 and disabling power save (WIFI_PS_NONE), which are good steps. You might also consider:

  • Disabling 802.11n (HT) capabilities if possible, falling back to 802.11b/g only. This simplifies the Wi-Fi protocol and might reduce RF complexity, potentially easing coexistence. However, this comes at the cost of lower throughput.
  • Manually setting the Wi-Fi channel on the Android hotspot (if possible) to one that might have less BLE interference. BLE typically operates in the 2.4 GHz band, as does Wi-Fi. Finding a less congested channel could theoretically help, though this is often difficult with mobile hotspots.

If your application allows, you could also explore alternative provisioning methods that don't rely on BLE immediately before Wi-Fi connection. For instance, if you can pre-configure Wi-Fi credentials through other means (like a web server or a serial interface) and then activate BLE after the Wi-Fi connection is established, you might bypass the problematic coexistence scenario altogether. However, for typical BLE provisioning workflows, this is not an option.

Finally, keeping your ESP-IDF updated is crucial. Espressif frequently releases updates that address bugs and improve performance, including in the Wi-Fi and BLE stacks. While this specific issue might require a targeted fix, a newer version of ESP-IDF might contain subtle improvements to the coexistence arbiter that resolve or lessen the problem. You should also monitor the ESP-IDF issue tracker for updates related to IDFGH-16793 or similar coexistence problems. If you find a combination of coexistence settings that works reliably for your specific set of target Android devices, document it thoroughly. This information can be invaluable for others facing the same challenge and for providing feedback to Espressif.

Coexistence Configuration Tuning

When dealing with the tricky balance between Wi-Fi and BLE on the ESP32-S3, particularly when facing disconnects like the 0x5A0 error on newer Android hotspots, coexistence configuration tuning becomes paramount. The esp_coex_preference_set() function is your primary tool here. While the default settings or even ESP_COEX_PREFER_WIFI during the connection phase might seem logical, the reality on the airwaves can be more complex. The issue here is that BLE events, even brief ones, can occur at precisely the wrong moment during the Wi-Fi association or handshake process. Newer Android hotspots might be more sensitive to these tiny timing disruptions, leading to the connection failure. Experimentation is key. You might try setting the coexistence preference to ESP_COEX_PREFER_BLE briefly just before initiating the Wi-Fi connection, and then immediately switching back to ESP_COEX_PREFER_WIFI once the connection is established. This is a delicate dance and requires precise timing. You could also explore the CONFIG_ESP_COEX_TX_INTERRUPT and CONFIG_ESP_COEX_RX_INTERRUPT options in the menuconfig if you are comfortable diving deeper into the Wi-Fi driver configuration. These settings control how the Wi-Fi driver interrupts the BLE controller, and altering them might change the dynamic. Another advanced technique is to temporarily disable BLE just for the duration of the Wi-Fi connection attempt. While the log shows esp_bt_controller_disable(), which is a full disable, perhaps a more graceful suspend/resume of the BLE controller might be feasible if the ESP-IDF or NimBLE library offers such a function. This would momentarily pause BLE operations, allow Wi-Fi to connect without interference, and then resume BLE. This needs careful implementation to ensure no data is lost during the BLE suspension. It is crucial to test these configurations against the specific problematic Android 13+ hotspots to see which combination yields the most stable results. Remember to always reset coexistence preferences to a balanced state (ESP_COEX_PREFER_BALANCE) when Wi-Fi is not actively trying to connect or when BLE is the primary focus, to ensure overall system performance isn't degraded.

Alternative Provisioning Strategies

If direct Wi-Fi connection with active BLE remains unstable on certain Android hotspots, considering alternative provisioning strategies can be a viable path. The core of the problem lies in the simultaneous demand on the radio during the critical Wi-Fi connection phase, exacerbated by the behavior of newer Android hotspots. If your project permits, one approach is to decouple the provisioning steps. Instead of using BLE for real-time Wi-Fi credential delivery right before connection, you could:

  1. Pre-provisioning: If the device is accessible during manufacturing or setup, you could use a wired connection (like USB to UART) or a simpler, non-BLE wireless method to upload the Wi-Fi credentials. Once the Wi-Fi is configured and connected, you can then enable BLE for other functionalities or for secondary configuration.
  2. Wi-Fi Access Point Mode Provisioning: Configure your ESP32-S3 to act as a Wi-Fi Access Point (AP) temporarily. A user would connect their phone to this temporary AP, access a simple web server hosted on the ESP32, and enter the desired Wi-Fi credentials there. Once the ESP32 connects to the target network, it exits AP mode. This bypasses BLE entirely for the initial Wi-Fi setup.
  3. Third-Party Provisioning Services: For more complex deployments, consider using cloud-based provisioning services or apps that might handle the credential exchange differently, perhaps via QR codes or other protocols that minimize simultaneous radio contention.

However, assuming BLE provisioning is a requirement, focusing on optimizing the existing flow is usually preferred. The external link provided below offers valuable insights into ESP-IDF's networking capabilities and troubleshooting.

Conclusion

The ESP32-S3 disconnect issue when connecting to Android 13+ hotspots with BLE active is a complex challenge that highlights the intricacies of wireless coexistence. While the ESP32-S3 is a versatile chip, the interaction between its Wi-Fi and BLE stacks, especially under specific network conditions presented by newer Android versions, can lead to unexpected failures like the WIFI_REASON_CONNECTION_FAIL (205) error. The key takeaway is that the problem isn't necessarily a fundamental flaw in the ESP32-S3 hardware but rather a subtle interplay of software drivers, coexistence algorithms, and the RF behavior of certain access points. By carefully analyzing debug logs, understanding the timing sensitivities, and systematically testing configuration adjustments, developers can often find workarounds. Experimenting with coexistence preferences, Wi-Fi parameters, and potentially alternative provisioning strategies are the main avenues for resolution. For more in-depth information on ESP-IDF and networking, exploring the official documentation is highly recommended.

For further reading and more advanced networking solutions with ESP-IDF, check out the ESP-IDF Programming Guide.

You may also like