Real-time streaming between two ESP32

Hi everyone! This is my first post in the forum, so I’ll try to be as clear as possible (hoping it will be enough).

I am working on a project and I need that two ESP32 that are far away from each other (e.g. two different cities) communicate with each other every 50ms max (30ms would be better). The communication must be bidirectional and the information sent each time is only one bit (0 or 1).

The problem is that each ESP32 should receive the information from the other almost in real-time, the delay cannot be higher than 50ms.

I did some research and found different protocols suggested (TCP, UDP, MQTT, HTTP, ESP-NOW), but each of them seems to be not the best suit:

  • UDP and TCP need port forwarding in order to be able to connect two devices in different LANs, and even though this could be done I need something more flexible (e.g. I want to be free to change house for one ESP32 and still connect to the other and vice-versa). Moreover, I noticed that there is a delay that creates a problem with the synchronization
  • MQTT works properly with two LANs, but the delay is too high (even 1 second)
  • HTTP needs port forwarding too, moreover the delay is higher than UDP
  • ESP-NOW has a limited range

In your opinion, is it possible to achieve this kind of streaming? And in case, do you know a protocol that I can use or a way to better use the protocols I have already found? Any suggestion would be really appreciated.

Francesca

You could use a VPN, but I'm not shure you will be able to reach a such low latency time.
In addition, VPN usually are not for free.

Try to evaluate also WebSocket (it's on TCP layer)

Maybe it's easyier try to change the way you share data between the two device; for example have you evaluated the possibility to send a "time synced" buffer of measures instead of stream, if is feasible for your application.

I did not think of VPN, that would solve the problem of the LANs but would (probably) make the delay even higher...

I already tried this with the library ESPAsynchWebServer and it is based on HTTP requests, so it is even slower than basic TCP.

This would be surely easier, but my application works on the idea that one ESP32 receives the information from the other almost instantaneously.

To have freedom, you need a central server that both connect to. The server can relay the data to the other one. I don't have enough knowledge how to do that in the server.

Websockets do not have to be slower than TCP. The delay will not be in code, but in the online timing. Speedtest.net tells me that my ping is 12ms (that is not very fast). With two devices and a central server it is at least 24ms.

WebSocket can run also without HTTP (S) request.
It is the technology used for online multiplayer games where latency time is a problem like in your application.

1 Like

Take a look at this test server (it is for a C library, but it doesn't matter for the moment).

If you enable the Developer Tools (F12) in your browser, you are able also to track the timing of websocket data packets

For example this is a test with my browser and my actual connection (with a ping to DNS of 10ms).
The libwebsockets server is located in France while I'm in Italy: the measured time is for a request starting from my browser -> to server -> back to my browser

I don't know if with ESP32 you can achieve similar perfromance, but for sure WebSocket is one of the best options you have with your needs.

1 Like

Gamers minimize latency by using Ethernet instead of WiFi. Use an Ethernet connection directly to the router on both ends. WiFi adds 5-10 ms while Ethernet adds < 1 ms.

If using plain TCP, be sure to disable Nagle's algorithm on both sides.If you want to stick with ESP32 WiFi, I am pretty sure ESP32 has an API function to disable Nagle. If using a library built on top of TCP (for example, websockets and HTTP), search the source code for "nodelay" or "nagle" to see if it a optimized for low latency.

Raw UDP is your best bet. Maybe send 3 duplicate packets instead of one to account for any packet loss that may happen in transit.

I have a setup where my MCU talks to an ESP8266 module over UART at 921.600 Kbps (AT commands) to transmit UDP and my "send UDP" state machine takes about 6ms to complete with a packet payload of about 32 bytes. You should be able to achieve better than that with a newer ESP32 and direct programming.