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.

How to control GUIComposer graph sampling

Other Parts Discussed in Thread: CCSTUDIO

Hi,

I am starting to use GUIComposer, and I have to say that I am quite impressed with it, good job!

So, now I am starting to add some graphs to show some variable traces, and I notice that the whole UI gets much slower than before. I guess this is because the amount of data to read from the DSP now is much higher.

The thing is that I dont need this graph to be continuously updated, and I like to have a more responsive UI. So I would like to take a snapshot of the data on demand, so that I keep the speed of the UI fast. Is this possible?

I have seen some examples like here, but it is only keeping the data in a variable, and passing it to the widget when a certain condition is met, but I believe that the buffer data is still being transferred all the time, slowing things down. What I would need is actually controlling the reading of the big buffers, so that they are only read when I want to take a snapshot.

Best regards,

Pedro

  • Hi Pedro,

    Before I suggest some of the methods to make the UI responsive, I have some questions.

    • What is the purpose of the graph, is it for visualization or comparing data?
    • Do you need to have the entire buffers to be visible on the screen? The screen has a fix resolution, so you might not need to have all the data.
    • How often is the target buffer changed? The polling rate from the IDE to target is 1 second (configurable), so you might get into partial buffer read issue.
    • If you use a GUI var and not bind it a widget, are you seeing any performance issue?

    Regards,
    Patrick

  • Hi Patrick,

    The purpose of the graph is to visualize the signals of a control system. They are quite heavy, I am currently showing three float arrays with 4096 elements each.

    It is nice to see the entire buffer, I know that the screen has limited resolution, but I can view one whole cycle, and if there is an are with a problem in it, I can zoom in and see the detail about the problem.

    The target buffer is changed very seldomly, I mean the actual data changes every 50Hz, but I only need to take an acquisition on demand, not continuously.

    As to the partial buffer read, I ran into that, and now I have solved it by using a similar mechanism to what is said here. So now I can see the whole buffer in the graph without interruptions, but I think that the big buffers are still monitored for changes, so the UI gets very slow, I would like to make it so the buffers are ignored except when an acquisition is needed.

    About the GUI var, that's what I'm doing right now. I have a control variable that determines if a new acquisition should be done (for the DSP) or should be grephed (for the GUI), if the GUI sees that there is a new graph available, he stores the three buffers in GUI Vars (which were bound to the buffers in the DSP) and passes the data to the graph. I think that what I would like to do is to break the binding between the GUI Var and the buffers at run time, and enable the binding only when it is needed to do an acquisition.

    Best regards,

    Pedro

  • Hi Pedro,

    There isn't a way to unbind the target variable at runtime. However you can try to play around with these two options

    • Set the host to target polling rate see http://processors.wiki.ti.com/index.php/GUI_Composer/Debugger_Refresh_Rate
    • You can also try to use these undocumented binding properties to drop the sample and to force an update. Within your widget's option, add these two properties:

      {
          "propertyName": "series1",
          "serverBindName": "value:pm.active.myVar",
          "widgetId": "myGraphId",
          "options": {
              "dataType": "Array",
              "dropUpdate": "1000",
              "forceUpdate": "3000"
          }
      }

    Hope these can help to make your UI more responsive.

    Regards,
    Patrick

  • Thanks Patrick,

    What do these parameters mean? I can imagine that the dropUpdate parameter would set it to 1000ms. But I cant imagine what is the 3000 in forceUpdate.

    Also, when a widget is bound to a variable, is the value of that variable read continuously, or does the dsp detect a change and only then send an update?.

    Thanks and best regards,

    Pedro

  • Hi Pedro,

    dropUpdate - This is use by the browser to drop gui update for the widget when the data respond time exceeded the specified time
    forceUpdate - this is a safety catch, the widget is forced to update regardless of the dropUpdate condition


    Here is an example that you can use without binding the graph to a target variable, it requires some JavaScript coding and shouldn't be too difficult to do. It requires some adjustment to our GUI Composer library which we haven't fully exposed this feature yet.

    GUI Composer Library:
    Edit this file, eclipse\plugins\davinci.gc_1_5_1.0.0.201404071800\WebContent\gc\backplane\guiComposer.js, line 1520 (DSS function). Replace the DSS function with this snippet. The differences are highlighted in green.

    DSS : function ( functionName) {
        var callbackFunc = null;

        var onCompleted = function ( result, requstId) {
            if( result && result.status && result.status.type === "ERROR" ) {
                $TI.helper.showError('DSS script error', result.status.message);

            } else if (result && callbackFunc) {
                callbackFunc(result.result);
            }
        };
        var args = Array.prototype.slice.call(arguments);
        args.shift();

        if (args.length > 1 && (typeof args[args.length-1] === "function")) {
            callbackFunc = args.pop();
        }

        var appPath = $TI.helper.getPathName();
        var params = {
            appPath : appPath,
            func : functionName,
            params : args
        };
        $TI.guiComposerServer.executeAsynchOperation('pm.$execute', params, onCompleted, 0);
    },

    DSS Script:
    Now that the library is modified, create a dsScript.js file in your GUI app (http://processors.wiki.ti.com/index.php/GUI_Composer/DSS_Scripts), and add the following snippet.

    importPackage(Packages.com.ti.ccstudio.scripting.environment)
    var session = null;
    var address = 0;

    function readArray(i) {
        if (session == null) {
            var debugServer = ScriptingEnvironment.instance().getServer('DebugServer.1');
            session = debugServer.openSession($active_context_name);
            address = session.expression.evaluate("array[" + i + "]");
        }
        return session.memory.readWord(0, address, 100);
    }

     

    app.js
    Add the following function to app.js.

    function doUpdate() {
        TI.DSS("readArray", 0, function(result) { // 0 is passed to the readArray function in the DSS script
            var graph = dijit.byId("graphWidget");
            graph.set("series0", result);
        });
    }

     

    GUI App:
    Now that all the plumbing is done, you can add a button to your app and line graph to your app. give the graph widget the id 'graphWidget'. For the button, select the Events tab on the right and click on the onclick event and enter 'doUpdate'. This will call the function in the doUpdate in the app.js file. The doUpdate will call the DSS function, readArray. When the result returns from the readArray, the doUpdate will update the widget.

    I hope this help you to update the graph on demand. Note that my target array is defined as int array[4][100].

    Regards,
    Patrick

  • OK, that sounds very, very useful. I will not be able to try it out next week, but I will get back to this on the following and give it a try.

    Thanks again,
    Pedro