Initializing an array of clusters in a CIN?

I'm trying to write a CIN to connect to a mySQL database, retreive some information, and return it to labVIEW for display. The connection works perfectly using ODBC, but I'm having major trouble getting the information back to LabVIEW. I'm new to CINs and I'm still slightly confused as to how the different structures work. I want to return the data in an array of clusters (using struct names, a 'Set' of 'Records'). LV generated the structs, and I simply renamed some of the fields/names. The code I have so far works up to the point specified in the source below, when I try to initialize the array for data entry. I think what's throwing me off is the conplexity of my structures. Since it's an array of clusters, and not an array of say strings or integers, I'm getting confused. If anyone could help me out by telling me what's wrong with my code, and/or filling in the section of the while loop I'm rather clueless on.
typedef struct {
LStrHandle Number;
LStrHandle SerialNumber;
} Record;
typedef struct {
int32 dimSize;
Record ptr[1];
} Set;
typedef Set **SetHdl;
MgErr CINRun(COpt *ConnectionOptions, LStrHandle *Number, SetHdl *RecordSet);
MgErr CINRun(COpt *ConnectionOptions, LStrHandle *Number, SetHdl *RecordSet)
// LV error code
MgErr err = noErr;
// ODBC environment variables
HENV env = NULL;
HDBC dbc = NULL;
HSTMT stmt = NULL;
// Connection options data variables
UCHAR* dsn = malloc(SQL_MAX_DSN_LENGTH * sizeof(UCHAR));
UCHAR* user = malloc(32 * sizeof(UCHAR));
UCHAR* pass = malloc(32 * sizeof(UCHAR));
UCHAR* num = malloc(16 * sizeof(UCHAR));
// Query variables
INT qlen;
INT nlen;
UCHAR colNumber[5];
SDWORD colNumberSize;
UCHAR* query;
INT numRows;
// ODBC return code storage
RETCODE retcode;
/** Prepare data from LV for C++ manipulation **/
strcpy(dsn, LStrBuf((LStrPtr)(*(ConnectionOptions->DSN))));
dsn[(*(ConnectionOptions->DSN))->cnt] = '\0';
strcpy(user, LStrBuf((LStrPtr)(*(ConnectionOptions->Username))));
user[(*(ConnectionOptions->Username))->cnt] = '\0';
strcpy(pass, LStrBuf((LStrPtr)(*(ConnectionOptions->Password))));
pass[(*(ConnectionOptions->Password))->cnt] = '\0';
strcpy(num, LStrBuf((LStrPtr)(*Number)));
// Program crashes here too, but that's the least of my concerns right now. Keep reading down.
//num[(**Number)->cnt] = '\0';
qlen = (int)strlen(
"SELECT m.Number FROM master AS m WHERE (m.Number LIKE '');"
nlen = (int)strlen(num);
query = malloc((qlen + nlen + 1) * sizeof(UCHAR));
sprintf(query,
"SELECT m.Number FROM master AS m WHERE (m.Number LIKE '%s'\0);",
num);
// Prepare and make connection to database
SQLAllocEnv (&env);
SQLAllocConnect(env, &dbc);
retcode = SQLConnect(dbc, dsn, SQL_NTS, user, SQL_NTS, pass, SQL_NTS);
// Test success of connection
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
retcode = SQLAllocStmt(dbc, stmt);
retcode = SQLPrepare(stmt, query, sizeof(query));
retcode = SQLExecute(stmt);
SQLBindCol(stmt, 1, SQL_C_CHAR, colNumber, sizeof(colNumber), &colNumberSize);
SQLRowCount(stmt, &numRows);
//Program crashes on the following line. I get an error in LV saying something about an error in memory.cpp
DSSetHandleSize((*RecordSet), sizeof(int32) + (numRows * sizeof(Record)));
(**RecordSet)->dimSize = numRows;
retcode = SQLFetch(stmt);
numRows = 0;
while (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
/* Need code here to retreive/create Records and put them in the array */
retcode = SQLFetch(stmt);
numRows++;
SQLDisconnect(dbc);
else
// Free ODBC environment variables
SQLFreeConnect(dbc);
SQLFreeEnv(env);
// Return LV error code
return err;

This looks incorrect:
MgErr CINRun(COpt *ConnectionOptions, LStrHandle *Number, SetHdl *RecordSet)
Did you let LabVIEW generate the C file??
When you pass an array of clusters to a CIN, what is passed is a handle to the array. You are declaring a pointer to a handle. I just did a test passing an array of clusters to a CIN. The C file looks like this (comments are mine):
typedef struct {
int32 Num1;
int32 Num2;
} TD2; // the cluster
typeDef struct {
int32 dimSize;
TD2 Cluster[1];
} TD1; // the array
typeDef TD1 **TD1Hdl; // handle to the array
CIN MgErr CINRun(TD1Hdl Array);
Notice that it passes you a HANDLE, not a pointer to a handle.
On this line:
DSSetHandleSize((*RecordSet), sizeof(int32) + (numRows * sizeof(Record)));
If RecordSet is a HANDLE, then (*RecordSet) is a POINTER - you are passing a POINTER to a routine that expects a HANDLE.
The line:
(**RecordSet)->dimSize = numRows;
Is also incorrect - if RecordSet is a HANDLE, then (*RecordSet) is a POINTER, and (**RecordSet) is an ARRAY, but you're asking it to be a pointer. (*RecordSet)->dimSize would be the size to fetch.
Read the rules again on what is passed to CINs.
I strongly suggest developing the interface first - the VI that calls the CIN. Put the CIN in place and let LabVIEW generate the initial C file.
Then modify the code to do something simple with the input arguments, like fetch the array size, and put this number into an output argument. Something VERY basic, just to test the ins and outs. Debug this until all ins and outs are working.
THEN AND ONLY THEN add code to do whatever work needs doing.
Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com
Blog for (mostly LabVIEW) programmers: Tips And Tricks

Similar Messages

  • Initializing data in an Array of Clusters

    First, thanks in advance for reading this request.
    Second, the situation:
    I am using an array of clusters for process control.
    The cluster contains a boolean, a typedef ring control, and two numeric controls (doubles).
    Depending upon the user-requested operation I need anywhere from four to 20 cluster elements in the array.
    Raw data for the two numeric controls are contained as elements in three different input clusters.
    Each numeric control in each array cluster can use from none to four elements from the input clusters with various additions and subtractions (no mults or divs).
    The boolean and ring can be set as constants for each element based on the user request.
    Third, the request:
    Is there a simple way to initialize the values in the cluster (and hence the array) without having to run wires everywhere?
    I have been writing embedded code and PC applications for many years and am only recently tackling LabView.
    In C, I would create a structure of the four elements and then create and array of structures.
    The initialization would require a few lines of code.
    I have tried using formula nodes (perhaps incorrectly).  All they do is remove the Numeric blocks (like + and -), but they don't create the cluster.
    I am sure that there is an easier way of accomplishing what I need to do, I am just too inexperienced to know what it is.
    Any help or suggestions is welcome.
    Thanks in advance.

    Create a cluster with the desired default values as diagram constant, wire it to "initialize array" and wire the desired array size.
    The output will be the desired construct that you could write to e.g. a local variable of the target.
    I hope I understood you correctly. If not, attach a small VI containing your array.
    LabVIEW Champion . Do more with less code and in less time .

  • Array Of Clusters Not Initializing or Possible Race Conditions

    Hi all,
    I've been working on a fairly complex project for work, and I haven't worked with Labview before. Unfortunately nobody in my office really has experience with it so I'm on my own. I've mostly got the project working, and it might be a little cumbersome, but if it works that's fine.
    Essentially it's a temperature control device and I made it so it's expandable, thus the clusters and arrays everywhere.
    My question is this. I've got an array of clusters indicating the status of all the plates in the system. When I start up the VI for the first time they do not initialize. They just stay grey, but when I stop it and start it once, it will work every time. I think this is kind of strange behavior. I've heard of race conditions and while I've tried to make sure t hat's not happening, it might be without me noticing.
    I've tried putting an initialize array block in the first call while loop and that doesn't do anything, and if I remove the initializer from the shift register in the top while loop that stops them being initalized altogether.
    I guess I was hoping someone might have an idea what's causing it, or could possible give my code the once over. The main bulk of it is in the very top of the code, but there are a lot of smaller events taking care of GUI type stuff.
    I've included all source code. It might be a little much but I didn't want to start pulling it apart if I don't know what's happening.
    Thanks in advance.
    Chris.
    Solved!
    Go to Solution.
    Attachments:
    Error During Cycle Controls.zip ‏3107 KB
    Stop Cycle Controls.zip ‏2115 KB
    Stop Cycle Controls.zip ‏4975 KB

    Chris Johnson wrote:
    So just to confirm, I can have one event structure with say 10 events happening? In this case could an event happen simultaneously with another? I thought I read something about each event having it's own event structure and while loop to make sure this works out.
    Each event case must complete before it can handle the next event, but many events will complete so quickly that this is not an issue (such as your "pause chart" button).  In general you should have only one event loop.  If you expect an event to take a long time to process, use a queue to hand that task off to another dedicated-purpose loop, so that the event structure can go back to waiting.  This is one example of the producer-consumer structure often mentioned on this forum: the producer is the loop containing the event structure, and it queues (produces) items to process.  A separate loop dequeues (consumes) those items and handles them appropriately.
    As GerdW mentioned, you have race conditions all over the place.  You'll never know whether the Plate Info Cluster Array is properly updated because it's being written and read simultaneously in so many places.  I'm assuming that is also where you're seeing the issue that inspired the post, and, in fact, one of those race conditions could explain what you're seeing.
    Chris Johnson wrote:
    Also, again, to confirm what I think I already know. When the event completes it outputs whatever data you output from the structure and then you can place it in a shift register. Where does this go until the next event takes place?
    I don't understand what you're asking.  Where does what go until the next event?  If by this you mean the data in the shift register - it stays in the shift register, accessible at the corresponding terminal on the left side of the loop.

  • Call library function node with array of clusters using array data pointer

    Hello all.
    I am writing a LabVIEW wrapper for an existing DLL function.
    The function has, as one of its parameters, an array of structs.  The struct is very simple, containing two integers.  I am using the call library function node to access it.
    In Labview I created an array of clusters, where the cluster has two 32-bit integers as its members.  So far, so good.
    Now I have to pass this in to the Call Library Function Node.  Here I am running into trouble.
    I have used The topic in LAVA and The topic in the knowledge base as my primary sources of information, though I have read a bunch of forum topics on the subject too.
    I do understand that I could write a new function which takes as a parameter a struct with the size as the first member and an array as the second, and I might just do this and have it call the regular function, but I was hoping to do it more simply.
    According to the C file which LabVIEW generates for me from the CLFN when I choose "Adapt to Type" and "Array Data Pointer", the prototype it is expecting is:
    int32_t myFunc(uint32_t handle, uint16_t channel,
    int32_t FIFOnumber, void data[], int32_t numWords, int32_t *actualLoaded,
    int32_t *actualStartIndex);
    And the prototype of the function in my DLL is
    int borland_dll myFunc(DWORD handle, usint channel,
    int FIFOnumber, struct mStruct *data, int numWords, int *actualLoaded, int *actualStartIndex);
    This looks like a match to me, but it doesn't work (I get garbage in data).  From the topic in LAVA referenced above, I understood that it would work.  It does not.
    If I cast data to the pointer-to-pointer I get when I generate c code by wiring my struct to a CIN and generating, then I seem to get what I expect. But this seems to work when I choose "pointers to handles" too, and I would expect array data pointer to give a different result.
    Is there any way to get this to work directly, or will I have to create a wrapper?  (I am currently using LabVIEW 2011, but we have customers using 2009 and 2012, if not other versions as well).
    Thank you.
    Batya
    Solved!
    Go to Solution.

    OK, here is more detailed information.
    I have attached the VI.
    This is the code from the  "C" file created by right-clicking the CLN and creating a "C" file. 
    When the parameter in the CLN is set to "array data pointer":
    /* Call Library source file */
    #include "extcode.h"
    int32_t Load_Transmit_FIFO_RTx(uint32_t handle, uint16_t channel,
    int32_t FIFOnumber, void data[], int32_t numWords, int32_t *actualLoaded,
    int32_t *actualStartIndex);
    int32_t Load_Transmit_FIFO_RTx(uint32_t handle, uint16_t channel,
    int32_t FIFOnumber, void data[], int32_t numWords, int32_t *actualLoaded,
    int32_t *actualStartIndex)
    /* Insert code here */
     When the parameter is "pointers to handles":
    /* Call Library source file */
    #include "extcode.h"
    /* lv_prolog.h and lv_epilog.h set up the correct alignment for LabVIEW data. */
    #include "lv_prolog.h"
    /* Typedefs */
    typedef struct {
    int32_t control;
    int32_t data;
    } TD2;
    typedef struct {
    int32_t dimSize;
    TD2 data[1];
    } TD1;
    typedef TD1 **TD1Hdl;
    #include "lv_epilog.h"
    int32_t Load_Transmit_FIFO_RTx(uint32_t handle, uint16_t channel,
    int32_t FIFOnumber, TD1Hdl *data, int32_t numWords, int32_t *actualLoaded,
    int32_t *actualStartIndex);
    int32_t Load_Transmit_FIFO_RTx(uint32_t handle, uint16_t channel,
    int32_t FIFOnumber, TD1Hdl *data, int32_t numWords, int32_t *actualLoaded,
    int32_t *actualStartIndex)
    /* Insert code here */
     When the parameter is set to "handles by value":
    /* Call Library source file */
    #include "extcode.h"
    /* lv_prolog.h and lv_epilog.h set up the correct alignment for LabVIEW data. */
    #include "lv_prolog.h"
    /* Typedefs */
    typedef struct {
    int32_t control;
    int32_t data;
    } TD2;
    typedef struct {
    int32_t dimSize;
    TD2 data[1];
    } TD1;
    typedef TD1 **TD1Hdl;
    #include "lv_epilog.h"
    int32_t Load_Transmit_FIFO_RTx(uint32_t handle, uint16_t channel,
    int32_t FIFOnumber, TD1Hdl *data, int32_t numWords, int32_t *actualLoaded,
    int32_t *actualStartIndex);
    int32_t Load_Transmit_FIFO_RTx(uint32_t handle, uint16_t channel,
    int32_t FIFOnumber, TD1Hdl *data, int32_t numWords, int32_t *actualLoaded,
    int32_t *actualStartIndex)
    /* Insert code here */
    As to the DLL function, it is a bit more complicated than I explained above, in the current case.  My VI calls the function by this name in one DLL, and that DLL loads a DLL and calls a function (with the same name) in the second DLL, which does the work. (Thanks Rolfk, for helping me with that one some time back!)
    Here is the code in the first ("dispatcher") DLL:
    int borland_dll Load_Transmit_FIFO_RTx(DWORD handle, usint channel, int FIFOnumber, struct FIFO_DATA_CONTROL *data, int numWords, int *actualLoaded, int *actualStartIndex)
    t_DispatchTable *pDispatchTable = (t_DispatchTable *) handle;
    int retStat = 0;
    retStat = mCheckDispatchTable(pDispatchTable);
    if (retStat < 0)
    return retStat;
    if (pDispatchTable->pLoad_Transmit_FIFO_RTx == NULL)
    return edispatchercantfindfunction;
    return pDispatchTable->pLoad_Transmit_FIFO_RTx(pDispatchT​able->handlertx, channel, FIFOnumber, data, numWords, actualLoaded, actualStartIndex);
    borland_dll is just "__declspec(dllexport)"
    The current code in the DLL that does the work is:
    // TEMP
    typedef struct {
    int control;
    int data;
    } TD2;
    typedef struct {
    int dimSize;
    TD2 data[1];
    } TD1;
    typedef TD1 **TD1Hdl;
    // END TEMP
    int borland_dll Load_Transmit_FIFO_RTx(int handlertx, usint channel, int FIFOnumber, struct FIFO_DATA_CONTROL *data, int numWords, int *actualLoaded, int *actualStartIndex){
    struct TRANSMIT_FIFO *ptxFIFO; //pointer to transmit FIFO structure
    usint *pFIFOlist; //pointer to array of FIFO pointers to FIFO structures
    int FIFOentry, numLoaded;
    usint *lclData;
    usint nextEntryToTransmit;
    // TEMP
    FILE *pFile;
    int i;
    TD1** ppTD = (TD1**) data;
    TD1 *pTD = *ppTD;
    pFile = fopen("LoadFIFOLog.txt", "w");
    fprintf(pFile, "Starting Load FIFO with %d data words, data pointer 0x%x, with the following data&colon; \n", numWords, data);
    for (i = 0; i < numWords; i++) {
    fprintf(pFile, "%d: control--0x%x, data--0x%x \n", i, data[i].control, data[i].data);
    fflush(pFile);
    fprintf(pFile, "OK, using CIN generated structures: dimSize %d, with the following data&colon; \n", pTD->dimSize);
    for (i = 0; i < numWords; i++) {
    fprintf(pFile, "%d: control--0x%x, data--0x%x \n", i, pTD->data[i].control, pTD->data[i].data);
    fflush(pFile);
    // END TEMP
    if ((handlertx) <0 || (handlertx >= NUMCARDS)) return ebadhandle;
    if (cardrtx[handlertx].allocated != 1) return ebadhandle;
    pFIFOlist = (usint *) (cardrtx[handlertx].segaddr + cardrtx[handlertx].glob->dpchn[channel].tr_stk_ptr​);
    pFIFOlist += FIFOnumber;
    ptxFIFO = (struct TRANSMIT_FIFO *)(cardrtx[handlertx].segaddr + *pFIFOlist);
    //use local copy of ptxFIFO->nextEntryToTransmit to simplify algorithm
    nextEntryToTransmit = ptxFIFO->nextEntryToTransmit;
    //on entering this routine nextEntryToLoad is set to the entry following the last entry loaded
    //this is what we need to load now unless it's at the end of the FIFO in which case we need to wrap around
    if ( ptxFIFO->nextEntryToLoad >= ptxFIFO->numEntries)
    *actualStartIndex = 0;
    else
    *actualStartIndex = ptxFIFO->nextEntryToLoad;
    //if nextEntryToLoad points to the last entry in the FIFO and nextEntryToTransmit points to the first, the FIFO is full
    //also if nextEntryToLoad == nextEntryToTransmit the FIFO is full and we exit without loading anything
    if (( (( ptxFIFO->nextEntryToLoad >= ptxFIFO->numEntries) && (nextEntryToTransmit == 0)) ||
    ( ptxFIFO->nextEntryToLoad == nextEntryToTransmit)) && (ptxFIFO->nextEntryToLoad != INITIAL_ENTRY)){
    *actualLoaded = 0; //FIFO is full already, we can't add anything
    return 0; //this is not a failure, we just have nothing to do, this is indicated in actualLoaded
    numLoaded = 0;
    lclData = (usint *)data; //must use 16 bit writes to the module
    //conditions are dealt with inside the for loop rather than in the for statement itself
    for (FIFOentry = *actualStartIndex; ; FIFOentry++) {
    //if we reached the end of the FIFO
    //if the module is about to transmit the first element of the FIFO, the FIFO is full and we're done
    //OR if the module is about to transmit the element we're about to fill in, we're done - the
    //exception is if this is the first element we're filling in which means the FIFO is empty
    if ((( FIFOentry >= ptxFIFO->numEntries) && (nextEntryToTransmit == 0)) ||
    ((FIFOentry == nextEntryToTransmit) && (FIFOentry != *actualStartIndex) )){
    *actualLoaded = numLoaded;
    //set nextEntryToLoad to the end of the FIFO, we'll set it to the beginning next time
    //this allows us to distinguish between full and empty: nextEntryToLoad == nextEntryToTransmit means empty
    ptxFIFO->nextEntryToLoad = FIFOentry;
    return 0;
    //we reached the end but can continue loading from the top of the FIFO
    if ( FIFOentry >= ptxFIFO->numEntries)
    FIFOentry = 0;
    //load the control word
    ptxFIFO->FifoData[FIFOentry * 3] = *lclData++;
    //skip the high of the control word, the module only has a 16 bit field for control
    lclData++;
    //now put in the data
    ptxFIFO->FifoData[(FIFOentry * 3) + 2] = *lclData++;
    ptxFIFO->FifoData[(FIFOentry * 3) + 1] = *lclData++;
    numLoaded++;
    //we're done because we loaded everything the user asked for
    if (numLoaded >= numWords) {
    *actualLoaded = numLoaded;
    ptxFIFO->nextEntryToLoad = FIFOentry+1;
    return 0;
    //if we reached here, we're done because the FIFO is full
    *actualLoaded = numLoaded;
    ptxFIFO->nextEntryToLoad = FIFOentry;
    fclose (pFile);
    return 0;
     As you can see, I added a temporary diagnostic with the structures that were created in the "Handles by value" case, and print out the data.  I see what is expected, whichever of the options I pick in the CLN!  
    I understood (from the information in the two links I mentioned in my original post, and from the name of the option itself) that "array data pointer" should pass the array of data itself, without the dimSize field.  But that does not seem to be what is happening.
    Batya
    Attachments:
    ExcM4k Load Transmit FIFO.vi ‏15 KB

  • Reference to Array of Clusters with an array element

    Hi,
    I have an array of clusters CONTROL (calling it as "top level cluster array") with one of the cluster elements being a cluster array (please see attached).
    I plan to pass "Reference" of this top level cluster to different VIs (like add element VI, insert element VI, delete element VI etc) and access (add/modify delete) the elements in this array.
    In my code, how do I typecast the Array Element (cluster) to the inner cluster (as shown in the figure) ?
    I am using LV RT on PXI.
    Solved!
    Go to Solution.

    You cannot use references in the same way that you use pointers around in C. LabVIEW does not manage memory in the same way that C does. This is actually a good thing, though C programmers find it "cumbersome" or "restrictive". I have also programmed in C, and frankly I prefer LabVIEW's memory management any day of the week.
    You had not initially mentioned that this was going to be done in multiple places at (potentially) the same time. Given that, my recommendation is to look into using Action Engines. They provide a means of basically providing a one-location acccess for your data. By using a single VI to access/modify your data you preclude the generation of race conditions. You may also want to join this with the concept of using variants to provide a means to quickly find your data rather than looping to find the element you're interested in. This technique has been around for a while and it has been discussed before. There are examples floating around. Will need to check to find one. 
    As for your question regarding using the reference method which you tried to employ in your initial approach, that's simply not going to gain you anything. You will still be creating buffers when you try to access the cluster elements. But you already have this information in the array inside the outer for loop, so you're just creating unnecessary extra programming for yourself. 

  • How can I modify the cluster values in an array of clusters?

    Hi all - I can't believe that I am having trouble with this but for some reason I am completely wrapped around the axel with it. I have an array of clusters, they are all strings but with different names. I am using key configuration VIs to setup a readable text file for the user. I also want the user to be able to load up the array of clusters with the values that are in the text file. So I am reading the keys and trying to populate the array of clusters to show what is in the text file and then run the test using those values. However I am not able to get the clusters populated correctly. Does any one have an example of what I am trying to do? Basically I am trying to populate an existing array of clusters with new values. That is what it comes down to. Thanks in advance for any help.

    Go to jki and dowload VIPM (VI Package Maager). From there you ca install OpenG. Lot's of useful stuff.
    Also if you cosider XML to be readable you can use flatten to/from XML.
    =====================
    LabVIEW 2012

  • Using Event Structures with Array of Clusters

    Using LabVIEW 8.5
    Hi all,
    I'm trying to convert an existing application to one that can be used
    through a touch screen. I updated the UI and added an event structure
    to listen for mouse ups on controls that require a HMI keyboard or
    numpad to show up. Although I've been programming for a while, I'm new
    to LabVIEW and am struggling with a problem:
    Is there any way to have an event case listen to an event within
    arrays? I've seen a few examples on the forums, but they all start with
    breaking up the arrays into individual variables. Using the variables,
    they build arrays. This seems pretty tedious, and I'm pretty sure I
    can't apply it to one of my arrays. Essentially, I just want to know
    which cluster in which array the user has clicked on, so I can open the
    HMI keyboard or numpad and send the text to that cluster. In my watered down app (Array of Clusters.vi), I've put 3 arrays of clusters and a few stand-alone controls to give you guys an idea of what I'm taking about.
    BTW, I'm using the HMI Keyboard and Numpad built by the Beta Community (http://decibel.ni.com/content/docs/DOC-1062) and modified it to add a "Clear" button to the keyboard and numpad. Please let me know if I implemented this in the best way.
    Thanks for the help,
    Kunal
    Message Edited by bhatiak on 08-04-2008 03:55 PM
    Attachments:
    Array of Clusters4.llb ‏274 KB

    My old tic tac toe example shows how to determine which square of a 2D array has been clicked.
    http://forums.ni.com/ni/board/message?board.id=170&view=by_date_ascending&message.id=247044#M247044
    You probably can adapt some of it for the arrays on the right. If the array can be scrolled, you also need to account for the "indexvals" offset.
    The Layers controls is easiest, because you only show one element. Just read the "index vals" property to get the array element and parse the coordinates to get the cluster element.
    btw: the small while loop on the right serves no purpose at all and acts just as a CPU burner. You can delete it without any change in functionality. Is there anything else to it?
    LabVIEW Champion . Do more with less code and in less time .

  • How can i segregate an array of clusters with channels id in the cluster

    Hi All
    i am using a keithley 2010 DMM for power measurements,
    i am using the 2010 scan read VI which gives the reading output as an array of clusters, these clusters contain the measurement,units,channel.
    i have 6 channels for measuring voltage across and i want to make 5 readings per second on each channel which makes upto 30 readings per second.
    i want to segregate these clusters from the array according to the channel id and take the results,
    please tell me if we have function for this or you have any possible solution for the same.
    i would be very happy to hear from you and get this solved
    please help
    Thanks in advance
    Sandeep K Shyam

    yeah this looks great...thanks for your response,
    i have modified accordingly and attaching the VI, can you please look into this once
    also one more problem i have with this VI is whenever i am trying to run the VI, the  sub VI (Scan config.vi) gets popped up and waits for user response (next) cntrl+right arrow,  how can i get rid of this and run the VI in continues mode?
    i am attaching my VI along with the kei2010 lib,
    please check this
    Thanks again
    sandeep K shyam
    Attachments:
    sandeep-FinalKeithley20101.vi ‏822 KB
    kei2010.llb ‏901 KB

  • Control mouseover image does not display when contained in an array of clusters.

    I have been using system booleans (with some customization) for the ability to impement mouseover animations.  For example (default system booleans):
    The mouseover feedback works well with my UI, and for the most part everything is going great.
    However, the mouseover image does not load if the the boolean is contained within an array of clusters (a single cluster with the boolean inside or an array of booleans works as expected):
    The mouseover animation does work for a single array element in the above case (the one which was most recently clicked), but this behavior isn't desirable and it seems buggy if I were to leave this on my UI as it is.
    So I guess I'm just wondering if anybody has encountered this or has any suggested workarounds?  The few that I've thought of so far (maintain a separate array for any set of system boolean controls, check coordinates myself on mouse move event and try to update the proper element in the array, avoid using mouseover animations entirely for this set of controls) aren't all that desirable.  Even though this issue could be considered cosmetic, the UI is very important to me as this code is something shipped to customers.
    This is LV 2011 by the way, so if by some chance the behavior in 2012 is correct please let me know (this alone might be reason enough to convert the project up).  If there is a CAR ID for this behavior and an NI employee wishes to share it I would also appreciate that.
    Best Regards,  
    John Passiak
    Solved!
    Go to Solution.

    Hey Jason,
    A reproducing VI would be any VI that contains an array of clusters with a system control boolean inside.  Here's an example:
    Single Boolean, Single Cluster, and Array of Booleans all show the proper mouseover image.
    Array of Clusters always shows the mouseover effect on the last element which was clicked, but does not show the mouseover effect on other array elements (actually, it seems to be inconsistent--every now and then it does show the mouseover effect on other array elements but it is not at all reliable).
    Best Regards,
    John Passiak
    Attachments:
    MouseoverTester.vi ‏9 KB

  • Array of Clusters Counters / Shift registers

    Hello All,
    In my Array of Clusters, I'm having trouble controlling my MISS PACKET indicator. Each time a packet is missed , the MISS PACKET indicator increments by 1. My problems is, that the same number of miss packets is showing up in the MISS PACKET indicator in each array index if a packet is missed. Ex. So if index[0] has missed 30 packets, whenever index[1] misses a packet it will display 31 and not 1. I'm using a shift register to keep  a count of the number of missed packets. I believe the shift register is the issue because the  previous value is store whenever a packet is missed.
     Any help would be appreciate !
    Thanks
    Attachments:
    Final-Demo - 3.vi ‏52 KB

    The first time i tried using  a shift register I had the initalization done outside of the while loop and still got the same results
    Attachments:
    Final-Demo - 3.vi ‏47 KB

  • Array of clusters TAB next element

    I have an array of clusters and I want with the TAB key, when I am at the last element of the cluster i, move to the first element of the cluster i+1.
    Jean-Marc
    Jean-Marc
    LV2009 and LV2013
    Free PDF Report with iTextSharp
    Attachments:
    Array of clusters.jpg ‏132 KB

    Thanks for they answers.
    My problem is the triple TAB (TAB -TAB -TAB) to change the array line  i to i+1.  
    Click on an element in the array and move with the TAB key.  When you  are at the element "VOC":
    - the first TAB (event "<VOC>:Key Down?" ) generate CTRL +UP (return to tabbing among front panel controls -return to CLUSTER at line i);
    - the second TAB (event "<Cluster>:Key Down?" - sequence through the array- move to the array line i to line i+1)
    - the third TAB (event "<Cluster>:Key Down?" )generate CTRL + DOWN ( move the key focus inside the array or cluster -move inside the cluster at the line 1+1);
    I try to reduce the number of TAB.
    Jean-Marc
    "Complete the following steps to
    use the <Tab> key to move through elements within a single array
    or cluster when you run a VI.
    Display the front panel. While the VI is running, press the <Tab> key until the array or cluster is highlighted.
    Press the <Ctrl> key and the down arrow key to move the key focus inside the array or cluster. (Mac OS) Press the <Command> key. (Linux) Press the <Alt> key.
    Press the <Tab> key to sequence through the array or cluster elements and the array indexes.
    To return to tabbing among front panel controls, press the <Ctrl> key and the up arrow key. (Mac OS) Press the <Command> key. (Linux) Press the <Alt> key."
    Jean-Marc
    LV2009 and LV2013
    Free PDF Report with iTextSharp
    Attachments:
    Tab Array Clusters LV8_0.vi ‏94 KB

  • Array of clusters and in the cluster is a bar meter, how can I change the color individually?

    Array of clusters and in the cluster is a bar meter, how can I change the color of the bar meter individually for each element of the array?  I have just figured out that you can't change properties of one element of the array without all elements changing.  For the scaling I had to make numeric indicators for each tick of the scale so that each bar meter in the clustered array would have individual scales.  I also had to do some math to scale each barmeter to display correct proportions from 0 to 100%.  Now I'm stumped on the color of the bar meter.  Basically, if the value goes over a setpoint, the bar meter needs to turn red.  It has to be in an array to be infinitely scalable.
    Thanks
    Matt
    Solved!
    Go to Solution.

    You can't do that-
    without a little trick.
    You could consider laying a custom color box over the bar graph in the cluster you can set the color based on the value of the bar graph or even make a "Pseudo"- bar graph using a series of color boxes stacked to look lie a bar and changing values of the Color boxs from empty to full to red.
    Here is an example to demonstrate
    Jeff
    Attachments:
    Pseudo bar.vi ‏12 KB

  • How to change the tabbing order of an array of clusters?

    How to change the tabbing order of an array of clusters?  I have the cluster arranged in table in the front panel.   The cluster element goes horizontal and array element goes vertically.   When I press the tab key, the cursor goes to the next array element instead of the next cluster item (down instead across).
    Solved!
    Go to Solution.

    Broken Arrow wrote:
    Harold asked a perfectly reasonable and necessary question, but how is that a Solution ???
    I believe it is called the Socratic Method.
    Sea-Story time
    I had the privledge of working for Ron Davis when he managed the Allegheny District of DEC. He was an ex-WO4 (Highest possilbe rank for non-commisioned officer in US Navy, required act of congress to confirm).
    Ron never answered any question I ever saw presented to him. I remember a group of managers in a frenzy over some issue  running to him to to see what he thought. He asked them a series of questions that lead them to the solution and soon they were smiling and slapping each other on the back as they walked away.
    Who is that has a signature that read "it is the questions that guide us"?
    Ben
    Ben Rayner
    I am currently active on.. MainStream Preppers
    Rayner's Ridge is under construction

  • Brick Wall Problem: Array of Clusters, Size of array from reference

    Good Morning Forums,
    I have hit a brick wall with my application and I am hoping somebody can help!
    I have an array of clusters of indeterminate size (the cluster is generic, data contained not relevant.).
    Inputs to the VI are: a reference to the array, and a variant containing the data.
    My problem is I need to determine the array size from these two inputs and I cannot find a way to do it!
    If the array contained a standard data type I can use the class name property to determine data type, and the size of the array returned from "select size" property to determine dimension size.  With this information i can cast the variant into the correct data type and use this to determine the size of the array.  If the data is a cluster the class name simply returns "cluster" so I cannot cast the variant and therefore am unable to determine the size.
    I am not worried about casting the data (once i determine the size this bit is no issue), I just need to determine the size (and preferably number of dimensions) of the array. Can this be done?
    Cheers for any help
    J
    John.P | Certified LabVIEW Architect | NI Alliance Member
    Solved!
    Go to Solution.

    John.P wrote:
    Good Morning Forums,
    I am not worried about casting the data (once i determine the size this bit is no issue), I just need to determine the size (and preferably number of dimensions) of the array. Can this be done?
    Cheers for any help
    J
    There seem to be a couple of potential solutions.:
    #1 if the varient is created within LabVIEW you can wite size(s) to a varient attribute.  This would be pretty straightforward and easy to implement- I imagine you would have thought of that so you may not have access to the code writing cluster to varient and it gets a bit trickier.
    #2 cast the varient to string and return string length-  this should give you a measure of total size and you would need to know the size per element of cluster (just cast one instance of cluster array to varient and then to string with size and size++) but this only returns the total size of the array since nDim arrays are actually stored sequentially. 
    Hope this helped
    Jeff

  • How can I get a ref to a ring in a cluster that are in a array of clusters?

    I have a cluster (typdef'd) with controls. Two of the controls is rings. I place that cluster in a array. I then fill the array of clusters up with data. Can I get the ref to the rings in each cluster? I must load them, individually, with strings[].
    Solved!
    Go to Solution.

    Mike,
    I have here a example....please look at it. It's an array that the user can look into each post (that is loaded from a XML-file).
     I cant get the ref. to the individually ring beacuse I don't know where in the array I am. 
    Attachments:
    example.vi ‏54 KB
    LiggInmatCluster.ctl ‏22 KB

Maybe you are looking for

  • HT4436 how do i add an email to my iCloud account

    How do I add an email address to my iCloud account

  • Functions in Graphical message mapping

    Hi All, I hve a scenario where i have to use various functions in Graphical mapping tool like lastindexof,  format number, etc etc . Can anyone has sample examples explainng the functionality of all the functions in message mapping tool. Atleast a fe

  • SQL Server upgrade with merge replication

    We are planning to upgrade SQL Server 2005 to SQL Server 2012 and both the databases will be hosted on two different servers. SQL Server 2005 has around 25 merge publication and have around 400 laptops that subscribe to these publications. The new SQ

  • Elitebook 8760w - Which batteries are compatible?

    HI all, I have only recently migrated over to HP from Thinkpad and would require bit of guidance from the elitebook experts to kindly help me with these two questions: 1. My battery has gone kaput and I would require replacement. I called up my local

  • How I can change my email?

    Hi, I would like change email on my oracle account. How I can do it? Thanks Z.