Verfasst am: 08.01.2016, 18:17
Titel: Frequenz und Amplitude aus Messdaten bestimmen
Hallo allerseits
Dies ist mein erster Beitrag in diesem Forum. Ich würde mich freuen, wenn ihr mir helfen würdet.
Zurzeit bin ich mit meiner Bachelorarbeit beschäftigt und brauche Hilfe bei Matlab.
Es geht um das Thema Reibschwingungen (Stick Slip) bei der Schraubenmontage.
Den Matlab-Code für das Plotten hab ich bereits geschrieben (siehe unten).
1) Nun muss ich die Frequenz und die Amlipute an einer beliebigen Stelle bestimmen, jedoch weiß ich leider nicht wie das funktioniert.
2) Ein anderes Problem ist, dass der Plottbereich der von Bedeutung ist (Ab Anfang des Stick Slip Effeks), für jede Messung an einer anderen Stelle auf der x-Achse beginnt, also entlang der x-Achse versetzt ist (siehe Foto). Kann man realisieren, dass der Beginn des Stick-Slip-Effekts bei x=0 ist für jede Messung?
Vielen Dank im Voraus.
Code:
%% Import data from text file. % Script for importing data from the following text file:
%
% H:\Testmessung 1.BIN
%
% To extend the code to different selected data or a different text file, % generate a function instead of a script.
%% Read columns of data as strings: % For more information, see the TEXTSCAN documentation.
formatSpec = '%s%s%s%s%s%s%s%[^\n\r]';
%% Open the text file.
fileID = fopen(filename,'r');
%% Read columns of data according to format string. % This call is based on the structure of the file used to generate this % code. If an error occurs for a different file, try regenerating the code % from the Import Tool.
dataArray = textscan(fileID, formatSpec, 'Delimiter', delimiter, 'ReturnOnError', false);
%% Convert the contents of columns containing numeric strings to numbers. % Replace non-numeric strings with NaN.
raw = repmat({''},length(dataArray{1}),length(dataArray)-1);
for col=1:length(dataArray)-1
raw(1:length(dataArray{col}),col) = dataArray{col};
end
numericData = NaN(size(dataArray{1},1),size(dataArray,2));
for col=[1,2,3,4,5,6,7] % Converts strings in the input cell array to numbers. Replaced non-numeric % strings with NaN.
rawData = dataArray{col};
for row=1:size(rawData, 1);
% Create a regular expression to detect and remove non-numeric prefixes and % suffixes.
regexstr = '(?<prefix>.*?)(?<numbers>([-]*(\d+[\.]*)+[\,]{0,1}\d*[eEdD]{0,1}[-+]*\d*[i]{0,1})|([-]*(\d+[\.]*)*[\,]{1,1}\d+[eEdD]{0,1}[-+]*\d*[i]{0,1}))(?<suffix>.*)';
try
result = regexp(rawData{row}, regexstr, 'names');
numbers = result.numbers;
% Detected commas in non-thousand locations.
invalidThousandsSeparator = false;
ifany(numbers=='.');
thousandsRegExp = '^\d+?(\.\d{3})*\,{0,1}\d*$';
ifisempty(regexp(thousandsRegExp, '.', 'once'));
numbers = NaN;
invalidThousandsSeparator = true;
end end % Convert numeric strings to numbers. if ~invalidThousandsSeparator;
numbers = strrep(numbers, '.', '');
numbers = strrep(numbers, ',', '.');
numbers = textscan(numbers, '%f');
numericData(row, col) = numbers{1};
raw{row, col} = numbers{1};
end catch me
end end end
%% Replace non-numeric cells with NaN
R = cellfun(@(x) ~isnumeric(x) && ~islogical(x),raw); % Find non-numeric cells
raw(R) = {NaN}; % Replace non-numeric cells
%% Clear temporary variables clearvars filename delimiter formatSpec fileID dataArray ans raw col numericData rawData row regexstr result numbers invalidThousandsSeparator thousandsRegExp me R;
%% Plot
plot(Time,Mges,'r') hold on
grid on
plot(Time,Mkopf,'g') % plot(Time,Mgew,'b') % plot(Time,Fax,'k')
Verfasst am: 09.01.2016, 11:48
Titel: Re: Frequenz und Amplitude aus Messdaten bestimmen
kako12 hat Folgendes geschrieben:
1) Nun muss ich die Frequenz und die Amlipute an einer beliebigen Stelle bestimmen, jedoch weiß ich leider nicht wie das funktioniert.
2) Ein anderes Problem ist, dass der Plottbereich der von Bedeutung ist (Ab Anfang des Stick Slip Effeks), für jede Messung an einer anderen Stelle auf der x-Achse beginnt, also entlang der x-Achse versetzt ist (siehe Foto). Kann man realisieren, dass der Beginn des Stick-Slip-Effekts bei x=0 ist für jede Messung?
Zu 1) Du kannst folgende Funktion zur Erstellung des Amplitudenspektrums nutzen:
Code:
function[mag, mag_dB, fv] = FFT_betragsspektrum( signal, nfft, fa, window, scale) % Input: % Signal im Zeitbereich % nfft = Anzahl Messwerte für fft % wenn nfft > length(sig) -> fft(sig,nfft) führt Zeropadding durch % fa = Abtastfreq. % window: Fensterfunktion als Vektor % scale: 0 = keine Impulsantwort als Eingang, 1 = Impulsantwort % Output: % Magnitude des Spektrums linear und dB skaliert % Frequenzvektor fv in [Hz] von 0...fa/2
% un-,gerade Anzahl Messwerte? ifmod(nfft,2) == 0;
k = (nfft/2) + 1;
else
nfft = nfft + 1;
k = (nfft/2) + 1;
end
% Betrag - nur positives Freq.spektrum if scale == 0
Fy_pos0 = abs(Fy(1:k));
% Skalierung
mag = [Fy_pos0(1)/Lsig ;Fy_pos0(2:k-1)/(Lsig/2);Fy_pos0(k)/Lsig];
else% nicht durch nfft teilen bei Impulsantwort
mag = abs(Fy(1:k));
end
% Umrechnung in dB
mag_dB = 20*log10(mag + eps); % eps = kleine Konstante zur Vermeidung von log(0)
fa = ...% Abtastfrequenz in Hz
nfft = % Anzahl Messwerte in Segment
Signal = ...; % Messsignal
window = 1; % Nutzung der Hanning Fensterfunktion zur Minderung von Leakage. Sollte bei realen Messdaten immer verwendet werden.
scale = 0;
Zum Thema FFT gibt es Forum unzählige Beiträge. Einfach mal die Suchfunktion nutzen!
Zu 2) Da wirst du dir selbst eine Funktion schreiben müssen, welche den Anfangspunkt findet. Z.B. in dem du einen Schwellenwert festlegst, innerhalb dem sich das Nullsignal (Rauschen in den ersten 2 sec?) bewegen darf. Wird der Schwellenwert überschritten, beginnt das Messignal. Nun evtl. den letzten Nulldurchgang vor der gefundenen Überschreitung des Schwellenwerts ermitteln. Evtl. kann dir auch die Funktion
findpeaks
weiterhelfen.
vielen Dank für Ihre Antwort. Die Suchfunktion im Forum hatte ich auch vor diesem Thema benutzt und auch das umfassende FFT-Beispiel mir angeschaut, allerding hab ich noch ein paar Fragen.
Zuerst vllt zusätliche Infos zu meiner Aufgabe;
Meine Aufgabe ist es, um Reibschwingungen bei der Schraubenmontage zu analysieren, auf einem Prüfstand Schrauben mit unterschiedlichen Drehzahlen anzuziehen und die dabei auftretenden Reibmomente im Gewinde und unter Kopf auszuwerten.
Die Messdaten sind in einer BIN-Datei gespeichert und besteht aus sieben Spalten.
Ich brauch jedoch nur Werte der Spalte 6 und Spalte 5... Spalte 1 liefert die Zeitwerte (sekunden..)
Da die Messerfassung nicht direkt mit dem Anziehvorgang beginnt, muss ich erst die Messung starten ( Messungen werden aufgenommen aber da der Anziehvorgang nicht gestartet ist --> konstanter Wert (Rauschen) ) und dann den Anziehvorgang starten (Anziehvorgang beendet - Messung läuft weiter -->konstanter Wert (Rauschen) ) Deswegen ist das Rauschen bei jeder Messung vor und nach dem Anziehvorgang unterschiedlich lang. Es sind also zwei Programme auf dem PC, eins für die Messung eins für die Steuerung des Anziehens.
Zu dem Code habe ich ein paar Fragen. Ich weiß nicht wo ich den Code einfügen muss und ob ich den Code als m-file speichern muss. Ich weiß leider auch nicht an welcher Stelle meine Messdatei aufgerufen/geladen wird. Und es müssen ja nicht alle Spalten des Codes ausgewertet werden sondern nur 2 Spalten.
Und eine Frage zur Abtastfrequenz: kann ich sie aus meiner Zeitspalte ableiten?
PS: Da die Messdatei die Endung .BIN hat, kann ich sie hier nicht hochladen, deswegen ein Screenshot davon.
Die Funktion FFT_betragsspektrum sicherst du als m-file unter dem Namen "FFT_betragsspektrum.m" in deinem Matlab work-Verzeichnis. Damit ist Matlab die Funktion bekannt und kann benutzt werden. Aber nicht anders bennennen...das führt nur zu Fehlern.
Zur Berechung und Darstellung nutzt du diese Zeilen...schreibe sie in einen anderen m-file...du kannst sie ja auch unter dein Importskript schreiben.
Code:
dt = diff(Time); % Schrittweite Zeitbereich
Ta = dt(1); % aber du solltest darauf achten, dass alle Werte in dt gleich sind. Kleinere Abweichung z.B. wegen Rundungen oder Zahlendarstellung sind ok. Aber im Prinzip muss die Abtastrate des Signals über den Messzeitraum konstant sein!! % Lass dir mal min(dt) und max(dt) ausgeben.
fa = 1/Ta; % Abtastfrequenz in Hz
nfft = length(Mges);% Anzahl Messwerte in Messfenster
Signal = Mges; % Messsignal
window = 1; % Nutzung der Hanning Fensterfunktion zur Minderung von Leakage. Sollte bei realen Messdaten immer verwendet werden.
scale = 0;
Nicht unterstützte Dateiformate einfach packen...dann kannst du sie im Forum anhängen. Es sollte aber mit meinem Code kein Problem sein, dass nun selbst zu lösen
%% Import data from text file. % Script for importing data from the following text file:
%
% H:\Testmessung 1.BIN
%
% To extend the code to different selected data or a different text file, % generate a function instead of a script.
%% Read columns of data as strings: % For more information, see the TEXTSCAN documentation.
formatSpec = '%s%s%s%s%s%s%s%[^\n\r]';
%% Open the text file.
fileID = fopen(filename,'r');
%% Read columns of data according to format string. % This call is based on the structure of the file used to generate this % code. If an error occurs for a different file, try regenerating the code % from the Import Tool.
dataArray = textscan(fileID, formatSpec, 'Delimiter', delimiter, 'ReturnOnError', false);
%% Convert the contents of columns containing numeric strings to numbers. % Replace non-numeric strings with NaN.
raw = repmat({''},length(dataArray{1}),length(dataArray)-1);
for col=1:length(dataArray)-1
raw(1:length(dataArray{col}),col) = dataArray{col};
end
numericData = NaN(size(dataArray{1},1),size(dataArray,2));
for col=[1,2,3,4,5,6,7] % Converts strings in the input cell array to numbers. Replaced non-numeric % strings with NaN.
rawData = dataArray{col};
for row=1:size(rawData, 1);
% Create a regular expression to detect and remove non-numeric prefixes and % suffixes.
regexstr = '(?<prefix>.*?)(?<numbers>([-]*(\d+[\.]*)+[\,]{0,1}\d*[eEdD]{0,1}[-+]*\d*[i]{0,1})|([-]*(\d+[\.]*)*[\,]{1,1}\d+[eEdD]{0,1}[-+]*\d*[i]{0,1}))(?<suffix>.*)';
try
result = regexp(rawData{row}, regexstr, 'names');
numbers = result.numbers;
% Detected commas in non-thousand locations.
invalidThousandsSeparator = false;
ifany(numbers=='.');
thousandsRegExp = '^\d+?(\.\d{3})*\,{0,1}\d*$';
ifisempty(regexp(thousandsRegExp, '.', 'once'));
numbers = NaN;
invalidThousandsSeparator = true;
end end % Convert numeric strings to numbers. if ~invalidThousandsSeparator;
numbers = strrep(numbers, '.', '');
numbers = strrep(numbers, ',', '.');
numbers = textscan(numbers, '%f');
numericData(row, col) = numbers{1};
raw{row, col} = numbers{1};
end catch me
end end end
%% Replace non-numeric cells with NaN
R = cellfun(@(x) ~isnumeric(x) && ~islogical(x),raw); % Find non-numeric cells
raw(R) = {NaN}; % Replace non-numeric cells
%% Clear temporary variables clearvars filename delimiter formatSpec fileID dataArray ans raw col numericData rawData row regexstr result numbers invalidThousandsSeparator thousandsRegExp me R;
%------------------------------------
%fft
dt = diff(Time); % Schrittweite Zeitbereich
Ta = dt(1); % aber du solltest darauf achten, dass alle Werte in dt gleich sind. Kleinere Abweichung z.B. wegen Rundungen oder Zahlendarstellung sind ok. Aber im Prinzip muss die Abtastrate des Signals über den Messzeitraum konstant sein!! % Lass dir mal min(dt) und max(dt) ausgeben.
fa = 1/Ta; % Abtastfrequenz in Hz
nfft = length(Mges);% Anzahl Messwerte in Messfenster
Signal = Mges; % Messsignal
window = 1; % Nutzung der Hanning Fensterfunktion zur Minderung von Leakage. Sollte bei realen Messdaten immer verwendet werden.
scale = 0;
function[mag, mag_dB, fv] = FFT_betragsspektrum( signal, nfft, fa, window, scale) % Input: % Signal im Zeitbereich % nfft = Anzahl Messwerte für fft % wenn nfft > length(sig) -> fft(sig,nfft) führt Zeropadding durch % fa = Abtastfreq. % window: Fensterfunktion als Vektor % scale: 0 = keine Impulsantwort als Eingang, 1 = Impulsantwort % Output: % Magnitude des Spektrums linear und dB skaliert % Frequenzvektor fv in [Hz] von 0...fa/2
% Betrag - nur positives Freq.spektrum if scale == 0
Fy_pos0 = abs(Fy(1:k));
% Skalierung
mag = [Fy_pos0(1)/Lsig ;Fy_pos0(2:k-1)/(Lsig/2);Fy_pos0(k)/Lsig];
else% nicht durch nfft teilen bei Impulsantwort
mag = abs(Fy(1:k));
end
% Umrechnung in dB
mag_dB = 20*log10(mag + eps); % eps = kleine Konstante zur Vermeidung von log(0)
ich möchte auch meine Messdaten untersuchen und bindabei hier gelandet. Soweit alles sehr Hilfreich und verständlich. Dafür schon einmal danke.
Im Code Steht:
Code:
dt = diff(Time); % Schrittweite Zeitbereich
Ta = dt(1); % aber du solltest darauf achten, dass alle Werte in dt gleich sind. Kleinere Abweichung z.B. wegen Rundungen oder Zahlendarstellung sind ok. Aber im Prinzip muss die Abtastrate des Signals über den Messzeitraum konstant sein!! % Lass dir mal min(dt) und max(dt) ausgeben.
Bei meiner Messung wurden die Daten nicht kontinuierlich aufgenommen, sondern es wurde immer für 10 Sek gemessen, dann 10 Sek Paus, dann wieder 10 Sek Messen usw...
Daher habe ich Sprünge in der Zeit.
Für dt bekomme ich dann immer dt=3.91e-4 nur an den Stellen der Sprünge ist dt=30.0004. Ich denke ich liege Richtig damit, dass das keine "kleineren Abweichungen" mehr sind.
Kann ich die Funktion trozdem so verwenden, oder wie muss ich meine Daten anpassen? Der Sprung tritt bei ca. 1,9 mio Werten nur ca 75 mal auf.
Danke im Voraus!
MfG Alex
Einstellungen und Berechtigungen
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.