Spice3f5

Fitting a filter response with optimise

Fitting a Sallen-Key low pass to a Butterworth response.

The optimise command varies both capacitors of a unity-gain Sallen-Key low pass so that its magnitude response matches an ideal 1kHz second-order Butterworth response across the whole sweep. The expected values are C1 = 22.5nF and C2 = 11.25nF.

-40-30-20-1001001k10kfrequency (Hz)db(v(out))
Fitted response (dB)
  • db(v(out))

Output

Optimising 2 parameters, targeting (1/sqrt(1+(frequency/1k)^4)) = mag(v(out))
   1: mse = 0.0046153    c1=1e-08 c2=1e-08
   2: mse = 0.00223941   c1=1.5849e-08 c2=1e-08
   6: mse = 0.00162405   c1=1.7783e-08 c2=1.2589e-08
   8: mse = 0.00148056   c1=2.5119e-08 c2=1e-08
  11: mse = 0.000351736  c1=2.4406e-08 c2=1.1885e-08
  13: mse = 0.000198428  c1=2.0983e-08 c2=1.1715e-08
  15: mse = 0.000155502  c1=2.3842e-08 c2=1.0863e-08
  17: mse = 7.81756e-05  c1=2.1412e-08 c2=1.099e-08
  19: mse = 1.44593e-05  c1=2.1774e-08 c2=1.1314e-08
  22: mse = 1.11318e-05  c1=2.3073e-08 c2=1.133e-08
  25: mse = 6.16131e-06  c1=2.2551e-08 c2=1.1163e-08
  27: mse = 1.56679e-06  c1=2.2286e-08 c2=1.128e-08
  29: mse = 1.54395e-06  c1=2.2743e-08 c2=1.1275e-08
  31: mse = 8.53334e-07  c1=2.2532e-08 c2=1.122e-08
  33: mse = 1.18149e-07  c1=2.2461e-08 c2=1.1264e-08
  39: mse = 5.89111e-08  c1=2.2559e-08 c2=1.1255e-08
  41: mse = 1.59336e-08  c1=2.2523e-08 c2=1.125e-08
  43: mse = 1.45814e-08  c1=2.2501e-08 c2=1.1258e-08
  45: mse = 8.13916e-09  c1=2.2489e-08 c2=1.1254e-08
  47: mse = 6.74787e-10  c1=2.2509e-08 c2=1.1253e-08
 100: mse = 6.50059e-10  c1=2.2503e-08 c2=1.1254e-08
Converged after 100 simulations
Best mean square error = 6.50059e-10 (rms 2.54963e-05)
Parameter                     initial        final          min          max
c1 capacitance                  1e-08   2.2503e-08        1e-09        1e-07
c2 capacitance                  1e-08   1.1254e-08        1e-09        1e-07
Final results are in plot ac1

The circuit: examples/optimise_demo.cir

optimise_demo.cir - fit a Sallen-Key low pass to a 1kHz Butterworth response

* Unity gain Sallen-Key low pass, with an ideal buffer
vin in 0 dc 0 ac 1
r1 in a 10k
r2 a b 10k
c1 a out 10n
c2 b 0 10n
eamp out 0 b 0 1

.control
* Fit c1 and c2 so |v(out)| matches the ideal 2nd order Butterworth
* magnitude 1/sqrt(1+(f/1k)^4) across the whole sweep.  The target is
* evaluated on each run's results, so it can use the frequency scale.
* Expect c1 = 22.5n, c2 = 11.25n.
optimise analysis ac dec 10 100 10k vary c1 1n 100n vary c2 1n 100n target (1/sqrt(1+(frequency/1k)^4)) mag(v(out))

* The final run is left as the current plot
let ideal = 1/sqrt(1+(frequency/1k)^4)
plot db(v(out)) db(ideal) title "Sallen-Key fitted to Butterworth"
.endc
.end

Run it with spice optimise_demo.cir, or open it with File › Load netlist in the Qt window. The plots and output above were made by util/mkexamples.py, which runs the deck in batch mode. All examples