LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

saving and plotting acquired data

smercurio,

 

That is the perfect answer to the DAQ question and a great start towards a state machine implementation.  Kudos 

 

 

Robbo13,

 

The TDMS Open.vi has an input terminal labeled operation.  One of the options is to  create a new file.  If you try to create a file that already exists, an error is generated and the existing file should be untouched.  As far as auto incrementing the filename, you can always use a shift register or functional global to hold the last number used.

Message 11 of 34
(1,838 Views)

smercurio_fc wrote:

The best way to do this is to append some sort of timestamp to the filename. You can use the Time functions to return you a string to indicate the date and/or time.

 


Aha thats a great idea, thanks!
I had been looking into state machines after the earlier posts but that link looks very helpful, i'll get reading that right away.
The only reason I had for wanting to use the DAQ assistant was that I know it's very easy to add more channels later on, however given how well you've explained the breakdown of the DAQmx functions involved in the example I reckon I'll try and do it that way instead.  
Well i've got a lot to be getting on with for now, thanks to you both for your help, its much appreciated.

 

0 Kudos
Message 12 of 34
(1,831 Views)

Robbo13 wrote:
The only reason I had for wanting to use the DAQ assistant was that I know it's very easy to add more channels later on, however given how well you've explained the breakdown of the DAQmx functions involved in the example I reckon I'll try and do it that way instead.  

It's also quite easy to do it using the DAQmx VIs directly. The example I pointed to has a "physical channel" input. This does not have to be a single channel. You can specify a range. Since it's a control you would not need to change code. Alternatively, instead of using the "physical channel" input you can use the "task" input. Then you can simply create a task outside of LabVIEW using Measurement and Automation Explorer (which gets installed when you install DAQmx). 

0 Kudos
Message 13 of 34
(1,817 Views)

I've had a go at putting this together, unfortunately I wont be able to test it with actual DAQ hardware for a few days since uni is shut for Easter. I've got a few queries about what I've done so far (apart from 'will it work?'....... will it?!).

 

I created the state machine using the labview template and i'm unsure what effect the 'milliseconds to wait' function will have. Does this add a wait in between each iteration in the loop, therefore meaning that in every loop there will be a 100 millisecond or so gap in my recorded data? 

 

Also as the program is at the moment would it be better to move the creation of the TDMS file into the start state? To me it looks like if you've pressed start, recorded your data and pressed stop the program will return to the initialise state and wait for a user input. Wont this then create a new TDMS file which will be empty if the user doesnt then want to start the loop again? Come to think if it i don't think they have a choice right now as pressing exit will only do something if data is actually being recorded, i'd better change that!

 

I think i've at least tried to do everything smercurio_fc suggested, with the exception that the program doesn't check to see if data acquisition has already been started, as I wasn't sure how to do that.

 

If anyone could give it a quick once over and see how it's looking i'd be really grateful. Thanks once again to all who've helped so far 

0 Kudos
Message 14 of 34
(1,799 Views)

A very good start, actually. Well done. Give yourself £10. Smiley Very Happy

 

You actually can run the code without hardware. DAQmx allows you to create simulated devices and you can use Measurement & Automation Explorer to do so. I don't recall you mentioning what kind of device you have, but if it's not in the list of devices that can be simulated you can always find one that's close, especially since all you're doing is performing a simple voltage read. Then in your code you need to select the channels for whatever device you created. That's how I ran your code.

 

Code comments:

 

  • My comment about checking whether or not data acquisition was started was based on the UI state checking if a user pressed any of the front panel buttons. Since you've changed the state machine operation such that the "Collect" state goes back to itself unless the Stop or Exit has been pressed (an acceptable alternative), this is no longer necessary. However, you still need to check if the user pressed on the Exit button in the UI state. Otherwise, there's no way to stop the program if you're in the UI state. 
  • "Also as the program is at the moment would it be better to move the creation of the TDMS file into the start state?" Yes, for the reasons you stated. The Initialize state should take care of setting up the front panel, and initializing any internal variables that a program requires. You should not perform any I/O operation (such as creating file that are dependent on a data acquisition) until a user specifically starts an acquisition.
  • "I created the state machine using the labview template and i'm unsure what effect the 'milliseconds to wait' function will have. Does this add a wait in between each iteration in the loop, therefore meaning that in every loop there will be a 100 millisecond or so gap in my recorded data? " Yes, it will. You can mitigate this by moving the wait inside the UI case, since that's the only place where it matters. In your "Stop" state if the user is simply stopping, go back to the UI state.
  • You are converting a Boolean into a floating point value, only to checkif the value is zero in the "Stop" state. Instead, have the shift register pass around a Boolean directly (in this case the value of the Exit button).
  • You should have some form of error checking so that if an error occurs in any state you will know it. As you have it now, the only way you will get an error dialog is when the user presses the Stop button. If, say, an error occurs when you configure the DAQ and the user presses Exit rather than Stop, you will never know about the error. One way to handle this is to have an "Error" state that the state machine goes to whenever an error gets generated. What you do in this "Error" state is really up to you. You can have something as simple as displaying a dialog and then pass out a no error condition so the state machine can continue (e.g., to try to restart the acquisition). Or, you can have it display the dialog and then immediately terminate the program.
  • Do not leave the shift registers uninitialized. If you run the VI again, the shift registers will "remember" the value from last time. Note that this can be taken care of in the "Initialize" state.
  • Don't know if this is going to be an issue or not, but your filename is based on hour/minute. Thus, if you stop an acquisition that has been running for less than a minute and then start it again while still within that same minute, then you will get an error when trying to create the TDMS file. Like I said, not sure if this is an issue for you.
Message 15 of 34
(1,792 Views)
Ha ha, touché! I'd better get on ebay! :smileytongue:
Couple of things i'm having trouble with:
  • can i have my buttons appearing in more than one case? So for example my exit button currently appears in the collect case, can i also have it in the UI case somehow so that I can allow the program to be stopped at that point? Or do i have to do this some other way?
  • when trying to move the creation of the TDMS file to the start state, presumably i have to also move the 'set file properties (TDMS).vi' with it?
  • Regarding initialising the shift registers, is this just a case of setting a zero value for them, as with the (what was a floating point but is not a boolean shift register)? You say that at the stop state if the user is only stopping then to go back to the UI state, do the shift registers not need reinitialising at this point before the next set of data can be recorded?
  • I like the idea of having an error state and i've found a function to reset the error once a dialog box has been shown, but i'm not sure how to navigate the program to the error state when an error occurs. At present anytime i need to choose between possible states it's done by just using the select function to choose between 2 options. How can i add in the 3rd option of moving to the error state, and make this take precedence over the other 2 options?
When it comes to actually using the system for real the hour and minute time stamp should be fine, but for testing the program i might add in seconds too just to prevent anything going wrong. 
I'm really pleased with how well it's gone so far, thanks for your patience! 

 

 

0 Kudos
Message 16 of 34
(1,784 Views)

Robbo13 wrote:
  • can i have my buttons appearing in more than one case? So for example my exit button currently appears in the collect case, can i also have it in the UI case somehow so that I can allow the program to be stopped at that point? Or do i have to do this some other way?

Sort of. You would need to use local variables (see below for WARNING) or property nodes to read the value. However, the default action of push buttons is "Latch", which is not compatible with local variables (and using the "Value" property on a push button with "Latch" is an error). Thus, you would need to change the mechanical action to "Switch". This just means you need to set the value of the button when you first start the program so you start at a known value.

 


  • when trying to move the creation of the TDMS file to the start state, presumably i have to also move the 'set file properties (TDMS).vi' with it?

Yes. Basically everything in the "Initialize" state goes into the "Start" state.

 


  • Regarding initialising the shift registers, is this just a case of setting a zero value for them, as with the (what was a floating point but is not a boolean shift register)? You say that at the stop state if the user is only stopping then to go back to the UI state, do the shift registers not need reinitialising at this point before the next set of data can be recorded?

Basically, yes. You just want to make sure you've set everything up so the state machine can operate properly. In your case you want the "Stop" to act as a "reset", so it makes sense to go back to the "Initialize" state where you can start fresh.

 


  • I like the idea of having an error state and i've found a function to reset the error once a dialog box has been shown, but i'm not sure how to navigate the program to the error state when an error occurs. At present anytime i need to choose between possible states it's done by just using the select function to choose between 2 options. How can i add in the 3rd option of moving to the error state, and make this take precedence over the other 2 options?

All that you really need to do is to look at the error cluster at the output of the state machine and override the state that's supposed to be next. You unbundle the error cluster. If "status" is true, then go to the "Error" state. Otherwise, go to the intended state. Note that this requires that the "Error" state not generate an error, otherwise you're caught in an infinite loop.

 

You've clearly put some effort into this and I think you should know what changes to make. I'm attaching a modified version of your code with the tweaks I mentioned above. My recommendation is to try to make the changes yourself first, and then compare them to my working copy. Remember, there is no single solution to this.


WARNING: I mentioned the use of local variables before. I don't know how much LabVIEW programming you will be doing once this little project is done, but do not abuse local variables. The way I've used them it causes no harm since they cannot create race conditions, but there is a camp that basically advocates the complete destruction of local variables as they consider them abominations. There is some legitimacy to their arguments since newbies tend to abuse them and cause race conditions.
Download All
Message 17 of 34
(1,779 Views)

Thanks very much, i've had a good look through what you did and had a go at most of it on my program and i'm pretty sure i understand everything and can arrive to a similar solution myself.

 

I'm very much looking forward to getting this up and running now. I've tested the program by setting up simulated hardware and i got it working which is a good start.

 

The final 2 steps are to modify it so that it acquires data from 7 channels, and then somehow port it so that it runs on a PDA. Do you have any experience working with the PDA toolkit? Any idea how much work it'll be getting this ported?

 

Just for interests sake we're going to be running a USB-6008 with an accelerometer, 2 pressure transducers, 2 passive magnetic pickups as wheel speed sensors, a throttle position sensor and a crankshaft speed sensor.

 

When adding more channels do i have to duplicate the DAQmx create channel.vi with each instance configuring 1 channel, or is it possible to create 7 separate channels using the 1 .vi?

 

I honestly can't thank you enough for all your help, I'm also glad that i've done it myself rather than getting someone else to do it, so bonus points for that one!  

0 Kudos
Message 18 of 34
(1,763 Views)

Unfortanately, I have no experience with the PDA toolkit so I can't help you there.

 

As for reading multiple channels you would not need to duplicate the Create Channels VI. All that you would need to do is to change the range of channels for the "physical channels" input if you're using that, or just to change the task if you're using the "task" input and you created the task using MAX. Check the documentation on the Create Channels VI and it will tell you how to specify multiple channels. I can't look at the VI right now, but if I recall correctly, I believe the data acquisition read should already have been setup to read multiple channels.

Message 19 of 34
(1,744 Views)

I've had the chance to test the program with an accelerometer connected and it works brilliantly. I'm now onto the other program which reads and formats the data. I'm trying to open a TDMS file, then extract the results from the various channels within the file and display them onto some charts. I've attached a bit of code which I'm hoping to put into this program (i started it ages ago and don't have access to it right now), would someone be able to check that it's along the correct lines? Also how do I change the data type of the 2nd chart so that it will display the data from both the pressure1 and pressure2 channels? 

Hmmm i can't seem to attach the file right now, all I'm getting is 'an unexpected error occurred'...
Message Edited by Robbo13 on 04-18-2009 12:35 PM
Message Edited by Robbo13 on 04-18-2009 12:37 PM
0 Kudos
Message 20 of 34
(1,631 Views)