mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP FFT in Python kalibrieren/normieren


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.
Autor: Gustl B. (-gb-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich verwende Python um Messdaten von ADCs zu erfassen. Aus diesen Daten 
möchte ich dann eine FFT rechnen lassen. Dasfunktioniert auch fein, ich 
sehe ein Spektrum im Plot, aber die Amplitude kann nicht stimmen.

Jetzt möchte ich das irgendwie kalibrieren oder normieren. Aber was 
sollte man verwenden? dBFS dBV oder was ganz anderes? Ich kann hier 
einen Sinus mit bekannter Amplitude anlegen und dann an den ADC Werten 
sehen wieviele Quantisierungsstufen verwendet wurden. Also ich weiß 
wieviele Volt einer Stufe entsprechen. Ich weiß aber nicht wie ich das 
der FFT mitteile.

Weil ich lieber Elektronik bastel als mich mit Software rumzuschlagen 
würde ich mich auch sehr über einen fertigen Codeschnipsel freuen.

Danke!

Autor: void (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> Ich weiß aber nicht wie ich das
> der FFT mitteile.

https://www.cbcity.de/die-fft-mit-python-einfach-erklaert

-> y-Axis: The Amplitude of the FFT Signal

Autor: Analogopa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> Python um Messdaten von ADCs zu erfassen.
Da muss aber irgendwo noch eine HW dazwischen hängen. Wenn die nicht 
wichtig ist, dann ist der Umstand, dass es ADC-Werte sind auch nicht.

Bei einer Normierung hingegen wäre beides wichtig.

>Weil ich lieber Elektronik bastel als mich mit Software rumzuschlagen
>würde ich mich auch sehr über einen fertigen Codeschnipsel freuen.

Es wäre aber zweckmäßig, wenn du dich näher mit Signalverarbeitung und 
Messtechnik befassen würdest, um die Hintergründe zu verstehen.

>dBFS
Das ist so der einzige Weg.

Kalibrierung erfordert die gesamte Strecke.

Autor: Gustl B. (-gb-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Analogopa schrieb:
> Da muss aber irgendwo noch eine HW dazwischen hängen.

Welche Hardware meinst Du denn genau? Der ADC ist Hardware, dahinter ist 
ein FPGA, der ist auch Hardware, dann kommt der FTDI USB Stein, auch 
Hardware, dann ein PC auch Hardware?! Aber die ändern an den ADC Werten 
nichts mehr.

Vor dem ADC hängt auch Hardware. Was muss ich denn davon wissen für die 
FFT?

Ich weiß folgendes:
1. Welche Spannung die von aussen angelegt wird welchem ADC-Wert 
entspricht.
2. Welche Spannung einer Quantisierungsstufe entspricht. Sprich die 
volle ADC Spanne entspricht x Volt, dann entspricht eine ADC Stufe x 
Volt geteilt durch die 2^n Stufen.
3. Kann ich einen externen Sinus anlegen mit bekannter Amplitude und 
dann eben an den ADC Werten sehen wie viele Stufen dieser Sinus 
verwendet.
4. Die Samplerate ist bekannt.

void schrieb:
> y-Axis: The Amplitude of the FFT Signal

Ja, wie das grundsätzlich funktioniert ist mir schon klar. Aber auch in 
deinem Link findet keine Normierung statt. Ausserdem ist da die 
Amplitude nicht in dB angegeben.

Analogopa schrieb:
>>dBFS
> Das ist so der einzige Weg.

Ist das wirklich so? Wenn ich weiß welche Spannung dem vollen ADC 
Wertebereich entspricht müsste doch auch dBV machbar sein?

Aber auch hier kommen Verwirrungen rein:
Der ADC liefert 16 Bit Werte als Offset Binary. Sprich von 0 bis 2^16-1. 
Setze ich dann als Referenz für dBFS 2^16 oder die Hälfte? Ich habe mal 
Beispielcode gesehen der für ein 16 Bit Signal das aber symmetrisch um 
die 0 ist nur 2^15 für die Referenz verwendet hat.

Autor: -gb- (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, habe mal ein kleines Beispiel gebaut, den Großteil habe ich aus im 
Internet, aber es funktioniert und erzeugt einen Plot. Im Anhang ist 
jetzt das Python und eine Datei die Samplewerte enthält. Die kommen von 
einem 16 Bit ADC und wurden mit 25 MSamples/s aufgenommen.
import numpy
import matplotlib.pyplot as plt
from scipy.fftpack import fft, fftshift
from scipy.signal import blackman

ADC_FS = 25.0 #MHz
ADC_Bits = 16
ADC_Steps = 2**ADC_Bits
ADC_N_Samples = 2**13
ADC_Samples = []
file = open("sine64k_10MHz.txt", "r")
# Read Samples
linecounter = 0
for line in file:
  if linecounter < ADC_N_Samples:
    ADC_Samples.append(int(line))
    linecounter +=1
file.close()

freq = numpy.linspace(-ADC_FS/2, ADC_FS/2, ADC_N_Samples)
A = fft(ADC_Samples*blackman(ADC_N_Samples))
response = 20 * numpy.log10(numpy.abs(fftshift(A / abs(A[1:ADC_N_Samples]).max())))
plt.plot(freq, response)
plt.axis([-0.5, 0.5, -140, 0])
plt.xlim(xmax = ADC_FS/2, xmin = 0)
plt.title("Blackman window")
plt.ylabel("Amplitude [dB]")
plt.xlabel("f [MHz]")
plt.show()

Autor: -gb- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich schrieb es funktioniert, aber damit meinte ich nicht, dass es die 
Lösung ist. Die Amplitude stimmt weiterhin nicht.

Autor: void (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> Ja, wie das grundsätzlich funktioniert ist mir schon klar. Aber auch in
> deinem Link findet keine Normierung statt.

Doch genau das. Für die x- (Frequenz) und die y- Achse (Amplitude). Mit 
schrittweise erklärtem Python Code. Hätte man aber lesen und vertehen 
müssen. Einfach nur den Großteil aus dem Internet abschreiben 
funktioniert halt nicht.

Gustl B. schrieb:
> Ausserdem ist da die
> Amplitude nicht in dB angegeben.

Dann multipliziert man sie noch einmal mit 20*log(n) und ist fertig.

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.