Aaron L Posted March 6, 2008 Report Share Posted March 6, 2008 Okay, I just don't know the right search term to figure out what should be amazingly easy. :headbang: All I want to do is wait until I receive a CR/LF combo from a serial port, 9600/8/N/1, then execute the rest of my code. I looked at the example codes built into LV 8.5 to no avail. They have reads, simple and complex, but all of them time out rather than stopping on my CR/LF character combo. Really, all I need is the LF character. It can't be this difficult, right? I'm receiving a simple string from a photometer that ends in a CR/LF. I've tried setting the Enable termination, setting Status, but to no avail. I know what the length of the string is and have terminated on that, but if something goes wrong in the transmission, I don't want to get out of sync by just counting characters. It's important that I catch the LF character and halt on that, as this is a 6 hour operation. I can tollerate one bad message but the system can't tollerate getting out of synch. Thanks! Quote Link to comment
Tim_S Posted March 7, 2008 Report Share Posted March 7, 2008 QUOTE(Aaron L @ Mar 5 2008, 07:21 PM) All I want to do is wait until I receive a CR/LF combo from a serial port, 9600/8/N/1, then execute the rest of my code. I looked at the example codes built into LV 8.5 to no avail. They have reads, simple and complex, but all of them time out rather than stopping on my CR/LF character combo. Really, all I need is the LF character. It can't be this difficult, right? Years ago I had to do this and wound up reading the serial port then buffering the string. I've not looked to see if there are newer tools that can do this, but I'm suspicious that's what you're going to be doing. Quote Link to comment
Phillip Brooks Posted March 7, 2008 Report Share Posted March 7, 2008 I don't have a direct answer, but did you look at this post from a few weeks ago that includes a "Terminal" program? It might provide some ideas you can use... Quote Link to comment
shoneill Posted March 7, 2008 Report Share Posted March 7, 2008 QUOTE(Phillip Brooks @ Mar 6 2008, 01:11 PM) I don't have a direct answer, but did you look at this post from a few weeks ago that includes a "Terminal" program?It might provide some ideas you can use... Why not just do this? http://lavag.org/old_files/monthly_03_2008/post-3076-1204806507.png' target="_blank"> "10" is the ASCII value for Linefeed. You can also set the termination condition seperately for both in and out directions (Bottom enums). These are found under the "Serial Settings" for the Serial Instr reference type. All others are found under "Message Based Settings". Shane Quote Link to comment
LAVA 1.0 Content Posted March 7, 2008 Report Share Posted March 7, 2008 QUOTE(shoneill @ Mar 6 2008, 07:30 AM) Why not just do this? http://lavag.org/old_files/monthly_03_2008/post-3076-1204806507.png' target="_blank"> "10" is the ASCII value for Linefeed. You can also set the termination condition seperately for both in and out directions (Bottom enums). These are found under the "Serial Settings" for the Serial Instr reference type. All others are found under "Message Based Settings". Shane I'd go with Shane recomendation shown above IF you be sure that "LF" never appears in your data stream. If LF is a valid character (aprt from the termination sequence) then I have cracked that nut by reading all bytes at port and buffering them in a SR. Afeter each read from the port, parse the buffered data for a frame that starts with CR/LF and ends with CR/LF. Toss anything that comes before the first cr/LF and decode what in-between for your data. Ben Quote Link to comment
shoneill Posted March 7, 2008 Report Share Posted March 7, 2008 QUOTE(neB @ Mar 6 2008, 02:36 PM) I'd go with Shane recomendation shown above IF you be sure that "LF" never appears in your data stream. If LF is a valid character (aprt from the termination sequence) then I have cracked that nut by reading all bytes at port and buffering them in a SR. Afeter each read from the port, parse the buffered data for a frame that starts with CR/LF and ends with CR/LF. Toss anything that comes before the first cr/LF and decode what in-between for your data.Ben True, True. It would of course be required to check and received string for a proper \cr\lf combination, otherwise buffer until both are found...... I personally prefer the half-half approach of leaving the buffering to the OS and just taking string by string (or sub-string by sub-string if some buffering is required). Generally though, any element of a termination character should NOT be present in the transmission data. It's just good design. OTOH, much in life is simply beyond our control..... Shane Quote Link to comment
ASTDan Posted March 7, 2008 Report Share Posted March 7, 2008 I came accross VISA Events latly. I used them in my last Serial I/O project with great sucess. Here is a sample of basicaly how it works. Dan Quote Link to comment
shoneill Posted March 7, 2008 Report Share Posted March 7, 2008 QUOTE(ASTDan @ Mar 6 2008, 05:19 PM) I came accross VISA Events latly. I used them in my last Serial I/O project with great sucess. Here is a sample of basicaly how it works. http://lavag.org/old_files/monthly_03_2008/post-8614-1204820334.gif' target="_blank"> Dan Dan, slightly off topic here, but How do you get them to work? I've tried them in the past, but I can NOT get them to work...... On the other hand, isn't this basically what the VISA read does in the background with "ASRLEndIn" set to "TermChar" ? You're also not guaranteed that the string read at this time is only up to the TermChar. Timing effects (especially at hugh Baud) mean you still have to deal with reading more characters than you want and buffering and so on..... Shane. Quote Link to comment
Aaron L Posted March 7, 2008 Author Report Share Posted March 7, 2008 QUOTE(ASTDan @ Mar 6 2008, 08:19 AM) I came accross VISA Events latly. I used them in my last Serial I/O project with great sucess. Here is a sample of basicaly how it works. http://lavag.org/old_files/monthly_03_2008/post-8614-1204820334.gif' target="_blank"> Dan Dan, I was able to take your example and get it to work. This is the first code that seems to do what I want. I'll have to try it at full speed to see how it handles things. Attached is a VI with the basic program. Thanks! Quote Link to comment
ASTDan Posted March 7, 2008 Report Share Posted March 7, 2008 Cool! Glad I could be of some help Dan Quote Link to comment
Aaron L Posted March 7, 2008 Author Report Share Posted March 7, 2008 QUOTE(shoneill @ Mar 6 2008, 04:30 AM) Why not just do this? http://lavag.org/old_files/monthly_03_2008/post-3076-1204806507.png' target="_blank"> "10" is the ASCII value for Linefeed. You can also set the termination condition seperately for both in and out directions (Bottom enums). These are found under the "Serial Settings" for the Serial Instr reference type. All others are found under "Message Based Settings". Shane Shane, I built up the code you suggested but the system still doesn't halt on a LF character, it only passes right through to the VISA read. Perhaps I'm missing something? I've attached a pic of the code and attached the code itself. I believe this is likely a more proper way to do this than event driven action, but I have yet to crack this one. Any suggestions? Quote Link to comment
ASTDan Posted March 7, 2008 Report Share Posted March 7, 2008 QUOTE(shoneill @ Mar 6 2008, 12:39 PM) Dan,slightly off topic here, but How do you get them to work? I've tried them in the past, but I can NOT get them to work......On the other hand, isn't this basically what the VISA read does in the background with "ASRLEndIn" set to "TermChar" ?You're also not guaranteed that the string read at this time is only up to the TermChar. Timing effects (especially at hugh Baud) mean you still have to deal with reading more characters than you want and buffering and so on.....Shane. I don't know how I got them to work. You might want to try setting the TermChar to True in the Init VISA. This enables VISA to be able to recognize TermChar. Also the default is LF to change to CR do the following. There are also some other interesting events that my be applicable i.e. Serial break 0xA is the hex equivalent of a linefeed character (\n). Change the termination char to 0xD for message strings that terminate with a carriage return (\r). On the other hand, isn't this basically what the VISA read does in the background with "ASRLEndIn" set to "TermChar" ?Events allow VISA to trigger a Read. The "ASRLEndIn" set to "TermChar" tells VISA where to stop reading.I would aggree you may have to do some buffering on a high baud serial comunication.What I like about Events is I can trigger my read on something usefull. Not just reading whatever is on the serial port every x seconds. This can save parsing headaches.My $0.02DanQUOTE(Aaron L @ Mar 6 2008, 02:11 PM) Dan,I was able to take your example and get it to work. This is the first code that seems to do what I want. I'll have to try it at full speed to see how it handles things. Attached is a VI with the basic program.Thanks! You don't need that wait before enabling the event. When you create the event that is telling VISA to wait until it sees a Term Char on the serial port.Dan Quote Link to comment
shoneill Posted March 7, 2008 Report Share Posted March 7, 2008 @Dan Thanks for the reply. IIRC I never actually tried setting the TermChar and ASRLEndIn AND using events. That's probably my problem. @AAronL Set the number of Bytes to read to the maximum you should ever receive. I typically set it to double my maximum packet size. The reason is that the VISA read will terminate whenever the number of bytes was read OR the termination character is received, whichever comes first. So we remove the limitation of our Nr. of Bytes by telling it to read s silly amount of data. Then it will quit when it receives the LF Character. Of course, don't set the Nr of characters to read TOO high, otherwise you'll be risking locking up your program...... Also, set the termchar options immediately after opening the port, before the wait. Otherwise it'll miss the first X events. This actually seems to be a downside of my approach. With user-controlled Buffering, blocked programs can be avoided nicely. Is there a way to trigger an event on the serial port? Preferebly without OS calls? I suppose a break might do it, huh? Shane. Quote Link to comment
Aaron L Posted March 7, 2008 Author Report Share Posted March 7, 2008 QUOTE(shoneill @ Mar 6 2008, 11:56 AM) @DanThanks for the reply. IIRC I never actually tried setting the TermChar and ASRLEndIn AND using events. That's probably my problem. @AAronL Set the number of Bytes to read to the maximum you should ever receive. I typically set it to double my maximum packet size. The reason is that the VISA read will terminate whenever the number of bytes was read OR the termination character is received, whichever comes first. So we remove the limitation of our Nr. of Bytes by telling it to read s silly amount of data. Then it will quit when it receives the LF Character. Of course, don't set the Nr of characters to read TOO high, otherwise you'll be risking locking up your program...... Also, set the termchar options immediately after opening the port, before the wait. Otherwise it'll miss the first X events. This actually seems to be a downside of my approach. With user-controlled Buffering, blocked programs can be avoided nicely. Is there a way to trigger an event on the serial port? Preferebly without OS calls? I suppose a break might do it, huh? Shane. Shane, Great, that worked! Thank you. It's attached in this post so when people like myself need to find the solution to this problem, there are multiple available here. I'll go with this method for my application. Aaron Quote Link to comment
Aaron L Posted March 7, 2008 Author Report Share Posted March 7, 2008 Here's the ultimate version that writes a command out, reads back the data: OK00, AAA45.678<CR><LF> And is immediately ready with another command. The VI ping pongs very well. The loop doesn't have to wait an arbitrary hold time, so it's ready as soon as the <LF> is received. Thanks all for your help and I hope this helps someone in the future. Quote Link to comment
shoneill Posted March 8, 2008 Report Share Posted March 8, 2008 QUOTE(Aaron L @ Mar 7 2008, 12:29 AM) Here's the ultimate version that writes a command out, reads back the data:OK00, AAA45.678<CR><LF> And is immediately ready with another command. The VI ping pongs very well. The loop doesn't have to wait an arbitrary hold time, so it's ready as soon as the <LF> is received. Thanks all for your help and I hope this helps someone in the future. Aaron, The setting of the TermChar settings should be done only once immediately after you open a reference to the serial port. There's no need to call it in every loop. It might even have detrimental effects. Shane. PS Glad to be of help. Quote Link to comment
Aaron L Posted March 28, 2008 Author Report Share Posted March 28, 2008 QUOTE (shoneill @ Mar 7 2008, 02:27 AM) The setting of the TermChar settings should be done only once immediately after you open a reference to the serial port. There's no need to call it in every loop. It might even have detrimental effects. Shane, Interestingly enough, when you take out the TermChar from the Instr, the system does not respond immediately, but waits for the time out period to happen from the VISA serial origination. I'm not sure why this happens. The setup still works, but the communication rate is limited to whatever the time out period is. Thanks! Aaron Quote Link to comment
shoneill Posted March 29, 2008 Report Share Posted March 29, 2008 QUOTE (Aaron L @ Mar 27 2008, 07:50 PM) Shane,Interestingly enough, when you take out the TermChar from the Instr, the system does not respond immediately, but waits for the time out period to happen from the VISA serial origination. I'm not sure why this happens. The setup still works, but the communication rate is limited to whatever the time out period is. Thanks! Aaron What do you mean with "take out the TermChar"? If you don't set the option at all, then it's expected that the Read will wait until timeout. This is because we're telling it to read too many bytes, which it can't do. Hence the timeout. The TermChar option simply gives the Read an earlier Termination option. A Read has three main options for termination: TermChar Timeout Bytes to read In order to make sure we stop at the "Termchar", we need to set this as a termination option. Otherwise the other two remain active, and by setting the "Bytes to Read "too high, the Timeout becomes the only real termination option left. If you lower the "Bytes to Read" (without TermChar) then at some stage (Length of your received message) the "Bytes to Read" termination option will prevail and the timeout will become irrelevant. A Read always stops when the FIRST termination option is fulfilled. For giggles, set the Timeout to -1, no "TermChar" and a huge "Bytes to Read" and you've got a VI which hangs. By doing this you've effectively removed any termination option available. There's always the otion of a Reboot Shane. Quote Link to comment
lbaute Posted June 18, 2015 Report Share Posted June 18, 2015 I've tried the above code w/events, the following code is the one that worked for me. Hope it helps. Quote Link to comment
Phillip Brooks Posted June 19, 2015 Report Share Posted June 19, 2015 I posted an idea on the NI forums about a year ago that is long overdue; the ability to define a regex for VISA message termination. http://forums.ni.com/t5/LabVIEW-Idea-Exchange/Add-regex-based-termination-string-option-to-NI-VISA/idi-p/2859152 I had the idea after tinkering with a .NET library called SSH.NET. One of the methods of a stream is Expect. http://forums.ni.com/t5/LabVIEW/Plink-PuTTY-works-30-of-the-time-using-System-Exec-vi/m-p/3006795#M860452 1 Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.