How to continuously update a plot? - matlab

I'm trying to plot in 'real time' in Matlab from Arduino. I have the following code to get the data:
clear all; close all;clc;delete(instrfind({'port'},{'COM12'}));
puerto=serial('COM12');
puerto.BaudRate=115200;
fopen(puerto);
for i=1:1000
a=fscanf(puerto, '%d');
v(i)=a;
++i;
end
fclose(puerto);
delete(puerto);
However, sometimes I get an error saying the following (in reference to variable a):
In an assignment A(I) = B, the number of elements in B and I must be the same.
Error in (line 8)
v(i)=a;
So I have 3 questions:
How can I avoid the error I mentioned?
How can I plot (v) continuously?
Is there a way to send an array of integers from Arduino to Matlab?

Try something like this. Using the BytesAvailableFcn of the serial port.
See Documentation
function serialTest()
lineHandle = plot(now,0);
hold on;
delete(instrfind({'port'},{'COM12'}));
puerto=serial('COM12');
puerto.InputBufferSize = 200; %Set to an appropriate number of bytes see docs
puerto.BaudRate=115200;
puerto.BytesAvailableFcnCount = 100; %Set to an appropriate number see docs.
set(puerto,'BytesAvailableFcn',{#bytesFcnCallback,lineHandle});
drawnow
fopen(puerto);
function bytesFcnCallback(puerto,evtData,lineHandle)
temp = fgetl(puerto); %Read a single line from the com port.
C = textscan(temp,'%f');
lineHandle(1).YData= [lineHandle(1).YData C{1}];
lineHandle(1).XData(end+1) = now;
Edit: Update to show how to continuously update a plot.

Related

Uploading Arbitary waveform on to a DS345 via Matlab

I am having difficulty in uploading an arbitrary waveform on to the DS345 function generator via the Instrument Control Toolbox in Matlab.
I have used the manual provided here (see page 3-8) to try to achieve this. The code I use is:
%% Instrument Control of DS345 Signal Generator
clear all
clc
COMtype = 'COM4';
% Find the a serial port object
obj1 = instrfind('Type', 'serial', 'Port', COMtype , 'Tag', '');
% Create the serial port object if it does not exist
% otherwise use the object that was found.
if isempty(obj1)
obj1 = serial(COMtype);
else
fclose(obj1);
obj1 = obj1(1);
end
N = 512;
Sum = 0;
number = 10;
data = zeros(number,1);
X = zeros(number,1);
Y = zeros(number,1);
obj1.OutputBufferSize = N;
fopen(obj1);
checkConnection =strcat( query(obj1,'*IDN?') );
if strcmp(checkConnection,'StanfordResearchSystems,DS345,43862,1.04') ~=1
disp(['Device Connection not working... Query msg ' ...
checkConnection])
else
disp(['Connection to ' checkConnection(25:29) ' established.'])
end
% Generating Function
for i = 1:number
X(i) = 1*i;
Y(i) = 0;
data(2*i-1) = i;
data(2*i) = 0; %8*i*(-1 + 2*(mod(i,2)));
Sum = Sum + (data(2*i-1) + data(2*i));
end
figure(1)
plot(X,Y)
grid minor
checksumdata = sum(data);
data(2*number+1) = checksumdata;
% size(data)
% convert into 16-bit binary array
data = int16(data);
dataBin = dec2bin(data,16);
checkLDWF = strcat(query(obj1,['LDWF? 1,' num2str(2*number)]));
if checkLDWF =='1'
disp('Ready to Download...')
end
pause(1)
disp('downloading...')
disp('sending DataBin...')
fwrite(obj1,dataBin,'short','async')
stopasync(obj1)
fclose(obj1);
In the code, I generate an array of straight lines and I want to upload an arbitrary vector waveform, which means using the LDWF command.
The manual suggests that I should send the 16-bit binary data followed by a checksum which is simply the sum of the data array.
The error I get is 'LOADING ERROR...' which implies that it has been waiting for 10s for the data stream and nothing has arrived. so it timeouts with the 'loading error'. Would appreciate any help/guidance possible.
I don't see anything wrong with your code.
Unfortunately I don't have access to Matlab right now.
In the meantime you might want to take a look at the method I proposed here.
It will allow you to see what is really on your port while you are sending data from Matlab to your function generator. This way you can be sure the data you are sending is correct and in particular if you are sending the right amount.

In Matlab I keep getting undefined variable or function error despite clearly defining the variable

I have this piece of code in Matlab which should take an Airfoil profile and increase the number of points so that when I plot the profile in another programme I will get a smoother curve.
clear
%reading an external data file
fid = fopen('NACA0015.txt');
a = fscanf(fid,'%g %g',[2 inf]); % It has two rows now.
a = a'; % matrix transpose
n = input('200') %e.g., n=35
for i=1:n
for j=1:2
fprintf('%12.7f',a(i,j)); %a(i,1) is first column, a(i,2) is 2nd col
end
fprintf('\n');
end
fclose(fid);
for i=1:n
x(i)=a(i,1); %x , y vectors
y(i)=a(i,2);
end
% use spline to create more points
xx=0:0.01:1 % e.g., step =0.01 (number of points = (1-0)/0.01=100)
yy = spline(x,y,xx); % xx and yy are new generated values of Naca0012
fprintf('\n print spline values \n');
plot(xx,yy,'ro')
hold on
plot(x,y,'*')
When I run this I get the error
Undefined function or variable 'x'.
Error in reading_external_data_and_spline (line 26)
yy = spline(x,y,xx); % xx and yy are new generated values of Naca0012
I am at a complete loss as to why this is not working when the x variable is clearly defined in the code, please could someone help me with this
It's how you're using input. The argument in input isn't the default value, it's the prompt text. If you type the command into the console and hit enter, you get this:
>> n = input('200')
200
n =
[]
>>
Input doesn't accept a default. If you really want to have an interactive prompt with a default answer, you want inputdlg:
answer = inputdlg('Enter a number of lines to parse', 'n', 1, '200');
n = str2double(answer);
note that inputdlg returns text always, so you need to convert to a number.

Error creating a plot in MATLAB using values I got from excel using actxserver.

Hello so I am attempting to write a MATLAB script that reads multiple excel files at ones and gathers values from the worksheet. through some research I found that using actxserver is a very quick way to get the data. The values are stored in the out and out1 variables and by using vertcat function I create an array that has all the 300,000 values that I need to store. This seems to work. However when I try to plot the values in a simple x vs y graph using plot I get an error that states:
Error using plot
Not enough input arguments.
Error in opener (line 36)
plot(out0,out1)
Below is the code. I am sure it is a simple fix but I have looked and not found anything helpful.
clc;
filename = 'C:\Users\Public\Documents\DASYLab\13.0.0\eng\data\TRIAL\';
D = dir([filename, '\*.csv']);
Num = length(D(not([D.isdir])));
f = Num;
ex = actxserver('excel.application');
o = 0;
k = 0;
for i=1:f
if(i<=10)
ex.Workbooks.Open([filename,'mydataIII_0',num2str(i-1)]);
else
ex.Workbooks.Open([filename,'mydataIII_',num2str(i-1)]);
end
out0 = get(ex.Range('A8:A40967'),'Value');
out = vertcat(o,out0);
o = out;
out1 = get(ex.Range('C8:C40967'),'Value');
outone = vertcat(k,out1);
k = outone;
end
figure;
plot(out0,out1)
ex.Quit
Hello sorry I but I figured it out. The issue was that when the get function was used to get the value it created a cell array.
http://www.mathworks.com/help/matlab/cell-arrays.html
if you want to convert the data to a ordinary array one can use the cell2mat() function

How to get value of Eccentricity from struct of Eccentricity in MATLAB?

I want to print Eccentricity of each connected component of my image and following is part of my code:
[B,L] = bwboundaries(bw,'noholes');
stats = regionprops(L,'Eccentricity');
for k = 1:length(stats)
stats(k);
end
But it doesn't really print any thing on output console. I want to get Eccentricity of each component on console.
And I want to store the float value of Eccentricity of each component in new one dimensional array so how do I do it ?
The ; in MATLAB suppresses the output of the executed line, and unlike most other languages is not required to terminate the end of a line. The easy way to "fix" this is to remove the ; from the for loop:
for k = 1:length(stats)
stats(k)
end
But it's a best practice to always have a ; at the end of every line. Rather than display this way, consider using disp() instead:
for k = 1:length(stats)
disp(stats(k));
end

Different function returns from command line and within function

I have an extremely bizzare situation: I have a function in MATLAB which calls three other main functions and produces two figures for me. The function reads in an input jpeg image, crops it, segments it using kmeans clustering, and outputs 2 figures to the screen - the original image and the clustered image with the cluster centers indicated. Here is the function in MATLAB:
function [textured_avg_x photo_avg_x] = process_database_images()
clear all
warning off %#ok
type_num_max = 3; % type is 1='texture', 2='graph', or 3='photo'
type_num_max = 1;
img_max_num_photo = 100; % 400 photo images
img_max_num_other = 100; % 100 textured, and graph images
for type_num = 1:2:type_num_max
if(type_num == 3)
img_num_max = img_max_num_photo;
else
img_num_max = img_max_num_other;
end
img_num_max = 1;
for img_num = 1:img_num_max
[type img] = load_image(type_num, img_num);
%img = imread('..\images\445.jpg');
img = crop_image(img);
[IDX k block_bounds features] = segment_image(img);
end
end
end
The function segment_image first shows me the color image that was passed in, performs kmeans clustering, and outputs the clustered image. When I run this function on a particular image, I get 3 clusters (which is not what I expect to get).
When I run the following commands from the MATLAB command prompt:
>> img = imread('..\images\texture\1.jpg');
>> img = crop_image(img);
>> segment_image(img);
then the first image that is displayed by segment_image is the same as when I run the function (so I know that the clustering is done on the same image) but the number of clusters is 16 (which is what I expect).
In fact, when I run my process_database_images() function on my entire image database, EVERY image is evaluated to have 3 clusters (this is a problem), whereas when I test some images individually, I get in the range of 12-16 clusters, which is what I prefer and expect.
Why is there such a discrepancy? Am I having some syntax bug in my process_database_images() function? If more code is required from me (i.e. segment_images function, or crop_image function), please let me know.
Thanks.
EDIT:
I found the source of the problem. In my load_image function, after I call img = imread(filename), I convert the image to double: `img = im2double(img);'. When I comment this line out, I get the desired result. Anyone know why this happens? (and also how I can 'close' this question since I have located the problem).
clear all at the top of your function is unnecessary and may be the source of your trouble.
Also, turning off all warnings is a bad idea since it may mask other problems.
Let's look at this code, simplified by removing redundant code or unused code:
function [textured_avg_x photo_avg_x] = process_database_images()
type_num_max = 1;
img_max_num_photo = 100; % 400 photo images
img_max_num_other = 100; % 100 textured, and graph images
for type_num = 1:2:type_num_max %% 1:2:1 => 1
img_num_max = 1; %This nullfiies everything in the if block above anyways
for img_num = 1:img_num_max %% 1:1 => 1
[type img] = load_image(type_num, img_num); %% Input (1,1)
img = crop_image(img);
[IDX k block_bounds features] = segment_image(img);
end
end
end
It looks like this code runs through the double nested for loop exactly once, maybe that is why you get only one answer, three clusters.
Try calling your function on the command line with the same amount of return values as in the function you wrote. Instead of
>> segment_image(img);
Try:
>> [IDX k block_bounds features] = segment_image(img);
Functions in Matlab check how many return values are expected, and may behave differently depending on that.