A Blue Shoe
A Blue Shoe

Reputation: 157

MATLAB timer acts differently inside function than in command window

I have some code that takes measurements from an external device and I want to take measurements for a set amount of time. I need to record the measurements along with timestamps, so I put together a while loop to run during execution of the timer, with the condition to exit the loop when the timer reaches zero.

The "meter" variable is the handle to the external device, and talking to it is not a problem.

The issue is that the while loop never exits when the code is executed within a function, even though the "Finished!" method successfully displays. The code works fine if I run it alone in the command window, and there are no other instances of timers running in the code, so I have no idea why this different behavior occurs. I would use a pause to keep track of the time, but I want to take as many readings as possible during the 10 seconds, so that just won't fly.

fprintf('\nCollecting 10 s data from detector...');
i = 1;
t1 = timer('TimerFcn','stat=false; fprintf(''\nFinished!'')','StartDelay',10);
start(t1);
stat = true;
while(stat==true)
    Timestamps{i} = datetime('now');
    fprintf(meter,':READ?');
    Current(i) = str2num(fscanf(meter));
    i = i + 1;
end

Any thoughts on why this might behave differently when within a function?

Upvotes: 2

Views: 72

Answers (1)

gnovice
gnovice

Reputation: 125854

Your problem has to do with variable scoping. When your code is run in a function, the variable stat exists in that functions local workspace, not in the base workspace (i.e. the workspace of the Command Window). When you supply a string callback to the timer function, the code in that string is executed in the base workspace. Therefore, when your timer fires, it prints a message and modifies a variable stat in the base workspace, but the variable stat in the local function workspace is unchanged.

The way I prefer to handle this is to create a nested function for the timer callback, nested within your larger function containing the loop. For example:

function Current = collect_data(meter)

  fprintf('\nCollecting 10 s data from detector...');
  i = 1;
  t1 = timer('TimerFcn', @timer_callback, 'StartDelay', 10);
  start(t1);
  stat = true;

  while (stat == true)
    Timestamps{i} = datetime('now');
    fprintf(meter, ':READ?');
    Current(i) = str2num(fscanf(meter));
    i = i + 1;
  end

  function timer_callback(~, ~)
    stat = false;
    fprintf('\nFinished!');
  end

end

In this case, the variable stat is shared across the functions collect_data and timer_callback, and the loop terminates as expected when the timer fires.

Upvotes: 4

Related Questions