I built a GUI using the GUIDE feature in Matlab. I have many push buttons. I start by clicking one push button to start tic. Then when I click any of the other push buttons, I want to build a vector of toc time stamps. How do I do this?
The most robust solution is to store and manipulate the vector in the GUI's handles structure. First, in your "create function", initialize the start and stop vectors:
function yourGui_CreateFcn ( hObject , eventdata , handles )
% Initialize the start and stop vectors.
handles.timeStart = [];
handles.timeStop = [];
% Update the GUI handles structure.
guidata ( hObject , handles );
end
Then, in your first button, start the timer and store it to your handles vector.
function button1_Callback ( hObject , eventdata , handles )
% Start the timer, updating the value in the handles structure.
handles.timeStart = tic;
% Update the GUI data so that timer is available to other functions.
guidata ( hObject , handles );
end
Next, in each of your other button callbacks, retrieve the starting time from the handles structure and determine the elapsed time:
function button2_Callback ( hObject , eventdata , handles )
% Retrieve the start time.
timeStart = handles.timeStart;
% Determine the elapsed time.
timeElapsed = toc ( timeStart );
% Store the new value in the handles structure.
handles.timeStop(end+1,1) = timeElapsed;
% Update the guidata.
guidata ( hObject , handles );
end
Finally, you can output the values from the GUI using the "output function".
function yourGui_OutputFcn ( hObject , eventdata , handles )
% Specify the output variables.
varargout { 1 } = handles . timeStart;
varargout { 2 } = handles . timeStop;
end
You would then execute your gui using the following statement in the command line:
>> [timeStart,timeStop] = yourGui ( );
Related
I want to ask how I make the following code functioning for side-by-side simulation of Simulink files, which are saved in 'PATH', by using for-loop in MATLAB GUI or if you know an alternative way to do it. After I started to run the code, nothing happened although no error message has come. Also I hope that some of you get solutions of my problem.
Thank you very much in advance!
function nightly_simulation_Callback(hObject, eventdata, handles)
% hObject handle to nightly_simulation (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
PATH = 'C:\Users\xxx\Documents\Saved_Models';
files=dir([PATH,'*.slx']);
fileNames={files.name};
fileNames=sort(fileNames);
nFiles=numel(fileNames);
selection = questdlg('Sure to start?',...
'Confirmation',...
'Yes','No','Yes');
switch selection
case 'Yes'
for i=1:nFiles
x = [PATH,fileNames{i}];
open_system(x);
sim(x);
end
case 'No'
return
end
Replace
x = [PATH,fileNames{i}];
with
x = fullfile(PATH, fileNames{i});
since otherwise a '\' is missing in the filename.
I changed my code like this:
function nightly_simulation_Callback(hObject, eventdata, handles)
% hObject handle to nightly_simulation (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
PATH = 'C:\Users\xxx\Documents\Saved_Models';
files = dir( fullfile(PATH,'*.slx') ); %# list all *.slx files
fileNames = {files.name}';
fileNames=sort(fileNames);
nFiles=numel(fileNames);
selection = questdlg('Sure to start?',...
'Confirmation',...
'Yes','No','Yes');
switch selection
case 'Yes'
for i=1:nFiles
x = fullfile(PATH, fileNames{i});
open_system(x);
sim(x);
end
case 'No'
return
end
Also it worked. Thanks for your advice!
I have program where at the end a GUI is launched. I built it using guide. I load 4 variables from my program into 4 GUI text boxes using a mat file called n.mat (and a pushbutton feature).
In the program
n = [nuno, ndue, ntre, nquattro];
save n.mat
In the GUI interface pushbutton
% --- Executes on button press in upload.
function upload_Callback(hObject, eventdata, handles)
% hObject handle to upload (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
S = load('n.mat');
handles.v1 = S.nuno;
handles.v2 = S.ndue;
handles.v3 = S.ntre;
handles.v4 = S.nquattro;
set(handles.initial1,'String',num2str(handles.v1));
set(handles.initial2,'String',num2str(handles.v2));
set(handles.initial3,'String',num2str(handles.v3));
set(handles.initial4,'String',num2str(handles.v4));
guidata(hObject, handles);
Then I have other 4 text boxes where I change the value of the variables and save them in another mat file. I'm not sure if I'm doing this correctly.
In the program (before calling myGUI) I initialize the m vector for the updated variables.
nunof = 0;
nduef = 0;
ntref = 0;
nquattrof = 0;
m = [nunof, nduef, ntref, nquattrof];
save m.mat
In the program (after calling myGUI) I try and load the m.mat file and extract the variables from it so I can use them in some calculations further in the program.
load m.mat;
nunof = m.nunof;
nduef = m.nduef;
ntref = m.ntref;
nquattrof = m.nquattrof;
Before this, in the GUI interface 'done' button I try and save my inputs into the m.mat file like this:
function done_Callback(hObject, eventdata, handles)
% hObject handle to done (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% save the parameters to file
load('m.mat');
m = [nunof, nduef, ntref, nquattrof];
nunof = str2num(get(handles.final1,'String'));
nduef = str2num(get(handles.final2,'String'));
ntref = str2num(get(handles.final3,'String'));
nquattrof = str2num(get(handles.final4,'String'));
save('m.mat','-append');
I want to know why this isn't working and how can I change it. Thanks a lot.
You can't use save('m.mat','-append');. You're missing an option to get to append.
In order to use append you have to declare a filename, the variable and then append.
save(filename,variables,'-append')
Taken from - https://au.mathworks.com/help/matlab/ref/save.html
Also, from your code you're not redefining the variables in your m struct.
Suppose vec_A, vec_B, vec_c are some matrices with random data. I want to write data to text file for every 5 min, My code as follows:
function samplegui_OpeningFcn(hObject, ~, handles, varargin)
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 300, ... % Initial period.
'TimerFcn', {#open,hObject}); % Specify callback
handles.output = hObject;
handles.vec_A=[];
handles.vec_B=[];
handles.vec_C=[];
guidata(hObject, handles);
function open_Callback(hObject, eventdata, handles) % push button to receive serial data.
cnt=0;
while 1
% Getting data from Serial Port
get_lines=fgets(handles.se) % getting data from serial port
if~isempty(get_lines)
cnt=cnt+1;
if strfind(get_lines,'T') %Parsing data
handles.vec_A=[handles.vec_A;[timet newword]];
plot(handles.vec_A(:,1),handles.vec_A(:,2:end),'r'); % plotting
% Same follows for parsing and plot vec_B and Vec_C
drawnow(); % to update the Plots
end
end
Pause(.05);
start(handles.timer); % saving the data
dlmwrite('My_sample1.txt',handles.vec_A);
dlmwrite('My_sample2.txt',handles.vec_B);
dlmwrite('My_sample3.txt',handles.vec_C);
stop(handles.timer);
end
guidata(hObject, handles);
While running my code, following error occurs:
Error while evaluating TimerFcn for timer 'timer-6'
Too many input arguments.
How to execute timer in this case to write data successfully for every five minutes or suggest any other way to do it.
You have defined your TimerFcn to be {#open, hObject} but you don't have a function named open. Instead, it is trying to call the built-in open with three input arguments (the timer object, an event object, and hObject) and this is producing the error because open only accepts one input argument.
That being said, it's not clear at all how the code that you have provided will accomplish anything close to what you want. Something like this may work better.
function samplegui_OpeningFcn(hObject, ~, handles, varargin)
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 300, ... % Initial period.
'TimerFcn', #(s,e)write_data()); % Specify callback
handles.output = hObject;
handles.vec_A=[];
handles.vec_B=[];
handles.vec_C=[];
guidata(hObject, handles);
start(handles.timer);
%// Now update your data in a loop
cnt = 0;
while true
%// Getting data from Serial Port
get_lines = fgets(handles.se)
if ~isempty(LINES)
cnt = cnt + 1;
if strfind(LINES, 'T')
handles.vec_A = [handles.vec_A; [timet newword]];
plot(handles.vec_A(:,1), handles.vec_A(:,2:end),'r');
drawnow
end
end
end
function write_data()
%// Write it to file
dlmwrite('My_sample1.txt',handles.vec_A);
dlmwrite('My_sample2.txt',handles.vec_B);
dlmwrite('My_sample3.txt',handles.vec_C);
end
end
I get the following error message about too many input arguments in my fprintf function. But it seems to me that just the right amount of arguments were passed.
All this is in the context of a guide GUI I made (see picture at the end).
Error while evaluating uicontrol Callback
calibration button hit
20
200
10
10
2520
25197
2520
25197
'C0 2520 25197 10 10'
Error using serial/fprintf (line 115)
Too many input arguments.
Error in UserInterface>StaticCalibrationBtn_Callback (line 202)
fprintf(handles.s, 'C0 %s %s %s %s',StartStepsStr,EndStepsStr,Increment,Wait);
Here is the code
function StaticCalibrationBtn_Callback(hObject, eventdata, handles)
% hObject handle to StaticCalibrationBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
disp('calibration button hit');
Start = str2double(get(handles.CalFromUserTxt, 'string')); % Fetches the user inputed start location in mm and converts to double
disp(Start);
End = str2double(get(handles.CalToUserTxt, 'string')); % same for End position
disp(End);
Increment = get(handles.CalUserIncrementTxt, 'string'); % fetches the increment user inputed data as a string
disp(Increment);
Wait = get(handles.CalUserSpeedTxt, 'string'); % fetches the wait inputed data as a string
disp(Wait);
StartSteps = round(Start/0.00793750000); % computes the starting step position,double division
disp(StartSteps);
handles.StartSteps = StartSteps; % creats a place for the start steps inside the handles structure, to be fetched by anythingelsest be saved with guidata(hObject,handles)
EndSteps = round(End/0.00793750000); % computes the end step position
disp(EndSteps);
handles.EndSteps = EndSteps; % stores the end steps to be accessed by anything else must be saved with guidata(hObject,handles)
StartStepsStr = num2str(StartSteps); % converts the StartSteps double into a string so it can be sent over serial as a string
disp(StartStepsStr);
EndStepsStr = num2str(EndSteps); % converts the EndSteps double into a string so it can be sent over serial as a string
disp(EndStepsStr);
OutputString = strcat('C0' , {' '} , StartStepsStr , {' '} , EndStepsStr , {' '} , Increment , {' '} , Wait);
disp(OutputString);
fprintf(handles.s, 'C0 %s %s %s %s',StartStepsStr,EndStepsStr,Increment,Wait);
and where handles.s comes from
function SerialBtn_Callback(hObject, eventdata, handles)
% hObject handle to SerialBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA
comPort = get(handles.COMportTxt,'String');
if(~exist('serialFlag','var'))
[handles.s, handles.serialFlag] = setupSerial(comPort);
end
guidata(hObject,handles);
end
And the setupserial funciton
function [ s, flag] = setupSerial(comPort)
%Initialize serial port communication between Arduino and Matlab
%Ensure that the arduino is also communicating with Matlab at this time.
%if setup is complete then the value of setup is returned as 1 else 0.
flag =1;
s = serial(comPort);
set(s,'DataBits',8);
set(s,'StopBits',1);
set(s,'BaudRate',9600);
set(s,'Parity','none');
fopen(s);
a='b';
while (a~='a')
a=fread(s,1,'uchar');
end
if (a=='a')
disp('serial read');
end
fprintf(s,'%c','a');
mbox = msgbox('Serial Communication setup.'); uiwait(mbox);
fscanf(s,'%u');
end
USING THE FOLLOWING RESOLVED THE ISSUE
OutputString = sprintf('C0 %s %s %s %s',StartStepsStr,EndStepsStr,Increment,Wait);
fprintf(handles.s,'%s', OutputString);
There are multiple functions called fprintf, one for files, one for serial objects and some others. You are using functionally which you know from the fprintf for files, but you are using it with a serial object. Check the right documentation which can be accessed via doc serial/fprintf
I want to create a button which work as on/off switch: If the user pushes it, it starts counting and displays the counter on a static text. If the user pushes it again, it stops counting. Then, if the user pushes it for a third time, it continues counting.
I tried this code
function startStop_togglebutton_Callback(hObject, eventdata, handles)
% hObject handle to startStop_togglebutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of startStop_togglebutton
persistent counter ;
if isempty(counter)
counter = 0 ;
end
button_state = get(hObject,'Value');
if button_state == get(hObject,'Max')
set(handles.startStop_togglebutton,'String','Stop','ForegroundColor','red')
setappdata(handles.startStop_togglebutton,'sw',1)
while counter < 10
counter = counter+1;
set(handles.statusBar,'String',strcat(['the counter = ' num2str(counter) ]))
pause(1)
end
set(handles.startStop_togglebutton,'String','Finished','ForegroundColor','cyan')
elseif button_state == get(hobject,'min')
set(handles.startstop_togglebutton,'string','resume','foregroundcolor','blue')
setappdata(handles.startstop_togglebutton,'sw',0)
set(handles.statusBar,'String',strcat([' stopped & the counter = ' num2str(counter) ' !']))
end
but it doesn't work correctly: When I push the button for the first time, it starts counting and when I pushed it a second, time it's name changed but it was still counting.
In your present implementation of the counter, the while loop in the startStop_togglebutton callback is activated the first time you press the pushbuttonn to Start counting.
It keeps running until the condition (counter < 10) holds even if you press again the ushbutton to Stop the counting.
Therefore, to fix the problem you can use the value of the startStop_togglebutton insted of "1" to increment the counter.
Below, you can find the updated version of the callback. I've also added a couple of "if" blocks to manage the displaying of the strings in the statusbar
% --- Executes on button press in startStop_togglebutton.
function startStop_togglebutton_Callback(hObject, eventdata, handles)
% hObject handle to startStop_togglebutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of startStop_togglebutton
% hObject handle to startStop_togglebutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of startStop_togglebutton
persistent counter ;
if isempty(counter)
counter = 0 ;
end
button_state = get(hObject,'Value');
if button_state == get(hObject,'Max')
set(handles.startStop_togglebutton,'String','Stop','ForegroundColor','red')
setappdata(handles.startStop_togglebutton,'sw',1)
while counter < 10
%
% Inserted acquisition of button state within the while loop
%
button_state = get(hObject,'Value');
%
% Modified the counter increment:
% the increment is based on the status of the button
%
% counter = counter+1;
counter = counter+button_state;
%
% Added "if" condition
% The "statusbar" is updated only if counting is on
%
if(button_state)
set(handles.statusBar,'String',strcat(['the counter = ' num2str(counter) ]))
end
pause(1)
end
%
% Added "if" condition
% The "statusbar" is updatred only if counting is finished
%
if(counter == 10)
set(handles.startStop_togglebutton,'String','Finished','ForegroundColor','cyan')
end
elseif button_state == get(hObject,'min')
set(handles.startStop_togglebutton,'string','resume','foregroundcolor','blue')
setappdata(handles.startStop_togglebutton,'sw',0)
set(handles.statusBar,'String',strcat([' stopped & the counter = ' num2str(counter) ' !']))
end
UPDATING TO ANSWER TO THE COMMENT
The reason for using the value of the togglebutton to increment the counter is the following.
The first time you push the togglebutton to start the counter, the while loop is activated and the GUI is "waiting" for another callback regardless the loop is completed.
Moreover the while loop has been coded into the if block that catches the Start / Continue action.
This implies that when you push the togglebutton to stop the counter, the while loop is skipped.
Getting the value of the togglebutton in the while loop allows to catch the change of the status of the button independently of the intended action (Stop / Restart).
Indeed, when you push it to Stop the counter, the value is set to 0 so it does not increment the counter while when you push it to restart, its value is set to 1 and the counter is incremented.
I suggest to model the counter GUI in a different way:
To code the counter in a separate ".m" file (or in a function)
To code in this ".m" file the logic for the increment of the counter (based on the value of the togglebutton)
To add a pushbutton which run the counter (the ".m" file)
To use the startStop_togglebutton callbach only to update the string displayed on the togglebutton
The handling of the data between the GUI and the ".m" file is done by using the guidata function.
The ".m". files identifies the GUI through its tag (in the code I've used to test the solution I've set the GUI figure tag as counter_gui).
You should also set the property HandleVisibility of your GUI to 'on'
In the following you can find:
the updated startStop_togglebutton callback, now very simple
the callback of the pushbutton used to start the counter
the ".m" file chich manages the counter
startStop_togglebutton Callback
% --- Executes on button press in startStop_togglebutton.
function startStop_togglebutton_Callback(hObject, eventdata, handles)
% hObject handle to startStop_togglebutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of startStop_togglebutton
% hObject handle to startStop_togglebutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of startStop_togglebutton
button_state = get(hObject,'Value');
if(button_state == 1)
set(handles.startStop_togglebutton,'String','Stop','ForegroundColor','red')
else
set(handles.startStop_togglebutton,'string','resume','foregroundcolor','blue')
end
run_counter callback
% --- Executes on button press in run_counter.
function run_counter_Callback(hObject, eventdata, handles)
% hObject handle to run_counter (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
set(handles.startStop_togglebutton,'enable','on');
set(handles.startStop_togglebutton,'Value',1);
set(handles.run_counter,'enable','off');
% Run the counter ".m" file
run_counter;
".m" file managing the counter
% Get tha handle of the GUI figure
gui_h=findobj('tag','counter_gui');
% Get gudata
gui_my_data=guidata(gui_h);
counter=0;
while(counter < 10)
% Get togglebutton value
button_status=get(gui_my_data.startStop_togglebutton,'value');
% Increment to counter only if the togglebutton is set to "Start/Resume"
counter=counter+button_status;
% Update strings
if(button_status)
set(gui_my_data.startStop_togglebutton,'String','Stop','ForegroundColor','red')
set(gui_my_data.statusBar,'String',strcat(['the counter = ' num2str(counter) ]))
else
set(gui_my_data.statusBar,'String',strcat([' stopped & the counter = ' num2str(counter) ' !']))
end
pause(1);
end
set(gui_my_data.startStop_togglebutton,'String','Finished','ForegroundColor','cyan')
set(gui_my_data.startStop_togglebutton,'enable','off');
set(gui_my_data.run_counter,'enable','on');
Hope this helps.