We are experiencing a strange problem with the ESP8266 used as a TCP <=> UART bridge.
The external application (an Adroid App) fails to work correctly with this bridge while it has worked OK with a different commercial WiFi module, which is now discontinued.
So we are trying to use the ESP8266 as a replacement.
Our testers today tried to figure out why so they added code in the loop() function to dump the data being transferred onto the debug serial port Serial1 in addition to sending it the normal way.
What happened is that the application started to work normally!
The only way I can explain this is if the Serial1.write function is basically unbuffered so the caller has to wait until all data have been put into the UART FIFO on the ESP8266.
Is this the case?
Or is there a serial buffer associated with these ports (Serial and Serial1), but of limited size such that they will be blocking for data sizes above some limit?
If so what size is the buffer and is it adjustable in code?
There doesn't seem to be any software write buffer associated to the ESP8266 serial port (except for the hardware FIFO buffer which is 128 bytes). Those 128 bytes can fill up quite easily, especially when using low bit rates.
OK, then what about the other direction, incoming data on the UART?
In the loop() function there is basically this code section dealing with incoming serial data (there are similar checks for TCP data etc, but mostly loop() has nothing to do:
char serbuf[512]; //Buffer for serial server
//check UART for data
while ((bytesAvail = SerialSS.available()) > 0)
{
bytesIn = SerialSS.readBytes(serbuf, min(sizeof(serbuf), bytesAvail));
if (bytesIn > 0)
{
//push UART data to connected telnet client
if (tcpServerClient && tcpServerClient.connected())
{
tcpServerClient.write((uint8_t*)serbuf, bytesIn);
delay(0); //Needed to stop wdt resetting on long operations
}
}
}
Obviously this code gets called every time the loop() function runs and it will extract the data that at this time are available in the Serial buffer.
Given that the serial baud rate is 38400 it means that every single byte takes some 0.26 ms to get through the UART shift register and wind up in the buffer.
So my question now is how often loop() gets executed? Is it say a 1 ms loop or is it quicker than that?
If all the other checks in the loop() turns out false then the execution time of the loop() itself should be very short and if it just starts over immediately when it finishes, then I guess that all the incoming serial data the code will find in the check above will be either zero or one byte (4 bytes max if loop runs every 1 ms).
So will this in turn mean that each byte read from serial will be sent as a single byte payload in a TCP packet to the client?
Or is the TCP subsystem on an ESP8266 designed to wait for more bytes before actually sending off the package over the network?
It basically boils down into how the tcpServerClient.write() function works inside the library and beyond...
If it waits for more data then it can potentially affect the flow expected on the client side...
PS: Based on the discussion above it really now seems to be overkill to have a serial buffer of 512 bytes.... DS
So what I have been able to check now is that if I send a packet of bytes through the serial port in one continuous transmission every 1000 ms, then what is received in the other end is a single TCP packet every second with exactly the packet data.
So how does this work?
When I send 20 bytes of data in each serial transmission it takes 5.2 ms for them to arrive through the wire.
They all wind up in the same TCP transmission. I have tried to extend the data sent this way to 60-70 bytes and it still results in them all getting into the same packet!
It does not seem like the tcpServerClient.write() results in the tcp packet going out on the wire at all. This seems to be managed by something else like a timeout or such...
Question:
Is there any way to tell the tcpServerClient object that it is supposed to dump all data currently in its out buffer onto the network?
We need the data to basically instantly be forwarded to the tcp client when they arrive on the serial wire.
Maybe I should start a new thread about this since the subject really is about blocking serial.write functions, which I now know is not the reason for the problems we have.