Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve MajorPeak with parabola #41

Closed
MarScaper opened this issue Jan 21, 2020 · 2 comments
Closed

Improve MajorPeak with parabola #41

MarScaper opened this issue Jan 21, 2020 · 2 comments

Comments

@MarScaper
Copy link
Contributor

I would like to submit you an improvement in frequency estimation by using a parabola estimation using three points...
Red Parabola

It improves frequency estimation but also amplitude/magnitude estimation. Here is my project with the current MajorPeak() code...
Capture d’écran 2020-01-21 à 21 14 08

And now with my parabola estimation...
Capture d’écran 2020-01-21 à 21 13 36

Here is my code. Feel free to use It... :)

double arduinoFFT::MajorPeakParabola()
{
    double maxY = 0;
    uint16_t IndexOfMaxY = 0;
    //If sampling_frequency = 2 * max_frequency in signal,
    //value would be stored at position samples/2
    for (uint16_t i = 1; i < ((this->_samples >> 1) + 1); i++)
    {
        if ((this->_vReal[i-1] < this->_vReal[i]) && (this->_vReal[i] > this->_vReal[i+1]))
        {
            if (this->_vReal[i] > maxY)
            {
                maxY = this->_vReal[i];
                IndexOfMaxY = i;
            }
        }
    }
    
    double freq = 0;
    if( IndexOfMaxY>0 )
    {
        // Assume the three points to be on a parabola
        double a,b,c;
        Parabola
        (IndexOfMaxY-1,this->_vReal[IndexOfMaxY-1],
         IndexOfMaxY  ,this->_vReal[IndexOfMaxY  ],
         IndexOfMaxY+1,this->_vReal[IndexOfMaxY+1],
         &a,&b,&c);
        
        // Peak is at the middle of the parabola
        double x = -b/(2*a);

        // And magnitude is at the extrema of the parabola if you want It...
        // double y = a*x*x+b*x+c;  
              
        // Convert to frequency
        freq = (x  * this->_samplingFrequency) / (this->_samples);
    }
    
    return freq;
}

void arduinoFFT::Parabola(double x1, double y1, double x2, double y2, double x3, double y3, double *a, double *b, double *c)
{
    double reversed_denom = 1/((x1 - x2) * (x1 - x3) * (x2 - x3));
    
    *a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) * reversed_denom;
    *b = (x3*x3 * (y1 - y2) + x2*x2 * (y3 - y1) + x1*x1 * (y2 - y3)) * reversed_denom;
    *c = (x2 * x3 * (x2 - x3) * y1 + x3 * x1 * (x3 - x1) * y2 + x1 * x2 * (x1 - x2) * y3) *reversed_denom;
}
@HorstBaerbel
Copy link

Looks really useful. Why not send a pull request?

@Phatcat
Copy link

Phatcat commented Feb 6, 2021

I think you can close this issue now it´s been implemented.

@kosme kosme closed this as completed Feb 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants