From 04:00 PM CDT – 08:00 PM CDT (09:00 PM UTC – 01:00 AM UTC) Tuesday, April 16, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Need explanation of waveform chart x scale properties

Solved!
Go to solution

HI All,

 

I need a little help in understanding how to dynamically change the x scale of a waveform chart.

 

Scenario: User would collect 1-4 channels of a biosignal from a USB-6001 DAQ board and sampling rate would be 1000 - 2048 Hz. The duration of the collection could range from 5s to 30s.

 

If I wanted to display data on a waveform chart in real-time, what would my x scale properties be? For example, if I was collecting at 2048 Hz, set my update mode to strip chart, want to display 5s window worth of data, and have X axis represent # of samples collected, what would my properties be?

 

- no values for XScale.Minimum and XScale.Maximum? - how do I determine the range?

- Xscale.Multiplier = 1/2048 ?

 

What if I wanted my x axis to reflect time (s or ms) instead of # of samples collected? What if I have an additional wait(ms) function in my display loop? My program has an event handling loop, an acquisition loop, and display loop.

 

Looking through a number of threads, I have determined that XScale.Min, Max, Multiplier would be important in dynamically configuring my Waveform chart but I need clarification in how they are related to each other.

 

Thanks in advance,

 

Anton

0 Kudos
Message 1 of 21
(6,625 Views)

I have attached a portion of code to give you an idea of what I am doing.

0 Kudos
Message 2 of 21
(6,617 Views)
Solution
Accepted by topic author atrinh

Hi, Anton.

 

Sometimes the best way to learn how things work is to build a Test Case and do some Experiments.  As it turns out, there is a funny relationship between the Maximum and Multiplier properties, which you can experiment with using the following code I just cobbled together:

Chart Test.png

The Signal Chart is a Waveform Chart operating as a Scope Chart (mainly so you can see it "sweep").  The top three controls, Sample Freq, # Samples, and Signal Freq control a Triangle Wave Generator -- the default settings of 10, 100, and 100 means that it generates a 10 Hz Triangle Wave sampled at 100 Hz (so 10 points per cycle) and generates 100 points at a time.  The Wave part is fed into a timing loop to generate points every 1000/(Sample Freq) milliseconds (i.e. at a frequency of Sample Freq) and feed it to the Signal Chart.

 

The other two controls influence the X axis.  When the Chart is initialized (by having its History set to an empty Array), X Minimum is 0 (the default value) and we set X Maximum to the value at the right edge of the plot (default 100).  X Multiplier (default 1) determines how many "plot points" each X input takes on the Chart.  Ignore for now that I set both of these twice (we'll come back to this!).

 

If you run this with these default settings, it will "paint" 10 Triangle Waves across the screen, starting from 0 to 100, then 100 to 200, then 200 to 300, etc.  Here, the X Axis is clearly "generated points".  Try setting X Max to 50, then try setting it to 200.  What do you predict would happen?  Did it?

 

But suppose you want the X axis to be Time, not Points.  The default settings generate 10 waves every second, and plot 10 waves, so the plot updates every second.  Thus to show Time, X Max should be 1 (so Time goes from 0 to 1, 1 to 2, etc.).  But now X Mult, the amount of "plot" each X point takes, is only 1/100 of the plot, so X Mult should be 0.01.  So set X Max to 1, X Mult to 0.01, and before you run the test, make a prediction of (a) how the Waveform plotted differs from the X Max = 100, X Mult = 1 case, and (b) how the X "labels" will differ.  Were you correct?

 

So why did I set the Maximum and Multiplier twice?  Good question, best answered by doing more experiments.  Change the Block Diagram by deleting those two duplicate settings and see how the Plot changes.  You'll have to make a change, then "unmake" the change to "get a surprise".  Why does this happen?  It's a bit of a Chicken-and-Egg problem -- the two parameters are not really independent, but interact in a funny way.  It is also the case that when setting Properties, the order of the Property Nodes can matter (and does, in this case).

 

Anyway, explore, and teach yourself how to do this to solve your own problem.  I'll also attach this VI so you don't have to recreate it from the Snippet (in case Snippets aren't working ...).

 

Bob "Learn by Experimenting" Schor

Message 3 of 21
(6,575 Views)

Thank you for the detailed suggestion Bob! I have played around with some of the suggestions - perhaps you can tell me if I am seeing things correctly.

 

If you run this with these default settings, it will "paint" 10 Triangle Waves across the screen, starting from 0 to 100, then 100 to 200, then 200 to 300, etc.  Here, the X Axis is clearly "generated points".  Try setting X Max to 50, then try setting it to 200.  What do you predict would happen?  Did it?

- pretty straightforward and what I expected; waveform chart plotted 50 samples and 200 samples respectively.

 

But now X Mult, the amount of "plot" each X point takes, is only 1/100 of the plot, so X Mult should be 0.01.  So set X Max to 1, X Mult to 0.01, and before you run the test, make a prediction of (a) how the Waveform plotted differs from the X Max = 100, X Mult = 1 case, and (b) how the X "labels" will differ.

- I predicted X axis remained unchanged and this is what I found

- I thought this because changing the x axis to 0-1 in range, requires changing the multiplier to 0.01 and adapt the waveform chart to still display 100 points per second (each second displaying 100 data points).

- To me the multiplier almost represents an increment between each data point; if I wanted to display 1s of data I would just take the product of the multiplier and sample rate

- I tried settings of 1000 Hz sampling rate, X max of 1000 or 1, and multiplier of 1 or 0.001 - behaviour of waveform chart was what I expected

- If I tried settings of 2048 Hz sampling rate, X max of 2048 or 1, and multiplier of 1 or 0.000488 - behaviour of waveform chart was NOT what I expected. Is this related to chart history length of 1024? I would have suspected the waveform chart to display what I was hoping for which was a second worth of data (2048 points).

 

So why did I set the Maximum and Multiplier twice?  Good question, best answered by doing more experiments.  Change the Block Diagram by deleting those two duplicate settings and see how the Plot changes.  You'll have to make a change, then "unmake" the change to "get a surprise".  Why does this happen?

- Behaviour here was interesting. With settings of 100 Hz for sampling rate, X max of 100, and multiplier of 1, the change initially caused the plot to display 2 points instead of 100. If changed the code back and I ran it again, it would revert back to displaying 100 points instead of 2. Interestingly, if I left the code without duplicating the settings and ran it again, it would also revert back to 100 points instead of 2. This isn't what you were hoping I would see is it?

0 Kudos
Message 4 of 21
(6,562 Views)

Regarding trying to plot more points than the History can hold, I haven't "done the Experiment", but suspect you are right (like trying to put 10 pounds of manure in a 5 pound bag).  As for changing Maximum and Multiplier only once, I haven't played enough to be able to say I have deduced the algorithm NI is using here, but there are definitely ways to make it "fail" and "recover", entirely depending on how the settings are ordered.  For safely, "Do it twice and don't worry about it" (particularly since changing the scale takes a tiny fraction of the time to actually produce and show the plot).

 

I hope this answers your question.  If you mark my response as a "Solution", then the next user with a similar question will have a clue where to look for help.

 

Bob Schor

0 Kudos
Message 5 of 21
(6,552 Views)

HI Bob,

 

Thanks for the quick response! I like your idea of do it twice and don't worry about it approach. Your solution does help me out partially for sampling rates up to 1000 - do you have any insight in how to tackle sampling rates above 1000 like 2048 Hz. It is common for students and researchers in our labs to sample that quick and I need to find a way of displaying that data.

0 Kudos
Message 6 of 21
(6,549 Views)

I played around with the program a little bit more and I found if I removed the Wait function, the behaviour was more of what I expected. This does bring me to my next question of factoring in a Wait function for a display loop. Does my multiplier change if a Wait function is embedded? I have struggled with reconciling real time display of data and the wait function so if I can understand this, I think I might have all my questions answered!

0 Kudos
Message 7 of 21
(6,533 Views)

My Demo didn't have a built-in "clock", so to simulate generating (and displaying) data at the sampling frequency, I used the Wait function.

 

Your "Demo" is using (very appropriately) DAQmx and the Analog Input function, together with a Producer/Consumer Loop, so the DAQmx Read function is the "clock".  The Consumer (the Display) will be "clocked" by its DeQueue function (it can't run any faster than elements come onto the Queue, controlled by the Producer), so it absolutely does not need, nor should it have, a Wait function.

 

So congratulations, you "did the right thing" in diagram-disabling it.  Now you can remove it completely!

 

So here's a final "semi-advanced" lesson for you.  You have two While loops running in parallel, and you want to stop both of them.  Well, you really want to stop the Producer, and have the Consumer "know" when it should stop.  Local Variables are not a good way to pass this sort of data between loops (lots has been written about this, and I'm not the one to discuss it ...).  But here's an "old-fashioned" way that works really well (and has been incorporated into Channel Wires, a new way of sending asynchronous data between loops that was first formally introduced in LabVIEW 2016) -- it is called a Sentinel.

 

The idea is that the Producer "knows" when it is time to exit, so it sends one more "distinctive" data set called a Sentinel.  Where does it do this?  Why, after it exits its While Loop (i.e. after Stop is True).  What could be a Sentinel?  Well, its data element is a Waveform (consisting of a single sample) -- what if you constructed a Waveform and wired in an Empty Array?  That would certainly be different!

 

Now, on the Consumer side (where time is not as critical), when you unbundle the Signal (Y), you can check for an Empty Array, and wire that to the Stop Indicator (if True, you have been sent the Sentinel, and you should exit).  Note that plotting the Sentinel will have no effect -- the loop will simply exit.

 

When I was starting to use Queue, I knew about "not using Local Variables", but even though I'd learned about Sentinels years ago, I didn't remember them initially.  I used to stop loops in a "clumsy" way -- I'd have the Producer release the Queue, which would cause the Consumer to error when trying to dequeue, and I'd exit on error.  But that's perverse -- deliberately causing an Error that really isn't an Error ...  Sentinels are better!

 

Bob Schor

Message 8 of 21
(6,518 Views)

Hi Bob,

 

Yes I did know local variables are not great for stopping loops or passing data between parallel loops. Just had to whip something up quick.

 

This idea of Sentinel's is actually great and may solve some of my other coding issues I have had. I can see that I have access to the vi's but it is not showing up on palette. Do you know what palette category it falls under or could you direct me how to install the palette for the stream functions? I have LabVIEW 2016.

 

Also what is the difference between the stream and real time stream functions? I can still compile basic programs that utilize the stream functions correct? I will post up a final vi with this suggestion of yours once I can find those functions on my palette.

0 Kudos
Message 9 of 21
(6,502 Views)

I figured out how to get the Channel Write and Read vi's. Here is my implementation of a basic DAQmx read and display of data using Channel Wires.

 

0 Kudos
Message 10 of 21
(6,497 Views)