2012-01-05 46 views
7

Ho scritto uno script Matlab che legge i dati utilizzando una porta COMM virtuale in in tempo reale. Ho eseguito una quantità significativa di elaborazione del segnale in un file.GUI Matlab che utilizzano GUIDA: desidera aggiornare dinamicamente i grafici

Successivamente, ho sentito la necessità di avere una GUI compatta che visualizza le informazioni come sommario.

Recentemente ho iniziato a scavare e leggere altro strumento GUI integrato di Matlab, GUIDE. Ho seguito alcuni tutorial e sono riuscito a visualizzare i miei grafici sulla GUI dopo aver premuto un pulsante.

Tuttavia, voglio la GUI per l'aggiornamento in tempo reale. Il mio vettore di dati è in costante aggiornamento (lettura dei dati dalla porta COMM). Voglio che la GUI mantenga aggiornando i grafici con i dati più recenti, anziché fare affidamento su un pulsante per un aggiornamento. Qualcuno può indicarmi la giusta direzione per l'aggiornamento in background?

Ecco il codice pertinente attualmente per la 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); 

modificare il codice modificato:

% --- 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); 

L'errore che ottengo è:

??? 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 
+0

Possibile duplicato: http://stackoverflow.com/questions/1007385/getting-matlab-timer-to-update-matlab-guide-gui – Nzbuu

+0

@ c0d3rz Controlla questo collegamento sulla definizione delle richiamate timerfcn http: // www. mathworks.com/help/techdoc/matlab_prog/f9-39541.html#f9-42494 Provare a impostare 'timerfcn' su @GUIUpdate e modificare GUIUpdate in modo che contenga due input 'GUIUpdate (obj, event)'. 'obj' sarà la maniglia dell'oggetto timer e 'evento' avrà alcuni dettagli su come è stato chiamato. Per impostazione predefinita, i callback delle funzioni timer verranno passati almeno a questi due argomenti. Non sono sicuro che sia la causa esatta del tuo errore ma il tuo campione non sembra corretto. Se avrò una possibilità più tardi, cercherò di pubblicare un timer di esempio. –

risposta

10

Ecco un esempio che utilizza un timer con un callback timerFcn. Ho creato una semplice GUI con 1 asse e 1 pulsante.

Nella funzione di apertura, inizializzo il grafico e creo il timer. Nel richiamo del pulsante di avvio avvio il timer e inizio a manipolare i dati. La richiamata della funzione timer aggiorna semplicemente i dati y della linea tramite la sua maniglia. Di seguito sono elencate le funzioni rilevanti di M-file di della GUI (sezione init snipped e FCN uscita.

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); 

Si consiglia un pulsante Stop per fermare il timer a seconda di come la vostra interfaccia grafica è strutturata e sono stati/come i dati è . aggiornato

Edit: gestisce informazioni di base alcune di queste è piuttosto semplice e si può già sapere che:

una maniglia individuo a un oggetto contiene un gruppo di proprietà che si può leggere con la funzione get() o impostato con la funzione set(), quindi ad esempio forse volevo cambiare il testo di startButton per qualche motivo nella mia GUI.

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

Si può semplicemente voler impostare un punto di interruzione nel codice da qualche parte (magari in una pressione di un pulsante) e giocare con la struttura di maniglie. Esecuzione dei comandi get() su vari oggetti per apprendere le loro proprietà.

Ora la struttura delle maniglie contiene tutto ... umm ... gestisce gli oggetti della GUI e tutti gli elementi personalizzati che potrebbero essere utili per il salvataggio. La maggior parte dei callback della GUI viene automaticamente passata alla struct degli handle in modo da poter accedere facilmente a tutte le parti della GUI.

Es. Il callback "startButton" è stato automaticamente superato handles. Così ho avuto facile accesso all'oggetto timer tramite handles.timer.

Il che mi porta ad attaccare le cose personalizzate in handles. Nella funzione di apertura ho aggiunto un nuovo elemento alla struttura delle maniglie handles.timer e handles.plot perché sapevo che sarebbero stati utili in altri callback (come la pressione dei pulsanti e la richiamata timerFcn).

Tuttavia, per memorizzare queste cose in modo permanente è necessario utilizzare la funzione 'guidata'.In pratica, questa funzione memorizza la struttura modificata handles o recupera una copia di handles a seconda di come la si chiama. Quindi la riga seguente nella funzione di apertura sta memorizzando la struttura delle maniglie modificata (aggiunta .timer e .plot) nella GUI principale.

guidata(hObject,handles); 

Fondamentalmente ogni volta che si aggiunge qualcosa in handles si dovrebbe avere quella linea per rendere il cambiamento permanente.

Ora l'altro metodo di chiamarla è:

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

Questo sarà recuperare la struttura maniglie per la GUI.

E l'ultimo handles.output = hObject è l'output predefinito quando si avvia la GUI. Se si chiama la GUI tramite la riga di comando di Matlab come questa , è necessario restituire l'handle alla GUI.

+0

Grazie mille Aero Energy. Penso di dover lavorare come volevo con l'aiuto del codice. I REALMENTE apprezzo l'aiuto. Ho letto l'aiuto del timer sul sito web, ma non ho potuto farlo bene, il tuo frammento di codice ha davvero aiutato. Mi stupisce che tu abbia preso il tempo di scrivere il codice pertinente per aiutarmi. Grazie ancora! – c0d3rz

+0

Potresti per favore cosa fanno queste due righe di codice: handles.output = hObject; guidata (hObject, handle); – c0d3rz

+0

Non sono sicuro di utilizzare questo handle. * Notazione. Ho letto il file della guida di Matlab sull'utilizzo di Handles, ma non aveva molto senso per me. – c0d3rz

1

è necessario utilizzare a timer object. Imposta la callback come funzione che aggiorna i grafici.

+0

C'è un'alternativa? – c0d3rz

+0

Non per quanto ne so. C'è una buona ragione per cui non puoi farlo in questo modo? – Nzbuu

+0

Puoi per favore dare un'occhiata alla mia modifica. Non riesco a utilizzare correttamente la funzione timer. – c0d3rz

1

Dai uno sguardo a Making Graphs Responsive with Data Linking e al comando linkdata.

Se la stessa variabile appare nei grafici in più cifre, è possibile collegare uno qualsiasi dei grafici alla variabile. Puoi utilizzare i grafici collegati nel concerto con Marking Up Graphs con Data Brushing, ma anche sul loro . Il collegamento trame consente di

  • Fai grafici rispondono ai cambiamenti nelle variabili nello spazio di lavoro di base o all'interno di una funzione
  • Fai grafici rispondono quando si cambia variabili nella editor delle variabili e riga di comando
  • modificare le variabili mediante spazzolatura dei dati che colpiscono diverse rappresentazioni grafiche in una volta
  • Creare grafici "finestre di orologi" a scopo di debug

Guarda le finestre sono utili se si programma nel linguaggio MATLAB. Per l'esempio , quando si raffina un algoritmo di elaborazione dati per passare attraverso il codice , è possibile visualizzare i grafici che rispondono ai cambiamenti nelle variabili mentre una funzione esegue le istruzioni.

Ho fatto un test rapido e sporco visto di seguito e non sono sicuro di come funzioni in una GUI rispetto a una funzione, ma potrebbe fare il trucco.

Nota 1: ho dovuto aggiungere un punto di interruzione nella mia subroutine in cui modifica loglobale per visualizzare effettivamente l'aggiornamento automatico della trama. Potresti aver bisogno di una combinazione di drawnow, pause o timer se i dati vengono modificati rapidamente.

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: ci possono essere modi per aggirare l'uso di variabili globali a seconda di come le funzioni sono strutturati ... ma io non ho il tempo di scavare in esso per molto.

+0

Grazie Aero, tuttavia non sono stato chiaro nella mia domanda. Oltre a cambiare i grafici, ho anche alcune caselle di testo statico, che voglio anche aggiornare. Sembra che Timer sia la strada da percorrere ... – c0d3rz

+0

@ c0d3rz Vedi la mia altra risposta per chiedere aiuto per far funzionare il timer. –

0

È possibile aggiungere una richiamata sull'oggetto seriale che esegue una funzione di stampa. È necessario associare la richiamata all'evento 'BytesAvailableFcn' sull'oggetto (vedere this per ulteriori dettagli sulle proprietà dell'oggetto com).

In sostanza, quando sono disponibili byte sulla porta COM, si istruisce MATLAB ad eseguire una funzione specifica. Nel tuo caso, sarà la funzione che aggiorna la GUI. Se è necessario elaborare prima i dati in entrata, allora la funzione di callback eseguirà prima l'elaborazione del segnale e quindi eseguirà i comandi di tracciamento.

+0

Grazie Jorge, tuttavia non sono stato chiaro nella mia domanda. Oltre a cambiare i grafici, ho anche alcune caselle di testo statico, che voglio anche aggiornare. Sembra che Timer sia la strada da percorrere ... – c0d3rz

+0

Puoi anche aggiornare le caselle usando get/set. Il fatto è che io non conosco la logica del tuo codice. – Jorge

Problemi correlati