Speed up serial Communication with parallel computing

Hello everybody,
I have a Mikrocontroller, which (with the help of a gain and phase detector) measure the gain and phase signals of a RLC-Circuit. I want to process and display the signals on the pc with matlab. The problem is that the serial communication is very slow. I want to make it faster by using parallel computing. I want to divide my code in two sections: One section (or one Worker) is reading out the Data and process it and the other is plotting it (Live plotting with drawnow). This all repeats continious in a while-loop. Meanwhile the second worker is plotting, the Data must be read out again. In these case i can make it faster. below is my Code.
The Problem i have is that the second worker only print the first fprintf (The "Resonanzfrequenz"). Their is no plotting. Furthermore i do not feel that the speed is increased. Can somebody help me?
spmd
switch labindex
case 1
%Verbindung zum Mikrocontroller aufbauen
if ~isempty(instrfind)
fclose(instrfind);
delete(instrfind);
end
%Port vom User angeben lassen, andem der Arduino angeschlossen ist
s=serial('COM4','BaudRate',9600); %Einrichten der seriellen Schnittstelle
fopen(s);
fprintf(s,'%s\n',num2str(freq_start));
fprintf(s,'%s\n',num2str(freq_stop));
fprintf(s,'%s\n',num2str(freq_schritt));
fprintf(s,'%s\n',num2str(messung_start));
messdaten = zeros(1,(messwerte_max)+1);
for i=1:(messwerte_max+1)
messdaten(i) = str2double(fscanf(s)); %Speichern der Messdaten /Gibt ascii code aus aber betrachtet jeden char einzeln
end
fclose(s);
labSend(messdaten,2);
case 2
messdaten = labReceive(1);
amplitude=zeros(1,scala);
phase=zeros(1,scala);
temperatur = messdaten(messwerte_max+1);
inkrement = 1;
i = 1;
while inkrement <= messwerte_max
phase(1,i) = messdaten(1,inkrement);
inkrement = inkrement + 1;
amplitude(1,i) = messdaten(1,inkrement);
inkrement = inkrement + 1;
i = i + 1;
end
f=freq_start:freq_schritt:freq_stop; % Frequenzvektor
f=double(f);
amplitude(1:10)=amplitude(10);
phase(1:10)=phase(10);
% Umrechnen der Messdaten zu Volt-Werten
amplitude = amplitude.*(3.3/2^13);
phase = phase.*(3.3/2^13);
% Umrechnung der Messdaten in dB für die Amplitude und Grad für Phase
amplitude=(amplitude-0.9)./0.03;
phase=-(((0.9-phase)./0.01)+90);
% -------------------------------------------- Rauschunterdrückung mit Wavelets ----------------------------------------------------
amplitude_bereinigt=Rauschunterdrueckung(amplitude);
phase_bereinigt=Rauschunterdrueckung(phase);
% -----------Berechnung der Frequenz - und Dissipationsänderung-------------
% Ermittlung der Resonanzfrequenz
peak_height = 0.8*max(amplitude_bereinigt);
peak_distance = 10^6;
[amp_max, fr]=findpeaks(amplitude_bereinigt,f,'MinPeakHeight',peak_height, 'MinPeakDistance',peak_distance);
% Ermittlung des Dissipationsfaktors
max_half = amp_max/2;
% Ermittlung der beiden Frequenzen, die die Halbwertsbreite bilden
diff = 1;
f_half1 = 0;
f_half2 = 0;
for i=1:length(amplitude_bereinigt)
kandidat_diff = abs(max_half-amplitude_bereinigt(i));
if diff > kandidat_diff
diff = kandidat_diff;
f_half1 = f(i);
x1=amplitude_bereinigt(i);
end
if amplitude_bereinigt(i) == amp_max
break;
end
end
diff = 1;
for i=i:length(amplitude_bereinigt)
kandidat_diff = abs(max_half-amplitude_bereinigt(i));
if diff > kandidat_diff
diff = kandidat_diff;
f_half2 = f(i);
x2=amplitude_bereinigt(i);
end
end
% Halbwertsbreite
FHWM = abs(f_half2-f_half1);
% Dissipation
D = FHWM/fr;
% ne Umrechnung
fr = fr/10^6;
% Ausgabe
fprintf('Resonanzfrequenz: %d MHz\n', fr);
fprintf('Dissipation: %d\n', D);
fprintf('Temperatur: %d\n',temperatur);
figure(1);
subplot(2,1,1);
plt1 = plot(NaN,NaN,'b'); % Plot empty line
hold on;
grid on;
axis([min(f) max(f) min(amplitude_bereinigt) max(amplitude_bereinigt)]);
title('Rauschbefreites Amplitudensignal')
xlabel('Frequenz/[MHz]');
ylabel('Amplitude/[dB]');
subplot(2,1,2);
plt2 = plot(NaN,NaN,'r'); % Plot empty line
hold on;
grid on;
axis([min(f) max(f) min(phase_bereinigt) max(phase_bereinigt)]);
title('Rauschbefreites Phasensignal')
xlabel('Frequenz/[MHz]');
ylabel('Phase/[°]');
for k = 1:length(amplitude)
set(plt1,'XData',f(1:k),'YData', amplitude_bereinigt(1:k));
set(plt2,'XData',f(1:k),'YData', phase_bereinigt(1:k));
pause(0.01);
drawnow limitrate
end
delete(plt1);
delete(plt2);
end
end

 Accepted Answer

When you plot inside a parallel worker of any kind, the result cannot be sent to the user display.

5 Comments

should i use Dataque then? Will it help me to improve the speed?
I cannot tell for sure what your values look like, but the part where you scale by 2^13 suggests that they might be the decimal representation of a 12 or 13 or 14 bit number, so possibly a 5 digit number plus a newline for a total of 6 characters each. The connection is 9600 baud if you are using a true serial port instead of a USB port, and 9600 baud is 960 characters per second, divided by 6 is 150 data items per second, each of which is phase and angle, so 75 readings per second. Putting the serial i/o in another process is not going to improve that. And I might be misinterpreting and the readings might be floating point and quite possibly twice that number of characters each.
To improve a situation like that you would need to switch to higher baud rate, or you would need to switch to USB (which has its own limits smaller than most people realize), or you would need to switch to binary, or you would need to switch to Ethernet.
Thank you for your answers. I experiment a little bit with the baudrate of matlab and arduino. the numbers are 4 digit. I achieved a increase of 5 seconds. Nevertheless it is stil slow (it takes 15 seconds). It must be a way to read the serial, while plotting the data. Because plotting the data takes like 8 seconds. If the serial port is readed out in parallel, the next plot will be not in 15 seconds but in 7.
If you are using USB to the arduino instead of true serial port:
Are you emitting a newline after every number? If so then change that to emit a newline less often, even if it is after every pair of numbers would help. USB has a limit on the number of "transactions per second", and newlines can potentially signal the end of a transaction. For USB purposes you would prefer to fill as close to 1020 characters as possible per packet... if you were to group 100 pairs, (4 digits+delimiter)*2*100 -> 1000 characters per packet then your throughput would improve.... at the cost of greater latency, and inability to track the times of the individual readings.
Thank you very much! I could reduce the execution time to 3 seconds!

Sign in to comment.

More Answers (0)

Categories

Find more on Graphics Performance in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!