C
C#4mo ago
kianyuen

How to stream bytes from SerialPort (System.IO.Ports) into a chart.

I'm using WPF on .NET Framework 4.8. The packet that I'm trying to catch is sent at 250Hz. I was under the assumption My current basic implementation is as follow: On port.DataReceived, I will collect the data then store it to another buffer to further process it later (to deal with potential last unfinished packet by just queueing them).
SerialPort spL = (SerialPort)sender;
byte[] buf = new byte[spL.BytesToRead];
spL.Read(buf, 0, buf.Length);
_receiveBuffer.AddRange(buf);
SerialPort spL = (SerialPort)sender;
byte[] buf = new byte[spL.BytesToRead];
spL.Read(buf, 0, buf.Length);
_receiveBuffer.AddRange(buf);
I personally think this is hacky and non-efficient, is there a better existing approach that I'm not aware of?
10 Replies
Omnissiah
Omnissiah4mo ago
this is pretty standard how would you improve it
kianyuen
kianyuenOP4mo ago
i got some problem with implementing it and had some trouble finding an existing implementation online, but it kinda sorted out for now. i was thinking maybe there was already some way to just pull it packet by packet from the existing buffer of the port but I guess it is inherently this way.
Omnissiah
Omnissiah4mo ago
the fact is serial is pretty raw so determining a strategy for reading from it may heavily depend on the protocol for example if the first 2 bytes were the size of the message you would already know how big to allocate it other than that, usually manifacturer should provide a client that implements the protocol (but serial stuff is old or it is used in cheap devices so at most they give a pdf (if you are lucky) which hopefully tells you something about it)
kianyuen
kianyuenOP4mo ago
The one I'm currently dealing with is pretty simple, first byte will be used as a header (documented in a PDF file) for each packet (data range from 0 to 7 bytes). This one is pretty overwhelming to me tho, I asked for a demonstration app/source code from the supplier and all they said were "we currently only have the instruction set": - Request data format Command head + command word + length word + data filed + check word Command head: two bytes, Default is 0X55, 0XAA Command word: one byte Length word: two bytes, indicate this command start from length word to check words bytes (not include check word),low-order in front Data filed: this option can be 0 Check word: Byte-by-byte XOR value from the command head to the last byte of the data field - Reply data format Command head + command word + identifier word + length word + data field + check word Command head: two bytes, Default is 0x55,0xAA Command head: one byte Identifier word:one byte, 0x00 means response successfully, others means defeated or error Length word:two bytes,indicate this command start from length word to check words’ bytes (not include check word),low-order in front Data filed: this option can be 0 Check word: Byte-by-byte XOR value from the command head to the last byte of the data field
Omnissiah
Omnissiah4mo ago
seems pretty straightforward, there isn't even escaping needed i would tell you just do it that it works, read data, parse the fields, even in the ugliest and fastest way you know of, but just verify that it works then do it well there are not details about the endianness of the fields, but hopefully it's the correct one already (ps if you need help taking primitive types from byte[] there's BitConverter.ToInt16 etc.; if you need to be aware of the endianness there is System.Buffers.Binary.BinaryPrimitives.ReadInt16LittleEndian etc.)
kianyuen
kianyuenOP4mo ago
About parsing, my current flow is 1. loop through the buffer scanning for header 2. process/store the data based on the packet definition 3. (haven't implemented validation, but i guess i should put it here) 4. just prune everything til the last processed packet in the buffer. That's it, right?
Omnissiah
Omnissiah4mo ago
why the 4
kianyuen
kianyuenOP4mo ago
It's queue, so I just delete anything I processed, no?
Omnissiah
Omnissiah4mo ago
so you are saying you keep the packets in a queue instead of processing them immediately?
kianyuen
kianyuenOP4mo ago
yeah. because it's the snippet to read from the port buffer
SerialPort spL = (SerialPort)sender;
byte[] buf = new byte[spL.BytesToRead];
spL.Read(buf, 0, buf.Length);
_receiveBuffer.AddRange(buf);
SerialPort spL = (SerialPort)sender;
byte[] buf = new byte[spL.BytesToRead];
spL.Read(buf, 0, buf.Length);
_receiveBuffer.AddRange(buf);
I keep this snippet as it is because I didn't know what else can I do.
Want results from more Discord servers?
Add your server