12/21/2017

Read Binary Data From Serial Port Configuration

Read Binary Data From Serial Port Configuration

I have a project where I need to send commands to a device and receive fixed length data back from it. This needs to be done through a serial port (till the device is updated). There is also a Kermit send to the device as well. I have seen some information on doing text through a serial port, mostly where arbitrary length data is returned at undetermined times. Does anyone know the best way to do command/response type communication through a serial port?

Can the serial port class be used without events when this type of communication is needed, or am I going to be stuck with figuring out how to work with the threading, waiting for data, etc.? Well, since no one has replied to your post, I'll give it a try. We work with instrumentation here, communicating with the devices over actual or virtual serial ports, or over a USB connection to embedded FTDI chips. Now I should caution you that our experience is limited to passing strings back and forth. My guess is that working with binary data across a serial port might pose a problem that I've never encountered, but I can tell you that Microsoft's SerialPort Class works exceptionally well when the data passed back and forth are printable strings, for instance.

Microsoft does all the heavy lifting. Users need only instantiate the SerialPort class, open a serial port, and attach their data-receive function to the event (i.e.

Subscribe to the event). Heck, even I can do THAT. You mention threading as a concern. Well there IS some threading going on but it's largely invisible to you. Your data-receive function will be operating on a different thread, but that's not much of a problem unless your data-receive function attempts to display the data on a form or interacts with an object subject to access by other threads (in which case, you might consider locks or other exclusionary measures).

I'm reading serial data in binary format from a stream. Read binary serial data and parse integers. Read and write data to/from Serial Port in C#.

Read Binary Data From Serial Port Configuration

In summary, it has been my (our) experience that the SerialPort class is simple to use and very reliable (but in your particular case, I should restate: working with binary data may introduce complications I've never encountered, and thus cannot address). You'll like it! The data will be extracted from the received stream into a structure. The data in the structure will then be displayed on a form.

All of this occurs sequentially. The send/response is initiated by a button or tab click, the external device is queried, the data interpreted, then presented on the form, then everything stops till another click. There is only one exception and that is a trigger by a timer that basically does the same as the button click on the form. It calls the same routines. This thing was originally written in C++ with QT Creator for the GUI. I am trying to get away from the multiple product issues and stick with straight C#/Forms. Andy, I just copied your code to a project here and (after a coupla changes of the sort 'internal' to 'public' granting myself access to your functions) it works just fine.

I'm seeing and responding to 'DataReceived' calls. When you applied the null modem, did you have it loop back? You didn't leave it 'open-ended' did you?

Anyway, your code's workin' just fine here. Re the polling vs responding to DataReceived. Polling is a perfectly fine way to proceed. Here, however, where the delay can be measured in seconds ( especially if motion is involved!) that's a potentially long time to poll; time which might be more profitably spent addressing other issues. On the other hand, if the response is immediate or reasonably so, then either way is fine. Best o' luck.

Well, OK, maybe I spoke too soon. (I spoke as soon as the breakpoint was hit in Data received). There might be a problem in that first statement (SerialPort1.BytesToRead!= BytesToRead ). At that point, 'BytesToRead' is zero.

I just resolved that issue by setting 'BytesToRead' as follows. SerialPort1.Write(Buffer, 0, (BytesToRead = Len)); in function 'PutData'. Incidentally, it's not clear to me that it will always be the case that datareceived is called ONLY after all bytes to be read have been read. That is, you might have to capture data on an accrual basis. Just a thought. 're the polling vs responding to DataReceived. Polling is a perfectly fine way to proceed.

Here, however, where the delay can be measured in seconds ( especially if motion is involved!) that's a potentially long time to poll; time which might be more profitably spent addressing other issues. On the other hand, if the response is immediate or reasonably so, then either way is fine' I have a feeling that this might be directed to my response, since I can't find any response (including mine) that addresses polling. Acer Szw 3300u Scanner Driver Win7. Polling doesn't usually work very well with the.NET SerialPort. Using the DataReceived event for a send/response system doesn't either. The Read method with appropriate use of the ReadTimeout property is simpler and usually performs better. You are correct, Sir.

My comment about polling was directed toward your suggestion. But certainly there was no criticism intended. To me, ignorant as I am, repeatedly doing a read to see if a response has been received IS polling.

In a case where the response is immediate or nearly so, not a problem. But as mentioned earlier, where a response may take seconds to appear, the time might be better spent elsewhere. Re the DataReceived functionality not working or working poorly. Gee, I've used that method and it hasn't failed yet.

I work with instruments that may take many seconds to send the complete response, and with some commands, the response may return in several different packets, widely spaced in time (hence my comment re working on an accrual basis). Indeed, I thought it worked so well that I modeled my FTDI code after Microsoft's DataReceived event so that we now have a DLL which can handle either conventional RS-232, virtual RS-232, or (for lack of a better word, 'native') FTDI. So if you were offended, please chalk it up to an old man's ignorance.

An inability to distinguish between what I assume could come down to repeated calls to Read, and 'polling'. I fear that in my old age, I'm beginning to exhibit moments of aphasia. I hope you'll accept my sincere apologies. 'To me, ignorant as I am, repeatedly doing a read to see if a response has been received IS polling. In a case where the response is immediate or nearly so, not a problem.

But as mentioned earlier, where a response may take seconds to appear, the time might be better spent elsewhere.' The SerialPort.Read method blocks until at least one byte is available.

You can use the ReadTimeout property to post a request to repeat, enter the idle state and service other requests For send/response, it works as well as the DataReceived event should, but without the threading side effects.; By send/response, I specifically mean that a message is sent to the port and a message is received from the port within a predictable time span. If the time of arrival of the individual byes of the response message is unpredicatable, then the DataReceived event should be used. I'm glad you have had such good luck with the.NET SerialPort. It's not a common occurrence. I am using virtual ports that can be set as a pair connected in null modem fashion. I haven't had the chance to change the code to use public rather than internal, but my understanding is internal acts like public within the project, just doesn't expose the methods to access outside the scope of the project (namespace). If this is the case, using internal shouldn't make a difference.

Maybe I missed something when it comes to the differences, or maybe it effects events differently than regular methods. Anyway, I know the null modem is working since I can run 2 instances of a terminal program on each port and anything sent using either terminal shows up in the other.

Note You need a license for both the Instrument Control Toolbox™ and Simulink ® software to use this block. This block has no input ports. It has one or two output ports based on your selection of blocking or nonblocking mode.

If you select blocking mode, the block will have one output port corresponding to the data it receives. If you do not select blocking mode, the block will have two output ports, the Data port and the Status port. A First In, First Out (FIFO) buffer receives the data.

At every time step, the Data port outputs the requested values from the buffer. In a nonblocking mode, the Status port indicates if the block has received new data.

If the Status port displays 1 it means new data is available and if the Status port indicates 0 it means no new data is available. Communication port Specify the serial port that you will use to receive from. You have to select an available port from the list.

By default, the Communication port field contains the text Please select a port. And you must change this to a valid port.

If you have not configured a port, the block will prompt you to do so. You can select a port from the available ports and then configure the port using the Serial Configuration block. Each Serial Receive block must have a configured serial port.

If you use multiple ports in your simulation, you must configure each port separately. Header Specify data that marks the beginning of your data block. The header indicates the beginning of a new data block and the simulation will disregard data that occurs before the header. The header data is not sent to the output port.

Only data that occurs between the header and the terminator is sent to the output port. By default none or no header is specified. Anything entered in the header is treated as a character. If you want to specify numbers, you need to use the corresponding ascii characters for them. For example, to specify [40 41], you can enter () in the field. Note that single quotes are also treated as characters. You can use the corresponding ascii characters for the numbers between 32 and 126.

Terminator Specify data that marks the end of your data block. The terminator indicates the end of the data block and the simulation will account for any data that occurs after the terminator as a new data block.

The terminator data is not sent to the output port. Only data that occurs between the header and the terminator is sent to the output port. By default or no terminator is specified.

Other available terminator formats are. • single • double • int8 • uint8 (default) • int16 • uint16 • int32 • uint32 Byte order When you specify a data type other than int8 or uint8, you can specify the byte order of the device for the binary data.

Your options are BigEndian or LittleEndian. Enable blocking mode Specify if you want to block the simulation while receiving data.

This option is selected by default. Clear this check box if you do not want the read operation to block the simulation. If you enable blocking mode, the model will block the simulation while it is waiting for the requested data to be available. When you do not enable blocking mode, the simulation runs continuously.

The block has two output ports, Status and Data. The Data port contains the requested set of data at each time step. The Status port contains 0 or 1 based on whether it received new data at the given time step. Action when data is unavailable Specify the action the block should take when data is unavailable. Available options are. • Output last received value — Block will return the value it received at the preceding time step when it does not receive data at current time step.

This value is selected by default. • Output custom value — Block will return any user–defined value when it does not receive current data. You can define the custom value in the Custom value field. • Error — Block will return an error when it does not receive current data. This option is unavailable if you do not select blocking mode.

Custom value Specify a custom value for the block to output when it does not receive current data. The default value is 0. The custom value can be scalar or value equal to the size of Data that it receives (specified by Data size field). Block sample time Specify the sample time of the block during the simulation.

This is the rate at which the block is executed during simulation. The default value is 1 second.

Here is a starting point for you: Once you have loaded your data into a string from the COM port, you can use the Mid function to extract a single byte at a time. Therefore to get the third of the 23 bytes out of your string (called sWholeString in this example), use: sHigh = Mid(sWholeString,3,1) That is a string. Then you can use Asc(sByte) to get the Ascii value. IHigh = Asc(sHigh) Then if your low byte is in the next byte, use this to get your 16 bit value: sLow = Mid(sWholeString,4,1) iLow = Asc(sLow) iTotal = sHigh * 256 + iLow Try it out and if it works and you want more detail let me know.