0
$\begingroup$

enter image description hereI'm doing work on SDR for GNSS and I'm tracking the signals I/Q using PLL. The calculations for the PLL is done like the following for error estimation:

double PLLAtan::compute(const CorrelationResult &correlation_result)
{
    sampleType I_P = correlation_result.getPromptCorrelator().real();
    sampleType Q_P = correlation_result.getPromptCorrelator().imag();

    double discriminator = static_cast<double>(std::atan(Q_P / I_P)) / (2 * M_PI);
    return discriminator;
}

in each epoch time frame:

pll_fll_filter_.setDiscriminator(pll_disc_->compute(correlation_result));

My problem is the PLL filter is oscillating between 0.98 to 0.96 and it never locks to 1

Should I do something like accumalting the error in the correllation result from the I/Q calculate the error between last I/Qs and current and use it as input for PLL phase error correction ?

    double LoopFilterPLLFLL::updateLoop()
    {
        if(filter_order_ == 2)
        {
            double out_velocity = velocity_integrator_.setInput(w0f_ * fll_discriminator_ + w0_ * w0_ * discriminator_);
            loop_output_        = a2_ * w0_ * discriminator_ + out_velocity;
        }
        if(filter_order_ == 3)
        {
            double out_acceleration
                = acceleration_integrator_.setInput(w0f_ * w0f_ * fll_discriminator_ + w0_ * w0_ * w0_ * discriminator_);
            double out_velocity = velocity_integrator_.setInput(a2_ * w0f_ * fll_discriminator_ + a3_ * w0_ * w0_ * discriminator_
                                                                + out_acceleration);
            loop_output_        = b3_ * w0_ * discriminator_ + out_velocity;
        }
        return (loop_output_);
    }


void LoopFilterPLLFLL::setLoopParameters()
{
    LoopFilter::setLoopParameters(fp_.filter_order_pllfll, fp_.update_rate, fp_.narrow_noise_bandwidth_pll);

    calcLoopParameter(0.0, fp_.wide_noise_bandwidth_fll);
}

void LoopFilterPLLFLL::calcLoopParameter(double pll_noise_bandwidth, double fll_noise_bandwidth)
{
    if(filter_order_ == 2)
    {
        w0f_ = fll_noise_bandwidth / 0.25;
        w0_  = pll_noise_bandwidth / 0.53;
    }

    if(filter_order_ == 3)
    {
        w0f_ = fll_noise_bandwidth / 0.53;
        w0_  = pll_noise_bandwidth / 0.7845;
    }
}

Gain Parameters:

 "pll": {
                "filter-order": 2,
                "discriminator": "PLL-ATAN",
                "wide-bandwidth": 20,
                "narrow-bandwidth": 5
            },
            "fll": {
                "discriminator": "FLL-DP",
                "wide-bandwidth": 10,
                "narrow-bandwidth": 2
            }

enter image description here

enter image description here

$\endgroup$
41
  • $\begingroup$ That's just the phase discriminator. What does the rest of your PLL do? $\endgroup$ – Marcus Müller Feb 8 '20 at 11:06
  • $\begingroup$ Agree with Marcus; please include a diagram of your complete loop as well as the gain coefficients for each block (counts/radian from your discriminator, radians/count from your carrier recovery phase rotator etc) and what you already understand as to how to design your loop filter and its parameters. $\endgroup$ – Dan Boschen Feb 8 '20 at 13:15
  • $\begingroup$ @DanBoschen I have updated the post, please let me know if you need more information $\endgroup$ – Ahmed Saleh Feb 8 '20 at 13:46
  • $\begingroup$ If you include a simple control loop block diagram, and show all the gain parameters in that, I can help you! I could probably derive that from all the code you listed, but have minimum time today. $\endgroup$ – Dan Boschen Feb 8 '20 at 13:47
  • $\begingroup$ @DanBoschen Thanks for your help, I just did it from the book above by kaplan $\endgroup$ – Ahmed Saleh Feb 8 '20 at 13:55

Browse other questions tagged or ask your own question.