Speed up serial Communication with parallel computing

5 views (last 30 days)
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

Walter Roberson
Walter Roberson on 3 Mar 2021
When you plot inside a parallel worker of any kind, the result cannot be sent to the user display.
  5 Comments
Walter Roberson
Walter Roberson on 10 Mar 2021
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.
Fire Phoenix
Fire Phoenix on 15 Mar 2021
Thank you very much! I could reduce the execution time to 3 seconds!

Sign in to comment.

More Answers (0)

Categories

Find more on MATLAB 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!