08-09-2018 03:38 PM
Very new to labview serial commands, so I may be going about this in the wrong manner, but I'm having some trouble.
I'd like to be able to write a serial command to a device (based on a button click) then read and store what the device returns. The device returns ~10 separate, consecutive lines of data. I've noticed that if I put the write command inside a case, it works properly, but I have to wait ~7 seconds for the data to return (Method 1 below). I assume this is because the read has to timeout before the write can work again?
If I trigger the read command based on bytes being available at the port, I get bits of junk data (portions of what I'm expecting to return from the command, but not everything) preceding the proper return format. It also returns the proper chunk of data 2+ times, seemingly at random, but all of this happens extremely quickly.
What's the proper flow to get it to return the data once, quickly, and on-demand?
Solved! Go to Solution.
08-09-2018 04:09 PM
Normally the communication protocol is either fixed length and/or has a termination character which you can use to configure the end of the serial read. You can play around with the various kinds of flow control quickly inside of NI MAX using the serial port you are interested in. Once you figure out the settings in NI MAX, you can then configure the appropriate settings in your application.
08-09-2018 04:18 PM
You need to use an event case to wait for the button press, then write, then read. The way it is set up now it is spending most of its time just sitting there waiting for the read to timeout.
Here's a video that might help if you don't know what that is.
08-09-2018 04:39 PM - edited 08-09-2018 04:41 PM
You probably want to use an Event Structure at the least and possibly a State Machine if you want to extend it further.
#1 - As it is your loop is running flat out hogging resources and trying to read from device on every iteration.
#2 - Obligatory: Don't use Bytes at Port!
A simple setup with Event structure would be as follows.
Edit: Had stop button in wrong case.
08-09-2018 04:53 PM
You've gotten good, but maybe "incomplete", advice. When you interact with Serial Devices, you need to have some understanding about how they send data to you. A lot is hidden in the VISA Configure Serial Port that @CStorey showed you. In addition to such things as Baud Rate (how fast your device talks to you) and bit structure, there are two terminals on top that control whether and how your device uses a Termination Character. By default, it is set to expect a Termination Character, and by default that character is 0xA, <Line Feed>.
What this means is you expect your Device to send a command of some (unknown) number of characters, ending with <LF>. So when you do a VISA Read, instead of trying to specify how many bytes to read, specify 1000 (far too many), knowing that your device will send maybe 10-20, then a <LF>, which will cause the Read to terminate and give you the String.
What if the device is turned off? Well, you can also add a TimeOut (I almost never do this, as I know to turn my device On before running my program ...) so if 10 seconds goes by without your Device talking to you (or 1 minute, or whatever time interval you specify), the VISA Read will abort and signal this with an Error on the Error Line.
Bob Schor
08-09-2018 05:09 PM - edited 08-09-2018 05:31 PM
- Edit- Cstorey thanks for the example.
The problem now is that I can read data as fast as the button press event lasts. I'd have to click the button multiple times to read all lines of data. I've tried putting Waits inside the loops but I think it's causing an overrun error. The button mechanical action is latch until release.
Bob, the problem is I don't have a proper termination character (as least as far as I can determine). The data comes in on multiple lines, each with a carriage return. The only way I know I've received all the data is because I know how many lines it will be.
08-09-2018 06:10 PM - edited 08-09-2018 06:18 PM
Bob's advice is good, look at changing the termination characters and see if you can read the entire response. If that doesn't work, then do the the read in a while loop. As long as there are characters being returned by the read, keep reading until there are no characters returned.
Serial devices these days often have poor or incomplete documentation. I find its sometimes tedious to do thorough and complete command testing and response debugging when starting a project involving serial. But I'm almost always happy I did a few days/weeks/months or years later that I did when I reuse the code and have left myself nice comments about all those command/response strings. So make yourself a table of commands and responses, do responses vary by command order? Test it all and note it all down!
If you get stuck post some of your code with response strings. Maybe even mention the serial device name and you could find someone with code waiting to be shared...but don't hold your breath. 😉
Craig
08-09-2018 07:47 PM
You know how many lines! You're golden. Read that many lines in a for loop and concatinate the array. Yes that means you're going to have to make a look up table for lines expected for each command. Make sure you document the source reference for that table in case it changes or someone rearranges the commands.
08-10-2018 08:08 AM
Try the VI I posted at https://forums.ni.com/t5/LabVIEW/Communication-with-serial-device/m-p/3791957#M1069773
It uses bytes at port (GASP!) but can handle multiple lines. Make sure you configure use VISA not to use the carriage return\new line termination if that is the message terminator.
mcduff