LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to Verify Synchronization?

Solved!
Go to solution

There are multiple posts on how to synchronize various combinations of inputs/outputs but I can't seem to find anything on how to check/verify the level of synchronization.  Based upon what I've read, some techniques have the drawback of drifting apart over time so how would one go about "measuring" this increasing out-of-sync condition? 

 

I have a cDAQ 9189 chassis with three modules:

  1. 9264 analog output
  2. 9202 analog input
  3. 9403 digital IO

Let's say I'm passing analog and digital waveforms to the analog output and digital output cards and I'm recording a bunch of channels of analog input data while these "profiles" are running...and all of this is happening at 10,000 hz.  Are there labview functions/features that allow me to compare absolute timestamps of the write operations on both cards so I can verify that they are synchronized?  The application is for an ultra-fast laser steering device (analog outputs) and while the device is steering the beam around the digital output waveform is turning the beam on and off (so these two events being perfectly timed is super important).  The current VI I've written doesn't seem to be perfectly synchronized and I can't figure out how to go about measuring/outputting, in absolute time, when the two output events are occurring so I can troubleshoot this issue.  Is there a timing property node that can output a timestamp value for when each output waveform starts and stops?

 

I'd post my VI but it's extremely complicated (probably part of my problem) and I think I can start to figure it out on my own if I had a way to output some sort of data on when these events are occurring.

 

Thanks for the help!

0 Kudos
Message 1 of 10
(393 Views)

Normally you synchronise multiple tasks not by PC measured time, but by common trigger signal that starts each frame, and (if necessary at high speeds and many samples) by using the same (or derived from the same) sample clock (one board generates clock or timebase signal for others). Look at Counter output tasks, they can generate common clock and triggers and retriggerable acquisition to restart each sequence on trigger (and restore synchronisation).

To check synchronisation you can acquire the same signal (the one that you generate for example) on digital and analog channels . If they show the same - you are good.

Message 2 of 10
(380 Views)

Attached are an example VI and an example profile input file (csv file with no headers - first column is time, second column is the first analog output channel, third column is the second analog output channel, and the fourth column is the digital output state).

 

When I run this:

  • The measured loop time is never 10.000 seconds (per the profile)
  • The loop counter gets up to something like 640-650 counts

This is missing the analog input and file saving code because I stripped it out to make it easier for someone to help me.

 

Is this the right way to do this?

0 Kudos
Message 3 of 10
(370 Views)

I don't have LV 2019 installed, can't look at the code, and have limited time.  A few thoughts nevertheless:

 

1. My favorite way to sync tasks is by sharing a common sample clock.  Better yet, *generate* that sample clock with a counter so you can control the *offset* between output and input (giving the system a chance to react to your new output sample before taking an input sample.)  See this thread for a little more detail.

 

2. Dunno your specific cDAQ modules and what they support.  In particular, analog modules based on "Delta-Sigma" converters won't accept external sample clock signals, making it trickier to accomplish sync.

 

3. If you *can* share sample clock signals, there's pretty much no "out of sync" to measure .  The tasks simply won't drift apart from one another.

 

4. Sync is established by driving tasks off common hardware signals.  The time-of-day timestamps you can get from DAQmx won't be nearly as accurate or trustworthy.

 

 

-Kevin P

Message 4 of 10
(349 Views)

I replied to your other message, but this one gives me a chance to say "Get Rid of the Sequence, use Data Flow (which you already have).  The Sequence does nothing for you except stagger the start of the two output loops, for no apparent purpose or effect.  Note that, in any case, the While loop can't start until both DAQmx Tasks have been started.

(The Purists will say that I'm wrong, that your original code sequenced the Starts, which is technically (= actually, I admit) correct, but I'd argue "unnecessary, unless you have a good reason to impose a sequential order".  And if you do, you probably want more code to make sure you've "done it correctly"].

 

Enjoy.  Use Data Flow.

 

Bob Schor

 

P.S. -- check your wires.  I found a few where the data flowed "backwards" (from right to left), usually because the wire (on the right) was going into a Control (with input on the left) or a Function (with input on the left).  Example -- your Stop button.  Also check out the simple VI Icon.

Message 5 of 10
(266 Views)

This is great - thank you!

 

For my understanding, what defines the data flow?  I’ve seen this concept applied by using sequence structures and error lines?

 

Thanks again for the help!

0 Kudos
Message 6 of 10
(254 Views)

@needhelp2378 wrote:

For my understanding, what defines the data flow?  I’ve seen this concept applied by using sequence structures and error lines?

Look at any VI, any Structure, anything with Wires going In, and Wires coming Out.

 

The Principle of Data Flow says basically the following things:

  • Nothing happens "on the inside" until all of the Inputs having Wires have data on the Wire.  Note that if you write a VI and have input Controls wired from its Front Panel, when you put that VI on the Block Diagram, you don't have to connect a wire to it for it to run (it will use the Default value of the Front Panel input), but if you do connect a Wire to it, until that Wire is given data to pass in to your VI, it will not run.
  • Once on the inside (of a function or Structure), it will not exit until everything "inside" has run.
  • The outputs (of a function or Structure) are not available to anything connected to them until the function or Structure exits.  Again, it's an "All or Nothing" Principle -- you either have all the outputs satisfied and available, or none of them available.

So there are two what-seem-to-be-exceptions.  What about a Queue?  You create a Queue, pass it in to a While Loop and put something on the Queue inside the While.  You branch the Queue before it enters the While Loop and put a Dequeue on it.  When the Enqueue (inside the While Loop) puts something on the Queue, the Dequeue function can dequeue it, even though the While Loop has not exited.  Well, this isn't really "broken Data Flow" -- the Queue is implemented by references.  When you Enqueue something, you are putting it "somewhere else", and triggering code that tells the Dequeue function "Hey, there's something here for you".  There are some other "reference-based" functions on the Synchronization Palette (and User Events) that work in a similar manner.

 

The other example that comes to mind are Asynchronous Channel Wires (called "Channel Wires", for short).  These actually do violate Data Flow (which is why they have Asynchronous in their name).  But they have a Visual Metaphor to remind you of this -- they look like Pipes, not Wires, and sit "on top of" structures, they don't "tunnel" through the structure's edge.

 

Hope that answers the question.  

 

Bob Schor

Message 7 of 10
(249 Views)
Highlighted

This was super helpful - thank you Bob!

0 Kudos
Message 8 of 10
(234 Views)

When a Reply to your post is "Super Helpful", a nice way to show it is to push the button with a yellow star at the left bottom corner of the Reply, marked "Kudo", and give the person who replied a "Kudo".  If someone provides a solution to your question/problem, you should mark their reply as the Solution (technically, only you, the Original Poster, can designate a Solution).

Message 9 of 10
(226 Views)
Solution
Accepted by topic author needhelp2378

@Bob_Schor wrote:

The Sequence does nothing for you except stagger the start of the two output loops, for no apparent purpose or effect.  Note that, in any case, the While loop can't start until both DAQmx Tasks have been started.

(The Purists will say that I'm wrong, that your original code sequenced the Starts, which is technically (= actually, I admit) correct, but I'd argue "unnecessary, unless you have a good reason to impose a sequential order".  And if you do, you probably want more code to make sure you've "done it correctly"].

 


The first-started output (Digital) is sampled on the second-started output's AO Sample Clock, so I suspect that you might observe different results without the ordering (if AO starts first, then it can write some of the samples out before the DO starts).

 

That being said, you can of course avoid using the Flat Sequence Structure (FSS) by combining error wires with Merge Errors or similar, but since you might not want to have your errors merged (maybe you want to know which had a problem etc) then in this case perhaps there is an (I'd like to say rare, but I think this is a common-ish case, and so maybe not rare - my goal is to suggest FSS is usually not necessary) opportunity to make good use of the FSS. It only needs to be around the Starts though, not everything else 🙂

 

I am still (as in the other thread) confused by the loop timer value you're getting, but I suppose part of it (in this case) could be that in principle there can be a delay between AO-Start and reference time (for the tunnel into the While Structure). For your 10s output, what is a typical value of "Loop Timer" when finished?

Note that the "Loop Counter" value is pretty irrelevant here - your loop will spin quickly and at an unpredicatable rate and so whilst it can be interesting to see, you probably can't guess much based on that value.

Further note that if you placed a Wait (ms) with 20000 wired to it in this loop, the value of Loop Counter should be only 1 (2 iterations), the loop timer will eventually read ~20s, but the outputs should still not do anything after 10 seconds (although Stop.vi won't be called until the loop is stopped 30 seconds after that, a total of 40 seconds - highlighting a possible problem with your "last - before" timing).


GCentral
Message 10 of 10
(205 Views)