passing a file to the timer function
조회 수: 4 (최근 30일)
이전 댓글 표시
Hi, I am having trouble with my program. I am receiving data from 8 channels in one file. At the beginning of the program, I open up the file and parse through it, making an array for each of the channels. Then I plot these values on one graph. Every 100ms the data is updated. I would like for my graph to update as my data is updated. I am using a timer function to try to accomplish this. Everytime the timer function is called, it opens the updated file, parses through the data, makes the 8 arrays for the 8 channels, then updates the graphs and repeats repeats repeats.
The problem I am currently having is that after the first callback of the timer, the command window says "Reference to a cleared variable filetoRead." So obviously the file has been cleared and its trying to read a cleared file. How do I pass the "filetoRead" to the callback function. I tried using UserData but this didnt seem to work. Is there an easier way to refresh the file that i had once previously opened? I have asked this question two times before on the forum and no one answered it for me.
댓글 수: 3
채택된 답변
Jan
2017년 8월 3일
편집: Jan
2017년 8월 3일
The shown code contains several problems:
- You have some variables with an index hidden in the name. This requires to create a lot of redundant code, instead of using a smart loop with using a real indexed array:
assignin('base','channel1',channel1);
- In addition the "remote controlled" creation of variables in the base workspace suffers from the same problems as global variables.
- Both together decreases the readability of the code such massively, that I cannot see the intention anymore and would not dare to edit the code in consequence.
- Some code parts can be massively simplified:
y2=zeros(1,NDataPoints);
ind=1;
for p=1:NDataPoints;
y2(1,ind)=channel2(1,p);
ind=ind+1;
end
What about:
y2 = channel2(1, 1:NDataPoints);
or even:
y2 = channel2; % Because channel2 is a [1 x NDataPoints] vector already
- In the timer callback, the variable "filetoRead" does not exist at all. You should get an error message:
function TimerCallback(TimerH, EventData)
fid = fopen(filetoRead,'r','b');
...
Or is this a nested function? Then the darn clear all at the end of the main function would kill the contents. Note that clear all is junk at all, because it removes all functions loaded to memory and the reloading from disk wastes a lot of time. Simply omit this.
Then access the UserData of the timer, because you have defined it already:
TimerH = timer('Period', 0.1, 'ExecutionMode', 'fixedRate', ...
'TimerFcn', @TimerCallback, 'UserData', filetoRead);
% And then in the Timer's callback:
function TimerCallback(TimerH, EventData)
filetoRead = get(TimerH, 'UserData');
fid = fopen(filetoRead,'r','b');
- Defining the Timer callback as nested function might have advantages, if shared variables are used. But here I do not see a reason for this. Better move the callback to an own function. Store the handles of the plot's either in the Timer's UserData, or by guidata in the figure.
- If you import the complete file repeatedly, you will get timing problems: 0.1 seconds is short for reading a growing file. The import method looks quite confusing and due to the lack of comments, it is hard to guess the intention.
- If you read a file simultaneously with another process writing to it, you cannot be sure to catch the correct end of file. This is a racing condition and it will fail from time to time.
- Most of all: clean up the code and remove the hidden indices in the names.
- Use a proper code intentation: Ctrl-a Ctrl-i
- There are no semicolons behind for, end, case, switch, otherwise.
댓글 수: 4
Jan
2017년 8월 4일
편집: Jan
2017년 8월 4일
Do not use "a1", "a2", ... as set of variables, but a vector a with different indices a(1), a(2), ... In your case replace this:
channel1 = zeros (1,NDataPoints,'double');
channel2 = zeros (1,NDataPoints,'double');
channel3 = zeros (1,NDataPoints,'double');
channel4 = zeros (1,NDataPoints,'double');
channel5 = zeros (1,NDataPoints,'double');
channel6 = zeros (1,NDataPoints,'double');
channel7 = zeros (1,NDataPoints,'double');
channel8 = zeros (1,NDataPoints,'double');
by:
channel = zeros(NDataPoints, 8);
Then your old "channel7" is "channel(:, 7)", which can be processed in a loop easily. (Note that I have transposed the array, because Matlab stores arrays in columnwise order and processing neighboring elements is faster.)
Instead of
for k=1:NDataPoints;
channel8(1,k)=temp_dbl(k);
end
Write:
channel(:, 8) = temp_dbl;
추가 답변 (1개)
KL
2017년 8월 3일
You need to get the UserData from the timer object inside your timer function.
filetoRead = get(TimerH, 'UserData');
댓글 수: 0
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!