MATLAB GUI с помощью руководства: хотите динамически обновлять графики

Я написал сценарий Matlab, который считывает данные с помощью виртуального COMM-порта в в режиме реального времени. Я сделал значительное количество обработки сигналов в mfile.

затем я почувствовал необходимость иметь компактный графический интерфейс, который отображает информацию в виде резюме.

Я только недавно начал копать и читать больше встроенного инструмента GUI Matlab, руководство. Я следил за несколькими учебниками и успешно могу получить мои графики для отображения на моем GUI после -нажмите кнопку.

однако, я хочу GUI для обновления в режиме реального времени. Мой вектор данных постоянно обновляется (чтение данных из порта связи). Я хочу, чтобы GUI, чтобы сохранить обновление графики С более новыми данными, в отличие от полагаться на прессе кнопки для обновления. Может кто-нибудь, пожалуйста, укажите мне в правильном направлении для обновления фона?

вот соответствующий код в настоящее время для GUI:

% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global data
global time

% Time domain plot
axes(handles.timeDomainPlot);
cla;
plot (time, data);

изменить изменить код:

% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

%Setting it to display something when it ends
% t = timer('TimerFcn', 'timerOn=false; disp(''Updating GUI!'')',... 
t = timer(... 
            'TasksToExecute', 10, ... % Number of times to run the timer object
            'Period', 3, ...                
            'TimerFcn', GUIUpdate()); 

%Starting the timer
start(t)

function GUIUpdate()
global data
global time
%Parameters below axes
    global min
    global max 
      % Time domain plot
    axes(handles.timeDomainPlot);
    cla;
    plot (time, data);
    %Other parameters:
    set(handles.mean, 'String', mean);
    set(handles.max, 'String', max);

ошибка, которую я получаю:

??? Error using ==> GUI_Learning>GUIUpdate
Too many output arguments.

Error in ==>
@(hObject,eventdata)GUI_Learning('pushbutton1_Callback',hObject,eventdata,guidata(hObject))


??? Error while evaluating uicontrol Callback

4 ответов


вот пример использования таймера с обратным вызовом timerFcn. Я сделал простой графический интерфейс с 1 осями и 1 кнопкой.

в функции открытия я инициализирую график и создаю таймер. В кнопке "Пуск" обратного вызова я запускаю таймер и начинаю манипулировать данными. Функция таймера callback просто обновляет y-данные линии через ее дескриптор. Ниже приведены соответствующие функции из M-файла GUI (обрезанный раздел init и выходной fcn.

function testTimer_OpeningFcn(hObject, eventdata, handles, varargin)
global y x
x = 0:.1:3*pi; % Make up some data and plot
y = sin(x);
handles.plot = plot(handles.axes1,x,y);
handles.timer = timer('ExecutionMode','fixedRate',...
                    'Period', 0.5,...
                    'TimerFcn', {@GUIUpdate,handles});
handles.output = hObject;
guidata(hObject, handles);

% --- Executes on button press in startButton.
function startButton_Callback(hObject, eventdata, handles)
global y x
start(handles.timer)
for i =1:30
   y = sin(x+i/10); 
   pause(1) 
end

function GUIUpdate(obj,event,handles)
global y 
set(handles.plot,'ydata',y);

вы может потребоваться кнопка остановки, чтобы остановить таймер в зависимости от того, как ваш GUI структурирован и был/как данные обновляются.

Edit: Basic handles info некоторые из них довольно просты, и вы, возможно, уже знаете это:

отдельный дескриптор объекта содержит кучу свойств, которые можно прочитать с помощью функции get() или задать с помощью функции set (). Так, например, может быть, я хотел изменить текст startButton по какой-то причине в моем GUI.

set(handles.startButton,'String','Something Other Than Start');

вы можете просто установить точку останова в своем коде где-нибудь (возможно, при нажатии кнопки) и поиграть со структурой ручек. Бег!--4--> команды на различные предметы, чтобы узнать их свойства.

теперь структура handles содержит все ... МММ... обрабатывает объекты вашего GUI, а также любые пользовательские элементы, которые могут быть удобны для вашего хранения там. Большинство обратных вызовов GUI автоматически передаются структуре дескрипторов, поэтому у вас есть легко доступ ко всем частям GUI.

Ex. Обратный вызов "startButton" был автоматически передан handles. Таким образом, у меня был легкий доступ к объекту timer через handles.timer.

что приводит меня к вставке пользовательских вещей в handles. В открывающей функции я добавил новый элемент в структуру handles handles.timer и handles.plot потому что я знал, что они будут полезны в других обратных вызовах (например, нажатие кнопки и обратный вызов timerFcn).

однако, хранить эти вещи постоянно вам нужно использовать функцию "guidata". Эта функция в основном либо хранит измененный handles struct или получения копии handles в зависимости от того, как вы его называете. Таким образом, следующая строка в функции открытия сохраняет измененную структуру ручек (добавлено .таймер и. сюжет) в основной графический интерфейс.

guidata(hObject,handles);

в основном в любое время вы добавляете что-то в handles у вас должна быть эта строка, чтобы сделать изменение постоянным.

теперь другой метод называя его:

handles = guidata(hObject); %hObject can be any handle who is a child of the main GUI.

это извлечет структуру дескрипторов для GUI.

и последний handles.output = hObject - это только вывод по умолчанию при запуске GUI. Если вы вызываете свой GUI через командную строку Matlab, как это h = myGUI; он должен вернуть дескриптор в ваш GUI.


вам нужно использовать таймер объект. Задайте функцию обратного вызова, которая обновляет графики.


посмотри создание графиков, реагирующих на привязку данных и linkdata.

Если одна и та же переменная появляется на графиках на нескольких рисунках, вы можете свяжите любой из графиков с переменной. Связанные участки можно использовать в концерт с разметкой графиков с чисткой данных, но и на их собственный. Связывание сюжетов позволяет

  • сделать графики реагировать на изменения переменных в базовой рабочей области или в пределах функции
  • сделать графики отвечают при изменении переменных в Редакторе переменных и командной строке
  • изменение переменных через чистку данных, которые влияют на различные графические представления их сразу
  • создать графический "watch windows"для отладки

окна просмотра полезны, если вы программируете на языке MATLAB. Для пример при уточнении алгоритма обработки данных для пошагового выполнения ваш код, вы можете видеть, как графики реагируют на изменения переменных как функция выполняет операторы.

Я сделал быстрый и грязный тест, показанный ниже, и я не уверен, как это будет работать в GUI стихах функции, но может сделать трюк.

Примечание 1: мне пришлось добавить точку останова в моей подпрограмме, где она изменяет глобальный y чтобы увидеть автоматическое обновление графика. При изменении данных может потребоваться комбинация drawnow, pause или timer быстро.

function testLinking()
global x y
%Links failed if the global did not also exist in the base workspace
evalin('base','global x y');
x = 0:.1:3*pi; % Make up some data and plot
y = sin(x);

h = plot(x,y,'ydatasource','y','xdatasource','x');
linkdata on
testSub

function testSub()
%Test to see if a sub can make a linked global refresh
global x y
for i = 1:10
    %This should automatically update the plot.
    y = sin(x+i/10); 
end

Edit: могут быть способы обойти использование глобалов в зависимости от того, как структурированы ваши функции ... но у меня нет времени копаться в этом.


можно добавить обратный вызов последовательного объекта, выполняющего функцию построения графика. Необходимо присоединить обратный вызов к событию' BytesAvailableFcn ' на объекте (см. этой для получения более подробной информации о свойствах объекта com).

по сути, когда на com-порту доступны байты, вы инструктируете matlab запускать определенную функцию. В вашем случае это будет функция обновления GUI. Если вам нужно сначала обработать входящие данные, то ваш обратный вызов функция сначала выполнит обработку сигнала, а затем выполнит команды построения графика.