High-Speed Digitizers

cancel
Showing results for 
Search instead for 
Did you mean: 

multiple recording of waveforms using an external trigger signal

Dear all,

Maybe somebody could help me with the following:

System:
Windows 2000,Pentium III,~800-900MHz,32-bit master PCI bus,256 MB RAM
PCI-NI 5122 Digitizer
PCI-GPIB card
PCI-DAQ card
Labview 7.1
NI Scope 2.7


Problem:

I want to acquire multiple waveforms (e.g. 100) using an external TTL trigger signal of ~40Hz. I have to acquire 1 waveform per trigger signal i.e. 100 subsequent trigger signals will acquire 100 subsequent waveforms.
After, or during the waveform acquisition (?), I have to transfer the waveforms as 100 1D-arrays from the onboard memory of the digitizer through my fitting routine (one-by-one!). The fitting routine accepts one waveform (1D-array) at the time, fits the waveform and calculates 1 fit-value per waveform. So, when I pass the acquired 100 waveforms subsequently through the fitting routine, I need to get out a 1D-array with 100 fit-values. This 1D-array with the 100 fit values will be further processed and a final value will be saved.
This procedure will repeat itself at different points in a sequence structure. The sequence structure will be located in a loop and running for several hours!

Please see attached program flow diagram.


Qustions:

1. When I want to acquire 100 waveforms using 100 subsequent trigger pulses, the attached VI (Multiple_record VI) gives me the following error message:

ERROR
"Possible reason(s):
Driver Status: (Hex 0xBFFA4009)
A previous acquisition is still in progress. If you are attempting to change an attribute, note you can only change fetch attributes while an acquisition is still in progress.

Status Code: -1074118647

What am I doing wrong? Is there a better and more efficient way to do this?


2. How can I transfer the 100 waveforms from the digitizer, one-by-one as 1D-arrays, through my fitting routine? A waveform will have ~2000-3000 data pts. (DBL type). Remember: I DO NOT HAVE TO SAVE THE WAVEFORMS!

3. Which way is faster, and more efficient (memory) for my PC system to transfer the waveforms from the onboard memory of the digitizer to the fitting routine?:

a) Start transfer of already acquired waveforms (1D-arrays), one-by-one through the fitting routine, during the waveform acquisition process is still in progress?
b) First, acquire the 100 waveforms (1D-arrays), store them in the onboard memory (digitizer) and then transfer them one-by-one through the fitting routine?

4. How can I make sure that after the waveforms were transferred through the fitting routine, the onboard memory of the digitizer is EMPTY (clear waveforms which have already been fetched) and ready to repeat the waveform acquisition at a different point of the sequence structure?

5. I do not want to display each acquired waveform because I think it will slow down the acquisition process. Instead, I want to display the last of the acquired 100 waveforms, so I can check my fit and maybe adjust the fit-parameters. How can I do that?


I think the important thing is to perform this process in the fastest way possible with the best use of the PC resources (memory etc.) because this process will run for hours. Any suggestions?


It would be very nice if somebody could give me some help with this.

Kind regards,

beam
0 Kudos
Message 1 of 24
(11,926 Views)
0 Kudos
Message 2 of 24
(11,914 Views)

  1. Without seeing your actual code and experimental setup, it is hard to tell exactly what is causing this error. However, it is probably what it says it is. You set up a multi-record acquisition and it did not finish before you tried to start another one. This is easy to do (read I have been bit). You are probably not getting enough triggers. However, if you can fetch all the data you asked for, this should be OK. If you get all the data you think you should get and still get the problem, try an abort before starting the new acquisition. This doesn't fix the real problem, it just bludgeons it out of existence. Also make sure you are allowing enough rearm time between acquisitions. If you can fetch all your data, this is probably not the problem. If you cannot find a mismatch in number of records asked for and triggers received, please file a bug report.

  2. Wire the data from the fetch directly to the fitting routine input. NI-SCOPE has a variety of fetch data types, so you should be able to find one which matches.

  3. The 5122 allows you to fetch while acquiring, so there is no need to wait for all the acquisitions to be done before starting analysis. I would initiate the acquisition, then poll the acquisition status at a decent interval. When the first record is ready, fetch it and wire it directly to your analysis. That said, the most efficient fetch size from the digitizer to memory is something on the order of 300,000 — 500,000 bytes. So, you may want to poll for acquisition status and wait until your acquisition is done before fetching. This has two disadvantages. First, your rearm time for your next set of data acquisitions will be slower. Second, you will probably want to analyze your data while the next set of acquisitions is occurring. This will increase your program complexity. I would go with fetch and analyze on the fly. If you do go with the second method, you may want to check out the tutorial Managing Large Data Sets in LabVIEW. You may want to anyway, since it has some nice data handling tips.

  4. Initiating an acquisition on the 5122 “clears” the memory. The memory is actually a ring buffer to facilitate fetch while acquiring and streaming forever, so it really just reinitializes pointers.

  5. The easiest way to do this is to put the graph terminal outside your analysis loop and wire the data from the fetch routine to it. If you have a FOR loop, you will need to pop-up on the terminal through the loop boundary and disable indexing or you will get all the data. When the loop exits, you will get the last set of data plotted. You may want to consider plotting your fit residual as well.

You may also want to do some research into program structure to help you write a maintainable solution. For example, sequence structures are very rarely used in normal LabVIEW programs since data flow on the wires (NI-SCOPE reference and error in your case) enforce the execution dependency. TIP — For a task based operation such as this one, a queue-based task handler works very well. I have attached an example.
Message 3 of 24
(11,909 Views)
Dear DFGray,

thank you very much for your comments and your help!

I tried to locate and solve the problem which gives me the error message during the quasi "multiple recoding of waveforms" as described under point 1), above. To make the situation as simple as possible, I applied a sinosoidal function (30Hz, 0.8V peak to peak) and were running the "Multi_record_1a VI" (see attachment).

With no. of records: 1 everything worked fine. When I increased the no. of records, I always get the error message. I tried the things you suggested in your reply but neither of them was successful. Additionally, I tried to allow more time between the loop cycles, changed the trigger holdoff time and trigger time out. Non of these solved the error message.

I have the feeling, that I am missing something fundamental, because similar approaches are described in examples like "niScope EX Binary Acquisition VI".

As I said before, I need only acquire 1 waveform (as 1D-array) per trigger event. So, 100 trigger events will give me 100 waveforms. Placed in a loop-structure this task should be pretty easy?!
In the future the trigger signal would be an external TTL signal of ~40Hz and the record length of each waveform would be ~20-30 micro-seconds

If you look at my Labview IV, you can see that I am always execute the "Initiate VI" before I call the "SINGLE Fetch WDT VI" in every loop cycle. I hope this is the correct way of doing it for my task (1 trigger = 1 waveform)?

HOW DO I SET THE TRIGGER REARM-TIME BETWEEN THE ACQUISITIONS?


Maybe you have some further ideas how to solve this problem?

Thank you very much for all your help and patience.


Kind regards,

beam
0 Kudos
Message 4 of 24
(11,902 Views)
You almost have it. With multi-record acquisition, you initiate once and fetch many times. In your case, initiate the acquisition, then fetch the 100 waveforms without initiating again. When you only fetch one waveform and reinitiate, the previous multi-record acquisition is still in progress, so you get the error. Check out niScope EX Multi Record.vi in the scope examples.

You can set the rearm time with trigger holdoff, but you won't need to. The 5122 won't have any trouble keeping up with the default values.
Message 5 of 24
(11,895 Views)
Dear DFGray,

thank you very much for your last comments - they were very helpful!

I have the following question to confirm that I understand the "multi-waveform fetch" and "initiate" issue correctly:

a) You said in your reply that "I only have to initiate the multi-record acquisition ONCE". So, am I understand correctly that this means: After the initiation, the next 100 trigger signals will acquire 100 waveforms in total (1 trigger signal=1 waveform)? Correct? Please see attached "Multi_record_1b VI".

Is my way to transfer the waveforms one-by-one ("on the fly") through the fitting procedure correct? As I said before, in the end I need a 1D array which consists of the fit-values from all fetched waveforms (10 waveforms=10 fit values).

I "simulated" the fitting procedure by using the array function "Max & Min" and the "x increment". Like in my real fitting procedure, I feed the waveform as 1D array into the fitting routine and the CORRESPONDING x increment value as DBL number. The output is a 1D array (indexed by the foor loop).

I hope my procedure is correct? Are there any things I could improve?


c) There is a difference between the "min record length" and the "actual record length". How can I get rid of this difference?

d) In my "Multi_record_1b VI" the "records done display" is not showing anything. Do I have to implement a delay? If yes, how?

e) In your first reply (point 3., above) you said that: "I could poll the acquisition status at a decent interval". How do I implement this in my loop-structure?

d) If you look at the "Double_Multi_record VI" you can see that I am doing the waveform fetch twice. In my real program I will have to do this a total of 4 times at different program stages during ONE loop iteration. Do you have any comments?

By the way, thank you for the LargeGUIApplicationsInLabVIEW.


Thank you very much,


Kind regards,

Beam
0 Kudos
Message 6 of 24
(11,882 Views)
I forgot to say that I am using now NI Scope 2.8 instead of 2.6.
0 Kudos
Message 7 of 24
(11,879 Views)
The method you use to analyze your data is fine. The only thing I would watch out for is memory problems. If you keep with the numbers you gave earlier, 100 waveforms at 3000 pts/wfm, you will be transferring 2.4MBytes of data per set. This is way over the 1MByte buffer NI-SCOPE uses for data transfer. It will work, but it might be slow. If you have problems, switch to niScope Fetch WDT.vi for your acquisition and move it inside the loop. Before you call the fetch VI, set the record it will fetch by using the property node and setting Fetch->Fetch Record Number using your loop index.

A couple of other performance tips I think you probably know. The graph inside the loop will slow you down a lot. In addition, the graph of all the data outside the loop will also take a fair amount of time (plotting 2.4MBytes of data). If you want to see just the last waveform, pop-up on the terminal going out of the loop and disable indexing so only the last waveform goes through, not all of them.

Your analysis method should work fine. You may consider doing an I16 fetch instead of the WDT fetch you are currently using. This will reduce your memory usage by a factor of four, provided you don't immediately convert it to a double array. If your analysis is actually finding a max/min, this is faster on an integer array than a double. You can scale the integers using the numbers in the information cluster. It is much faster to scale one integer at the end than a whole array. That said, the I16 fetch is not particularly faster than the WDT fetch, just less memory. This choice will depend on your analysis.

The min record length is the minimum number of points the device will acquire. The actual record length is different if the acquisition rate you ask for is not one of the acquisition rates the device is capable of. The acquisition rate is then coerced to the next highest rate and the record length increased so your acquisition time remains constant. This behavior is part of the IVI specification for digitizers. Using your VI as an example, you ask for 300kS/s acquisition rate and 800 data points. What you actually get is 300,300.3003 S/s and 801 data points. The sample rate is determined by an integer divisor from 100MHz, in this case 100,000,000/333. So, if you really want a certain number of data points, you need to set the sample rate to a physically realizeable one. Alternately, you can just fetch the number you want instead of all the points, realizing your sample window will be a bit shorter than you asked for.

You are correct. To see anything in the records done, you need to delay. However, in this code, the records done output is really not doing anything. The fetch won't fetch until everything is done, so you know all is finished when your data shows up. I would just delete it. If you do want to put a delay in, wrap a sequence structure around the records done query. Add a frame before the current frame and drop a Wait (ms)delay into it. You can find this primitive in the timing and dialog palette. This is an example of when the sequence is actually useful. The delay VI has no good way of enforcing data flow, so the sequence does it.

The way you have implemented it, you don't need to poll acquisition status. To get acquisition status, use niScope Acquisition Status.vi. You would put this in a WHILE loop before your acquire and exit the WHILE loop when the acquisition was done (or an error occurred) to proceed to the acquisition. Make sure you also put an appropriate delay in the WHILE loop or it will eat your entire processor capacity. The delay should be based on how long you expect the acquisition to take.

You should definitely put your fetch code in a subVI if you are going to call it more than once. LabVIEW makes it easy. Select the code you need to make into a subVI, then select Edit->Create SubVI. Don't forget to put an icon and documentation in the subVI. You will thank yourself later.

Let me know if you have any more questions...
Message 8 of 24
(11,875 Views)
Dear DFGray,

thank you very much for your help and suggestions.

As you suggested in the first paragraph, I switched to the "niScope Fetch WDT.vi" and placed it inside the for loop. Additionally, I included the property node with the "Fetch record Number" wired to the iteration terminal of the for loop (please see attached "Multi_Record_1c.vi" in the library).

When I run the code I get the following error message:


Error -1074118613 occurred at Error occurred at: niScope Fetch WDT.vi

Possible reason(s):
Driver Status: (Hex 0xBFFA402B)
This function may not be used for fetching multiple waveforms, or when the acquisition type is DDC.


If I want to acquire e.g. 10 waveforms, I will get this error message for the first 9 iterations of the foor loop. Only the last waveform is properly fetched (as you can see at the last element of the "Array of fit values").

What am I doing wrong?

I was re-calculating my number of records and record length. I think it will come down to ~128 - 256 records (maybe 512) with ~1000 - 2000 data pts. per record.
Is there any other way I can avoid to go over the 1MB buffer NI Scope uses for the data transfer, so the program will not slow down? Or is your earlier suggesting to use an I16 instead of the DBL the only possible way to improve the situation?

Some information about my data-analysis:
Actually, my data-analysis is fitting a Non-Linear Levenberg-Marquardt function to each recorded waveform. It first cuts some sections of the waveform away to get the waveform section wanted for the fit > creates the corresponding x-array for the fitting VI > then calculates the guess coefficients for the fit > and finally fits the waveform. As mentioned earlier, the output is 1 fit value per waveform.

Fitting 10 waveforms (~3000 data pts. each) will take ~3 seconds in total.


Any comments?


Thank you for your help


Kind regards,

beam
0 Kudos
Message 9 of 24
(11,863 Views)
Open mouth, insert foot...

I forgot a very important step. Before your acquisition loop, you need to set the number of records fetched to 1 or NI-SCOPE will think you are trying to fetch everything that has been acquired, resulting in the error you saw.

So, before the acquisition loop, insert a property node and select Fetch->Fetch Number of Records. Set this to “1” and you will be good to go.

Since you are fetching the waveforms one at a time, you don't have to worry about the NI-SCOPE 1Mbyte buffer. The slowdown would be insignificant compared to your calculation time in any case.

If you have trouble with instability in your calculation, you might want to check out more robust fitting methods (Levenberg-Marquart is a least-squares algorithm - fast, but not very error tolerant). Grab a copy of Numerical Recipes in C for hints - most libraries have it. LabVIEW contains most of the algorithms, so you just need to use them. I have found the downhill simplex with a Lorenzian error function to work well. Don't do this unless you need to. It will slow down your calculations.
Message 10 of 24
(11,848 Views)