On 11/11/2021 05:13 PM, Peter wrote:
> Hi All,
>
> I am trying to work out the likely phase lag for a lowpass filter
> whose job is to take out the notches from a DAC.
>
> The DAC is 12 bit and will be generating a 400Hz sinewave. It will be
> driven at around 250x i.e. 100kHz. So the fundamental to filter out
> will be 100kHz.
>
> I am not good at maths but doing some digging around, it looks like a
> simple RC has a 45 deg phase shift at the 1/2piRC point, and somewhere
> around 1 degree when a factor of 100 away from that (40kHz).
>
> I am happy with 1-2 degrees of lag, but more importantly it needs to
> be fairly constant from 400Hz to 500Hz, or at least quantifiable,
> because the table feeding the DAC can be shifted to compensate.
>
> What about a 2nd order filter? The filter performance should be better
> for a given phase lag, no?
>
> Obviously perfection is impossible to achieve but I think a 10kHz
> rolloff frequency would produce a really clean result. The Q is what
> delay can be achieved at that rolloff.
>
> There is a huge amount of stuff online but a lot of it is the audio
> stuff, which is full of BS :)
>
I believe Analog Devices has a pdf titled "Basic Linear Design"
which has a lot of filter coefficients and a bit of writeup on how to implement those.
supposedly gaussian and bessel are (kinda) linear phase.
I've played a bit with those in maxima.
trying to calculate component values.
you may keep any mistakes you find.
As always you have to be careful with the scaling. plotting the actual
transfer function with the parasitic Rs included will be necessary.
parallel(a,b):=1/(1/a+1/b);
series(a,b):=a+b;
ZL1:s*L1;
ZC1:1/(s*C1);
ZL2:s*L2;
ZC2:1/(s*C2);
ZL3:s*L3;
ZR3:R3;
/*
Vi L1 *V1 L2 *V2 L3 *Vo
C1 C2 R3
*/
IR1:Vi/series(ZL1,parallel(series(ZL2,(parallel(series(ZL3,ZR3),ZC2))),ZC1));
V1:IR1*parallel(series(ZL2,(parallel(series(ZL3,ZR3),ZC2))),ZC1);
IL2:V1/series(ZL2,(parallel(series(ZL3,ZR3),ZC2)));
V2:IL2*parallel(series(ZL3,ZR3),ZC2);
IL3:V2/series(ZL3,ZR3);
Vo:IL3*ZR3;
T(L1,C1,L2,C2,L3,R3,s):=''(ratsimp(Vo/Vi));
/*the pole locations in the analog book Basic Linear Design are absolute values*/
s1:-0.8075+%i*0.9973;
s2:-0.8075-%i*0.9973;
s3:-0.7153+%i*0.2053;
s4:-0.7153-%i*0.2053;
s5:-0.8131;
X(s):=1/((s-s1)*(s-s2)*(s-s3)*(s-s4)*(s-s5));
P1:ev(ratexpand(1/(T(L1, C1, L2, C2, L3, R3, s))),R3=1e3);
P2:ratexpand(1/(X(s)));
M:[
coeff(P1,s,0)=coeff(P2,s,0)/coeff(P2,s,0),
coeff(P1,s,1)=coeff(P2,s,1)/coeff(P2,s,0),
coeff(P1,s,2)=coeff(P2,s,2)/coeff(P2,s,0),
coeff(P1,s,3)=coeff(P2,s,3)/coeff(P2,s,0),
coeff(P1,s,4)=coeff(P2,s,4)/coeff(P2,s,0),
coeff(P1,s,5)=coeff(P2,s,5)/coeff(P2,s,0)];
res:solve(M,[L1,C1,L2,C2,L3]),numer;
/*
scale freq to 1.65 MHz
it seems the whole prototype filter(X(s))
is not centered around the -3db freq
-25db at f=1.54
place at:4.608MHz
XXX should've put at 7.68MHz and -48db
-10db at w=1.0
-48db at w=3.0 (**)
+2.4db at w=0.1 (??)
*/
scalef(x):=(lhs(x)=rhs(x)*1.54/(2*%pi*4.608e6));
f_res:map(scalef,res[1]);
parts:ev(f_res,numer);
/*
[L1 = 1.786926598348852E-4, C1 = 9.43803114632655E-11,
L2 = 6.250769103578177E-5, C2 = 3.951204204467418E-11,
L3 = 1.378438412673788E-5]
the values i have on board are a little different
used those for R(s)
*/
load(bode);
R(s):=''(T(180e-6,100e-12,68e-6,33e-12,15e-6,1000,s));
bode_gain(R(s),[w,2*%pi*1e6,2*%pi*4.608e6]);
20*log(cabs(R(%i*2*%pi*4.608e6)))/log(10),numer;
/*
yields
- 26.31120206227737dB
and
- 44.04870603874216dB
at 7.68MHz
- 3dB at 1.3MHz
*/
/*
properly scaled
*/
scalef(x):=(lhs(x)=rhs(x)*3.0/(2*%pi*7.68e6));
f_res:map(scalef,res[1]);
parts:ev(f_res,numer);
/*
[L1 = 2.088615504563594E-4, C1 = 1.103146497622583E-10,
L2 = 7.306093757429039E-5, C2 = 4.618290628598281E-11,
L3 = 1.611161781047285E-5]
*/
R(s):=''(T(209e-6,110e-12,73e-6,46e-12,16e-6,1000,s));
bode_gain(R(s),[w,2*%pi*1e6,2*%pi*7.68e6]);
20*log(cabs(R(%i*2*%pi*7.68e6)))/log(10),numer;
/*
yields
- 50.78836988946069 dB
at 7.68M
- 3dB at 1.1MHz
*/
/*
if I compromise on accuracy (4 bit)
and choose -24db at 7.68M
*/
scalef(x):=(lhs(x)=rhs(x)*1.5/(2*%pi*7.68e6));
f_res:map(scalef,res[1]);
parts:ev(f_res,numer);
/*
-24dB at 7.68M
-3dB at 2.1M
*/