06-29-2009 03:22 AM
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
06-29-2009 10:55 AM
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
06-29-2009 02:42 PM
06-30-2009 03:19 PM - edited 06-30-2009 03:21 PM
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
07-01-2009 10:38 AM
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
07-01-2009 10:52 AM
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
07-02-2009 06:29 AM
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
07-02-2009 06:57 AM - edited 07-02-2009 07:02 AM
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
07-02-2009 09:28 AM
Thanks a lot Ray, indeed using FileGlobalsDefault it works great!
Regards