Skip to content

Possible regression of serial communication performance since version 2.x #7505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1 task done
awawa-dev opened this issue Nov 23, 2022 · 17 comments · Fixed by #7525
Closed
1 task done

Possible regression of serial communication performance since version 2.x #7505

awawa-dev opened this issue Nov 23, 2022 · 17 comments · Fixed by #7525

Comments

@awawa-dev
Copy link

awawa-dev commented Nov 23, 2022

Board

ESP32 dev module

Device Description

Board capable of 2Mb serial speed (CH9102x)

Hardware Configuration

nothing is connected

Version

v2.0.5

IDE Name

Arduino IDE, PlatformIO

Operating System

Windows, Linux

Flash frequency

default

PSRAM enabled

no

Upload speed

default

Description

As of version 2.x I observe possible performance regression compared to version 1.x when high-speed communication is used (2 000 000 baud). We verify the integrity of the frame data to make sure the frame is complete and undamaged.

Simplified sketch and python test client provided as an attachment. 'Esp32 dev module' with CH9102x

With version 1.0.6 was working fine.
image

Sending 900 bytes frames without any problem to ESP32 board. The reception is confirmed.

image

Since version 2.x the same sketch does not work anymore, which was first reported by our users and then confirmed by us after testing. We are unable to maintain such communication, all 900 byte frames are damaged or incomplete:

image

None of 900 byte frames is receive undamaged and completed.

image

It starts to work for ~600 byte frame but with high error rate:

image
client_and_sketch.zip

Sketch

Test client and sketch provided as an attachment in the description section.

Debug Message

not applicable since it's not a bug

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@VojtechBartoska
Copy link
Contributor

Hello @awawa-dev, thanks for the issue.

I'm tagging @SuGlider who did bunch of improvements to Serial recently.

@SuGlider
Copy link
Collaborator

@awawa-dev - Please turn on Log messages (Core Debug Level: "Verbose") in the Arduino IDE.
You shall see this message:
RX Buffer can't be resized when Serial is already running.

Change your setup() to:

void setup()
{
	Serial.setRxBufferSize(MAX_BUFFER);  // before begin()
	Serial.begin(COM_SPEED);
	
	Serial.setTimeout(50);
        Serial.write("Hello tester!");
}

@awawa-dev
Copy link
Author

So 2.x caused that breaking change? Still it doesn't resolve the issue.
It's better for 900 byte frame but still experience degraded performance and very high error rate:
obraz

For comparison 1.0.6 could handle even 1800 byte frames:

obraz

@SuGlider
Copy link
Collaborator

For 900, the solution is to replace Stream::readBytes() with HardwareSerial::read()

  uint16_t internalIndex = min(Serial.available(), MAX_BUFFER);
  if (internalIndex > 0)
  {
    lastDataTime = millis();
//    internalIndex = Serial.readBytes(buffer, internalIndex);
    internalIndex = Serial.read(buffer, internalIndex);
  }
  else if (lastDataTime + 1000 < millis())
  {
    Serial.println(framesReceived);
    lastDataTime = millis();
    framesReceived = 0;
    state = TestProtocol::HEADER_A;
  }

@SuGlider
Copy link
Collaborator

Anyway, it doesn't work well with 1800. Let me analyze it further.

@awawa-dev
Copy link
Author

Thank you for your time and effort. I can confirm that it works for 1200 bytes frames now with usually no errors. Then it gets worse quickly if the frame is only slightly bigger.

@SuGlider
Copy link
Collaborator

@awawa-dev
PR #7525 allows the sketch presented in this issue to run perfectly fine with no errors.
I tested it with 5000 as packet size.

@awawa-dev
Copy link
Author

Great! I will test it right away.

@awawa-dev
Copy link
Author

@SuGlider Great job 😄 I've tested your PR not only using test sketch but also my main project: I confirm everything works now perfectly. Hope this PR will be merged soon. And that along with the changes you recommended here will finally allow me to upgrade my ESP32 LED driver to Arduino ESP32 ver. 2. Because of that performance issue, it was on hold for almost a year (I'm aware that it could be difficult to detect due specific serial chip capability and large frame/speed transmission configuration)

@SuGlider
Copy link
Collaborator

SuGlider commented Nov 27, 2022

Excellent!

@SuGlider
Copy link
Collaborator

SuGlider commented Dec 4, 2022

Added new change to override Stream:readBytes(). Now the original code using this Stream function runs correctly as well.
commit e072302

@awawa-dev
Copy link
Author

awawa-dev commented Dec 4, 2022

Thank you for the update. Just for your information, as I just received the ESP2-S2 mini lolin: it seems that the problem described here does not apply to this board, possibly due to the integrated onboard USB-UART instead of the external one.

@SuGlider
Copy link
Collaborator

SuGlider commented Dec 4, 2022

Thank you for the update. Just for your information, as I just received the ESP2-S2 mini lolin: it seems that the problem described here does not apply to this board, possibly due to the integrated onboard USB-UART instead of the external one.

Yes, but in that case the ESP32-S2 mini lolin uses USB CDC instead of UART. Therefore, it doesn't use HardwareSerial class, but HWCDC instead. Those two have completely different implementations.

@awawa-dev
Copy link
Author

Yes, but in that case the ESP32-S2 mini lolin uses USB CDC instead of UART.

Is there any preprocessor defined based on the board model (platformio) that could tell us, if we compile a firmware for CDC or for UART based Serial? Seems there are more differences like the buffer size (CDC could return much larger chunk of data than UART).

@SuGlider
Copy link
Collaborator

SuGlider commented Dec 5, 2022

Is there any preprocessor defined based on the board model (platformio) that could tell us, if we compile a firmware for CDC or for UART based Serial? Seems there are more differences like the buffer size (CDC could return much larger chunk of data than UART).

Yes, it is in the source files:
https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/HardwareSerial.h#L192-L207
https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/HardwareSerial.cpp#L99-L103
https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/HWCDC.h#L101-L107
https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/HWCDC.cpp#L384-L392

ARDUINO_USB_CDC_ON_BOOT is set in the IDE Board menu and this is set in the building process.

@SuGlider
Copy link
Collaborator

SuGlider commented Dec 5, 2022

For the ESp32-S2 mini lolin, it is set by default in the Board menu and setup in the boards.txt file:

https://github.com/espressif/arduino-esp32/blob/master/boards.txt#L5583

@awawa-dev
Copy link
Author

Thank you very much. Now I can handle all the cases for the different board variants I have.

awawa-dev added a commit to awawa-dev/HyperSerialESP32 that referenced this issue Jan 7, 2023
Bug espressif/arduino-esp32#7505 that affected non-CDC devices is finally fixed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants