Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost refresh rate of App Designer UI elements

I am currently trying to display data that I receive via serial port in a Matlab app designer application. I am suffering from abysmal refresh rate of the linear gauges (~1 Hz).

The gauges' values are updated by a fixed-rate timer which is set to 30Hz. A timestamp print in the timer callback shows me that it is called with the correct frequency. My computer is quite beefy and the Task Manager doesn't show any hints of high load - in fact, the MATLAB app consumes almost no CPU time at all. It's actually not just the gauges but all UI elements.

So my guess - or better: my hope - is that there must be some hard cap on the refresh rate. The official documentation doesn't give any hints about how to change this, though.

My MATLAB version is R2016b.

So my question(s):

  • Is this fixed with R2017a?

  • If not: can I do something about it, i.e. fiddling with MATLAB builtin files?

Here's a MCV example demonstrating the issue:

classdef testapp < matlab.apps.AppBase

% Properties that correspond to app components
properties (Access = public)
    UIFigure                  matlab.ui.Figure
    andwatchhowthisstartstospinsmoothlyGaugeLabel  matlab.ui.control.Label
    andwatchhowthisstartstospinsmoothlyGauge  matlab.ui.control.SemicircularGauge
    KeepturninghereKnobLabel  matlab.ui.control.Label
    KeepturninghereKnob       matlab.ui.control.Knob
end


properties (Access = private)
    tim_the_timer
    i = 0;
end

methods (Access = private)
    function app = refreshMeter(app, ~,~)
        % display timestamp
        datestr(now,'HH:MM:SS.FFF')

        % update the gauge
        app.andwatchhowthisstartstospinsmoothlyGauge.Value = app.i;
        app.i = app.i + 1;
        if app.i > 100
           app.i = 0;
        end
    end
end


methods (Access = private)

    % Code that executes after component creation
    function startupFcn(app)
       t = timer;
       t.TimerFcn = @app.refreshMeter;
       t.Period = 0.02;
       t.BusyMode = 'drop';
       t.ExecutionMode = 'fixedRate';
       start(t);
       app.tim_the_timer = t;
    end

    % Close request function: UIFigure
    function UIFigureCloseRequest(app, event)
        stop(app.tim_the_timer);
        delete(app.tim_the_timer);
        delete(app);
    end
end

% App initialization and construction
methods (Access = private)

    % Create UIFigure and components
    function createComponents(app)

        % Create UIFigure
        app.UIFigure = uifigure;
        app.UIFigure.Position = [100 100 640 480];
        app.UIFigure.Name = 'UI Figure';
        app.UIFigure.CloseRequestFcn = createCallbackFcn(app, @UIFigureCloseRequest, true);
        setAutoResize(app, app.UIFigure, true)

        % Create andwatchhowthisstartstospinsmoothlyGaugeLabel
        app.andwatchhowthisstartstospinsmoothlyGaugeLabel = uilabel(app.UIFigure);
        app.andwatchhowthisstartstospinsmoothlyGaugeLabel.HorizontalAlignment = 'center';
        app.andwatchhowthisstartstospinsmoothlyGaugeLabel.Position = [275 138 246 15];
        app.andwatchhowthisstartstospinsmoothlyGaugeLabel.Text = '... and watch how this starts to spin smoothly';

        % Create andwatchhowthisstartstospinsmoothlyGauge
        app.andwatchhowthisstartstospinsmoothlyGauge = uigauge(app.UIFigure, 'semicircular');
        app.andwatchhowthisstartstospinsmoothlyGauge.Position = [338 168 120 65];

        % Create KeepturninghereKnobLabel
        app.KeepturninghereKnobLabel = uilabel(app.UIFigure);
        app.KeepturninghereKnobLabel.HorizontalAlignment = 'center';
        app.KeepturninghereKnobLabel.Position = [119 265 112 15];
        app.KeepturninghereKnobLabel.Text = 'Keep turning here...';

        % Create KeepturninghereKnob
        app.KeepturninghereKnob = uiknob(app.UIFigure, 'continuous');
        app.KeepturninghereKnob.Position = [145 314 60 60];
    end
end

methods (Access = public)

    % Construct app
    function app = testapp()

        % Create and configure components
        createComponents(app)

        % Register the app with App Designer
        registerApp(app, app.UIFigure)

        % Execute the startup function
        runStartupFcn(app, @startupFcn)

        if nargout == 0
            clear app
        end
    end

    % Code that executes before app deletion
    function delete(app)

        % Delete UIFigure when app is deleted
        delete(app.UIFigure)
    end
end
end

Edit: I noticed that the gauge gets immediately updated when I turn a knob, slider, etc. So somehow the capability of a higher refresh rate is definitely there... but how to enable it without having to touch controls? Updated MCV accordingly.

like image 281
UnbescholtenerBuerger Avatar asked Jul 06 '17 23:07

UnbescholtenerBuerger


2 Answers

You should be able to force a refresh by calling the drawnow function in the refreshMeter callback.

like image 81
MrAzzaman Avatar answered Sep 23 '22 15:09

MrAzzaman


I would suggest the following things to help with your problem:

  1. follow this very useful link which provides mathworks solution for low-level graphics issues. It may have to do with your graphics card.

  2. following @MrAzzamans suggestion, drawnow and refreshdata could help solve your problem (keep in mind they have different summoning options).

  3. If you're using GUIDE, try changing to App Designer and see if it solves your problem.

Iv'e encountered similar problems when building a "video-player" in GUIDE, the first suggestion fixed it for me.

like image 45
yotabyte Avatar answered Sep 22 '22 15:09

yotabyte