LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

crio serial

Solved!
Go to solution

Hi,

 

I am trying to send data through the serial port of a cRIO 9024 using RT and running into timing issues.  I am using the VISA drivers in an RT vi to get the number of bytes at the serial port, then read the data and plot it (and pass some on to an FPGA vi).  The serial port read and the charts are in a While loop and I am using the Wait (ms) function to set the speed at which it checks for data at the serial port.  That works alright, except for the fact that occaisionally there is only one character available at the serial port and I end up with zeroes or weird values here and there. When that happens, I get an error related to the buffer - I inserted a clear buffer vi so that it clears the buffer after each iteration of the While loop, but still get the same error.

 

I can see that the routine running on the Arduino is very stable - 205 ms plus or minus one millisecond.  Also, using the serial monitor in the Arduino development environment I see all of the data with no problem.  There is no flow control in the serial monitor, but I guess I just wouldn't be able to see delays between some of the characters because it is running so fast. 

 

The baud rate is 115200, 8 data bits, 1 stop bit, no flow control.  I have experimented with different baud rates and see the same issue.  I suppose I could try to implement flow control using CTS/RTS, but before I take up a couple of digital lines on the Arduino I wonder if I am missing something else.  Any help would be appreciated.  Thanks! 

0 Kudos
Message 1 of 8
(3,928 Views)

Welcome to the wonderful(ly frustrating) world of serial comms!

 

I've found from experience you can not rely on any sort of timing when talking serial. Serial data can get held up in hardware or OS buffers, which can mess with timing. That's why serial messages nearly always have a fixed length and/or a delimeter.

 

What delimeter(s) does each serial packet you're trying to read have? A 0x02 and 0x03 character is common, as is a newline or carriage return (or both).

 

My general method of working with serial is to maintain a local buffer of data, and do any processing on that data buffer. So a basic VI would maintain a string in a shift register, then append bytes to that string as they are read from the port. When a certain number of bytes and/or delimiter is present in the string, substring that data and process it as necessary.

 

 

You also mention zeroes and weird values coming through, and you've experimented with baud rates. How long is the serial cable? Is it shielded? Have you got access to another serial cable to try?

 

 




Certified LabVIEW Architect
Unless otherwise stated, all code snippets and examples provided
by me are "as is", and are free to use and modify without attribution.
0 Kudos
Message 2 of 8
(3,903 Views)

Thanks for your reply. 

 

I am using a newline and carriage return delimiter.  The cable is 2 meters long and is shielded.  The data is formatted as two floating point numbers, one with 2 digits of precision and the other with three digits, separated my a character (letter "m") that I use to separate the two values in my vi.  That's a good point about the overall length - sometimes it's 20.234m1000.00 and sometimes it's 20.123m10.22, so I should probably fix the length and figure out how to fill in the rest of the characters with zeroes.  Is it possible to have the serial read function wait until an exact number of characters is in the buffer to complete the read?

 

I end up with zeroes when only one or two characters are transmitted - the second number is interpreted as zero.  The first is not zero, but doesn't lie along the same curve - the values are like 20, 19.96, then a 4 or something like that...

 

How would you set up the buffer in a while loop?  If I take away the Wait(ms) function, it will keep trying to read data from the serial port and put zeroes on my charts each time through the loop that there is no data present.  I guess I would eventually catch all of the characters, but I am concerned about being able to separate the zeroes coming from a "null" read and any zeroes that are part of the actual data, as well as the timing.  Should I make a separate loop inside the main While loop?  The timing issue is important because I would like the RT vi to make the data available to the FPGA vi at fairly regular intervals.   

 

0 Kudos
Message 3 of 8
(3,883 Views)

Hello,

 

Do you get the same incorrect data when you run some of the examples online?  Below are a few different examples that might also give you a different approach to your application.

 

Serial Data Transfer Between cRIO and Host:  When you run this does it ever give you incorrect data such as 0?

 

Communicatiing with GPIB Instruments using NI CompactRIO:  If you aren't communicating with GPIB this might at least help with architecture and understanding how to collect data from the serial port of a cRIO.

 

RS-232 Interface Reference Example for LabVIEW FPGA:  This provides an example using serial directly with the LabVIEW FPGA.

 

Regards,

M. Whitaker
ni.com/support
0 Kudos
Message 4 of 8
(3,842 Views)
Solution
Accepted by topic author CJF1077

Pictures tell a thousand words, so here's a a quick and dirty example of reading from a serial port in to a string buffer. It then checks the string buffer for delimeters before passing the data to a second loop which would write the data to the FPGA. Don't take this as gospel though, it's untested and incomplete! Note that the "\r\n" string is set to show escaped characters.

 

serial_buffer.jpg

 

To read an exact number of characters from a serial port, simply wait until bytes at port is greater than or equal to the number of bytes you want, then read that many bytes using the serial read VI. The code above relies on the delimeter and formatting of the serial message, rather than it's overall length, so it's a bit more flexible in that regard.

 

In terms of the bad numbers coming through, the scan from string VI will likely throw an error. You could use this to discard bad values.




Certified LabVIEW Architect
Unless otherwise stated, all code snippets and examples provided
by me are "as is", and are free to use and modify without attribution.
Message 5 of 8
(3,832 Views)
Thanks! I inserted a case selector and decreased the ms timer to 50 ms and that works for me.

I actually started with one of those examples Whit-E_Wall-E. Thanks for the input though.
0 Kudos
Message 6 of 8
(3,793 Views)

i am sending packets via radio to base and then via serial to pc, structure is "n2v2.9t15.3"   n-node,  v -voltage, t - temperature, how is correct data reading via labview from this string?

i am using serial read and filtering string with offsets.. but sometimes i get results that are equals ..

 

 

0 Kudos
Message 7 of 8
(3,526 Views)

Generally Bytes at Serial Port is (almost) always the wrong solution to any serial port communication implementation. It makes detecting the message boundaries not easier but much more complicated.

 

A proper serial protocol has either a specific termination character (or two) or is fixed size. Anything else are special purpose protocols or most likely home brew garbage. For termination character protocols VISA comes with all the facilities to allow you to forget Bytes at Serial Port entirely. Simply set the according termination character property and then issue VISA Read commands with a higher number of bytes to read than the maximum message length and a reasonable timeout. VISA Read will return if:

- an error occurred in any of the lower level interfaces OR

- the termination character has been receive (if enabled) OR

- the specified number of bytes have been received  OR

- the timeout occured

 

This makes sure you receive an entire message frame or get an error indication. The only difficulty that still remains is that the first received message frame may be a partial message since the device may have been already active when you initialized the port.

 

Fixed size messages are pretty uncommon for serial port communication and tend to be more complex to decode properly and reliably but can also be done without Bytes at Serial Port. The only situation where Bytes at Serial Port is really useful is if you try to do some Terminal like application where the received data is not interpreted by the software but simply displayed in a (scrolling) text control and any interpretation is left to the human viewer. In all other cases the use of Bytes at Serial Port is almost always guaranteed to make the parsing and interpretation of the received messages much more complex and error prone.

 

The solution from Michael Balzer could be extremely simplified and the buffer in the shift register entirely removed if the Serial Port was initialized with termination character 10 (0xA) and then the VISA Read would be all that is required in the loop. If VISA Read then returns without error there is a valid string in the returned data that is terminated with \n and you can simply parse it. If it returns with a warning to the effect of that the number of bytes returned are the actually requested number of bytes you may have chosen a to small value for the Bytes to Read and there might be no termination character in the string.

Rolf Kalbermatter
My Blog
0 Kudos
Message 8 of 8
(3,520 Views)