LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

USB-6008/DAQmx Read sampling

Solved!
Go to solution

I am using LabVIEW 2009 Student Edition with a USB-6008 DAQ on a Windows 7 computer.  I must confess that I am pretty self-taught in LabVIEW and may be lacking in fundamentals.

 

I have written a code to move a motor back and forth with a sine wave with the "Simulate Signal" VI and "DAQmx Write" VI.  I think this part of the code is OK but its probably sloppy.

 

The part I am concerned about is the "DAQmx Read" part - I use this to get a position feedback from the motor on a 0-5V analog scale through the AI1 port.  I also use this DAQmx Read to get another voltage feedback from a force transducer that senses the force in a piece of material stretched by the motor.  I want the information to all plot as graphs or charts with the last 30 seconds or so worth of information, but thats all I want to see since this cycle repeats for hours.  I also need to process this information - if the force in the material gets to high, I need to stretch less etc.  Up to this point, everything works ok but now I want to use the "Peak Detector" VI to specifically ensure that the "peak" of the sine wave falls within a certain force range and the "valley" falls within a second force range and clearly since I am reading this information as a single integer/sample there is no "memory" of the last few seconds in the form of an array of past samples or a waveform or something like that, I can't detect peaks.

 

So my question is - should I be sampling this information differently to store information temporarily (as a waveform or something?), or should I use the single samples to build a continuous array for the last 30 seconds?  In other words, what is the best way to read this information in a way that will make it easy to detect peaks over the last few seconds, but not store hours worth of endlessly repeated information?  I also want the graphs of both the output from LabVIEW and the feedback from the system to match so that the signal sent to the motor corresponds to the same positional signal returned to LabVIEW from the motor.  I should add that I dont care if the system works in real-time or on a small delay, but nothing more than like 30 seconds delay.

 

I have attached a code that I use to calibrate my system - its not the same one I talked about earlier, but the "DAQ Read" stuff is the same and you get the idea with the rest of it.  I can also attach the more detailed code if that would help.

 

Again, I am sorry for my bush-league coding skills and thanks for any help!

-Chris

0 Kudos
Message 1 of 4
(2,934 Views)
Solution
Accepted by topic author craxchris

If you are still using a waveform chart to display your data, and your happy with length of time of the chart, you can use the "History Data" property node to retrieve your 'short term' collected data.  From there you take the data and make a waveform datatype using the "build waveform" primitive.  


Paul
Message 2 of 4
(2,920 Views)

This worked exactly how I wanted to and thats a really easy way to do it!  Thanks a ton

-Chris

0 Kudos
Message 3 of 4
(2,901 Views)

Capturing 30 seconds of data at a time and then analyzing peaks and valleys is probably a safe bet.  Now for some code critique:

 

You don't need the Merge Error on the left side of the loop.  You end up splitting the error wire again anyway.  Merge errors at the very end of the code, after the loop.

 

Straighten wires wherever you can.  This makes it easier for us to read.

 

Most people prefer to see terminals instead of icons for controls and indicators.  Icons take up too much room.  Right click on an Icon and uncheck the option "View as Icon".  If you click on the Tool menu (top menu bar), then click on Options, then Block Diagram, look for the option "Place front panel terminals as icons" and uncheck that sucker.  I don't know why NI has to set this as default.

 

On the loop border where the error wires come in and where they exit, replace the terminals (square box) with shift regiters.  Right click on the box and select the option to replace with shift registers.  It will replace one and the mouse pointer will turn into a shift register with an arrow.  Just move it to the other side and click on the border near where the corresponding terminal is.  Do the same for the DAQmx task wire (maroon colored).  The reason for doing this to the error wire is this.  What if there were an error in one loop iteration.  On the next iteration, that error would be lost because at the beginning of the iteration, the value coming in on the error wire has no error.  The shift register forces the end value of one iteration to be carried over to the beginning value of the next iteration.  The reason for the DAQmx task wire is to form a habit of doing this.  If this was a For Loop, and it iterated zero times (it can happen), the value at the other end will be the default value for that wire.  In the task wire, the default is NULL (not a task).  You will get an error trying to close a NULL task.  The shfit register prevents the error by carrying over the input to the output so it will not be NULL.  Do this for all error wires, references, tasks, sessions, and such with all loops.

 

At the bottom right of the loop, you have a STOP function inside a sequence frame.  NEVER stop a program like this, except in extremely rare cases.  By stopping this way, the rest of the code, like the closing of tasks, do not get executed.  Instead, just wire a boolean to stop the loop.  Then the program can end normally.  Perhaps you could put the code inside the first two frames after the loop.  You can then eliminate the entire case structure.  Wire the max reached wire through an OR function to the loop stop.  When the loop stops, the frame code put after the loop will then execute.  Then the program will end naturally.

 

I'm not sure what the code is in the small loop after the main loop.  This code will run in parallel to the rest of the code.  I hope you don't think that it will only run after the main loop.  It will start running as soon as you press the white arrow run button because there is no data dependency (input wires from other functions).  What will happen is that the intial values for min reached (and other locals here) will be used.  The small loop will run once and then it will never run again.  Meanwhile your main loop runs and the values for all of these locals are changing.  The small loop will not run again, and those new values will never be used.  Result is that the Save Position Min and Max are probably wrong.  If you want this code to run only after the main loop has ended, you need a wire from somewhere inside the main loop to the border of the small loop.  It doesn't matter where it comes from and it doesn't matter if it is used inside the small loop.  What this does is that it causes the small loop to wait until there is data on that wire before it starts executing.  Data won't appear on that wire until the main loop stops.  Instead of using those local variables, find the wires for these values in the main loop, and wire those all the way out of the main loop and then into the small loop to where the locals are wired.  You really don't even need a loop here.

 

This is enough for now.

 

 

- tbob

Inventor of the WORM Global
Message 4 of 4
(2,894 Views)