LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Serializing read/write operations of network-published shared variables

Hi all,

 

I'm developing a distributed application (PC + CompactRIO), and using shared variables (SVs) for inter-device communication. Here's my journey so far:

 

Intended procedure

  1. PC parses file
  2. PC writes processed file data (custom cluster, large) into the 1st SV 
  3. PC writes a "grab data" signal/command (enum) into the 2nd SV
  4. cRIO polls the 2nd SV
  5. cRIO sees the command, then reacts by reading the 1st SV

Steps #2 and #3 were sequenced, using error wires.

 

Unexpected results

Even after the command is transmitted and the cRIO sees it, the cRIO could not read the data (which I wrote BEFORE the command) -- LabVIEW reported that the buffer was empty.

 

The operation succeeded when I placed a wait (5 seconds) between steps #2 and #3.

 

Questions

  1. What am I doing wrong, and how do I achieve my desired outcome?
  2. Is SV I/O asynchronous by design?
  3. Is it possible to use event-driven programming to handle SV access? (i.e. does LabVIEW signal when the new SV value has propagated across the network?)
Certified LabVIEW Developer
0 Kudos
Message 1 of 10
(3,306 Views)

How much data are you sending in the first Shared Variable.  You may need to Flush Shared Variable Data before writing to your second variable.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 2 of 10
(3,299 Views)

Thanks for the tip; I'll try manual flushing and see if that helps.

 

My test data was hovering somewhere around the 8 kB mark (not sure if it's over or under, as it was a package containing a few layers of clusters, arrays and variants).

 

Theoretically, would these statements be correct?:

  • If both SVs were under 8 kB, they should become available in the same order as they were written
  • If an SV was a bit over 8 kB, the first 8 kB would be sent first, then the rest would follow 10ms later
Certified LabVIEW Developer
0 Kudos
Message 3 of 10
(3,284 Views)

@JKSH wrote:
Theoretically, would these statements be correct?:
  • If both SVs were under 8 kB, they should become available in the same order as they were written
  • If an SV was a bit over 8 kB, the first 8 kB would be sent first, then the rest would follow 10ms later

My understanding is that if both SV were under 8kB, they will be published together.  So maybe not all of the data of the first has been sent by the time the second is complete.  I haven't researched it enough to say if your second statement is correct.

 

Regardless, flushing the buffer before sending the second variable should help.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 4 of 10
(3,279 Views)

Huh... I can't seem to replicate the issue anymore.

 

I'll still flush the buffer, just in case it's some kind of race condition.

 

Thanks  for your help, crossrulz

Certified LabVIEW Developer
0 Kudos
Message 5 of 10
(3,258 Views)

You could try using the timeout feature of the SV on the cRIO side to ensure you have updated data in the first SV (after you get the "notifier"). There's also a timestamp output you might leverage. This should help get around any assumptions about the order and time updated data may be available to the publisher.

0 Kudos
Message 6 of 10
(3,254 Views)

@BillMe: Thank you for your suggestions.

 

Yes, both approaches should guarantee that my variables are synchronized as expected.

 

However, I'm wondering if there are simpler ways to get that guarantee, without adding a few more elements to the block diagram. If I understand the Flush action correctly, forcing a flush before sending the "notifier" should provide that guarantee. Since my application does not stream data in real-time, I believe flushing is the most elegant solution.

Certified LabVIEW Developer
0 Kudos
Message 7 of 10
(3,231 Views)

Why do you have to "notify" the other end that data is available? The subscriber can simply sit in a loop doing a timed read just as if using a queue or notifier IPC. If it doesn't time out, you got new data. If it does time out, do some other processing if needed and then loop back for another timed read.

0 Kudos
Message 8 of 10
(3,226 Views)

@BillMe wrote:

Why do you have to "notify" the other end that data is available? The subscriber can simply sit in a loop doing a timed read just as if using a queue or notifier IPC. If it doesn't time out, you got new data. If it does time out, do some other processing if needed and then loop back for another timed read.


My sytem architecture is command-driven -- the cRIO listens for instructions from the PC interface (sent as an enum via one SV), and performs tasks (motor control) in response. One of the commands (the one described in this thread) happens to be "download a new motion profile from the PC, by reading the other SV". Given that the cRIO is already polling the command channel, I felt that there's no need to also poll the data channel (especially since the "download" command is issued very infrequenty). Plus, I thought that polling two channels would increase the chances of race conditions or illegal state transitions, particularly if the app is developed over a long term.

 

I am also new to LabVIEW, so my current programming style will heavily reflect my C++/Qt background while I get a feel for LabVIEW's strengths and weaknesses -- Qt is a heavily event-driven framework (even for networking!), where polling often means you're doing something wrong. 😉

 

Still, thank you for pointing out that I can use timeouts to determine if new data has arrived -- my subscriber current writes a null command back into the SV when it has consumed the command, but you showed me that I don't have to.

Certified LabVIEW Developer
0 Kudos
Message 9 of 10
(3,219 Views)

Could this be the cause of the issue?: Network-published shared variables are buffered by default.

 

In my case, the Command variable is polled so the old buffered command gets "read until it disappears". In contrast, the data variable is read once in a blue moon, so the next read returns old buffered data.

Certified LabVIEW Developer
0 Kudos
Message 10 of 10
(3,163 Views)