C
C#4mo ago
br4kejet

✅ SerialPort performance

I'm doing some tests on the performance of serial communication and I'm geting a fair chunk of perforance loss. At a baud rate of 38400, with 7 data bits and 1 stop bit, then I can expect to get a maximum of 26kbps, but I received 120 bytes in just under 50 milliseconds which seems to be about 20 kbps. Anyone know what would be causing this?
43 Replies
canton7
canton74mo ago
Is there any handshaking? Rts/cts etc?
br4kejet
br4kejetOP4mo ago
Not that I know of I'm not specifying any handshaking Just a baud rate of 38400, 7 data bits, one stop bits and even parity
canton7
canton74mo ago
Then it's just a dumb fire-and-forget protocol, so you'll get data as fast as the transmitting side is sending it
br4kejet
br4kejetOP4mo ago
I guess maybe its CPU is trying to manage doing work with sending data then
canton7
canton74mo ago
Is it some embedded device?
br4kejet
br4kejetOP4mo ago
Yeah A PLC One of those knockoff ones though
canton7
canton74mo ago
It's possible that it has all of the available to go at the start of the 50ms, and is DMAing it out, but it's not unusual to have little gaps as it does work, then transmits, etc Get a logic analyser / scope on that line
br4kejet
br4kejetOP4mo ago
I might give that a try I definitely saw gaps though
canton7
canton74mo ago
Its clock might be a little off also, if it's just an rc oscillator
br4kejet
br4kejetOP4mo ago
I did some rough timing (in debug mode though) using DateTime.Now, and found that I was basically receiving data 1 byte at a time which I guess is expected since my read function only used Thread.Yield(), sometimes the time between receiving bytes was less than a millisecond, sometimes it was maybe 2 milliseconds
canton7
canton74mo ago
The thread scheduling is normally only accurate to 3-5ms or something So if you're reading one byte then sleeping the thread, it's normally at least 3ms until it'll be woken again
br4kejet
br4kejetOP4mo ago
I guess I should just try and optimise when I read data and maybe even write too
canton7
canton74mo ago
(use a Stopwatch for that sort of timing, not DateTime also - much more accurate) Yeah, read into a 1024 byte buffer or so
br4kejet
br4kejetOP4mo ago
DateTime doesn't use the performance counter?
canton7
canton74mo ago
I don't think it does, no
br4kejet
br4kejetOP4mo ago
Damn
canton7
canton74mo ago
(could be wrong) You shouldn't need Thead.Yield in this sort of code Just read a bunch of bytes from serial, and it'll block until some are available
br4kejet
br4kejetOP4mo ago
I completely forgot the timeout functions work lol I had it to no timeout I think
canton7
canton74mo ago
You normally don't even want timeouts in this sort of code
br4kejet
br4kejetOP4mo ago
Well I mean, even for a short response from the PLC of maybe 6 bytes still takes about 10ms to receive for some reason Maybe it was the yielding though, might test it again
canton7
canton74mo ago
Just do a single 1024 byte read or so (and read all bytes that are returned, then do it again)
br4kejet
br4kejetOP4mo ago
My buffer is 32 bytes since most messages won't be that big
br4kejet
br4kejetOP4mo ago
It's using date time but a 6 byte response took 15ms to arrive fully, even after removing Thread.Yield()
No description
canton7
canton74mo ago
Not sure exactly how you're processing it, but the normal strategy if you're receiving something like a length prefixed message is to allocate a buffer to hold the max message, do a read into the buffer for the size of the buffer, that'll return when 1 or more bytes are available, read your length, figure out how many more bytes you need, then keep doing reads of the remaining length until you get all of those bytes
br4kejet
br4kejetOP4mo ago
My method is to check if the buffer contains a valid response, either it's an ACK/NAK or it has a checksum
canton7
canton74mo ago
I mean, at those sorts of times, scheduling times will likely dominate anything you're trying to measure Each Read might sleep the thread if there are no bytes available etc That'll be amortised out as you read larger chunks of data Also, when did you start the timer?
br4kejet
br4kejetOP4mo ago
At the start of the function, before infinitely looping until the message is fully received or my own timeout mechanism stops the loop
canton7
canton74mo ago
So you're potentially measuring a period before the plc starts sending its message?
br4kejet
br4kejetOP4mo ago
Yeah
canton7
canton74mo ago
OK, that too then 😆
br4kejet
br4kejetOP4mo ago
I write to the serial port and wait for a message to be received
canton7
canton74mo ago
Right, so you're also measuring the time taking to transmit the command, and the plc's processing time?
br4kejet
br4kejetOP4mo ago
No just timing how long it takes to receive the response
canton7
canton74mo ago
But you said you start timing after you do the write? (not after the first byte of the response is received or something)
br4kejet
br4kejetOP4mo ago
https://github.com/AngryCarrot789/HslCommunication-Community/blob/HslCommunication/Serial/SerialBase.cs#L193 That's my function for sending a message and getting a response The timing is only done in ReadMessageInternal
canton7
canton74mo ago
That's a 404 for me
br4kejet
br4kejetOP4mo ago
Oops double slash Nevermind
canton7
canton74mo ago
Same with that fixed
br4kejet
br4kejetOP4mo ago
GitHub
HslCommunication-Community/HslCommunication/Serial/SerialBase.cs at...
A library for communicating with common PLC devices. A open source and higher-performance edition of HslCommunication - AngryCarrot789/HslCommunication-Community
canton7
canton74mo ago
Right yes, after you queue the command for transmission Actual sending of bytes will happen asynchronously. Then you've got the time for the plc to think about it
br4kejet
br4kejetOP4mo ago
Hm I guess
canton7
canton74mo ago
Definitely put a scope on it Look at the timing of your command, the plc's thinking time, and how long it takes the response to come back, start to end $close
MODiX
MODiX4mo ago
If you have no further questions, please use /close to mark the forum thread as answered
Want results from more Discord servers?
Add your server