I am stuck in an error of timer function. Although I have tried to search, I find no answer.
function figure1_CreateFcn(hObject, eventdata, handles)
global t
t = timer( 'ExecutionMode', 'fixedRate', 'StartDelay',1, 'Period',1,'TasksToExecute',150);
t.TimerFcn = {#my_callback_fcn};
The error I got is:
Error while evaluating TimerFcn for timer 'timer-1'
Too many input arguments.
My MATLAB version is R2014a. The start function is called pushbutton2_Callback function.
I have tried to change Period to 1.0, TasksToExecute to inf or TimerFcn in the call to timer. It does not help.
Is there anyone who can help me out?
The error is caused because your provided callback function my_callback_fcn does not have two input arguments. You have two possibilities to solve that. Only do one of them:
Create an anonymous function with two input arguments when you assign the timer callback:
t.TimerFcn = {#(obj,event)my_callback_fcn};
Add two input arguments to my_callback_fcn so your first line of that function looks like:
function my_callback_fcn(obj,event)
You can ignore the arguments with ~ if you do not need them in the function. So your code from the question could look like this:
t = timer('ExecutionMode', 'fixedRate', 'StartDelay',1, 'Period',1, 'TasksToExecute',150);
t.TimerFcn = {#(~,~)my_callback_fcn};
Here is some more information on timer callback functions.
To address this comment and that one:
Don't attempt to apply both solutions at the same time because then you'll add two arguments to the function prototype and then don't provide it. The result would be the following error:
Error while evaluating TimerFcn for timer 'timer-1'
Not enough input arguments.
You only need to do solution 2 according to the prototype you posted in your comment. Here is a working demo:
function timertest
t = timer('ExecutionMode', 'fixedRate', 'StartDelay',1, 'Period',1, 'TasksToExecute',150);
t.TimerFcn = {#my_callback_fcn};
start(t); pause on; pause; stop(t); delete(t);
function my_callback_fcn(handles,~)
handles;
disp('xy');
Related
The problem with a timer in the MatLab App Designer.
It return an error: "Error while evaluating TimerFcn for timer.. Too many input arguments"
my code:
app.t.TimerFcn = #app.timerFunction;
function timerFunction(app, ~, ~)
%something
end
I've been looking for a solution. I also tried this:
app.t.TimerFcn = #(app, ~, ~)app.timerFunction
timerFunction(app, ~, ~)
app.t.TimerFcn = #(~,~)app.timerFunction
timerFunction(app)
Any help would be appreciated.
You can just use varargin and worry less about the number of input arguments which the event is throwing, i.e.
function timerFunction( app, varargin )
% stuff
end
This will also help you debug and see how many inputs MATLAB is in fact trying to pass, by looking at the contents of varargin.
In a similar way to your other attempts you can use varargin in your function handle too, although this doesn't allow for the same debugging
app.t.TimerFcn = #(varargin) app.timerFunction;
The found solution is:
callback function:
function timerFunction(app)
% stuff
end
timer settings
app.t.TimerFcn = #(x,y)timerFunction(app);
Had the same problem and just wanted to let you know that this error can be a bit misleading.
In my case, I called a function via a timer, and I had a normal function call in that callback function:
T = timer('TimerFcn', #(~,~) this.callback, 'StartDelay', waitTime);
...
function callback(this)
...
this.doStuff(x,y);
end
function doStuff(x, y)
...
end
which of course should have been:
function doStuff(this, x, y)
...
end
So the problem didn't have anything to do with the timer, but was just an error in some other part that was executed by the timer callback function.
I want to pause a timer function (for like 5 seconds) in the middle of its execution in MATLAB GUI. Pause(5) can do it but the problem is that it pauses all other callback functions to execute (including other timer functions I am using in the MATLAB GUI, for example).
I was thinkink maybe I can write a dummy loop that could be executed for 5 sec but it might not be accurate and efficient. Do you have any suggestion?
Additional info:
handles.maintmr = timer(...
'ExecutionMode', 'fixedRate', ...
'TasksToExecute',1,'StartDelay',299, 'Period', 1,...
'TimerFcn', {#ttl_timer, hObject});
handles.et_tmr = timer(...
'ExecutionMode', 'fixedRate', ...
'Period', 0.5, ...
'TimerFcn', {#timer_ET_rec, hObject});
handles.tmr = timer(...
'ExecutionMode', 'fixedRate', ...
'Period', 9.85, ...
'TimerFcn', {#timer_update_display, hObject});
These are the defined three timer functions I am using in MATLAB GUI
And these are how I call the callback timer functions:
function timer_ET_rec(obj,event,hObject,eventdata)
handles = guidata(hObject);
function timer_update_display(obj,event,hObject,eventdata)
handles = guidata(hObject);
function ttl_timer(obj,event,hObject,eventdata)
handles= guidata(hObject);
I would try something like
t = tic();
while toc(t) < 5
pause(0.1);
drawnow('limitrate');
end
I like Edric's solution. Other options:
Option 1
The waitfor(obj) function (interrupts execution until object 'obj' is deleted).
eg.
%Pop-up msg;
h1 = errordlg({'This message interrupts the code. Close me to continue'},...
'Hi! I'm a pop-up')
% interrupt until closed
waitfor(h1)
Option 2
The timer() function doesn't run off the wallclock (ie. actual real world time) so I'm not sure it can do what you seem to what --- maintaining regular execution of code every x minutes regardless of interrupts and pauses in the code. But some methods can get close to it.
a) use the timer function to regularly TEST if you have passed a particular period according to wallclock time or not (if statement with clock()). If so, execute some other code.
b) Change the timer 'BusyMode' from the assumed default 'drop' to 'queue'and it will insert code to run as close as possible to the desired time.
Best solution will depend on what exactly you are trying to achieve.
I'm trying to make a timer that counts down from 20 to 0 (seconds) in GUIDE. In the meantime the user will perform a simple action (clicking a radio button in a group button) and at the end of that 20 seconds a message will appear (depending on which button the user clicked).
I looked around but it seems that there isn't a timer object for GUIDE (why don't they make one since it's so useful??). However I tried to make one and below there's the result, it doesn't work.
I initialised setappdata in MyGUI_OpeningFcn:
% Initialize setappdata
timeout = 20;
setappdata(handles.figure1,'timeout', timeout);
Next_calculation is radio button and timerBox is a static text.
function Next_calculation_Callback(hObject, eventdata, handles)
[..]
timeout = getappdata(handles.figure1,'timeout');
t = timer('Period', 1.0,... % 1 second
'StartFcn', set(handles.timerBox,'String',num2str(timeout)), ...
'ExecutionMode', 'fixedRate', ... % Starts immediately after the timer callback function is added to the MATLAB execution queue
'TasksToExecute', timeout, ... % Indicates the number of times the timer object is to execute the TimerFcn callback
'TimerFcn', #my_timer ... % callback to function
);
start(t)
Once the timer begins, it calls TimerFcn that calls my_timer. I should pass a handle to my_timer, but I don't know exactly how.
function my_timer(hObject, eventdata)
% I think I'm supposed to pass (hObject, eventdata) to my_timer
% handles should be getting the current figure from hObject
handles = guidata( ancestor(hObject, 'figure1') );
timeout = getappdata(handles.figure1,'timeout');
t_left = timeout - 1.0;
% show the updated time
set(handles.timerBox,'String',num2str(t_left));
% update 'timeout'
setappdata(handles.figure1,'timeout',t_left)
You need to use a custom anonymous function for the TimerFcn to pass the necessary data to your timer callback
set(t, 'TimerFcn', #(s,e)my_timer(hObject, handles))
You can then define your my_timer callback as
function my_timer(hObject, handles)
% Do stuff with handles
end
Background
In Python and JS we have closures, which returns a function with some of the variables pre-defined. e.g.
def make_printer(msg):
def printer():
print msg
return printer
Do we have similar stuff in Matlab?
Here I have a callback function
function show(object, eventdata)
that is to be set to the callback of my GUI
func = #show;
set(gcf, 'WindowButtonMotionFcn', func);
However, I want to add some additional parameters to this show function.
Currently I'm using global variables to do that. But I think it would be elegant if we have a 'closures function'.
About anonymous function
Yes we do have anonymous function in Matlab. However it seems to me that it is too simple to support 60-line procedures.
There was once a document floating about the internet by Sergey Simakov. It was very terse , not especially descriptive but covered the bases. This was in my experience the most authoritive text on matlab GUI's. I suspect it still is ...
You're solving two/three problems :
Closure Problem
Nested functions resolve this problem.
function iterator = count(initial)
% Initialize
if ~exist('initial','var')
counter = 0
else
counter = initial
end
function varargout = next() % [1]
% Increment
counter = counter + 1
varargout = {counter} % [1]
end
iterator = #next
end
Note(s) :
One may not simply return counter ! It must be wrapped in varargout or assigned to some other output variable.
Usage
counter = count(4) % Instantiate
number = counter() % Assignment
number =
5
Closed Scope + State problem
No ugly braces, worrying about scope, cell arrays of strings. If you need access to something it's under SELF no more FINDOBJ, USERDATA, SET/GETAPPDATA, GLOBAL nonsense.
classdef Figure < handle
properties
parent#double
button#double
label#double
counter#function_handle
end
methods
function self = Figure(initial)
self.counter = count(initial) % [1]
self.parent = figure('Position',[200,200,300,100])
self.button = uicontrol('String','Push', 'Callback', #self.up, 'Style', 'pushbutton', 'Units', 'normalized', 'Position', [0.05, 0.05, 0.9, 0.4])
self.label = uicontrol('String', self.counter(), 'Style', 'text', 'Units', 'normalized', 'Position', [0.05, 0.55, 0.9, 0.4])
end
function up(self,comp,data)
set(self.label,'String',self.counter())
end
end
end
Note(s):
One uses the function listed in the Closure problem above
Usage :
f = Figure(4) % Instantiate
number = get(f.label,'String') % Assign
number =
5
You may prefer :
f.label.get('String') % Fails (f.label is double not handle, go figure)
h = handle(f.label) % Convert Double to handle
number = h.get('String') % Works
number =
5
Since it looks like my comment was helpful, I'll explain what I mean about the struct thing. I think the way you are calling the callback functions is slightly different, so this may not work so well).
If you have a bunch of different callback functions, and a bunch of variables you want to pass to them, it is annoying and difficult to have a big list of input arguments for each function. Instead, I do something like this:
First create a bunch of UI components , but don't specify their callback functions, e.g
radio1_handle=uicontrol(panel1_handle,'Style','radiobutton',...
'Min',0,'Max',1,'Value',0,'Units','normalized','Position',[.8 .8 .2 .25]);
once you have made all the components, create a struct of variables you will be using
vars=struct('varName1',var1,'varName2',var2);
then update the UI components to include the callback functions
set(radio1_handle,'Callback',{#radio1_callback,vars});
now create the actual functions
function radio1_callback(object,eventData,vars)
So it's nothing fancy, just a potentially neater way than using multiple arguments.
Inspired by this question and #David's comment, I came up with the solution. (Maybe this is #David's answer, but not explicitly explained. So let me extend his comment into an answer.)
There is actually a way to add extra parameters to callbacks.
Just add the parameters to the end of the parameter list
function show(object, eventdata, extra)
and set the callback like this:
func = #show;
set(gcf, 'WindowButtonMotionFcn', func);
Reference
Mathworks
Passing Additional Input Arguments
You can define the callback function to accept additional input
arguments by adding them to the function definition:
function myCallback(src,eventdata,arg1,arg2)
When using additional
arguments for the callback function, you must set the value of the
property to a cell array (i.e., enclose the function handle and
arguments in curly braces):
figure('WindowButtonDownFcn',{#myCallback,arg1,arg2})
Trying to use Timer in GUI. While attempting in following code it is showing error.
function main_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 1, ... % Initial period is 1 sec.
'TimerFcn', {#send_Callback,hObject});
guidata(hObject, handles);
function send_Callback(hObject, eventdata, handles)
comma = get(handles.Tx_send, 'String');%Tx_send is a text field
TxText = char(comma);
sf = rc4e2(TxText,key);%rc4e2 is an encryption
key = TxText;
DBC = char(sf);
disp(DBC);
fwrite(handles.serConn, DBC);%serConn is COM port
The error: Error while evaluating TimerFcn for timer 'timer-1'. Attempt to reference field of non-structure array.
Try changing your timerFcn to {'send_Callback',handles}.
In your version (as written in the original question), you have to write
'TimerFcn', {#send_Callback,handles});
The reason MATLAB is showing this error is because when it calls the Callback function, it automatically passes the timer handle as first argument and an empty event structure as second argument. The argument you provide by using the cell array is the third one. This means, your send_Callback is called with the argument list handles.timer,event,hObject (in this case, hObject is the window handle).
Then in the Callback function, you try to access handles.Tx_send, but since handles is the third argument and you provided just the window handle as the third argument, MATLAB will try to access handles.output.Tx_send, which does not exist.
Passing handles as described above should solve your problem because then the callback will have access to the handles object.