I'm pleased to post a new Audio Block that implements a real-time phase-locked-loop for use with the Teensy Audio Board. The necessary files are contained in the AudioPLL.zip file here: View attachment AudioPLL.zip
What is a PLL? Well, they are found everywhere in modern electronics. They are a feedback control system, but with a special purpose. They have an in-built frequency synthesizer that is "locked" to an external waveform in frequency and phase, by a feedback loop that continuously measures the instantaneous phase difference between the two signals, and modifies the synthesizer so as to reduce the phase difference to zero, thus locking the two signals together. They are most common in high frequency rf communications work.
The AudioPLL block works at audio frequencies, currently from less than 100Hz to about 12kHz, and over a >40dB range in the reference level. Further tweaking of the loop filter should extend the upper frequency limit. Internally the algorithms use quadrature processing, and a Hilbert Transformer is used to convert from the single input channel to quadrature.
These can be tricky little devils to understand, so I've put a bit of effort into comments in the code. In addition I've included a document that describes some of the issues in the designing analog hardware PLLs, it may help understand the concepts.
The necessary files are included in AudioPLL.zip, as well as another block, AudioSerialPlotter, that will let you view the output on the Arduino Serial Plotter. The set up is simple - here is the attached sketch included:
The block processing time is 330 usec on a Teensy 3.6 at 180 MHz.
Ongoing work includes generating a waveform that is related to, but not identical to, the reference. For example - a waveform that is offset from the reference frequency by a constant, or an arbitrary multiple of the reference (eg an integer harmonic or subharmonic, or a fractional factor).
PLLs can also be used to find and report (with sub-Hz) accuracy the frequency of the reference. The AudioPLL has a function myFrequency = myPLL.getFrequency that returns a float, BUT it can also stream the running frequency estimates as an int16() in Hz through the channel 1 output. by setting myPLL.analysisOutputs(), while if you set myPLL.quadratureOutputs() Channels 0 and 1 will contain the two synthesizer waveforms, that is cos(wt) and sin(wt).
Comments, criticisms, suggestions etc are all welcome
Derek
What is a PLL? Well, they are found everywhere in modern electronics. They are a feedback control system, but with a special purpose. They have an in-built frequency synthesizer that is "locked" to an external waveform in frequency and phase, by a feedback loop that continuously measures the instantaneous phase difference between the two signals, and modifies the synthesizer so as to reduce the phase difference to zero, thus locking the two signals together. They are most common in high frequency rf communications work.
The AudioPLL block works at audio frequencies, currently from less than 100Hz to about 12kHz, and over a >40dB range in the reference level. Further tweaking of the loop filter should extend the upper frequency limit. Internally the algorithms use quadrature processing, and a Hilbert Transformer is used to convert from the single input channel to quadrature.
These can be tricky little devils to understand, so I've put a bit of effort into comments in the code. In addition I've included a document that describes some of the issues in the designing analog hardware PLLs, it may help understand the concepts.
The necessary files are included in AudioPLL.zip, as well as another block, AudioSerialPlotter, that will let you view the output on the Arduino Serial Plotter. The set up is simple - here is the attached sketch included:
Code:
//------------------------------------------------------------------------------
// Simple test sketch for AudioPLL phase-locked-loop audio block
//
//
// D. Rowell Sept 20,2017
//------------------------------------------------------------------------------
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include "AudioPLL.h"
#include "AudioSerialPlotter.h"
//
AudioSynthWaveformSine ReferenceInput;
AudioPLL PLL;
AudioSerialPlotter Plotter;
AudioOutputI2S myOutput;
AudioControlSGTL5000 audioShield;
//
AudioConnection c2(ReferenceInput,0, PLL,0);
AudioConnection c3(PLL,0, Plotter,0); // Plot outputs on Arduino SerialPlotter
AudioConnection c4(PLL,1, Plotter,1); // (or view on SerialMonitor :-) )
//
//----------------------------------------------------------------------------
void setup() {
Serial.begin(57600); while(!Serial){};
audioShield.enable();
AudioMemory(20);
audioShield.inputSelect(AUDIO_INPUT_LINEIN);
//
float frequency = 500;
float amplitude = 0.5;
ReferenceInput.frequency(frequency);
ReferenceInput.amplitude(amplitude);
PLL.enable();
// PLL.analysisOutputs(); // Output synthesized output + frequency
PLL.quadratureOutputs(); // Output quadrature outputs
// Plotter.disable();
}
//----------------------------------------------------------------------------------
void loop() {
// Switch frequency every 3 secs.
ReferenceInput.frequency(200.);
delay(3000);
//
ReferenceInput.frequency(1500.);
delay(3000);
}
The block processing time is 330 usec on a Teensy 3.6 at 180 MHz.
Ongoing work includes generating a waveform that is related to, but not identical to, the reference. For example - a waveform that is offset from the reference frequency by a constant, or an arbitrary multiple of the reference (eg an integer harmonic or subharmonic, or a fractional factor).
PLLs can also be used to find and report (with sub-Hz) accuracy the frequency of the reference. The AudioPLL has a function myFrequency = myPLL.getFrequency that returns a float, BUT it can also stream the running frequency estimates as an int16() in Hz through the channel 1 output. by setting myPLL.analysisOutputs(), while if you set myPLL.quadratureOutputs() Channels 0 and 1 will contain the two synthesizer waveforms, that is cos(wt) and sin(wt).
Comments, criticisms, suggestions etc are all welcome
Derek