This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

GUI Composer cannot display the value of a variable inside a global structure???

Other Parts Discussed in Thread: CONTROLSUITE

Hi all,

I have successfully implemented the Sine Analyzer using Float Solar Lib. My target is to display the information, say e.g. signal frequency, to my GUI using GUI composer.

 

Inside the solar Float Library there is a structure SineAnalyzer_diff, I define an array of global structures as

SineAnalyzer_diff C28_SineAna[8];

 

I used GUI composer to display the value C28_SineAna[0].SigFreq on the screen using gc.dijit.TextBox. It fails to display that value.

 

After that, I created an global variable  

float32 g_test1;

I pass the value of the C28_SineAna[0].SigFreq regularly in a timer triggered task by

g_test1 = C28_SineAna[0].SigFreq;

 

The value of g_test1 can be display on the GUI successfully.

 

So am I do something wrong to handle the global structures SineAnalyzer_diff?

Thanks and regards,

Barry

  • What is the type of this variable? 

    C28_SineAna[0].SigFreq


    I'm guessing it has to do with data conversion. I'll forward this to the GUI C team.


  • Dear Chris,

    Thanks for your prompt reply. SigFreq is float type.


    Sorry that I forgot to mention that C28_SineAna is a structure of SineAnalyzer_diff which can be found from 

    C:\ti\controlSUITE\libs\app_libs\solar\v1.1\float\SineAnalyzer_diff.h

    BR,

    Barry

    typedef struct { float Vin; // Input: Sine Signal
    float SampleFreq; // Input: Signal Sampling Freq
    float Threshold; // Input: Voltage level corresponding to zero i/p
    float Vrms; // Output: RMS Value
    float Vavg; // Output: Average Value
    float SigFreq; // Output: Signal Freq
    float ZCD; // Output: Zero Cross detected
    // internal variables
    float Vacc_avg ;
    float Vacc_rms ;
    float curr_sample_norm; // normalized value of current sample
    Uint16 prev_sign ;
    Uint16 curr_sign ;
    float nsamples ; // samples in half cycle input waveform
    float inv_nsamples;
    float inv_sqrt_nsamples;
    } SineAnalyzer_diff;

  • GUI Composer does not support binding widgets to arrays of structs yet. 

    It will be added in future releases. 

    Currently the workaround suggested by the customer should work - assign the field to a global variable and bind the widget to that variable.

  • Dobrin,

    I'm binding variables in a structure today, ex:

    drv.adcBias.V.value[0]

    with pre-processing function Divide_by_Q24_eight_precision

    perhaps I have an unreleaed version that supports these features?

  • Dear Chris,

    I guess it supports array of variable but not array of structure.

    Did you try something like that?

    create an array of "drv"

    drv[0].adcBias.V.value[0]


    BR,

    Barry

  • Dear Dobrin,

    Thanks for your information. Pls forgive me to ask this simple question: could you describe what mean by "assign the field to a global variable"?

    is it something like (float) C28_SineAna[0].SigFreq ? I tried but it doesn't work. 

    can you estimate the date when the new GUI composer version release that support this feature?

    BR,

    Barry

  • ah, I see. Yes, that won't work.

    will creating a variable and putting your results in an array of that variable work for you?

    here is what we did for the InstaSPIN-FOC and InstaSPIN-MOTION GUIs, which have quite a few values that we plot in various graphs.  We created a variable for the array value and used that to store the values into specific variable arrays each time through (this was placed at the end of the main interrupt).

      Gui.gRecordBuffersIsrCnt++;

      if(Gui.gRecordBuffersIsrCnt >= 1000)
        {
          Gui.gRecordBuffersIsrCnt = 0;
          if(Gui.gRecordBuffers)
            {
              if(Gui.gRecordBuffersIndex < DATA_BUFFER_SIZE)
                {
                  Gui.Angle_kdeg_Buffer[Gui.gRecordBuffersIndex] = Gui.gAccAngle_kdeg;
                  if(Gui.gUseSpinTAC == TRUE)
                    {
                      Gui.SpeedRef_krpm_Buffer[Gui.gRecordBuffersIndex] = _IQmpy(STVELMOVE_getVelocityReference(st_obj.velMoveHandle), Speed_krpm_sf);
                    }
                  else
                    {
                      Gui.SpeedRef_krpm_Buffer[Gui.gRecordBuffersIndex] = _IQmpy(CTRL_getSpd_int_ref_pu(ctrlHandle), Speed_krpm_sf);
                    }
                  //Gui.SpeedEst_krpm_Buffer[Gui.gRecordBuffersIndex] = _IQmpy(CTRL_getSpd_out_pu(ctrlHandle), Speed_krpm_sf);
         Gui.SpeedEst_krpm_Buffer[Gui.gRecordBuffersIndex] = EST_getSpeed_krpm(obj->estHandle);
                  CTRL_getIdq_in_pu(ctrlHandle,(MATH_vec2 *)&Gui.gIdq);
                  Gui.Id_A_Buffer[Gui.gRecordBuffersIndex] = _IQmpy(Gui.gIdq.value[0],Current_A_sf);
                  Gui.Iq_A_Buffer[Gui.gRecordBuffersIndex] = _IQmpy(Gui.gIdq.value[1],Current_A_sf);
                  Gui.IdRef_A_Buffer[Gui.gRecordBuffersIndex] = _IQmpy(CTRL_getId_ref_pu(ctrlHandle),Current_A_sf);
                  if(Gui.gUseSpinTAC == TRUE)
                    {
                      Gui.IqRef_A_Buffer[Gui.gRecordBuffersIndex] = _IQmpy(CTRL_getIq_ref_pu(ctrlHandle),Current_A_sf);
                    }
                  else
                    {
                      Gui.IqRef_A_Buffer[Gui.gRecordBuffersIndex] = _IQmpy(CTRL_getSpd_out_pu(ctrlHandle),Current_A_sf);
                    }
                  CTRL_getVdq_out_pu(ctrlHandle,(MATH_vec2 *)&Gui.gVdq);
                  Gui.VdRef_pu_Buffer[Gui.gRecordBuffersIndex] = Gui.gVdq.value[0];
                  Gui.VqRef_pu_Buffer[Gui.gRecordBuffersIndex] = Gui.gVdq.value[1];
                  Gui.Torque_Nm_Buffer[Gui.gRecordBuffersIndex] = Gui.gTorque_Nm_iq;

                  if(Gui.WasherPlotSelection == 0)
                    {
                   Gui.WasherPlotBuffer1[Gui.gRecordBuffersIndex] = Gui.Iq_A_Buffer[Gui.gRecordBuffersIndex];
                   Gui.WasherPlotBuffer2[Gui.gRecordBuffersIndex] = Gui.IqRef_A_Buffer[Gui.gRecordBuffersIndex];
                    }
                  else if(Gui.WasherPlotSelection == 1)
                    {
                   Gui.WasherPlotBuffer1[Gui.gRecordBuffersIndex] = Gui.SpeedEst_krpm_Buffer[Gui.gRecordBuffersIndex];
                   Gui.WasherPlotBuffer2[Gui.gRecordBuffersIndex] = Gui.SpeedRef_krpm_Buffer[Gui.gRecordBuffersIndex];
                    }
                  else if(Gui.WasherPlotSelection == 2)
                    {
                   Gui.WasherPlotBuffer1[Gui.gRecordBuffersIndex] = Gui.Torque_Nm_Buffer[Gui.gRecordBuffersIndex];
                   Gui.WasherPlotBuffer2[Gui.gRecordBuffersIndex] = _IQ(0.0);
                    }
                  else if(Gui.WasherPlotSelection == 3)
                    {
                   Gui.WasherPlotBuffer1[Gui.gRecordBuffersIndex] = Gui.VdRef_pu_Buffer[Gui.gRecordBuffersIndex];
                   Gui.WasherPlotBuffer2[Gui.gRecordBuffersIndex] = Gui.VqRef_pu_Buffer[Gui.gRecordBuffersIndex];
                    }
                  else if(Gui.WasherPlotSelection == 4)
                    {
                   Gui.WasherPlotBuffer1[Gui.gRecordBuffersIndex] = Gui.Id_A_Buffer[Gui.gRecordBuffersIndex];
                   Gui.WasherPlotBuffer2[Gui.gRecordBuffersIndex] = Gui.Iq_A_Buffer[Gui.gRecordBuffersIndex];
                    }
                  else
                    {
                   Gui.WasherPlotBuffer1[Gui.gRecordBuffersIndex] = _IQ(0.0);
                   Gui.WasherPlotBuffer2[Gui.gRecordBuffersIndex] = _IQ(0.0);
                    }

                  Gui.gRecordBuffersIndex++;
                }
              else
                {
                  Gui.gRecordBuffers = TRUE;
                  Gui.gRecordBuffersIndex = 0;
                }
            }
          else
            {
              Gui.gRecordBuffersIndex = 0;
            }
        }

  • Hello Barry, 

    With my comment “Currently the workaround suggested by the customer should work - assign the field to a global variable and bind the widget to that variable.”

    I was confirming that the workaround you did with:

    “After that, I created an global variable  

    float32 g_test1;

    I pass the value of the C28_SineAna[0].SigFreq regularly in a timer triggered task by

    g_test1 = C28_SineAna[0].SigFreq;

     The value of g_test1 can be display on the GUI successfully.

    is the way to get around the current limitation of GUI composer.

     

    I am planning the support for bindings to arrays of structs to be available in the final Code Composer v6.

    Regards

    Dobrin

  • Thank  Dobrin :) 

  • Hi Dobrin,

    I have installed the latest CCS 6.0.1 and GUI Composer 6.0.

    What's new in GUI Composer v6.0 says that there is "Improved expression evaluation for binding variables. e.g. support for structs and arrays. "  So, I looked specifically at the wiki page for GUI Composer / Bind Expressions. But it wasn't clear from this page whether the planned support that you mention above for bindings to arrays of structs has been implemented in this latest version of GUI Composer.

    Can you please clarify if this is now supported, or when we can expect an improved JSON binding expression parser for this?

    Regards,

    Gordon Finlay

  • Hello Gordon, 

    Everything described in http://processors.wiki.ti.com/index.php/GUI_Composer/Bind_Expressions is available in GUI Composer the comes with Code Composer Studio 6.0 or up. Let me know if something is not working the way you expect it to. 

    Regards

    Dobrin

  • Hi Dobrin,

    The problem I have is that the Bind_Expressions wiki page says nothing about support for arrays of structs.

    I have a struct typedef as follows:

    typedef struct zXcvrConfig
    {
        float Freq;
        uint16_t Period;
        float DutyCycle;
    } tzXcvrConfig; // I define an array of tzXcvrConfig structures... tzXcvrConfig zTransceiverCfg[NUM_SCAN_ITER]; // I have code that updates a PWM device using a field of one structure element of from the array of structs retCode = PWMMGR_setDuty(myPwm1, tzTransceiverCfg[0].DutyCycle); // I would like to bind a widget on a GUI Composer form to this field: // tzTransceiverCfg[0].DutyCycle

    GUI Composer v5 had problems with binding to an array element which was a structure.

    The updated Bind_Expressions wiki page still says nothing regarding your comments to Barry earlier in this thread.
    You said:
                  " I am planning the support for bindings to arrays of structs to be available in the final Code Composer v6."

    Can you please clarify if this was done for v6?

    Regards,
    Gordon

  • Hi Gordon, 

    Yes, GUI Composer v6 supports arrays of structs, as promised earlier. 

    I tested your source code posted above and it works. I had to adjust a small typo - you declared the variable with missing t at the front: zTransceiverCfg instead of tzTransceiverCfg. 

    Would you be able to try CCS v6 too and let me know if you still have issues? 

    Regards

    Dobrin