Struct contents reference from a non-struct array object.

I am trying to control a microfluidic syringe pump. I want to create a timer to stop the liquid extrusion after it starts. Here is part of my code in which I am getting errors. I have more code, which I could provide if this isn't enough
% Create Timer to STOP flow after it has started
CONSTANT.color = 'cygm';
CONSTANT.channel = 1;
CONSTANT.serial = 1123;
CONSTANT.command = 1;
CONSTANT.test_channel = 1;
sample_period = 5; %5 was chosen arbitrarily for testing purposes; may need to be chaged
timer_period = sample_period / length(CONSTANT.channel);
timer_period = timer_period + mod(timer_period, 0.001);
CONSTANT.timer1 = timer('ExecutionMode','fixedRate',...
'Period',timer_period,...
'TimerFcn',{@timer_update_fcn},...
'StartDelay',0,...
'StartFcn', {@timer_start_fcn}, ...
'StopFcn', {@timer_stop_fcn},...
'BusyMode','drop');
% 'BusyMode','error',...
% 'ErrorFcn',{@timer_error_fcn});
The line that states:
'TimerFcn',{@timer_update_fcn},...
is calling a function script I have which has code ( i also have more code of this but am only posting up to where i get errors):
function timer_update_fcn(hObject,eventdata)
global CONSTANT MUTATE DATA QUEUE
MUTATE.last_update_time = toc(CONSTANT.timer_start_tic);
% tic
%%increment sequence (timer throw error for any missed update)
seq = MUTATE.next_sequence;
if seq < length(CONSTANT.channel)
MUTATE.next_sequence = seq + 1;
elseif seq == length(CONSTANT.channel)
MUTATE.next_sequence = 1;
else
MUTATE.next_sequence = 1;
end
% toc
%%find out what to write to CONSTANT
include = find(CONSTANT.test_channel == CONSTANT.channel(seq),1);
if isempty(include)
w = CONSTANT.command.mean;
else
w = interp1(CONSTANT.command.time,CONSTANT.command.value,MUTATE.last_update_time);
end
I am getting this error:
Error while evaluating TimerFcn for timer 'timer-1'
Struct contents reference from a non-struct array object.
The error seems to arise at the line:
%%find out what to write to CONSTANT
include = find(CONSTANT.test_channel == CONSTANT.channel(seq),1);
if isempty(include)
w = CONSTANT.command.mean;
else
w = interp1(CONSTANT.command.time,CONSTANT.command.value,MUTATE.last_update_time);
end
I think it has to due with me declaring CONSTANT.command = 1; because i took part of this code from the syringe pump code examples, I am not sure what value CONSTANT.command should equal. but they noted in the documents that
"% @ command is a structure containing input signal to the pump that
% will be sampled by the timer"

Answers (1)

Your posted code does not "global CONSTANT" before initializing CONSTANT.
Using global is not recommended.

6 Comments

I have placed
global CONSTANT MUTATE DATA QUEUE
before the declaration of
CONSTANT.color = 'cygm';
CONSTANT.channel = 1;
CONSTANT.serial = 1123;
CONSTANT.command = 1;
CONSTANT.test_channel = 1;
In the first part of my code, I just forgot to copy and paste it in the question, sorry about that. Are you suggesting to not use global at all?
It is better to note use global at all.
Notice you refer to CONSTANT.command.mean in the code, but you initialize CONSTANT.command to be a scalar.
Yeah that is the main issue I am confronting. I am not sure what CONSTANT.command should be initialized as. Majority of the code I got from the company that I got the syringe pump from. but they originally had it as "CONSTANT.command = command;" and left as that for you to input your own initialization command. But I am not sure if I am suppose to initialize it as an array or not if that makes sense?
It appears that it needs to be a struct with fields mean and time and value . The time and value fields should be vectors the same length, but mean should be a scalar.
I have to wonder if it is going to work, though: the value to interpolate at is going to depend upon toc() since a value that is not defined in the code, so it would not be surprising if the toc() happened to exceed the largest value in the time field. By default interp1() will return nan instead of interpolating beyond the existing data.
Once you have w, your posted code ignores it.
Your posted code hints that CONSTANT.timer_start_tic might need to be updated, but your posted code does not do that. If it is not updated then you will get the nan problem for sure.
If it makes anything clearer, here is the full code of the timer_update_fcn:
function timer_update_fcn(hObject,eventdata)
global CONSTANT MUTATE DATA QUEUE
MUTATE.last_update_time = toc(CONSTANT.timer_start_tic);
% tic
%%increment sequence (timer throw error for any missed update)
seq = MUTATE.next_sequence;
if seq < length(CONSTANT.channel)
MUTATE.next_sequence = seq + 1;
elseif seq == length(CONSTANT.channel)
MUTATE.next_sequence = 1;
else
MUTATE.next_sequence = 1;
end
% toc
%%find out what to write to CONSTANT
include = find(CONSTANT.test_channel == CONSTANT.channel(seq),1);
if isempty(include)
w = CONSTANT.command.mean;
else
w = interp1(CONSTANT.command.time,CONSTANT.command.value,MUTATE.last_update_time);
end
% toc
%%write and read
mfcs_set_auto(CONSTANT.handle,w,CONSTANT.channel(seq));
wt = toc(CONSTANT.timer_start_tic);
% toc
[r,chrono] = mfcs_read_chan(CONSTANT.handle,CONSTANT.channel(seq));
rt = double(chrono)*0.025 - CONSTANT.pump_start_time;
% toc
%%check bad read
if rt == MUTATE.pump_last_read_time(seq)
display('bad read')
end
MUTATE.pump_last_read_time(seq) = rt;
%%store
DATA(CONSTANT.channel(seq)).in_value = [DATA(CONSTANT.channel(seq)).in_value; w];
DATA(CONSTANT.channel(seq)).in_time = [DATA(CONSTANT.channel(seq)).in_time; wt];
DATA(CONSTANT.channel(seq)).out_value = [DATA(CONSTANT.channel(seq)).out_value; r];
DATA(CONSTANT.channel(seq)).out_time = [DATA(CONSTANT.channel(seq)).out_time; rt];
% toc
%%queue
QUEUE(CONSTANT.channel(seq)).in_value =...
[QUEUE(CONSTANT.channel(seq)).in_value(2:end); w];
QUEUE(CONSTANT.channel(seq)).in_time =...
[QUEUE(CONSTANT.channel(seq)).in_time(2:end); wt];
QUEUE(CONSTANT.channel(seq)).out_value =...
[QUEUE(CONSTANT.channel(seq)).out_value(2:end); r];
QUEUE(CONSTANT.channel(seq)).out_time =...
[QUEUE(CONSTANT.channel(seq)).out_time(2:end); rt];
% toc
if MUTATE.last_update_time >= CONSTANT.command.duration
if strcmp(get(CONSTANT.timer1, 'Running'), 'on')
stop(CONSTANT.timer1)
end
end

Sign in to comment.

Categories

Asked:

on 4 Jan 2018

Commented:

on 5 Jan 2018

Community Treasure Hunt

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

Start Hunting!