LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Read Serial Port with Termination Char?

Solved!
Go to solution

Hi, I have a particular piece of hardware that I'm communicating to which sends a 0xAh termination character at the end of the data written to the port. I'm having trouble reading the data from the port where I only get half of the data because of timing issues. I know it's related to looking at the bytes at port property node and reading those bytes which probably overrides the termination char setting. I have the termination char set correctly, so how does one poll for serial data at the port without using the bytes at port method since I don't think this works when using the termination char port method. Does anyone know this question?

 

Attached is simple VI which explains what my main VI is doing by setting the Term char and polling using the bytes at port method which is not working properly and results in data loss problems.

 

Thanks.

0 Kudos
Message 1 of 14
(11,099 Views)

Don't use bytes at port.  Use a very large number for your VISA read.  More than the length of the longest message you ever expect to get.  The VISA read will terminate when it gets the termination character, and the message will never be too short because you requested too few bytes.

Message 2 of 14
(11,091 Views)

Sounds good. Is there a way to suppress the timeout error that's reported if no data is available at the port and a timeout occurs? \\

 

Thanks.

0 Kudos
Message 3 of 14
(11,086 Views)

Just look at the error reported. If the error is a "Time out Error" (I don't know the value, you can easy identify this) then clear the error and do not stop the loop, just return back to reading again.

0 Kudos
Message 4 of 14
(11,079 Views)

Ok, I changed my code to just read a 1024 bytes of data and to ignore timeouts. I also set the timeout on the Serial Config to 200ms. For the most part it works pretty well, but every once and a while I get a bad read where it only gives me 5 - 20 bytes of data and not the whole header with the ending CRLF. Most of the commands the serial bus returns should be at least 34+ bytes long terminated with a CRLF. So why would the serial read terminate earily and only show half the data. This is weird. Any ideas?

 

Thanks.

0 Kudos
Message 5 of 14
(11,068 Views)

200 msec is not long.  If the timeout occurs before you've read the whole message, then it is going to be short and you have a timeout error.  At 9600baud,  you are only going to 1000 bytes in a second.  200 bytes in 200 milliseconds.  But the device needs time to get a message, compose a return message and send it out.  That could easily take a large fraction of a second.

 

Why did  you make the timeout only 200 milliseconds?  You should make it at least 2-3 seconds.

Message 6 of 14
(11,062 Views)

The reason I choose a short timeout is mainly because the controller can send terminated headers every 1000ms and I don't want to miss any. Granted 200ms is fast, but my thinking was that the the Visa Read serial command would only return data if the termination char was found. So, even if the read timed out in the middle, the next read would pick it up, but that doesn't seem to be the case. It looks like if the read times out before the data is completly written then read returns incomplete data regardless of meeting the termination code, which to me seems like a bug with the read command. How is the best way to do this inorder to get the timing correct if I need to read terminated data at rates of <1sec without ever getting a timeout condition in the middle of reading data.

 

Attached is revised version of what my polling routine looks like now ignoring read timeout errors. I pulled it out of my main code as an example to change.

 

Thanks.

0 Kudos
Message 7 of 14
(11,050 Views)

@QRP wrote:

The reason I choose a short timeout is mainly because the controller can send terminated headers every 1000ms and I don't want to miss any.


But you are reading the data.  If it doesn't send any, then you get the timeout.  Set the timeout to something more like 1000ms (1 second).  Some other tweaks to your code:

 

  1. There is no point in the property node there to set the termination character and what not.  That is all taken care of in the Configure Serial Port.
  2. You don't need the wait in the while loop.  The VISA Read will limit the speed of the loop.  Another reason to set the timeout to somethig more like 1 second.
  3. Instead of a case structure to clear the timeout error, use a select function.  It is a little faster, uses less diagram space, and is easier to read.

GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 8 of 14
(11,035 Views)

@QRP wrote:

, but my thinking was that the the Visa Read serial command would only return data if the termination char was found. So, even if the read timed out in the middle, the next read would pick it up, but that doesn't seem to be the case. It looks like if the read times out before the data is completly written then read returns incomplete data regardless of meeting the termination code, which to me seems like a bug with the read command.


No.  It is not a bug.  Read the help file on VISA read.  The VISA read ends and returns with data when any one of the three following things happen.

 

1.  The termination character has been read (if it has been enabled.)

2.  The requested number of bytes have been read.

3.  The timeout has been reached.

 

If the VISA read functioned the way you think it should, it would be a huge problem.  Suppose the termination character was never sent.  You request 1000 bytes, but because the termination character was not present, it actually returned none of them.  Then more bytes came in, but no termination character, and more ....  Eventually you'd fill up the buffer, generate an error, and never be able to recover from it or get the data that did come through because the VISA read would not return any data ever because the termination character has never been found.

 

I would set the time out for 2-3 seconds, not 1000 milliseconds.  Since you are expecting data every 1000 milliseconds, that is just too close to the timeout.  You might have a slight delay and it takes a little more than 1000 milliseconds to get the end of the data and the termination character.  Now you have a timeout error and an incomplete message.  Then next time you read, you'd get the rest of the bytes and the termination character, and that message won't be correct either.

 

The timeout should be long enough to guarantee you have enough time to get the message, but not so long that it causes excessive delays in your code if something happens like a serial cable gets unplugged accidentally.

 

Message 9 of 14
(11,025 Views)

Sounds good. I now understand what is happening =). I have never used the terminate char feature of the serial port in Labview, so this was a good exercise. Thank you both for the information.

 

Having a long timeout value on the VISA Read will not affect other thread/loops running will it? I have ~10 other timed loops monitoring other hardware that I don't want to interrupt while waiting for data on the serial port.

 

Thanks again.

 

0 Kudos
Message 10 of 14
(11,015 Views)