Open rogueeve575 opened 2 years ago
Hi,
I was pointed to this issue by e-mail. I don't expect e-mails for issues with my libraries, but decided to give a short answer.
This issue may be related to:
void Watchy::displayBusyCallback(const void *) {
gpio_wakeup_enable((gpio_num_t)DISPLAY_BUSY, GPIO_INTR_LOW_LEVEL);
esp_sleep_enable_gpio_wakeup();
esp_light_sleep_start();
}
For further analysis you could comment out the code of this method to see if it helps. You could try to let ESP32 auto-connect, if this exists (I use it on ESP8266).
So I modified the stock firmware demo ("Watchy" library) to replace the About Watchy menu item with a screen that's a little TV remote control which uses WiFi to connect to a simple server I wrote in C running on the computer that's connected to my TV, and synthesize a few common media control keys as selected from a menu on the watch. It's using a very simple protocol over raw TCP that just requires sending a modicum of authorization (sending a "random" uint32_t followed by another uint32_t hashed from the combination of the password and the first number), followed by a byte representing the key to be pressed, or "<" followed by a special sequence (such as <VOL+ or <BKSP).
It works great and is a lot of fun but one problem I can't resolve is that I could only to get it to work reliably if for every time the user asks to send a key I connect to wifi, connect to the server, send my packets and then shut down the wifi again, which is very slow. I tried to get it to leave the wifi connected for 12.5 seconds afterwards and re-use the connection for subsequent keypresses before going back into deep-sleep mode, but when I do this, about 70%-80% of the time WiFi.status() still returns WL_CONNECTED, but client.connect() hangs for a few seconds and then reports failure.
I created my own loop similar to the stock firmware's "fast menu" mode which it stays in for ~10 seconds on entering the "app" or after the first button press which wakes it back up from deep sleep so I know that other parts of the firmware shouldn't be messing anything up.
During debug I tried wrapping my entire connect/send packet/disconnect code in a big for loop and connecting/disconnecting (to the server, not the Wi-Fi) 50 times after wifi is brought up, and this works as expected 100% of the time.
I eventually traced it don to my showRemote function where if I comment out the display.display(), it doesn't exhibit the issue anymore (but of course you can only see what's going on through the debug serial interface).
I'm not too familiar with Arduino libraries as I usually prefer writing directly to the chip and am just recently getting into ESP32 development, however I have plenty of programming and embedded development experience on older devices such as AVRs.
Bear with me, I'll try to be thorough while hopefully not dumping too much non-relevant code...First, here is the main loop which the watch sits in for a while after activity before returning back to handleButtonPress and the normal Watchy code and going back to deep-sleep:
...here is the relevant showRemote function which draws the menu:
handleRemoteButton is just a switch statement; here's the relevant bit (the other cases just move the menu selection):
...and finally here is the meat of it all that gets called with the key to send once the wearer selects a menu item:
As I said there is no issue if I simply call remoteSendCommand repeatedly while taking out the parts that update the screen. And as you can see this screen takes over the Watchy while it's in the spin loop so other parts of the library shouldn't be running. Also debug() is just a macro for Serial.println(), but only if SERDEBUG is defined; otherwise it's just a no-op. So there is no serial communication actually going on in production. That didn't seem to affect it either way though as I was able to enable debugging and send multiple commands if I disabled the call to display.display().
So I'm not sure if this is some kind of hardware bug or if the GxEPD2 library's display.display() is doing something that breaks Wi-Fi, maybe something to do with the GPIO's, SPI, or sleep modes. I think it's interesting that it still reports WL_CONNECTED (always), and that it occasionally does reconnect successfully for a 2nd button press with leaveConnected set to true as it's supposed to be (but not very often).
I also noted that none of the few Wi-Fi features in the stock firmware ever leave it connected, so they wouldn't run into this bug/problem.
And lastly I don't know if this is normal or not or is related at all but I did notice that the range is not very good compared to other devices in my house. It will often fail to connect if I'm more than one room away from the room with the AP. My wifi signal is strong though and other devices have no issue. I'm using the aluminum Gameboy case so I don't know if that might weaken the signal. And of course I do realize that the 3D antenna is really tiny but I expected better range than that, so I don't know if that has anything to do with my issue. In testing I am sitting right next to the router and it always connects to wifi fine, just is unreliable about actually connecting to the server if I update the e-paper between bringing up wifi and calling WiFiClient::connect().