Togglebutton Problem

24 views (last 30 days)
Steve
Steve on 5 Feb 2012
Edited: Daniel on 15 Oct 2013
I am trying to use a toggle button in a project that I am working on and I am having trouble with the button it seems. I would like to execute certain code as long as the button is depressed (or the state is 1). However, it seems that the code goes into an infinite while loop. When I tried to check the state of the button as I pressed it, only 1's appeared and teh state did not change. Here is the simple code taht I am working with:
while Button == get(hObject,'Max')
EXECUTE CODE
if get(hObject,'Min')
break;
end
end
Any help is greatly appreciated!

Accepted Answer

Walter Roberson
Walter Roberson on 5 Feb 2012
You have to get() the Value of hObject. The Max and Min values do not change (not unless you specifically change them.)
Also, be sure that something in your code gives an opportunity for the GUI to react to events.
bmax = get(hObject, 'Max');
while get(hObject, 'Value') == bmax
EXECUTE CODE
drawnow(); %allow events
end
  3 Comments
Walter Roberson
Walter Roberson on 15 Feb 2012
I would need to see the current code and the full traceback of the error message. There is no inherent reason a pushbutton cannot open and read a serial object.
Steve
Steve on 15 Feb 2012
I added my code in an answer as it was easier to show you. I didn't include all of the code the gui_mainfcn file as there was over 300 lines of code.
Thanks Walter!

Sign in to comment.

More Answers (4)

Steve
Steve on 15 Feb 2012
This is the init code where it calls out an error:
function varargout = TEST(varargin)
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @TEST_OpeningFcn, ...
'gui_OutputFcn', @TEST_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
******_ gui_mainfcn(gui_State, varargin{:});******
end
This is within my code under the toggle button callback:
function togglebutton1_Callback(hObject, eventdata, handles)
while get(hObject, 'Value') == get(hObject,'Max')
for i = 1 : 125
******Out(i) = fread(s)******
if get(hObject, 'Value') == get(hObject,'Min')
fclose(s);
delete(s);
clear s;
break
end
end
end
Here is the code from the gui_mainfcn.m:
function varargout = gui_mainfcn(gui_State, varargin)
gui_StateFields = {'gui_Name'
'gui_Singleton'
'gui_OpeningFcn'
'gui_OutputFcn'
'gui_LayoutFcn'
'gui_Callback'};
gui_Mfile = '';
for i=1:length(gui_StateFields)
if ~isfield(gui_State, gui_StateFields{i})
error('MATLAB:gui_mainfcn:FieldNotFound', 'Could not find field %s in the gui_State struct in GUI M-file %s', gui_StateFields{i}, gui_Mfile);
elseif isequal(gui_StateFields{i}, 'gui_Name')
gui_Mfile = [gui_State.(gui_StateFields{i}), '.m'];
end
end
numargin = length(varargin);
if numargin == 0
% UNTITLED
% create the GUI only if we are not in the process of loading it
% already
gui_Create = true;
elseif local_isInvokeActiveXCallback(gui_State, varargin{:})
% UNTITLED(ACTIVEX,...)
vin{1} = gui_State.gui_Name;
vin{2} = [get(varargin{1}.Peer, 'Tag'), '_', varargin{end}];
vin{3} = varargin{1};
vin{4} = varargin{end-1};
vin{5} = guidata(varargin{1}.Peer);
feval(vin{:});
return;
elseif local_isInvokeHGCallbak(gui_State, varargin{:})
% UNTITLED('CALLBACK',hObject,eventData,handles,...)
gui_Create = false;
else
% UNTITLED(...)
% create the GUI and hand varargin to the openingfcn
gui_Create = true;
end
if ~gui_Create
% In design time, we need to mark all components possibly created in
% the coming callback evaluation as non-serializable. This way, they
% will not be brought into GUIDE and not be saved in the figure file
% when running/saving the GUI from GUIDE.
designEval = false;
if (numargin>1 && ishghandle(varargin{2}))
fig = varargin{2};
while ~isempty(fig) && ~isa(handle(fig),'figure')
fig = get(fig,'parent');
end
designEval = isappdata(0,'CreatingGUIDEFigure') || isprop(fig,'__GUIDEFigure');
end
if designEval
beforeChildren = findall(fig);
end
% evaluate the callback now
varargin{1} = gui_State.gui_Callback;
if nargout
[varargout{1:nargout}] = feval(varargin{:});
else
******feval(varargin{:});******
end
% Set serializable of objects created in the above callback to off in
% design time. Need to check whether figure handle is still valid in
% case the figure is deleted during the callback dispatching.
if designEval && ishandle(fig)
set(setdiff(findall(fig),beforeChildren), 'Serializable','on');
end
else
if gui_State.gui_Singleton
gui_SingletonOpt = 'reuse';
else
gui_SingletonOpt = 'new';
end
% Check user passing 'visible' P/V pair first so that its value can be
% used by oepnfig to prevent flickering
gui_Visible = 'auto';
gui_VisibleInput = '';
for index=1:2:length(varargin)
if length(varargin) == index || ~ischar(varargin{index})
break;
end
% Recognize 'visible' P/V pair
len1 = min(length('visible'),length(varargin{index}));
len2 = min(length('off'),length(varargin{index+1}));
if ischar(varargin{index+1}) && strncmpi(varargin{index},'visible',len1) && len2 > 1
if strncmpi(varargin{index+1},'off',len2)
gui_Visible = 'invisible';
gui_VisibleInput = 'off';
elseif strncmpi(varargin{index+1},'on',len2)
gui_Visible = 'visible';
gui_VisibleInput = 'on';
end
end
end
% Open fig file with stored settings. Note: This executes all component
% specific CreateFunctions with an empty HANDLES structure.
% Do feval on layout code in m-file if it exists
gui_Exported = ~isempty(gui_State.gui_LayoutFcn);
% this application data is used to indicate the running mode of a GUIDE
% GUI to distinguish it from the design mode of the GUI in GUIDE. it is
% only used by actxproxy at this time.
setappdata(0,genvarname(['OpenGuiWhenRunning_', gui_State.gui_Name]),1);
if gui_Exported
gui_hFigure = feval(gui_State.gui_LayoutFcn, gui_SingletonOpt);
% make figure invisible here so that the visibility of figure is
% consistent in OpeningFcn in the exported GUI case
if isempty(gui_VisibleInput)
gui_VisibleInput = get(gui_hFigure,'Visible');
end
set(gui_hFigure,'Visible','off')
% openfig (called by local_openfig below) does this for guis without
% the LayoutFcn. Be sure to do it here so guis show up on screen.
movegui(gui_hFigure,'onscreen');
else
gui_hFigure = local_openfig(gui_State.gui_Name, gui_SingletonOpt, gui_Visible);
% If the figure has InGUIInitialization it was not completely created
% on the last pass. Delete this handle and try again.
if isappdata(gui_hFigure, 'InGUIInitialization')
delete(gui_hFigure);
gui_hFigure = local_openfig(gui_State.gui_Name, gui_SingletonOpt, gui_Visible);
end
end
if isappdata(0, genvarname(['OpenGuiWhenRunning_', gui_State.gui_Name]))
rmappdata(0,genvarname(['OpenGuiWhenRunning_', gui_State.gui_Name]));
end
% Set flag to indicate starting GUI initialization
setappdata(gui_hFigure,'InGUIInitialization',1);
% Fetch GUIDE Application options
gui_Options = getappdata(gui_hFigure,'GUIDEOptions');
% Singleton setting in the GUI M-file takes priority if different
gui_Options.singleton = gui_State.gui_Singleton;
if ~isappdata(gui_hFigure,'GUIOnScreen')
% Adjust background color
if gui_Options.syscolorfig
set(gui_hFigure,'Color', get(0,'DefaultUicontrolBackgroundColor'));
end
% Generate HANDLES structure and store with GUIDATA. If there is
% user set GUI data already, keep that also.
data = guidata(gui_hFigure);
handles = guihandles(gui_hFigure);
if ~isempty(handles)
if isempty(data)
data = handles;
else
names = fieldnames(handles);
for k=1:length(names)
data.(char(names(k)))=handles.(char(names(k)));
end
end
end
guidata(gui_hFigure, data);
end
% Apply input P/V pairs other than 'visible'
for index=1:2:length(varargin)
if length(varargin) == index || ~ischar(varargin{index})
break;
end
len1 = min(length('visible'),length(varargin{index}));
if ~strncmpi(varargin{index},'visible',len1)
try set(gui_hFigure, varargin{index}, varargin{index+1}), catch break, end
end
end
% If handle visibility is set to 'callback', turn it on until finished
% with OpeningFcn
gui_HandleVisibility = get(gui_hFigure,'HandleVisibility');
if strcmp(gui_HandleVisibility, 'callback')
set(gui_hFigure,'HandleVisibility', 'on');
end
feval(gui_State.gui_OpeningFcn, gui_hFigure, [], guidata(gui_hFigure), varargin{:});
if isscalar(gui_hFigure) && ishandle(gui_hFigure)
% Handle the default callbacks of predefined toolbar tools in this
% GUI, if any
guidemfile('restoreToolbarToolPredefinedCallback',gui_hFigure);
% Update handle visibility
set(gui_hFigure,'HandleVisibility', gui_HandleVisibility);
% Call openfig again to pick up the saved visibility or apply the
% one passed in from the P/V pairs
if ~gui_Exported
gui_hFigure = local_openfig(gui_State.gui_Name, 'reuse',gui_Visible);
elseif ~isempty(gui_VisibleInput)
set(gui_hFigure,'Visible',gui_VisibleInput);
end
if strcmpi(get(gui_hFigure, 'Visible'), 'on')
figure(gui_hFigure);
if gui_Options.singleton
setappdata(gui_hFigure,'GUIOnScreen', 1);
end
end
% Done with GUI initialization
if isappdata(gui_hFigure,'InGUIInitialization')
rmappdata(gui_hFigure,'InGUIInitialization');
end
% If handle visibility is set to 'callback', turn it on until
% finished with OutputFcn
gui_HandleVisibility = get(gui_hFigure,'HandleVisibility');
if strcmp(gui_HandleVisibility, 'callback')
set(gui_hFigure,'HandleVisibility', 'on');
end
gui_Handles = guidata(gui_hFigure);
else
gui_Handles = [];
end
if nargout
[varargout{1:nargout}] = feval(gui_State.gui_OutputFcn, gui_hFigure, [], gui_Handles);
else
feval(gui_State.gui_OutputFcn, gui_hFigure, [], gui_Handles);
end
if isscalar(gui_hFigure) && ishandle(gui_hFigure)
set(gui_hFigure,'HandleVisibility', gui_HandleVisibility);
end
end
function gui_hFigure = local_openfig(name, singleton, visible)
% openfig with three arguments was new from R13. Try to call that first, if
% failed, try the old openfig.
if nargin('openfig') == 2
% OPENFIG did not accept 3rd input argument until R13,
% toggle default figure visible to prevent the figure
% from showing up too soon.
gui_OldDefaultVisible = get(0,'defaultFigureVisible');
set(0,'defaultFigureVisible','off');
gui_hFigure = openfig(name, singleton);
set(0,'defaultFigureVisible',gui_OldDefaultVisible);
else
gui_hFigure = openfig(name, singleton, visible);
end
function result = local_isInvokeActiveXCallback(gui_State, varargin)
try
result = ispc && iscom(varargin{1}) ...
&& isequal(varargin{1},gcbo);
catch
result = false;
end
function result = local_isInvokeHGCallbak(gui_State, varargin)
try
fhandle = functions(gui_State.gui_Callback);
result = ~isempty(findstr(gui_State.gui_Name,fhandle.file)) || ...
(ischar(varargin{1}) ...
&& isequal(ishandle(varargin{2}), 1) ...
&& (~isempty(strfind(varargin{1},[get(varargin{2}, 'Tag'), '_'])) || ...
~isempty(strfind(varargin{1}, '_CreateFcn'))) );
catch
result = false;
end
  1 Comment
Walter Roberson
Walter Roberson on 16 Feb 2012
Out(i) = fread(s)
Unless you set the buffer size to 1, or you are _sure_ that the only thing being transmitted is the terminator character (with nothing before it), fread() is going to return multiple characters and you are going to try to store that vector in to the single array element Out(i)
If you are wanting to read a line, consider fgetl() and storing in Out{i}
On the other hand, you have not defined the variable s within the scope of that function, so referencing s is going to fail before you read anything. None of the code you showed configured the port or opens it :(
Please also remember to use drawnow() or pause() to give an opportunity for the GUI to update the button state.

Sign in to comment.


Steve
Steve on 16 Feb 2012
I apologize, I left this part out:
if get(hObject, 'Value') == get(hObject,'Max')
s=serial('COM1');
set(s,'BaudRate',9600);
s.ReadAsyncMode='continuous'; s.InputBufferSize=1;
fopen(s);
end
I want to read 1 byte at a time and not worry about the terminator. I am also using the drawnow() function as well, it is just not shown.
Basically, I have 2 PCs connected: 1 with MatLab and one with HyperTerminal. When I run my program in MatLab, the figure window appears with the togglebutton. When I press the toggle button, I type in HyperTerminal and a graph appears (I left that code out as well) and the graph shows exactly what I am typnig which is all good. However, when I press that togglebutton to unlatch and stop collecting data, that is when I get those errors.
  1 Comment
Walter Roberson
Walter Roberson on 16 Feb 2012
Could you show the complete code for that routine, and also show the exact error messages being produced?
Have you put in a breakpoint and single-stepped through the close-down portion?

Sign in to comment.


Steve
Steve on 16 Feb 2012
Here is my code:
function varargout = TEST(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @TEST_OpeningFcn, ...
'gui_OutputFcn', @TEST_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% --- Executes just before TEST is made visible.
function TEST_OpeningFcn(hObject, eventdata, handles, varargin)
% Choose default command line output for TEST
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes TEST wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = TEST_OutputFcn(hObject, eventdata, handles)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on button press in togglebutton1.
function togglebutton1_Callback(hObject, eventdata, handles)
if get(hObject, 'Value') == get(hObject,'Max')
s=serial('COM1');
set(s,'BaudRate',9600);
s.ReadAsyncMode='continuous';
s.InputBufferSize=1;
fopen(s);
end
while get(hObject, 'Value') == get(hObject,'Max')
for i = 1 : 125
Out(i) = fread(s);
c=clock;
Time(i)=(c(5)+(c(6)/100));
subplot(2,2,1)
plot(Time,Out,'r')%1,'r',Time,Out5,'c')
title('Cocking Displacement','FontSize',12,'FontWeight','bold')
xlabel('Time (Minute.Seconds)')
ylabel('Degrees')
drawnow();
whitebg('black')
if get(hObject, 'Value') == get(hObject,'Min')
fclose(s);
delete(s);
clear s;
break
end
end
if get(hObject, 'Value') == get(hObject,'Min')
fclose(s);
delete(s);
clear s;
end
end
Here is the list of errors:
Error in ==> TEST>togglebutton1_Callback at 61
Out(i) = fread(s);
Error in ==> gui_mainfcn at 96
feval(varargin{:});
Error in ==> TEST at 16
gui_mainfcn(gui_State, varargin{:});
Error in ==>
@(hObject,eventdata)TEST('togglebutton1_Callback',hObject,eventdata,guidata(hObject))
??? Error while evaluating uicontrol Callback
  1 Comment
Walter Roberson
Walter Roberson on 16 Feb 2012
It just says there is an error there, but doesn't say what the error is?? Is it saying there was a timeout?
Is this on the first execution (i=1) of the first "while" ?
Note: in the loop you deltect Min and you fclose and delete and clear the object and break out of the loop. And then once the loop is broken out of, you again detect min and fclose the object and delete it and clear it, even though it is already gone.
Remember that the callback will be executed when the button is toggled back. In that case, it will not be Max so it will not create s, and it will not be Max so it will not loop, but it will be Min so it will try to fclose/delete/clear an object that does not exist. That is going to cause problems.
Suggest you "persistent" s . If s is [] and you have Min, nothing to be done so return. If s is not [] and you have Max, somehow s is initialized so leave it initialized and proceed to read the values. If s is not [] and you have Min, close / delete s, and set the persistent s to []. If s is [] and you have Max, initialize s in to the persistent variable and proceed with reading.
But -- watch out because s can appear or disappear at every drawnow(). And I am thinking that _maybe_ it could also interrupt after the fread(), but I am not certain of that.

Sign in to comment.


Steve
Steve on 19 Feb 2012
This is extremely frustrating as I have been stuck on this issue forever...I have tried different methods and even persistent, but I just can't seem to get around the errors. Here is the flow of what I want to do now:
- Configure the port
- If the button is pressed open the port
- Read the port and display data
- If the button is released close the port
Here is my current code:
function varargout = TEST(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @TEST_OpeningFcn, ...
'gui_OutputFcn', @TEST_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
function TEST_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
function varargout = TEST_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
function togglebutton1_Callback(hObject, eventdata, handles)
persistent s;
s=serial('COM1');
set(s,'BaudRate',9600);
s.ReadAsyncMode='continuous';
s.InputBufferSize=1;
set(s, 'Timeout', 75);
switch get(hObject, 'Value')
case get(hObject, 'Value') == get(hObject, 'MAX')
fopen(s);
for i = 1 : 125
Out(i) = fread(s);
c=clock;
Time(i)=(c(5)+(c(6)/100));
plot(Time,Out)
drawnow();
end
case get(hObject, 'Value') == get(hObject, 'MIN')
fclose(s);
end
This is what heppens when I run:
- I press the button
- The port opens and begins collecting the info I type from HyperTerminal
- I release the button and it stops
- I press the button again and as soon as I type a character in HyperTerminal the following errors appear:
Port: COM1 is not available. No ports are available.
Use INSTRFIND to determine if other instrument objects are connected to the requested
device.
Error in ==> TEST>togglebutton1_Callback at 128
fopen(s);
Error in ==> gui_mainfcn at 96
feval(varargin{:});
Error in ==> TEST at 47
gui_mainfcn(gui_State, varargin{:});
Error in ==>
@(hObject,eventdata)TEST('togglebutton1_Callback',hObject,eventdata,guidata(hObject))
??? Error using ==> drawnow
Error while evaluating uicontrol Callback
I understand that if the port has been configured, I don't want to reconfigure it. However, even when I put a 'while 1' around the non-configuration code, I get the same error. Also, when I try to include 'delete(s)' and 'clear s', I still get the error.
I know am not very good at programming, but it seems like this is such an easy thing to do, but MatLab is so finicky.
  1 Comment
Steve
Steve on 19 Feb 2012
Well I sat here an labored over it and tried to drill down step by step and I was able to get past it. Thanks Walter!!

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!