LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Questions regarding TCP communications


@BertMcMahan wrote:

The others here definitely have good advice, and I'd recommend listening to them.

 

I'd like to address your question of "it works in highlight execution mode but not in regular mode". Here's the timing diagram of what's happening from the POV of your instrument:

 

1: Command received

2: Process command, create reply

3: Transmit reply byte 1

4: Transmit reply byte 2...

..5: Transmit reply byte n

 

Your LV code does indeed wait on each sequence to finish. The issue is that when you're in highlight execution mode, you send the command (step 1), then while the little dot moves on the wire, your instrument finishes steps 2 through 5. By the time your code calls "TCP Read", it's all finished.

 

In "Immediate" mode, TCP Read returns when it gets any number of bytes. (https://www.ni.com/docs/en-US/bundle/labview-api-ref/page/functions/tcp-read.html)

 

This means that you call Write (step 1 happens), then you immediately call Read, you may be on step 4, where not all bytes have been read. Then you'll read too few bytes and get out of sync.

 

So, you have the issue of "how do I know what to return from TCP Read". Well, Termchars are the best way, but that's been discussed. The only other two options are return when you have a certain number of bytes or return after a certain time has elapsed. You don't know ahead of time how many bytes you have to get, so that leaves time alone.

 

In your application, your laser isn't sending unprompted data, so you can be sure that one and only one message will return when you send a command. You also know that it's probably very quick to reply, and you know an upper end of your bytes to receive. Right now this is basically what you're doing, except you're reading too fast.

 

The simplest answer here is to just add a "Stall Data Flow.vim" between TCP Write and TCP Read. Give it a value of, say, 100 ms (you can play with this; just make sure it's long enough to fully process and return a reply. You mention firmware, so it could be crazy fast and you could use 2 ms or something). Turn off Immediate mode, set your timeout low, and ask for 100 bytes (something more than you'll ever receive). See if that works.

 

I'd recommend making a subVI that does this for you too; a "Send message and get reply" function. That would bundle up the TCP Write, the Delay, and the Read. Now you can start to make some reusable code that can call one function that you've debugged instead of having to add all of this code for every single unique function.

 

(BTW, the other more complicated suggestions are good ones. The benefit there is that, if you made those functions, they're reusable anytime you have a similar application. Just adding a delay function should make this work for THIS application, but you'll have to repeat it every time. Same thing with the state machine suggestions- it WILL make your code more expandable, but I get it. Sometimes you just need to bang out a little helper program to automate a couple settings and you don't have the time budget to make something better. Maybe you have a deadline in 5 hours and just need some data. Still, I'd recommend following their advice if you see yourself using this code for a long time.)


First, all of this discussion about ACKs is about the TCP stack itself and really shouldn't be a concern for the application developer. All of this is handled by the low level TCP stack itself. Secondly, the sending side of a TCP connection is not waiting for the ACK to arrive before sending the next bit of data. It is waiting for enough data to buffer before sending the data. This is known as the Nagle algorithm. To minimize the overall TCP overhead data the sender will wait for a brief time such as the 50 ms you discussed before sending the data. If you are sending large blocks of data you will see the sender sending data as quickly as possible. It will only stop when the receiving side indicates its buffers are fall by indicating a window size of 0. In addition to this, the sender will retransmit data that has not been acknowledged by the receiver.

 

The Nagle algorithm is handled by the low level stack itself. If your protocol is such that you have short replies, this is where the delay is introduced unless the sending side disables the Nagle algorithm you will see short delays if the response data is short. Generally the Nagle algorithm wait until it has enough data for a full packet or the TCP-ACK from the receiver. Again, the TCP-ACKs are handled by the low level stack and you generally have no control of them at the application layer.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 11 of 15
(452 Views)

Did you perhaps quote the wrong message? I didn't mean "time between send and ACK", I meant "time between send and reply from remote device" (in my post you quoted). Or perhaps I wasn't quite clear in describing the timing.

0 Kudos
Message 12 of 15
(447 Views)

@BertMcMahan wrote:

Did you perhaps quote the wrong message? I didn't mean "time between send and ACK", I meant "time between send and reply from remote device" (in my post you quoted). Or perhaps I wasn't quite clear in describing the timing.


Indeed I did. I meant to quote Sebastian Weber's post.

 



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 13 of 15
(441 Views)

A quick followup - for most of the comms, I can brute-force count characters being read since I generally know what the reply will be.  The problem is that in some cases, the result may be two or three characters (e.g. 85 amps vs. 140 amps), so the count would be off and I'd either hang the read as it's waiting for more data that isn't there, or I truncate the reply.  Another example is that a status query could simply be "OK" or a multi-line list of errors.

 

I still haven't had a chance to talk to the bitheads regarding their choice of termination characters.  The cynic in me already knows their response though "We've done it this way for years and nobody's complained yet."  We'll see...

 

Have a great weekend!

0 Kudos
Message 14 of 15
(409 Views)

Attached is the basic VI for reading a large, unknown data block. This is the process that I had described earlier. You can adjust the two timeouts to values that are most efficient in your situation.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 15 of 15
(397 Views)