Frequency Offset Calibration for Receivers
This example shows how to measure and calibrate for the frequency offset between a transmitter and a receiver at the receiver using MATLAB® and Communications Toolbox™. You can either use captured signals or receive signals in real time using the Communications Toolbox Support Package for RTL-SDR Radio. The receiver monitors the received signal, calculates the frequency offset between the transmitter and the receiver and displays it in the MATLAB® command window.
Required Hardware and Software
To run this example using captured signals, you need the Communications Toolbox™.
To receive signals in real time, you also need an RTL-SDR radio and the corresponding Communications Toolbox Support Package for RTL-SDR Radio support package Add-On.
For a full list of Communications Toolbox supported SDR platforms, refer to Supported Hardware section of Software Defined Radio (SDR) discovery page.
If you choose to receive signals in real time using a radio, you need to tune to a known broadcast pilot tone or provide a signal source with a known center frequency to establish a baseline. If you do not have a signal generator available, you can use a low-cost Family Radio Service walkie-talkie as a source. Note that the signal source must be narrowband, with a sine wave being an ideal source.
All radio receivers exhibit a frequency offset as compared to the transmitter. In some cases, the frequency offset may be more than the receiver algorithm can handle. Therefore, you may need to calibrate your receiver to minimize the frequency offset.
The example provides the following information about the communication link:
The quantitative value of the frequency offset in Hz and PPM
A graphical view of the qualitative SNR level of the received signal
If you have a transmitter, you can use it to generate a narrowband signal, such as a tone.
If you do not have a transmitter, you may be able to use a broadcast signal. For example, in USA, the ATSC digital TV signals include a narrowband pilot tone on the RF carrier. The pilot tone is usually at a nominal frequency of 309.440 kHz above the bottom edge of the channel. If such a signal is present in your area, you can set the expected center frequency value to the frequency of the tone. This example uses the pilot tone of channel 29, which is at approximately 560e6 + 309.440e3 Hz. For a list of channel number and frequency values, see North American television frequencies.
If you are using an RTL-SDR radio as the receiver, specify the displayed PPM correction value as the FrequencyCorrection property of the RTL-SDR Receiver System object™ to compensate for the frequency offset. Be sure to use the sign of the offset in your specification. Once you've done that, the spectrum displayed by the receiver's spectrum analyzer System object should have its maximum amplitude at roughly 0 Hz.
Run the Example
Begin transmitting with your known signal source. If you are in the USA, you can set the expected center frequency to the pilot tone of a near by digital TV transmitter.
FrequencyOffsetCalibrationForReceiversExample script displays the spectrum of the received signal on a frequency range of -200 kHz to 200 kHz and prints the estimated frequency offset in Hz and PPM in the command window. In the case shown below, the frequency of the maximum received signal power is about -35 kHz.
The receiver asks for user input and initializes variables. Then it calls the signal source, DC blocker, coarse tone frequency offset estimator, and spectrum analyzer in a loop. The loop also keeps track of the radio time using the frame duration.
% Request user input from command-line for application parameters userInput = helperFrequencyCalibrationUserInput; % Calculate system parameters based on the user input [fcParam,sigSrc] = helperFrequencyCalibrationConfig(userInput); % Create a DC blocker system object to remove the DC component of the % received signal and increase accuracy of the frequency offset estimation. dcBlocker = dsp.DCBlocker('Algorithm', 'Subtract mean'); % Create a coarse frequency offset estimation System Object to calculate % the offset. The system object performs an FFT on its input signal and % finds the frequency of maximum power. This quantity is the frequency % offset. CFO = comm.CoarseFrequencyCompensator( ... 'FrequencyResolution', 25, ... 'SampleRate', fcParam.FrontEndSampleRate); % Create a spectrum analyzer scope to visualize the signal spectrum scope = spectrumAnalyzer(... 'Name', 'Actual Frequency Offset',... 'Title', 'Actual Frequency Offset', ... 'SpectrumType', 'Power',... 'FrequencySpan', 'Full', ... 'SampleRate', fcParam.FrontEndSampleRate, ... 'YLimits', [-40,10],... 'SpectralAverages', 50, ... 'FrequencySpan', 'Start and stop frequencies', ... 'StartFrequency', -200e3, ... 'StopFrequency', 200e3,... 'Position', figposition([50 30 30 40]));
msgLength = 0; radioTime = 0; secondCounter = 1; while radioTime < userInput.Duration rxSig = sigSrc(); rxSig = dcBlocker(rxSig); [~, offset] = CFO(rxSig); freqCorrection = (-offset / fcParam.ExpectedFrequency) * fcParam.FrontEndSampleRate; % Visualize spectrum and print results scope(rxSig); if radioTime > secondCounter fprintf(repmat('\b', 1, msgLength)); msg = sprintf(['Frequency offset = %f Hz,\n' ... 'Frequency correction value (Hz) = %f \n' ... 'Frequency correction value (PPM) = %f \n'], ... offset, -offset, freqCorrection); fprintf(msg); msgLength = numel(msg); secondCounter = secondCounter + 1; end % Update radio time radioTime = radioTime + fcParam.FrameDuration; end % Release all System objects release(sigSrc); release(dcBlocker); release(CFO);
Frequency offset = -35808.562500 Hz, Frequency correction value (Hz) = 35808.562500 Frequency correction value (PPM) = 63.908546
In this example, you used Communications Toolbox™ System objects to build a receiver that calculates the relative frequency offset between a transmitter and a receiver.