我在Matlab中编写了一个while循环,它应该使用Matlab中的tic toc延迟以指定的时间间隔将数组中的每个值从Matlab发送到arduino,然后读取值并将它们存储在变量中并将它们绘制成图形。
while循环的输出随着每次连续迭代而减慢。
我增加了缓冲区,这对它有很大帮助,但它仍然会减慢太多。是否有另一种方法来提高按时打印值的速度。我已经包含了另一个tic toc和图表来显示这里的执行速度是代码:
max = 80;
min = 40;
amp = (max-min)/2;
offset = amp + min;
btime = 5;
bpm = 12;
spb = 60/bpm;
sapb = spb/.05;
tosd = sapb*bpm*btime;
time1 = btime*60;
x = linspace(0,time1,tosd)';
x1 = amp*sin(x*(2*pi/20)) + offset;
pause(1);
fprintf(handles.UltraM,(['<P' num2str(offset) '>']))
pause(5);
y = [];
i = 1;
figure(1);
hold on;
title('Pressure Data');
xlabel('Data Number');
ylabel('Analog Voltage (0-1023)');
t1 = [];
figure(2);
hold on;
title('Time to execute task');
xlabel('iteration number');
ylabel('time taken');
while (i<=length(x))
t2 = tic;
t = tic;
fprintf(handles.UltraM,(['<P' num2str(x1(i)) '>']));
%disp((['<P' num2str(x1(i)) '>']));
y(i) = fscanf(handles.UltraM,'%d');
figure(1);
hold on;
plot(i, y(i), 'b*');
drawnow;
hold off;
while toc(t) < 0.05
continue
end
t1(i) = toc(t2);
figure(2);
hold on;
plot(i,t1(i),'b*');
drawnow;
hold off;
i = i + 1;
end
答案 0 :(得分:1)
经过一番反复思考后,我想我知道你想要实现的目标以及阻碍你的方向。
我已经编辑了你的代码,使其更加快速和可读。大多数情况下,操作仅略高于0.05
秒,并且在几个时间点可能比预期长约5
毫秒。你的millage当然可能会有所不同。由于我没有arduino,我不知道那里是否有瓶颈。您还应该尝试使用内置的Matlab分析器(它非常有用)来分析您的代码,以查看究竟是什么减慢了代码的速度。
我发现减慢代码的主要原因是你使用plot
函数一次向你的数字添加一个点。每次调用此函数时,它都会创建一个新的图形对象。几百个之后,事情变得缓慢。相反,您应该只更新已绘制的数据并使用drawnow
重绘它。
简而言之,解决方案是:
1)使用单个点初始化绘图并保存图形句柄以供以后使用:
p1 = plot(0,0,'b*');
2)然后,在循环内部,一旦更新了数据阵列,用新阵列替换现有绘图中的数据。
set(p1, 'XData', 1:i, 'YData', y(1:i));
3)重绘图以反映最新更新。
drawnow;
drawnow
最终会减慢您的代码速度,因为它必须在每次迭代时重绘越来越大的图。为了使工作更快,您可能希望在更长的间隔后刷新绘图。例如,以下内容将每10次迭代刷新一次:
if rem(i,10) == 0
drawnow;
end
以下完整代码。如果您还有其他问题,请与我们联系。
max = 80;
min = 40;
amp = (max-min)/2;
offset = amp + min;
btime = 5;
bpm = 12;
spb = 60/bpm;
sapb = spb/.05;
tosd = sapb*bpm*btime;
time1 = btime*60;
x = linspace(0,time1,tosd)';
x1 = amp*sin(x*(2*pi/20)) + offset;
pause(1);
%fprintf(handles.UltraM,(['<P' num2str(offset) '>']))
disp(['<P' num2str(offset) '>']); % replacing with disp (I don't have an arduino)
pause(5);
%y = []; % unnecessary here, preallocated before loop
figure(1);
p1 = plot(0,0,'b*'); % plotting one dot to create an object, data will be overwritten
hold on;
title('Pressure Data');
xlabel('Data Number');
ylabel('Analog Voltage (0-1023)');
%t1 = []; % unnecessary here, preallocated before loop
figure(2);
p2 = plot(0,0,'b*'); % plotting one dot to create an object, data will be overwritten
hold on;
title('Time to execute task');
xlabel('iteration number');
ylabel('time taken');
% preallocate t1 and y arrays for faster operation
t1 = zeros(size(x));
y = zeros(size(x));
i = 1; % moved closer to loop beginning for better readability
while i <= length(x) % parentheses unnecessary in Matlab
t2 = tic;
t = tic;
%fprintf(handles.UltraM,(['<P' num2str(x1(i)) '>']));
disp((['<P' num2str(x1(i)) '>'])); % replacing with disp (I don't have an arduino)
%y(i) = fscanf(handles.UltraM,'%d');
y(i) = randn; % replacing with random number (I don't have an arduino)
%figure(1); % unnecessary
%hold on; % unnecessary
%plot(i, y(i), 'b*');
% replacing the above with a slightly faster version
set(p1, 'XData', 1:i, 'YData', y(1:i));
%drawnow; % first one is annecessary
%hold off; % unnecessary
while toc(t) < 0.05
continue
end
t1(i) = toc(t2);
%figure(2); % unnecessary
%hold on; % unnecessary
%plot(i,t1(i),'b*');
% replacing the above with a slightly faster version
set(p2, 'XData', 1:i, 'YData', t1(1:i));
if rem(i,10) == 0 % refreshing every 10 iterations
drawnow;
end
%hold off; % unnecessary
i = i + 1;
end
对以前版本的问题的回答
您可以通过使用以下两个语句完全替换它来对您的循环进行矢量化:
% vectorizing num-to-string conversion
y4 = cellstr(strcat('<P',num2str(x1), '>'));
% deleting all spaces
y4 = cellfun(@(u) u(~isspace(u)), y4, 'UniformOutput', false)
这个小调整使您的程序在我的电脑上运行x4
更快。
显示/打印结果也可以使用cellfun
迭代器完成:cellfun(@disp, y4)