LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How do I get all serial data when there are no termination characters?

Attached is an example of serial data viewed with HyperTerminal.  This ASCII data is asynchronously sent via RS23 by a torque and tension sensor.  The baud rate is 19,200 and the data is updated at about 52 Hz.  There are no termination characters, line feeds, etc.   There are two fields of data within the serial data.  Where there is a “T”, tension data is in the following 5 digits.  (The data is hex.)  Similarly where there is a “Q”, torque data is in the following 5 digits.  Usually the T’s and Q’s alternate, but not always.  Sometimes depending on the activity within the sensor, there will be a number of “T” data fields before the “Q” data fields will reappear.  Vice versa for the “Q” data fields.

In short, how do I manipulate the serial buffer to gather all the serial data?  (I don’t know the proper serial jargon.)  A fellow programmer (using CVI) tells me that I need to run the buffer so that when the system sees the leading character (T or Q) it pulls that data field out from the buffer and then it strips out the next data field, which could be  T or Q data.

I’ve viewed and experimented with the various serial data examples but cannot see how they can apply to my need.  Maybe I’m missing the point.  In the past I’ve created serial data projects with a slower running loop in order to gather an adequate number of the ASCII data string.  I then strip out the data that I want, which means that some of the serial data will be lost.  However, for this project I’m tasked to not lose any of the serial data.

I need to port this project into a cRIO-9012 controller and use the controller’s serial port to acquire the serial data.  I’m currently using Win-7 and LV 2009 with SP1.

Please advise how I should approach this project using LabVIEW.

Thanks,

Dave
0 Kudos
Message 1 of 10
(5,971 Views)

In the VISA Configure Serial Port vi, set the Enable Termination Char to False.  Wait for 6 bytes at port, then read them.  Process the data.  Repeat.  See snippet:

 

NoTermChar.png

 

- tbob

Inventor of the WORM Global
0 Kudos
Message 2 of 10
(5,962 Views)
Read 6 bytes at a time.  Search the string for a Q or T.  If the Q or T is in the first position.  Then the next 5 bytes are a piece of data.  If it is later, store in a string and read how many more bytes needed.  (index 1, read 5;  index 2 read 4 more, ...)  Now you have a full piece of data.  From then on you should be able to just read 6 bytes of data at a time, but always check position to see if the Q or T is first.
0 Kudos
Message 3 of 10
(5,961 Views)

I might read all available bytes in one loop and pass the string to an analysis loop via a queue.  Discard up to the first five characters until you find the Q or T character.  Then break the string into data words.  When you get to the end of the string you may have a partial data set.  Put those remaining characters into a shift register and append the next string read from the port to them and continue with the analysis. 

 

The use of one loop to read the bytes at the port and push them into a queue and a second loop to analyze the results allows each process to be run at the speed which works best and should prevent any loss of data.  Look at the many examples and postings on Producer/Consumer. 

 

Lynn 

0 Kudos
Message 4 of 10
(5,937 Views)
Attached is my first attempt at using a producer/consumer system with serial data.  It doesn't work correctly.  I get serial data in the Raw String indicator.  However, the Case structure in the For loop never goes true.  Before I continue with this, am I at least on the right track for using the producer/consumer concept in conjunction with processing the serial data?  I'm not sure when to use Flush Buffer; if ever.
0 Kudos
Message 5 of 10
(5,916 Views)

The problem is in your inner most for loop in the upper loop.

 

You get the bytes at port.  Let's say you get 12Q345.  Well you go through the loop and take string subset starting at 0 and length of 0. so nothing.  Then starting at 0 length of 1 = "1".  Starting at 0 length of 2 = "12".  Starting at 0 length of 3 = "12Q".  That is not equal to "Q" nor is it equal to "T".  The only way you get lucky is if the Q ( or T) happens to come first.

 

You've made this way too complicated.  You should really be using Seach String.

 

Read 6 bytes at port.  Now you know it has a Q or a T, you just don't know where.  Search the string for the Q or the T.  Find the position.  Discard the earlier bytes.  Read x more bytes.  Now concatenate the end of the first string with the x more bytes you just read and analyze that.

 

Right now your producer/consumer architecture isn't really doing anything.  I wouldn't used the timed while loops or the Abort Loop function either.

0 Kudos
Message 6 of 10
(5,908 Views)

Ok I'll rethink the For Loop.  Do I need to use the Flush Buffer function or does the VISA Read handle the buffer?

For the sake of learning, why not use Timed While Loops?

0 Kudos
Message 7 of 10
(5,902 Views)

No need to flush the buffer.  Because once you get your bytes in synch,  you shouldn't lose any bytes or messages.  And flushing the buffer might accidentally cause you to lose bytes of the next message.  The VISA read pulls the bytes out of the buffer as they are read.

 

I have seen some message threads where there are concerns about timed loops working properly on Windows based systems.  The timed loops are really more intended for real-time targets.

 

A while loop should work just fine.  The waiting for 6 bytes on every iteration will adequately throttle your loop.  And if you need to pass data off to another loop for further processing, then the producer/consumer architecture will handle that timing just fine.

Message 8 of 10
(5,899 Views)

I appreciate everyone’s response.  After spending more time on this that I should have, I’ve come to the conclusion that I will not be able to catch all the data; at least not with my limited skills.  I think the primary problem is that the number of bytes received widely varies and I don’t think I have any control over it.  For example, the number of bytes received will radically vary between 12 and 34 bytes.  It’s all over the place…

I kept the timed loops because this application will use a cRIO controller.  The controller crashes when I attempt to use regular while loops.

In case anyone is interested, attached are the results of this effort.  This is an example of what I did to use producer/consumer architecture and the receiving of asynchronous and unstable serial data.   The purpose of the string shift registers in the producer loop is to issue that last valid string when a partial string was received.  Please note this was prepared using LV 2009 with SP1.

Thanks,

Dave
0 Kudos
Message 9 of 10
(5,853 Views)

Hi Dave,

 

I would use a state machine to parse the data as it arrives.....  See this thread.....

http://forums.ni.com/ni/board/message?board.id=170&thread.id=314821&view=by_date_ascending&page=1

 

 

0 Kudos
Message 10 of 10
(5,846 Views)