01-20-2012 11:40 AM
Forgive me but I have been away from LabVIEW for a quite a while. I have been working in the realm of LabWindows (99% of our work) for the last five years with some LabVIEW sprinkled in. I have been tasked with designing a replacement for an existing test stand at another facility in our company with a primary requirement being that LabVIEW is the development environment.
We have two very strong standard 'C' architectures that we try and use as a baseline on the majortiy of our work. I would like to try and implement one of these architectures in LabVIEW but am finding that part, and really a fundamental part, of this architecture is not translating very well. The centerpieces of this achitecture are global signal lookup structure(s) and a global system record. The signal lookup structure is a complete list of signals in the test system with scalar and offset information. The system record stores the current raw value for the of each of these signals. See the examples below:
typedef struct SignalType
{
int globalIndex;
double voltsPerEngUnit;
double voltageOffset;
char signalName[SIGNAL_NAME_LENGTH];
}SignalType;
struct SignalLookup
{
SignalType sigTable[MAX_SIGNALS];
SignalType *hardwareOutSpare100;
SignalType *hardwareOutSpare99;
SignalType *hardwareOutSpare98;
...
SignalType *hardwareInSpare100;
SignalType *hardwareInSpare99;
SignalType *hardwareInSpare98;
...
SignalType *time;
SignalType *dutyTime;
SignalType *frameTime;
SignalType *isrCounter;
SignalType *softwareOutSpare96;
...
SignalType *graphPlot1;
SignalType *graphPlot2;
SignalType *graphPlot3;
SignalType *graphGo;
SignalType *graphDomainMin;
SignalType *graphDomainMax;
SignalType *graphRangeMin;
SignalType *graphRangeMax;
SignalType *softwareInSpare91;
...
} signalLookup;
Initialization Functions:
void SignalTypeInit(SignalType * s, int global, char * name, double scalar, double offset)
{
s->globalIndex = global;
s->voltsPerEngUnit = scalar;
s->voltageOffset = offset;
strcpy(s->signalName, name);
}
void SignalLookupInit()
{
//Hardware Output
signalLookup.hardwareOutSpare100= &signalLookup.sigTable[0];
SignalTypeInit(signalLookup.hardwareOutSpare100, 0, "hardwareOutSpare100", 1.0000, 0.0000);
signalLookup.hardwareOutSpare99= &signalLookup.sigTable[1];
SignalTypeInit(signalLookup.hardwareOutSpare99, 1, "hardwareOutSpare99", 1.0000, 0.0000);
signalLookup.hardwareOutSpare98= &signalLookup.sigTable[2];
SignalTypeInit(signalLookup.hardwareOutSpare98, 2, "hardwareOutSpare98", 1.0000, 0.0000);
...
}
typedef struct SystemRecord
{
double sigTable [MAX_SIGNALS];
}SystemRecord;
How can I translate these structures to LabVIEW when LabVIEW with global structures and arrays being big no-nos in LabVIEW? I am open to all critiques and help I can get.
Regards-
John OC
Solved! Go to Solution.
01-21-2012 10:56 AM
I didn't look at the C code too closely, but is seems to me that you basically have a bunch of named signal definitions (structs) to which you want to get the data by name.
Personally, I would add all the additional needed data in there (such as the hardware address and the actual current value) and use a class or a library to wrap all of it in an easy to use API.
You can create the core of the functionality by having a lookup table of data value references (DVRs, which are somewhat (only somewhat!) similar to pointers, in that they point to specific data) which will each point to a single cluster (or object). Once you get the DVR to the cluster (or object) you use the in-place element structure to get the data inside the DVR and perform the specific operation you want (such as setting the initial configuration or reading the current calibrated value of the signal) on that data.
For the lookup, I would recommend a simple VI with a variant in a shift register. The shift register makes sure that the data is saved between runs of the VI and you use the variant attribute primitives to keep the DVRs - if an attribute with the current name doesn't exist in the variant, you create a new one and write it to the variant. Each attribute holds a DVR which is what you output.
So, for each VI in your API (Init, Read Current Value, etc.) you give the name as an input and start by calling the lookup VI to get the DVR. Then you use the DVR to operate on that specific signal.
If all that sounds too complicated, you can try going with something like this - http://zone.ni.com/devzone/cda/epd/p/id/5326