mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP FFT - Amplitudenachse skalieren?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Max U. (talha74)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen,

ich habe eine Druckkurve einer Pumpe aufgenommen und möchte nun über den 
Datensatz eine FFT jagen (Raspberry PI, Python). Funktioniert auch, nur 
das Problem ist, dass die y-Achse falsch oder garnicht skaliert ist 
(Amplitunden im Bereich von 10^6???).
Meine Frage ist, wie ich nun die Achse skalieren kann.
Zudem ist am Anfang des Plots ein riesiger Peak zu erkennen? Was hat der 
da zu suchen? Kann ich den Peak entfernen, indem ich einen Filter 
(Hoch-/Tiefpass) auf die Daten erst anwende? Oder erstmal den Mittelwert 
subtrahieren?

Ich bitte um Tipps.

Viele Grüße
Max

: Bearbeitet durch User
von mb (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Lass das doch mal über einen schönen Sinus (mit einer Frequenz die schön 
mittig in einem Bin landet) laufen.

Dann siehst du ja wo die Amplitude landet und kannst auf Fehlersuche 
gehen.

Wir können das mangels Code ja nicht.

von mb (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Max U. schrieb:
> Kann ich den Peak entfernen, indem ich einen Filter
> (Hoch-/Tiefpass) auf die Daten erst anwende?

Der bei 0Hz sollte logischerweise durch einen Hochpass verschwinden ja.

Die Frage ist, ob du das wirklich willst. Wenn dich der DC Anteil nicht 
interessiert, kannst du den ja immernoch einfach nicht-auswerten.

Max U. schrieb:
> Oder erstmal den Mittelwert
> subtrahieren?

Das wäre ein Hochpass, ja.

von Max U. (talha74)


Bewertung
0 lesenswert
nicht lesenswert
mb schrieb:
> Lass das doch mal über einen schönen Sinus (mit einer Frequenz die schön
> mittig in einem Bin landet) laufen.
>
> Dann siehst du ja wo die Amplitude landet und kannst auf Fehlersuche
> gehen.
>
> Wir können das mangels Code ja nicht.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from tkinter import filedialog
from tkinter import *
import sys
import warnings
if not sys.warnoptions:
    warnings.simplefilter("ignore")
#choose csv file
root = Tk()
root.filename = filedialog.askopenfilename ( initialdir = "/home/pi", title = "Datei auswählen", filetypes = (("Comma Seperated Values (CSV)", "*.csv"), ("Alle Dateien", "*.*")) )
# Import csv file
df = pd.read_csv(root.filename, delimiter = ';')
#convert Voltage to Bar
df_echt = df/0.01
#preparation for fft
df_neu = df.as_matrix()
time = df_neu[:,0]
voltage = df_neu[:,0]/df_neu[:,0].max()
df_tr = df_neu.T
#fft
amplitude = np.fft.rfft (voltage)
freq = np.fft.rfftfreq(len(time),np.diff(time)[0])
#plot time signal and fft
plt.xlabel ('Messung No.')
plt.ylabel('Druck [Bar]')
plt.plot (df_echt, lw = 0.8)
plt.legend (df)
plt.figure (2)
plt.xlabel('Frequenz [Hz]')
plt.ylabel('Amplitude')
plt.plot(np.absolute(amplitude), lw = 0.8)
plt.show()


Also das ist der Code. Hier ist sogar die y-Achse des Zeitsignlas 
skaliert.
Was ist der Unterschied zwischen einem Hochpass (also direkt aus der 
Library) und der MEthode wenn ich per Hand den Mittelwert berechne und 
dann vom Datensatz abziehe? Es sind doch prinzipiell zwei identische 
verfahren?
Gibt es da irgenwelche Vor-/ bzw. Nachteile?

von mb (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Max U. schrieb:
> Was ist der Unterschied zwischen einem Hochpass (also direkt aus der
> Library) und der MEthode wenn ich per Hand den Mittelwert berechne und
> dann vom Datensatz abziehe?

Mittelwert subtrahieren wäre ein idealer HP mit einer Grenzfrequenz von 
0Hz. Entfernt also wirklich nur genau die DC-Komponente und fasst das 
Signal ansonsten nicht an.

Was der HP der Library macht weiß ich nicht, aber ich vermute mal dass 
es da eher um die Simulation eines realen Hochpasses geht, d.h. 
Grenzfrequenz != 0 und mit einer begrenzten Steilheit von soundso vielen 
dB pro Dekade.

Der würde dann auch niederfrequente Anteile reduzieren.

von Norbert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Interessehalber: kannst du deine Daten in numerischer Form posten (CSV 
o. ä)?

von mb (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Btw. dein Signal hat einen Mittelwert von grob 4 und du hast etwas über 
10*10^5 Samples. Komplett aufsummiert also etwa 4*10^6

Die Amplitude deines DC bins ist...?

Da fehlt also offensichtlich eine Normierung.

von Max U. (talha74)


Bewertung
0 lesenswert
nicht lesenswert
mb schrieb:
> Btw. dein Signal hat einen Mittelwert von grob 4 und du hast etwas über
> 10*10^5 Samples. Komplett aufsummiert also etwa 4*10^6
>
> Die Amplitude deines DC bins ist...?
>
> Da fehlt also offensichtlich eine Normierung.

Genau das ist ja die Frage. Wie bekomme ich diese Normierung hin?
Ich habe mal bisschen recherchiert und gelesen, dass ich noch durch den 
Faktor N teilen muss, um die physikalisch korrekte NOrmierung 
hinzubekommen.
Wobei
N = len (amplitude)/2+1 
ist.
Und dann nachher beim plotten
plt.plot (2.0*np.abs(amplitude[:N])/N) 

Dann kriege jedoch folgenden Fehler:
Traceback (most recent call last):
  File "/home/pi/Desktop/fft.py", line 46, in <module>
    plt.plot(2.0*np.abs(amplitude[:N]/N), lw = 0.8)
TypeError: slice indices must be integers or None or have an __index__ method

Was ist denn hier fehlerhaft? Oder sind meine Überlegungen falsch?
Wie würdet Ihr die Skalierung vornehmen?

von mech (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Da steht's doch:

Max U. schrieb:
> slice indices must be integer

Aber

Max U. schrieb:
> len (amplitude)/2+1

Spuckt halt nicht zwingend eine ganze Zahl aus, das musst du im Zweifel 
z.B. durch int() erzwingen.

Man kann doch nicht aus kleinen Programmierfehlern gleich schließen, 
dass der Ansatz falsch ist, hör mal... So kommt man doch auf nix.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.