Forum: Digitale Signalverarbeitung / DSP / Machine Learning Signale mit leicht unterschiedlicher Abtastrate verarbeiten


von Alexander H. (ill_son)


Lesenswert?

Hallo,

folgende Frage:

Ich habe zwei Zeitsignale von zwei unterschiedlichen Sensoren, die ich 
sampleweise miteinander verrechnen möchte. Das Problem dabei ist, dass 
die Sensoren in ihrer Abtastrate leicht differieren (+-2%), sodass das 
eine Signal von t1 bis t2 bespielsweise 1000 Samples enthält, das andere 
aber 1025. Wie konditioniere ich die Signale ab besten, sodass ich meine 
Berechnung durchführen kann.

Grüße, Alex

von stänkerFritz (Gast)


Lesenswert?

Du willst zeitlich undefiniert versetzte Signale miteinander verrechnen?
Glaub ich nicht. Mir fällt kein Szenario ein, bei dem das Sinn machen 
könnte.

von mech (Gast)


Lesenswert?

Wenn's nicht so genau geht, 25 gleichmäßig verteilte Werte verwerfen.

Oder beim kleineren Datensatz 25 gleichmäßig verteilte Stellen 
interpolieren.

Das macht natürlich nur Sinn, wenn das Signal nur niedrige Frequenzen 
aufweist.

von Alexander H. (ill_son)


Lesenswert?

@stänkerFritz

Sie Signale sind nicht undefiniert versetzt. Start und Endzeitpubkt sind 
bekannt, nur die Abtastrate differiert etwas.


@mech,

Signalquellen sind zwei ADXL355 von Analog Devices, und da ist der 
Samplequarz eben nur so genau wie oben geschrieben. Samplefrequenz ist 
1000Hz, der Sensor stellt denn internen Tiefpass auf fs/4, allerdings 
ist das gemessene mechanische System recht träge, sodass ich keine 
Frequenzen mit nennenswerter Amplitude über 50Hz erwarte.

von Jan (Gast)


Lesenswert?

Tatsächlich kommt das ja immer vor, wenn man 2 vermeintlich synchrone 
Quellen sampelt. Merken nur viele Leute gar nicht, weil sie samples 
vergessen oder den internen fifo nicht benutzen.

Also, du kannst tatsächlich interpolieren. Aber dafür musst du eine 
konkrete Frequenz haben. Und einen gemeinsamen Teller finden.

Bei niederfrequenten Systemen nimmst du einfach einen Mittelwertfilter.

Jeder sensor hat seine eigene abtastrate, also gibt es auch 
Module/Instanzen. Jede Instanz weiss den momentanen Wert. Zb durch 
periodisches Abrufen des FIFOs.

Nur nicht aufeinander warten lassen, das ergibt Probleme

von Michael (Gast)


Lesenswert?

Hallo,

wenn ich die Frage richtig verstehe, möchtest Du aus dem aus 1025 
Abtastwerten bestehenden Signal ein Signal gleicher Dauer mit nur 1000 
Abtastwerten machen.

In MatLab oder Gnu Octave gibt es dazu die Funktion interp1, die Dir 
dabei helfen kann, die Signale zu interpolieren.

Beispielcode:
% s1 = ... (Dein Signal)
t1 = 1:1025;
t1neu = 1025/1000:1025/1000:1025;
s1neu = interp1(t1,s1,t1neu,'spline');


Viele Grüße
Michael

von Michael W. (Gast)


Lesenswert?

stänkerFritz schrieb:
> Du willst zeitlich undefiniert versetzte Signale miteinander verrechnen?
> Glaub ich nicht. Mir fällt kein Szenario ein, bei dem das Sinn machen
> könnte.

Mir fallen NUR solche Anwendungen ein, weil in keinem Messsystem alle 
Sensoren voll synchron arbeiten. Da heisst es interpolieren und auf ein 
und dieselbe Zeit ummünzen, wenn sie verglichen werden sollen,

Mein aktueller Fall: Strom und Spannung in einem Mehrphasensystem. Der 
Stromsensor arbeitet mit 20kHz +/- 2kHz Rate, wegen dynamischer Regelung 
und Umschaltung der PWM und die Spannung (an anderem Punkt gemessen) 
kommt mit 50kHz. Man könnte den ADC auf den Strommesspunkt triggern, 
wäre aber immer eine Messperiode hinterher.

Also die Spannung mit 150kHz interpolieren und dem Regelsystem zur 
Verfügung stellen, wenn es einen neuen Stromwert hat.

von Alexander H. (ill_son)


Lesenswert?

Hallo,

danke für die vielen Antworten. Zum Thema Interpolieren müsste ich noch 
ergänzen, dass ich die Daten in einer Anwendung verarbeite, die ich 
gerade selbst schreibe (C#, WPF). Das heißt, ich müsste das Ganze "zu 
Fuß" implementieren.

Michael schrieb:
> Beispielcode:
> % s1 = ... (Dein Signal)
> t1 = 1:1025;
> t1neu = 1025/1000:1025/1000:1025;
> s1neu = interp1(t1,s1,t1neu,'spline')

Wie arbeitet denn die interp1-Funktion? Upsampling um Faktor 1025 und 
dann downsampling um Faktor 1000 mit entsprechender Filterung und dem 
ganzen Prozedere, das dazu gehört (Stichwort CIC-Filter)?

Eine Implementierung würde ich mir in entsprechender Zeit gerade noch 
zutrauen, aber vielleicht fändeich da auch was Fertiges.

Grüße, Alex

von Jan (Gast)


Lesenswert?

Alexander H. schrieb:
> Wie arbeitet denn die interp1-Funktion? Upsampling um Faktor 1025 und
> dann downsampling um Faktor 1000 mit entsprechender Filterung und dem
> ganzen Prozedere, das dazu gehört (Stichwort CIC-Filter)?

Nein. Das ist ganz einfache Interpolation mit splines. Da werden keine 
sampleraten oder so berücksichtigt und du musst die abtastwerte selbst 
übergeben.
Die Funktion decimate 
https://www.mathworks.com/help/signal/ref/decimate.html filtert 
hingegen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn du die Signale nicht direkt während der Messung, sondern erst im
Nachhinein auswertest, kannst du auch eine sin(x)/x-Interpolation
verwenden, wie es bspw. auch Digitaloszis tun. Sie ist nicht schwieriger
umzusetzen als eine Spline-Interpolation, liefert aber für Signale, die
das Abtasttheorem erfüllen (also nur Frequenzanteile unterhalb der
halben Abtastfrequenz haben), mathematisch perfekte Ergebnisse.

Hier steht, wie es geht:

  https://de.wikipedia.org/wiki/Sinc-Funktion#Signalverarbeitung

Etwas ausführlicher:

  https://en.wikipedia.org/wiki/Whittaker%E2%80%93Shannon_interpolation_formula

Da bei dir die Abtastfrequenz (1kHz) viel höher als die erwartete
höchste Signalfrequenz (50Hz) liegt, wird der Unterschied zwischen den
einzelnen Interpolationsarten (linear, Spline, sin(x)/x) allerdings
nicht sehr groß sein.

von Udo S. (urschmitt)


Lesenswert?

Alexander H. schrieb:
> Das heißt, ich müsste das Ganze "zu
> Fuß" implementieren.

Ja und wo ist das Problem? Nennt sich Programmieren.
Da deine Signale deutlich langsamer als die Abtastrate sind sollte eine 
lineare Interpolation zwischen 2 Stützstellen doch reichen.

von Alexander H. (ill_son)


Lesenswert?

@Yalu:

ich habe noch ein Verständnisproblem, bezüglich Interpolation.

Wenn ich das recht verstanden habe, muss ich mit der von dir erwähnten 
Interpolation aus den 1025 Abtastwerten mein "Originalsignal" 
rekonstruieren, um das dann mit 1000Hz abzutasten. Stimmt das so?


In dem Wiki-Artikel ist ja von zeitkontinuerliche die Rede und
da ist eine Summe von -unendlich bis +unendlich. Ich finde gerade den 
Einstieg nicht. Kannst du mir bitte kurz erläutern, welche Schritte ich 
der Reihe nach unternehmen muss, um von dem 1025Hz-Signal zum 
1000Hz-Signal zu kommen.

von Udo K. (Gast)


Lesenswert?

Warum nimmst du nicht einfach den letzten Abtastwert?

Alles andere ist doch superkompliziert, und nur notwendig,
wenn du genauer als 0.x% sein willst...

und meiner Einschätzung nach weisst du noch nicht mal
wie genau das Ergebnis sein muss...

von Alexander H. (ill_son)


Lesenswert?

Udo K. schrieb:
> Warum nimmst du nicht einfach den letzten Abtastwert?

Sorry, aber ich verstehe deine Frage nicht. Nehmen wofür?

von Kurz Knackig (Gast)


Lesenswert?

mech schrieb:
> Wenn's nicht so genau geht, 25 gleichmäßig verteilte Werte
> verwerfen.

NEIN
> Oder beim kleineren Datensatz 25 gleichmäßig verteilte Stellen
> interpolieren.

Ja, u.U. genügt wiederholen, statt interpol.. die Werte sind ohnehin mit 
einem Quantisierungstauschen belegt.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Alexander H. schrieb:
> Das heißt, ich müsste das Ganze "zu
> Fuß" implementieren.

Du koenntest auch schauen, ob dir das Dingens hier weiterhelfen koennte:

http://www.mega-nerd.com/libsamplerate/index.html

Gruss
WK

von Alexander H. (ill_son)


Lesenswert?

Ich hab mal versucht, die Interpolation zu implementieren. Kann das mal 
einer querlesen bitte.
1
private List<DataPoint> Interpolate(IList<DataPoint> data, int sampleRateNew)
2
{
3
     if (data is null)
4
         return null;
5
6
     List<DataPoint> result = new List<DataPoint>(sampleRateNew);
7
8
     double startTime = data[0].X;
9
     double endTime = data[data.Count - 1].X;
10
     double timeStep = (endTime - startTime) / sampleRateNew;
11
     double sampleTimeOld = data.Count / (endTime - startTime);
12
13
14
     for (int i = 0; i < sampleRateNew; i++)
15
     {
16
         double time = startTime + i * timeStep;
17
         double yValue = 0;
18
         for (int j = 0; j < data.Count; j++)
19
             yValue += data[j].Y * Sinc((time - j * sampleTimeOld) / sampleTimeOld);
20
21
         result.Add(new DataPoint(time, yValue));
22
     }
23
24
     return result;
25
 }
26
27
 private double Sinc(double value)
28
 {
29
     return value == 0 ? 1.0 : Math.Sin(Math.PI * value) / (Math.PI * value);
30
 }

: Bearbeitet durch User
von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

am besten überprüfst Du es selbst anhand von Testdaten und vergleichst 
die Zahlen mit denen, die Octave liefert.

Hier findest Du beispielsweise Gnu Octave
https://octave-online.net/

Hier ein Beispielcode für eine Interpolation:

fs = 1000;
t1 = 1/fs*(0:102);
s1 = sin(2*pi*50*t1);
t1neu = 0:1/fs*103/100:1/fs*102;
s1linear = interp1(t1,s1,t1neu,'linear');
s1cubic  = interp1(t1,s1,t1neu,'cubic');
s1spline  = interp1(t1,s1,t1neu,'spline');

figure(1);
clf;
plot(t1,s1,'b.-'); hold on;
plot(t1neu,s1linear,'r.-');
plot(t1neu,s1cubic,'g.-');
plot(t1neu,s1spline,'k.-');
legend('Original','Linear','Cubic','Spline');
grid on;
hold off;

Die Daten kannst Du Dir durch eine Eingabe wie
s1    (ohne Semikolon; anschließend Drücken der Returntaste)
anzeigen lassen.


Viele Grüße
Michael

von Rechenfreak (Gast)


Lesenswert?

Alexander H. schrieb:
> ie konditioniere ich die Signale ab besten, sodass ich meine
> Berechnung durchführen kann.

Entweder in der Zeitebene resampeln oder in der Frequenzebene diskret 
transformieren.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.