Lock-In PID controller on Teensy 4.0 with Audio Library

Status
Not open for further replies.
Hello All,

I am planning to do a lock-in PID controller with Teensy 4.0 with the audio board (SGTL5000) and audio library.
This will be a relatively low frequency lock-in detector (between 1kHz to 10kHz) and PID controller (100 Hz to 1kHz, about 10x less bandwidth after low-pass).

-
The signal of interest goes into the ADC and is then mixed with a sine wave and a cosine wave separately ("local oscillators"). The two waves have the same frequency.
It then goes to a low-pass filter to remove the harmonics (lets call the signal S and C after low pass). The phase independent term R is sqrt(S^2 + C^2).

I have tested this lock-in detection part on Teensy 3.6 DAC output (without ADC and without the R calculation) by having an amplitude modulated sine mixing with the local oscillators and low-passing.
I can get the amplitude modulation signal out of the Teensy and it looks right scoped. The routing of the signals are done with the audio system design tool.

-
So the question now is how do I pipe the demodulated signals (S and C) into a PID controller ?
The signals seems to be "stuck" (sorry for lack of a better word) in the audio architecture way of doing things.
I want to use the PID controller to control the frequency and amplitude of the output - it is kind of to drive an object on resonance with constant amplitude. i.e. its a scaled local oscillator.

(side note, to get it on resonance, one drive the signal C to zero while changing the frequency/phase. To have constant amplitude, one would have drive S (or R) to the desired value)


Method One - Create a new audio object (following instructions here https://www.pjrc.com/teensy/td_libs_AudioNewObjects.html) to calculate R and write the PID in this audio object. This is not very ideal I guess, the audio cycle runs at 44kHz or so which is faster than what I really need.
Method Two - Create a new audio object to calculate R and some how "parse" it out of the audio library for use in Arduino main loop. Clearly my programming skills are not very good to understand how to do this.
Method Three - Create a new audio object to just serial output S and C and then do the processing on another teensy/device. This would probably work, but it runs at 44kHz as well and is not very efficient ( two teensy, connected by serial... )

Any suggestions would be appreciated.
 
I realised that perhaps posting this in the audio category might be a better choice.

Moderator do please help to shift it if this post is in the wrong place.
 
I realised that perhaps posting this in the audio category might be a better choice.

Moderator do please help to shift it if this post is in the wrong place.

most people read all categories (new posts shows all categories). I would not worry
 
Method 2 sounds best - have it similar to the AudioAnalyzePeak class, but returning the DC average per block perhaps.
You'd then just poll two of them for the quadrature signal.

One key question though: What range of cutoff frequencies are you envisaging for the LPF? Very low cutoffs are much more
complex to do digitally.

Have you thought about latency on the stability of the PID loop?
 
Method 2 sounds best - have it similar to the AudioAnalyzePeak class, but returning the DC average per block perhaps.
You'd then just poll two of them for the quadrature signal.

One key question though: What range of cutoff frequencies are you envisaging for the LPF? Very low cutoffs are much more
complex to do digitally.

Have you thought about latency on the stability of the PID loop?
 
Thanks for your reply. I forgot about AudioAnalyzePeak.. thats a good example of how to get the data back into the main loop when required.

I did try the biquad filter at 100Hz I think but there was a note that it may not perform well and for some reason it didn't work as well (Or I didn't try as hard).
A FIR filter at 100 Hz (I forgot the number of taps) worked fine.

I saw in another thread (https://forum.pjrc.com/threads/67513-Real-Time-Audio-Processing) that the latency would be about 3ms.
This could possibly cause some problems at high loop rate. Maybe I can push it down to 100Hz or 50Hz so 3ms is a smaller fraction of the loop time. Or try messing around with AUDIO_BLOCK_SAMPLES.
Typically I would just employ live tuning of Kp and Ki (no Kd usually) to get the output stable with no overshoot.



The alternative is an analog multiplier (AD633) or lock-in amplifier (AD630), but they have much more part count.
Laboratory instruments typically use FPGA based processing to reduce the latency for lock-in PID purposes.
Either feels like a overkill for kHz lock-in, so I am trying this at the moment.
 
The latency is more than 3ms, since the SGTL5000's ADC has internal latency too (its sigma-delta architecture), and
there's possibly double-buffering to consider (I forget what the actual total latency figure is, someone will know).

Reducing the audio block size is probably worth doing, the default 128 sample blocksize can be any power of two down to 16 I think for most
objects (a few are 128 only, like the FFT ones).

For very low bandwidth low-pass filters the strategy normally used is to do a more relaxed low pass filter, then decimate, then
refilter on the decimated signal - to do this you'd need to come out of the audio library.

For instance the first filter might have pass band to 500Hz, stop band from 1.35kHz, then decimate by 16, then you've a much
easier job of filtering down to 10's of Hz as the new sample rate is 2.756kSPS. Rinse and repeat as needed.
 
Status
Not open for further replies.
Back
Top