From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Chebychev LPF always gives Attenuating Sine Wave

Hello,

 

No matter what I pass through to the Chebyshev low-pass filter, I am getting an attenuating sine wave back.

 

I have tried passing double values derived from an FFT based on the code below:

 

FFTFrequency = Index * ForcingFunctionSampleRate / ForcingFunctionBlockSize
FFTMagnitude = ComplexDataArray(Index).Magnitude
FFTGraphedMagnitude = 2 / ForcingFunctionBlockSize * FFTMagnitude

I then use the X and Y Values of "FFTFrequency" and FFTGraphedMagnitude and pass those into the LPF function. I use the FFTGraphedMagnitude values as the input for the LPF function.

 

 

I have also attempted to completely skip this code, and pass in the ComplexDouble data from the FFT directly to the LPF function. It, again, gives me an attenuating sine wave for the .Real values.

 

What am I doing wrong?

 

Sample Rate is 1623.377 Hz, block size is 8192. Passband ripple is 1 db. Filter order is 10.

 

I am trying to LPF (cutoff frequency) at 140 Hz.

 

Here is my original function, a combination of multiple sine waves at frequencies of 180.3752, 162.3377, 147.5797, 124.8751, 108.2251, 90.18759, 81.16883, 70.58159, 60.12506, 50.73052, 40.58442, 30.06253, 20.04169, and 10.02084 Hz.

2017-03-23_12-32-24.png

 

Here's the FFT graph based off of the code that gives me the X and Y values I pasted above:

2017-03-23_12-34-35.png

 

And here is where it always goes sideways, regardless of the input data into the LPF function:

2017-03-23_12-36-08.png

 

I am completely baffled at what to do next, or what to test. Any and all help is greatly appreciated. I am using .NET 4.0 inside of Visual Studio 2013. I have the Professional edition.

 

Thank you,

 

John Lindsay

0 Kudos
Message 1 of 3
(2,525 Views)

Hi John,

 

Could you post a complete small reproducing case of your code?  It will help me understand better.

 

thanks,

Pat

0 Kudos
Message 2 of 3
(2,488 Views)

Here's a basic set of what I'm trying to do:

Imports System.Math
Imports NationalInstruments
Imports NationalInstruments.Analysis.Dsp.Transforms

Public Class Frequency
    Const ForcingFunctionBlockSize As Integer = 8192
    Const Timestep As Single = 0.000616
    Const ForcingFunctionSampleRate As Double = 1623.377

    Friend Function GenerateSineWave() As Double()

        Dim PulseAdded As Boolean = False
        Dim NumberOfPulsedTimeSteps As Integer = 2
        Dim ReturnedDataSet(ForcingFunctionBlockSize - 1) As Double
        Dim SineIncrement(14) As Double

        For BlockStep As Integer = 0 To ForcingFunctionBlockSize

            Select Case BlockStep

                Case 9 '180.3752
                    SineIncrement(0) = 2 * PI / BlockStep
                Case 10 '162.3377
                    SineIncrement(1) = 2 * PI / BlockStep
                Case 11 '147.5797
                    SineIncrement(2) = 2 * PI / BlockStep
                Case 13 '124.8751
                    SineIncrement(3) = 2 * PI / BlockStep
                Case 15 '108.2251
                    SineIncrement(4) = 2 * PI / BlockStep
                Case 18 '90.18759
                    SineIncrement(5) = 2 * PI / BlockStep
                Case 20 '81.16883
                    SineIncrement(6) = 2 * PI / BlockStep
                Case 23 '70.58159
                    SineIncrement(7) = 2 * PI / BlockStep
                Case 27 '60.12506
                    SineIncrement(8) = 2 * PI / BlockStep
                Case 32 '50.73052
                    SineIncrement(9) = 2 * PI / BlockStep
                Case 40 '40.58442
                    SineIncrement(10) = 2 * PI / BlockStep
                Case 54 '30.06253
                    SineIncrement(11) = 2 * PI / BlockStep
                Case 81 '20.04169
                    SineIncrement(12) = 2 * PI / BlockStep
                Case 162 '10.02084
                    SineIncrement(13) = 2 * PI / BlockStep
                    Exit For
            End Select
        Next

        For CurrentTimeStep As Integer = 0 To ForcingFunctionBlockSize - 1
            Dim CurrentTime As Single = CurrentTimeStep * Timestep
            Dim YValue As Double
            For Each Value As Double In SineIncrement
                YValue += Sin(Value * CurrentTimeStep)
            Next
            ReturnedDataSet(CurrentTimeStep) = YValue
        Next

        Return ReturnedDataSet

    End Function


    Friend Function FFTPulse(ByVal RawDataSetIn() As Double) As Double()

        Dim ReturnedDataSet(RawDataSetIn.Length) As Double
        Dim FFTFrequency As Double
        Dim FFTMagnitude As Double
        Dim FFTGraphedMagnitude As Double
        Dim ComplexDataArray(RawDataSetIn.Length - 1) As ComplexDouble
        Dim ComplexPartAsZero(RawDataSetIn.Length - 1) As Double

        ComplexDataArray = ComplexDouble.ComposeArray(RawDataSetIn, ComplexPartAsZero)

        Fft(ComplexDataArray)

        For Index As Integer = 0 To ComplexDataArray.Length - 1
            FFTFrequency = Index * ForcingFunctionSampleRate / ForcingFunctionBlockSize
            FFTMagnitude = ComplexDataArray(Index).Magnitude
            FFTGraphedMagnitude = 2 / ForcingFunctionBlockSize * FFTMagnitude
            ReturnedDataSet(Index) = FFTGraphedMagnitude
        Next

        LPFComplex(ComplexDataArray)

        Return ReturnedDataSet

    End Function


    Friend Function LPF(ByRef FFTMagnitudes() As Double) As Double()

        Dim FilterOrder As Integer = 10
        Dim CutoffFrequency As Double = 140
        Dim FilterRipple As Double = 1
        Dim NewFilter As New NationalInstruments.Analysis.Dsp.Filters.ChebyshevLowpassFilter(FilterOrder, ForcingFunctionSampleRate, CutoffFrequency, FilterRipple)
        Dim FFTMagnitudesArray(FFTMagnitudes.Length - 1) As Double
        Dim LPFReturn() As Double
        Dim ReturnedRawDataSet(FFTMagnitudes.Length - 1) As Double

        FFTMagnitudesArray = FFTMagnitudes

        LPFReturn = NewFilter.FilterData(FFTMagnitudesArray)

        For Counter As Integer = 0 To ForcingFunctionBlockSize - 1
            Dim Time As Double = Counter * Timestep
            Dim LPFYValue As Double
            LPFYValue = LPFReturn(Counter)
            ReturnedRawDataSet(Counter) = LPFYValue
        Next

        Return ReturnedRawDataSet

    End Function

    Friend Function LPFComplex(ByRef FFTComplexData() As ComplexDouble)
        Dim FilterOrder As Integer = 10
        Dim ForcingFunctionSampleRate As Double = 1623.377
        Dim CutoffFrequency As Double = 140
        Dim FilterRipple As Double = 1
        Dim NewFilter As New NationalInstruments.Analysis.Dsp.Filters.ChebyshevLowpassFilterComplex(FilterOrder, ForcingFunctionSampleRate, CutoffFrequency, FilterRipple)
        Dim FFTMagnitudesArray(FFTComplexData.Length) As Double
        Dim LPFReturn() As ComplexDouble
        Dim ReturnedDataSet(ForcingFunctionBlockSize - 1) As Double

        LPFReturn = NewFilter.FilterData(FFTComplexData)

        For Counter As Integer = 0 To (ForcingFunctionBlockSize - 1)
            Dim Time As Double = Counter * Timestep
            Dim LPFYValue As Double
            LPFYValue = LPFReturn(Counter).Real
            ReturnedDataSet(Counter) = LPFYValue
        Next

        Return ReturnedDataSet

    End Function

End Class

I pass the previous function's return into the next function to continue the process along.

 

Note I have had to convert this code to more basic code - we are using classes to create "holding" variables that hold the X and Y values of the outputs so we can graph as you see above. This code is specific to our application and therefore wouldn't be of value if I included it, on top of being really hard to include since the supporting classes would be needed as well. I suppose I could have used a tuple or a dictionary, but I wanted to make it as easy as possible to read.

0 Kudos
Message 3 of 3
(2,484 Views)