clearing serial buffer in matlab - matlab

i am simply printing there floats form my arduino or any other serial output device... in matlab i am receiving them and plotting them. it is being printed in arduino very fast but in matlab it is slower and after a a minute or so the plot is not reacting to the numbers from arduino fast... it seams matlab is slower and it is keeping the records in buffer? how can i clear it and get the fresh data plotted?
one more thing does it make sense that matlab can't import and plot a few numbers in 100Hz? What i am doing wrong or inefficient ?
clc
clear all
h = figure(1);
set(h,'UserData',1);
s=serial('/dev/tty.usbmodem1411','BaudRate',115200);
set(s,'DataBits',8);
set(s,'StopBits',1);
fopen(s);
s.ReadAsyncMode='continuous';
readasync(s);
tStart = tic;
xplot=subplot(3,1,1);
hold on;
xlabel('time(ms)');
ylabel('X angle(deg)');
yplot=subplot(3,1,2);
hold on;
xlabel('time(ms)');
ylabel('Y angle(deg)');
zplot=subplot(3,1,3);
hold on;
xlabel('time(ms)');
ylabel('Z angle(deg)');
cont=true;
xAngle = zeros(1,1000000);
yAngle = zeros(1,1000000);
zAngle = zeros(1,1000000);
i=0;
while(true)
i=i+1;
t = toc(tStart);
%angle = fscanf(s, '%f');
[x y z] = strread(fgetl(s,s.BytesAvailable),'%f %f %f');
plot(xplot,t,x,'.');
plot(yplot,t,y,'.');
plot(zplot,t,z,'.');
drawnow;
end
fclose(s);

It is likely that the speed of the 'plot' command is the problem. Creating a new plot is a slow operation, and so after you have received a few points, the time it takes to create the plot gets large. If you want to plot "real time" data in matlab, you will need to use some methods such as discussed in this question.
You can investigate the situation by changing your loop code to read data from the device and just print the line on the screen without plotting it. I expect you will see that the numbers can be printed as fast as they are received.

Related

Looping over subplots and holding [duplicate]

This question already exists:
Matlab subplots in loop: only shows plots in last iteration
Closed 3 years ago.
I'm trying to create a plot and layer multiple functions over each of the subplots. The output I'm getting, however, is only showing the final plot in each iteration. In other words, all subplots are filled with something, but only with the last curve that I 'added' (or at least I thought I did) -- the cyan curve. I tried using hold onin a number of different places, to no avail. Does anyone see what the problem might be?
%% Training phase
% Setting for plots
figure;
for tai = 1:length(training_algorithms)
% Create first subplot (and make sure we stay there)
subplot(3,2,tai);
% Plot the (sampled) sine function
plot(x,y,'bx');
hold on
colors = ['r', 'm', 'c'];
for nh = 1:length(num_hid)
net = networks{tai, nh}; % Load network
net.trainParam.showWindow = false; % Don't show graph
% Train network, and time training
tic;
[net, tr] = train(net, p, t);
durations(tai)=toc;
% Simulate input on trained networks (and convert to double format)
y_result = cell2mat(sim(net, p));
% Evaluate result
[slo, int, correlations{tai}] = postregm(y_result, y);
% Add network to array
networks{tai} = net;
% Plot network approximation results
plot(x,y_result,colors(nh))
ylim([-3 3])
title(training_algorithms{tai});
end
hold off
end
It looks like this has been answered already but it is also worth noting that even though you are setting the net.trainParam.showWindow property to 'false,' Matlab may still create a new figure and make it active even though it remains hidden. Then any plots you perform after that won't stack like you want unless you make the original plot active again.
For example, if you run the below code (I stripped out all of your specific functions but recreated the affect) you will see that at the end, there are 20 or so figures open but only 1 is visible. Uncommment the line towards the bottom in order to create the kind of stacked subplots you are after... Hope this helps.
Cheers.
% Training phase
% Setting for plots
f1=figure(1);
for i = 1:6
% Create first subplot (and make sure we stay there)
subplot(3,2,i);
x=0:.1:2*pi;
y=sin(x);
% Plot the (sampled) sine function
plot(x,y,'b');
hold on
colors = {'r', 'm', 'c'};
for j=1:3
f2=figure;
set(f2,'Visible','off');
y2=sin(x+j);
% Plot network approximation results
% figure(f1) % - uncommment me
plot(x,y2,colors{j})
end
hold off
end
figHandles = findobj('Type', 'figure')

Time series animation in Matlab

I am new to working with time series in Matlab and am struggling with getting this going. I have time series heat-transfer data (over a period of 20ms in steps of 1 microsecond) at these 11 locations (see code below). I am clueless as to how I could put them together to be able to generate a plot at each time step and use getframe at each timestep to make an animation. Any help on how to get started with this would be much appreciated. Here is a link to the 11 data files, providing time on column1 and heat transfer on column2: https://drive.google.com/open?id=1oDAdapqvL-blecb7BOLzxpeiJBsqLd59
Please feel free to suggest any other tools (matplotlib/plotly etc.) that may be better in this scenario as well. Thanks a ton!
close all
clear all
x1=399.5
x2=400.5
y0=0
y1=4
y2=8
y3=12
y4=16
y5=20
y6=-4
y7=-8
y8=-12
y9=-16
y10=-20
%The gauge locations for the first row will be [x1,y1], [x1,y3], [x1,y5], [x1,y6], [x1,y8],
%[x1,y10]
%The gauge locations for the second row will be [x2,y0], [x2,y2], [x2,y4], [x2,y7],
%[x2,y9]
figure
plot(x1,y1,'r.', x1,y3,'r.', x1, y5, 'r.', x1, y6, 'r.', x1, y8, 'r.', x1, y10, 'r.')
hold
plot(x2,y0,'b.', x2,y2,'b.', x2, y4, 'b.', x2, y7, 'b.', x2, y9, 'b.')
axis([390 410 -30 30])
In Matlab you can use, as you said the getFrame and writeVideo functions. Ill explain it for a very general case, which you can then apply to yours.
Let's say we have a plot that changes it's data at every iteration inside a for loop (happens frequently when solving PDEs and so on) with an exemplary function solverIteration (made up...). We are plotting a vector y over our domain x.
In order to record the video we have to do the following:
video = VideoWriter('myVideo.avi'); %Create a video object
open(video); % Open video source - restricts the use of video for your program
for m=1:K
y = solverIteration(y);
plot(x,y);
drawnow;
vidFrame = getframe(gcf);
% instead of gcf you can specify which figure you want to capture
clf;
writeVideo(video,vidFrame); % adds frames to the video
end
close(video);
This script is an example for how to record a video. There are several examples and explanations at the official matlab site.

Getting displacement data from acceleration in matlab

Im working on a project right now using arduino and im stuck,i didn't find a way to get the displacement data from the data i get from the 3-axis accelerometer im using this code:
clear all, clc
%delete(arduino)
com='COM_31';
delete(instrfind({'Port'},{com}));
arduino=serial(com,'BaudRate',9600);
fopen(arduino);
while(1)
donnee=fscanf(arduino,'%f\t %f\t %f'),
x=data(1); y=data(2) ;z=data(3),
plot3(x,y,z)
hold on
end
fclose(arduino);
is there a simple way i can achieve this and plot the result in 3D
thanks,
If you declare three vectors from the start and fill them with your measured data you can plot the whole trajectory.
clear all; clc
%delete(arduino)
com='COM_31';
delete(instrfind({'Port'},{com}));
arduino=serial(com,'BaudRate',9600);
fopen(arduino);
fig=figure(1);clf;
x=0;y=0;z=0;
vx=0;vy=0;vz=0;
tic
while(1)
data=fscanf(arduino,'%f\t %f\t %f');
dt = toc;tic;
vx=vx+dt*data(1);
vy=vx+dt*data(2);
vz=vz+dt*data(3);
x(end+1)=x(end)+vx*dt;
y(end+1)=y(end)+vy*dt;
z(end+1)=z(end)+vz*dt;
plot3(x,y,z)
end
fclose(arduino);

Visualising fft-signal__Waterplot

This is the kind of plot i imagined myself.
https://de.mathworks.com/help/matlab/ref/waterfall.html
Ok, i don't want to explain too much, how my code works. It would take too much time. Just try the second code yourself. Take any small wav-file you can find. When you compile the code, you can see three frequency bands and see that many spectrums are plotted every 30ms. If you have a specifically question concerning my code, how it works, ask me in the comments.
I want every spectrum, at least from one frequency band, to plot it in a 3-dimensional plot. In short, what are the coordinates of the first spectrum and the 2nd, the 3rd, the 4th and so on.
My time segment on which is a fft applied, is 30 ms long. The first point on the x-axis is 30 ms, the next one 60ms and the next one 90ms and so on. What is the y-coordinate from the 30ms? This would be on the frequency axis or the y-axis. The z-axis would be the magnitude out of a frequency component at some point in time (or at a given sliding window frame). How can i do that? How do i write that? I am having big trouble with this matter. And since every explanation is in another language, it makes it much more harder for me.
As you may know, i have an audiofile (music) on which i compute a STFT. I want to visualise it. See the following explanation in my code. Read the comments!
My first idea to do this way, was using the function "mesh" or something similar.
Here is my mesh-code:
X=1:10;
Y=1:15;
Z = [];
% Here i would define the number of time segments
% See the next following code, to understand, what i mean.
for i = 1:length(X)
% Here in this line, i want to compute my short fft
%
% number of frequencies
for j = 1: length(Y)
Z(j,i) = 1.0/(i*j);
end
end
mesh(X,Y,Z)
This code plots me a mesh, i just wanted to know for myself, how this works. Anyway please be aware, that i am quite sure that i do not know, how the function "mesh" works to the fullest, but i think, i understood most of it.
Another thing i need to mention is, that i am defining frequency bands in my next following code. I did this, because i noticed, i have very high amplitudes in a range from 1 - 1000Hz, which is why, i defined 3 frequency bands. It is not necessary to plot all of them, but i want to visualise at least one. Not visualising the whole frequency range from the audio signal, but only the specificially chosen band.
%% MATLAB
%_________________________________________
[y,fs]=audioread('dontstopmenow.wav');
% audioread = Read WAV-file
% y = Vector, which contains audio signal
% fs = Sample Rate
% 'dontstopmenow' = WAV-file
%_________________________________________
%PARAMETER FOR STFT
%_________________________________________
t_seg=0.03; % Length of segment in ms
fftlen = 4096; %FFT-Points
%Defining the length of my frequency bands
f_LOW= 1:200; % contain lower frequencies
f_MEDIUM= 201:600; % contain medium frequencies
f_HIGH= 601:1000; % contain higher frequencies
%_______________________________________________________
segl =floor(t_seg*fs);
% Length of segment, on which we use the fft
% "floor" rounds off the result
windowshift=segl/2;
% size of window which goes to the next segment
window=hann(segl);
%hann function
window=window.';
% From a row vector to a column vector
si=1;
%Start index
ei=segl;
%End index
N= length(y)/windowshift - 1;
% Number of time segements in audio signal
f1=figure;
% New window
f=0:1:fftlen-1;
f=f/(fftlen-1)*fs;
% frequency vector
Ya=zeros(1,fftlen);
%Plotting time segments!
for m= 1:1:N
y_a = y(si:ei);
y_a= y_a.*window;
Ya=fft(y_a, fftlen);
Ya=abs(Ya(1:end/2));
%One-sided-spectrum
drawnow; %Updates graphical objects
figure(f1);
plot(f(1:end/2), 20*log10(Ya));
%STFT __ plots the whole audio signal after a stft, every 30ms
%% L,M,H - Bands
subplot(3,1,1)
y_low = Ya(f_LOW);
plot(f_LOW,y_low);
ylim([-20 60]);
title('Spektrum (LOW)');
xlabel('f(Hz)');
ylabel('dB');
grid on
subplot(3,1,2)
y_medium = Ya(f_MEDIUM);
plot(f_MEDIUM,y_medium);
ylim([-20 30]);
title('Spektrum (MEDIUM)');
xlabel('f(Hz)');
ylabel('dB');
grid on
subplot(3,1,3)
y_high = Ya(f_HIGH);
plot(f_HIGH,y_high);
ylim([-20 30]);
title('Spektrum (HIGH)');
xlabel('f(Hz)');
ylabel('dB');
grid on;
si=si+windowshift;
% start index updated
ei=ei+windowshift;
% end index updated
end
Here's the list of statements you could add to your code to generate the waterfall plot:
Let's store all STFT outputs in a matrix named Yb. Firstly, allocate the memory by adding this line before the for-loop.
Yb = NaN(N, fftlen/2);
Next, in the for-loop, save the fft result for each segment. This can be done by adding the following line after you have finished the computation of Ya (just before drawnow).
Yb(m,:) = Ya;
Now you're ready to generate the waterfall plot. This can be done by adding the following code after the end of the for-loop.
figure;
waterfall(f(f_LOW), (1:N)*windowshift/fs, Yb(:,f_LOW));
xlabel('Frequency (Hz)');
ylabel('Time (s)');
Hope this achieves what you want.
Following is not related to the main question: I also have the following suggestions to improve some other aspects of your code:
(1) The computation of the frequency grid f has a small scaling error. It should be:
f=f/fftlen*fs;
(2) Depending on the WAV file you use, your code may get fractional values in windowshift and N, but both of them need to be integers. So, use appropriate rounding methods while computing them. I'd suggest the following:
windowshift = round(segl/2);
N = floor(length(y)/windowshift);
(3) In the for-loop, you plot the whole fft only to overwrite that with the subplots immediately. That line should be removed.

Plotting measured data along with Bode plot

I am taking a circuits class and for lab we need to do a little work with MATLAB to plot some of the results. I got the following code which I used to generate a Bode plot of the transfer function for a filter we were designing. I sort of get how it works but I don't really know or use MATLAB outside of this class.
clc;
close all
s=tf('s');
w=628*1000;
H=(1/(1 + 1.85*s/w + s^2/w^2))*(1/(1 + 0.77*s/w + s^2/w^2));
figure;
bode(H)
This worked fine but now I need to plot the transfer function I measured in the lab against this data on the SAME plot axis. How can I plot both of them together. I have the lab data as a list of gain frequency pairs.
Instead of bode(H), try:
[mag,ph,w] = bode(H); % gets the data without generating the figure
plot(w, mag, 'b'); % plots only the magnitudes
freqs = data(:,1); % These 2 lines depend on how your data is formatted
gains = data(:,2); % These 2 lines depend on how your data is formatted
hold on % will add new content to the existing figure without erasing the previous content
plot(freqs, gains, 'r');
hold off
you could also try (inspired by http://www.mathworks.com/help/ident/ref/bodeplot.html) :
h = bodeplot(H);
setoptions(h,'FreqUnits','Hz','PhaseVisible','off'); % suppress the phase plot
freqs = data(:,1); % These 2 lines depend on how your data is formatted
gains = data(:,2); % These 2 lines depend on how your data is formatted
hold on % will add new content to the existing figure without erasing the previous content
plot(freqs, gains, 'r');
hold off