NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Updating Locals in TestStand from C#

Hi ccds,

 

How do you write to Locals.Measurement?

Do you pass this value back from your code module directly into Locals.Measurement

eg public double MyTest(out bool errorOccurred, out int errorCode, out string errorMsg)

 

where within TestStand you have specified Return Value, Number(System.Double), Locals.Measurement

 

or do you write to Locals.Measurement within your code module using the SequenceContext?

 

Check out the Computer Motherboard Test Sequence example in TestStand, DotNet version, for examples of passing data back from the code module.

 

Regards

Ray Farmer

Regards
Ray Farmer
0 Kudos
Message 11 of 19
(2,165 Views)

Let me explain why I think you are having trouble getting the editing/running to work, but let me begin by saying I'd still recommend a different design for your system which I will go into more detail after this paragraph. Editsubsteps always operate on the edit time copy of the variables (which I assume is what you want). So you need to increment the change count on the file at the end of the code in your edit substep. If you do this you should see the edits in the sequence editor after your edit substep is done running. Also you mention an event mechanism for updating the variable, if this is happening asynchronously that is likely the source of your problem at runtime. You will need to synchronize things with the teststand sequence so that the variable is updated at a fixed time within the sequence before you try to access it from later steps. Perhaps you need to add code to your step type to wait until the measurement has been set before continuing to execute the rest of the sequence that depends on it. Basically, you might have a race condition in your code.

 

That said I think the following design for your step types would better fit in with TestStand and be more flexible:

 

First off, it's best to use step properties rather than local variables to store settings and measurements. That way you don't have to worry about creating corresponding variables for each step (i.e. you don't want to create 5 local variables everytime you create 5 measurement steps), and you don't need a configuration dialog to specify where to store things because it is always in the same place, in the step properties created specifically for this purpose. Step types provide this functionality quite nicely. When creating your step types you can add whatever variables you want your steps to have to your step type and whenever one of your steps is created it will have those variables.

 

For example. It sounds like you need two step types as follows:

 

Step Type 1: MyConfigureDMMStepType

 

1) This step type should have a property added to it to store the configuration string. I'd recommend something like Step.DMMConfigurationData.

2) Your GUI should be slightly rewritten or modified to either not ask for the location at all and just always use Step.DMMConfigurationData (which is what I'd recommend), or at least default to Step.DMMConfigurationData and use a TestStand Expression control to allow the user to specify an alternative location. The TestStand expression control already knows how to browse variables in the sequence context so you don't have to implement code for this from scratch.

3) Your step type should have an edit substep that brings up your gui and once it's done, saves the settings in Step.DMMConfigurationData and increments the change count on the sequence file.

4) In addition to an edit substep your step type also needs a postsubstep. A post substep is the code module run at runtime. You should configure this to call your code that sends the actual configuration data at runtime. You can even pass Step.DMMConfigurationData into it as a parameter so it doesn't even need to know anything about TestStand or the TestStand API.

5) On the first page of the step type properties dialog you should check the Designate adapter setting and select <None> as the step type does not require a user defined code module.

 

Step Type 2: MyAcquireDMMMeasurementStepType

 

1) This step type should have multiple properties added to it, one to store the settings string, if any, and another to store the measurement.

2) I'd recommend storing the measurement under the result property of the step, for example, Step.Result.Measurement. The nice thing about putting the measurement under Step.Result is that it will automatically be stored in the results for the sequence and can be used by things like report generation. If you want this measurement to automatically show up in reports, all you have to do is edit the flags on the measurement variable in your step type (use the properties dialog's Advanced button) and set the IsMeasurementValue, and IncludeInReports flags on the property.

2) Your GUI should be slightly rewritten or modified to either not ask for the location at all and just always use Step.Result.Measurement for the measurement value (which is what I'd recommend), or at least default to Step.Result.Measurement and use a TestStand Expression control to allow the user to specify an alternative location. The TestStand expression control already knows how to browse variables in the sequence context so you don't have to implement code for this from scratch.

3) Your step type should have an edit substep that brings up your gui and once it's done, saves the settings in Step.ConfigurationData or whatever variable you create for this purpose, and increments the change count on the sequence file.

4) In addition to an edit substep your step type also needs a postsubstep. A post substep is the code module run at runtime. You should configure this to call your code that does the actual acquiring of the measurement at runtime. You can even pass Step.Result.Measurement into it as an output parameter and your Step.ConfigurationData as an input parameter so it doesn't even need to know anything about TestStand or the TestStand API.

5) On the first page of the step type properties dialog you should check the Designate adapter setting and select <None> as the step type does not require a user defined code module.

6) I recommend no longer using an event mechanism to get back the data or at least make the postsubstep synchronously wait until it gets back the data and sets the variable before returning back to TestStand. If you want to take measurements asychronously, you are probably better off using the asynchronous functionality of TestStand for this purpose rather than doing so at the driver level. TestStand can run sequences in a separate thread or execution allowing for asynchronous execution at the TestStand level with lots of nice behaviors and supporting step types that better fit in with TestStand.

 

If you are concerned about keeping existing legacy sequences from your old sequencer then I'd recommend you consider what j_dodek mentioned and write an converter to convert your old sequences to the new way of doing things. I think in the long run you will find what I'm describing to be easier to use and a better fit of your code with TestStand than what you are currently considering. If any of this is unclear or you need more details about a particular aspect of step type creation please let us know.

 

Hope this helps,

-Doug

0 Kudos
Message 12 of 19
(2,155 Views)
Thanks Doug for all your comments and suggestions, I have some second thoughts about your recommendations, please correct me if I am wrong... In my example about the DMM, I have chosen this to try to explain my situation as easy as possible. In reality we have more then 100 device drivers for all devices in our production systems. The DMM example is an easy one, and uses only one variable for the measurement. Some of the device drivers are using up to 20 variables and more. The engineer developing the sequence is free to use as much variables as needed. I mean to configure something it is also possible to use variables instead of predefined values. This has as consequence that it is not possible to predict how many variables are used for a specific device driver. Because we have more then 100 device drivers and for each device driver we have from 1 up to 6 actions (Ex. the DMM has two actions, Configuration and Measurement), I would have more then 500 step types. The number of step types that can be used depends on the current selected test system. (Some test systems are more complicated then others and contains more devices) At this moment I do not think that this is good approach, is it not difficult to maintain such a number of step types? Now, I am trying to build one common step type that can be used for all device drivers and in fact it is very easy if I still use my event mechanism and the local variables and a view step type properties to store descriptive strings. I have implemented a step type with an edit sub step to view the GUI´s and a post step type to execute the code as you recommended. Another reason why I think I should use the variables, because it must be possible for the developer of the sequence to change the name of variables for an existing sequence, I do not think this is possible if I use properties from my common step type. Our sequencer is an executable and is written on top of all device drivers, a common public interface is used to communicate with the device drivers. All configuration settings about our test systems are stored on SQL server, we have intranet tools to maintain these configurations. It is possible for each device driver to define labels, Ex for an InputOutput driver, it is possible to give each input or/and output a user defined name. All this information is stored also in databases. So to use our device drivers we have to read a lot of data from SQL server and store this in objects in memory. Now, I have written an interface between Teststand via a common step type and a method in an interface dll between Teststand and the layer on top of all device drivers. The layer on top of all devicedrivers takes care off stuffing all objects with the data from the databases when constructed, the event handling is also done in this layer. In this layer I want to implement a method to update the local variables and I should be able to detect if the name of a local variable is changed in TestStand, up to now, I do not know if this is possible? Knowing this what do you recommend, is it still a better idea to write step types for each action? About your suggestion to convert all our existing sequences to TestStand sequences, I think this would be a tremendous amount of work! I think about using TestStand in the future, but it would beautiful it would be possible to reuse all our existing device drivers! Anyway, thanks again for all your comments I have already learned a lot about TestStand. Looking forward for your respons.
0 Kudos
Message 13 of 19
(2,145 Views)

Sounds like things are a lot more complicated than I thought. I agree, it probably doesn't make sense to create 500 step types. Are these actions something that really needs to be exposed at the sequence level? Perhaps you should just use the builtin step types such as numeric limit and keep the details and low level code inside of the code module called by the step.

 

I still don't fully know or understand what you are doing, but here are some thoughts.

 

1) You say " The engineer developing the sequence is free to use as much variables as needed. I mean to configure something it is also possible to use variables instead of predefined values" TestStand has a feature which is very similar to this that you might find useful. Basically you can let your users specify teststand expressions rather than variables. TestStand expressions can contain variables or even complex expressions with multiple variables and operators. You can use the TestSTand API to dynamically evaluate and get the result of expressions. So perhaps moving to using teststand for this might simplify things. Also if you are using the expression control anyway you can even get a nice bultin UI to let the user do the editing with.

 

2) did you figure out why your variable updating wasn't working? Is it because your events are asynchronous?

 


Anyway, perhaps we should focus on the technical problems you were having. If you are still having trouble getting the variable modification to work please explain that part in more detail or better yet, attach some example code which reproduces the problem.

 

-Doug

Message Edited by dug9000 on 06-30-2009 03:21 PM
0 Kudos
Message 14 of 19
(2,122 Views)

About updating the local variables, this problem is fixed.

Indeed it was a synchronization problem.

 

Now, I try to write some other data to a File Global variable (The serialized hash table with all defined local variables names and their corresponding unique integer). As you have already told I need to update IncChangCount for PropertyObjectFile.

 

Are there code samples available how to to this in C#.

 

By the way, is there a place available with code sources in C#, because TestStandReferenceManual does not contain code samples, the only source I have is TestStandAPIReferencePoster?

 

Best regards

0 Kudos
Message 15 of 19
(2,110 Views)

Glad to hear you got the variable updating working.

 

IncChangeCount is just a method on SequenceFile and PropertyObjectFile. At the end of your editsubstep, if any variables were modified, assuming you passed in the sequence context as a parameter you can just call:

 

context.SequenceFile.IncChangeCount();

 

There are various example sequences and source code under <TestStandPublic>\Examples. Not all of them are implemented in every programming languages, but some of them are. Also many of the components shipped with TestStand under <TestStand>\Components ship with source code, including the substep implementations of some of our step types. Also, using the API from C++/C is very similar to how you can use it from C#. Even if you don't know C++ or C very well you will likely be able to figure out the C# equivalent by looking at the code.

 

Hope this helps,

-Doug

0 Kudos
Message 16 of 19
(2,108 Views)

Hi Doug,

 

I have troubles writing the content of a FileGlobal to the sequence.I have implemented the method context.SequenceFile.IncChangeCount() as proposed.By stepping trough my C# code and looking to the property ChangeCount of object SequenceFile, the counter is set to 1.By putting a breakpoint in TestStand after this step and have a look to the specific variable in FileGlobals, it is updated, but the data is not written to the file!If I close the sequence and reopen the sequence, the data is lost?Any idea what the reason is for this behavior?

 

Best regards

0 Kudos
Message 17 of 19
(2,092 Views)

Hi,

 

It probably because you are updating the runtime version of the fileglobals instead of the static version.

 

The fileglobals you should be updating is FileGlobalsDefaults wihich is found under the Runstate.SequenceFile.Data property.

 

Regards

Ray Farmer

Message Edited by Ray Farmer on 07-02-2009 01:01 PM
Message Edited by Ray Farmer on 07-02-2009 01:02 PM
Regards
Ray Farmer
0 Kudos
Message 18 of 19
(2,088 Views)

Thanks a lot Ray, indeed using FileGlobalsDefault it works great!

 

Regards

0 Kudos
Message 19 of 19
(2,078 Views)