# Low-Sensitivity Sallen-Key Filter Design with the HP-41C Programmable Calculator

December 21, 2008

This program, which I originally wrote for the HP-67 calculator, addresses the problem of designing second order single op-amp low- and high-pass filters using the Sallen-Key topology.

The Sallen-Key filter topology has the advantage of using a minimum of components. The simplest Sallen-Key filters use only two resistors and two capacitors. Additional resistors may be added for input attenuation (low-pass only) and gain adjustment. The following schematics illustrate these generalized Sallen-Key circuits:

Generalized Sallen-Key low-pass filter

Generalized Sallen-Key high-pass filter

The equations governing the low-pass filter are as follows,

where f is the filter’s cut-off frequency, Q is its “quality”, and H is its gain at the cut-off frequency. The corresponding equations for the high-pass filter are:

The mathematically inclined will notice that in each case, there are three equations in either nine or ten variables. Thus there is no single “right” solution. At least six or seven of the variables have to be decided arbitrarily (f, Q, H, and three or four component values), at which point the remaining variables (component values) can be solved for. An article by Texas Instruments suggests a number of simplifications to help one choose component values, but this just adds the complication of which simplification to choose.

I recently came across a pair of application notes by National Semiconductor which gives a procedure for designing Sallen-Key filters to minimize the effect of component value tolerances on the performance of the filter. A side-effect of this procedure is to reduce the number of inputs to five: f, Q, H, RF, and R, where the latter is simply an indication of the magnitude of resistor values desired for R1, R2, and R3. The procedure then dictates how all the other values are chosen, even adjusting for available “real-world” values part way through the solution.

The program presented here implements this procedure, with some minor changes:

1. Instead of asking for a desired resistor magnitude, R, the program asks for a capacitor magnitude, C, since in my experience, the capacitors drive the design.

2. The formula given for internal gain variable K in the procedure (please refer to the application note) seems to have been derived empirically, and has a jump at Q = 1.1. To make the formula simpler to implement, I modified it slightly to:

The graphs of the original (pink) and revised (blue) formulae show the difference. Testing has shown that the resulting solution is generally at most one real-world capacitor value increment different (with corresponding changes in resistor values of course).

Also, if H > K, then K is set equal to H, since otherwise it will not be possible to achieve the desired gain.

For the low-pass circuit, the desired gain, H, is achieved by a combination of input attenuation, α (controlled by R1 and R3), and the internal gain, K, of the filter (controlled by RF and RG). The division of this gain between the two stages depends on H and Q and is chosen to minimize the sensitivity of the circuit to component tolerances. For example, for H = 1 and Q = 2, the attenuator gain is α = 0.629 and the internal gain is K = 1.59, for a net gain of H = αK = 1.

The high-pass circuit has no attentuation stage, so H must be at least 1, and higher for Q > 0.917. If too low a value is entered for H, it is increased as necessary to make the circuit solvable.

For either circuit, to achieve a result with minimum component sensitivity without regard to gain, set H = 0. The program will automatically choose the optimal value for K (and thus H). The resulting gain will be output when determining the performance.

## Using the Program

First type in the program and save it, or read it from a previously recorded magnetic card. The card should be labelled as follows:

LOW-SENSITIVITY SALLEN-KEY FILTER DESIGN
f Q H C RF
LP→RGC1C2R1R2R3   HP→RGC1C2R1R2   f,Q,H

### Filter Design from Specifications

Example: Design a 500Hz low-pass unity-gain filter with a Q of 2, using capacitors in the 10nF range, and a 47kΩ resistor for RF:

Description Keystrokes Display
Use engineering notation      ENG 2   0.00  00
Enter f  500

500.  00
Enter Q  2

2.00  00
Enter H  1

1.00  00
Enter C  10 EEx CHS 9

10.0 -09
Enter RF  47 EEx 3

47.0  03
Compute RG  A   79.5  03
Enter real-world RG and compute C1  82 EEx 3
R/S
31.6 -09
Enter real-world C1 and compute C2  33 EEx CHS 9
R/S
3.16 -09
Enter real-world C2 and compute R1  3.3 EEx CHS 9
R/S
15.4  03
Enter real-world R1 and compute R2  15 EEx 3
R/S
95.9  03
Enter real-world R2 and compute R3  100 EEx 3
R/S
26.1  03
Enter real-world R3  27 EEx 3
R/S
27.0  03

#### Notes

If a resistor is to be omitted (open circuit), this program displays a value of zero for the resistance. This is different than some of my other programs, which display a “large” value representing infinity.

When the value for RG is displayed as zero, meaning it can be omitted, the value of RF will not matter any more, and RF can be replaced by a direct connection.

### Filter Performance from Chosen Components

During the calculation of the solution above, we’ve entered real-world values in response to each computed value. The real-world values of C1 and C2 are used when computing the values of R1, R2, and R3. However, the real-world values of each of those resistors does not affect the computed value of the remaining ones. Thus, the final filter may not perform exactly as specified. To find out how it does perform, follow these steps:

Description Keystrokes Display
Compute resulting f  E   491.  00
Compute resulting Q  R/S   1.86  00
Compute resulting H  R/S   1.01  00

### A High-Pass Example

Using the parameters already entered for the low-pass filter above, determine the components for a high-pass filter:

Description Keystrokes Display
Compute RG for high-pass filter  C   79.5  03
Enter real-world RG and compute C1  82 EEx 3
R/S
31.4 -09
Enter real-world C1 and compute C2  33 EEx CHS 9
R/S
3.18 -09
Enter real-world C2 and compute R1  3.3 EEx CHS 9
R/S
9.59  03
Enter real-world R1 and compute R2  10 EEx 3
R/S
97.0  03
Enter real-world R2  100 EEx 3
R/S
0.00  00

Now determine the predicted actual performance:

Description Keystrokes Display
Compute resulting f  E   482.  00
Compute resulting Q  R/S   1.96  00
Compute resulting H  R/S   1.57  00

Notice that H is higher than the specified unity gain. This is because the filter is not possible to construct with unity gain when Q = 2. The smallest possible gain is H = 1.59 (which due to real-world components, has become Q = 1.89 and H = 1.57). To achieve H = 1, you will need either a pre-attenuator with low output impedance, or a post-attenuator with high input impedance.

## Program Listing

01♦   LBL “SK”
02♦   LBL a  Enter and store f
03  STO 11
04  RTN
05♦   LBL b  Enter and store Q
06  STO 12
07  RTN
08♦   LBL c  Enter and store H (gain)
09  STO 13
10  RTN
11♦   LBL d  Enter and store C (capacitor scale)
12  STO 00
13  RTN
14♦   LBL e  Enter and store RF
15  STO 04
16  RTN
17♦   LBL A  Low-pass filter: RG,C1,C2,R1,R2,R3
18  CF 00
19  GTO 00
20♦   LBL C  High-pass filter: RG,C1,C2,R1,R2
21  SF 00
22♦   LBL 00  Forward solution
23  RCL 12
24  2.2
25  ×
26  .9
27  −
28  RCL 12
29  .2
30  +
31  ÷  (2.2Q-0.9)/(Q+0.2)
32  1
33  x≤y?
34  x↔y
35  STO 15  K = max(1,(2.2Q-0.9)/(Q+0.2))
36  RCL 13
37  x>y?
38  STO 15  K = max(H,1,(2.2Q-0.9)/(Q+0.2))
39  RCL 15
40  ÷  H/K
41  x=0?
42  1  Use α = 1 if H/K = 0 (because H was 0)
43  FS? 00
44  1  Always use α = 1 for a high-pass filter
45  STO 14  α = H/K (always 1 for a high-pass filter or H = 0)
46  RCL 04
47  RCL 15
48  1
49  −
50  x≠0?
51  ÷  RG = RF/(K-1) if K ≠ 1, or zero if K = 1
52  R/S  Display RG and let user change it
53  STO 05
54  .1  Initialize n to √0.1;
55  √x
56  XEQ 07  n(1+√(1+4Q2(1+n2)(K-1)))/(2Q(1+n2))
57  RCL 08  √0.1 was stored here by subroutine 7
58  x≤y?
59  x↔y  max(n, n(1+√(1+4Q2(1+n2)(K-1)))/(2Q(1+n2)))
60  FS? 00  High-pass filter?
61  XEQ 06  2nQ/(1+√(1+4Q2(K-1-n2)))
62  STO 08
63  RCL 00
64  RCL 08
65  ÷  C1 = C/n
66  R/S  Display C1 and let user change it
67  STO 06
68  RCL 08
69  RCL 00
70  ×  C2 = nC
71  R/S  Display C2 and let user change it
72  STO 07
73  RCL 06
74  ×
75  √x  √(C1C2)
76  XEQ 04  Multiply by 2πf and take reciprocal
77  STO 09  N = 1/(2πf√(C1C2))
78  RCL 07
79  RCL 06
80  ÷
81  √x  n = √(C2/C1)
82  XEQ 03  2nQ/(1+√(1+4Q2(K-1-n2))) or n(1+√(1+4Q2(1+n2)(K-1)))/(2Q(1+n2))
83  STO 08
84  RCL 09
85  ×
86  STO 03  (R1||R3) = nN
87  RCL 14
88  ÷  R1 = (R1||R3)/α
89  R/S  Display R1 and let user change it
90  STO 01
91  RCL 09
92  RCL 08
93  ÷  R2 = N/n
94  R/S  Display R2 and let user change it
95  STO 02
96  RCL 03
97  1
98  RCL 14
99  −  ( 1-α (R1||R3) )
100  x≠0?
101  ÷  R3 = (R1||R3)/(1-α) if α ≠ 1, or zero otherwise
102  R/S  Display R3 and let user change it
103  STO 03
104  RTN
105♦   LBL 04  Multiply by 2πf and take reciprocal
106  RCL 11  f
107  ×
108♦   LBL 01  Multiply by 2π and take reciprocal
109  2
110  ×
111  π
112  ×
113  1/x
114  RTN
115♦   LBL 03  Compute either 2xQ/(1+√(1+4Q2(K-1-x2))) or x(1+√(1+4Q2(1+x2)(K-1)))/(2Q(1+x2))
116  FS? 00  High-pass filter?
117  GTO 07
118♦   LBL 06  Subroutine to compute 2xQ/(1+√(1+4Q2(K-1-x2)))
119  STO 08  Save x for later use
120  RCL 12
121  2
122  ×  ( 2Q x )
123  ×  ( 2xQ )
124  LASTx  ( 2Q 2xQ )
125  x2  ( 4Q2 2xQ )
126  RCL 15
127  1
128  −
129  RCL 08
130  x2
131  −  ( K-1-x2 4Q2 2xQ )
132  ×  ( 4Q2(K-1-x2) 2xQ )
133  XEQ 09  ( 1+√(1+4Q2(K-1-x2)) 2xQ )
134  ÷
135  RTN
136♦   LBL 07  Subroutine to compute x(1+√(1+4Q2(1+x2)(K-1)))/(2Q(1+x2))
137  STO 08  Save x in register 8 for later use both by this subroutine and the caller
138  XEQ 08  ( 2Q 1+x2 )
139  x2
140  ×  ( 4Q2(1+x2) )
141  RCL 15
142  1
143  −  ( K-1 4Q2(1+x2) )
144  ×  ( 4Q2(1+x2)(K-1) )
145  XEQ 09  ( 1+√(1+4Q2(1+x2)(K-1)) )
146  RCL 08
147  ×  ( x(1+√(1+4Q2(1+x2)(K-1))) )
148  RCL 08
149  XEQ 08  ( 2Q 1+x2 x(1+√(1+4Q2(1+x2)(K-1))) )
150  ×  ( 2Q(1+x2) x(1+√(1+4Q2(1+x2)(K-1))) )
151  ÷
152  RTN
153♦   LBL 08  Subroutine to populate stack with 2Q 1+x2
154  x2
155  1
156  +
157  RCL 12
158  2
159  ×
160  RTN
161♦   LBL 09  Subroutine to compute 1+√(1+x)
162  1
163  +
164  √x
165  1
166  +
167  RTN
168♦   LBL E  Compute actual f, Q, and Gain
169  XEQ 02  R1 or (R1||R3)
170  RCL 06
171  ×
172  STO 08  Save R1C1 for use in calculating Q
173  RCL 02
174  RCL 07
175  ×
176  STO 09  Save R2C2 for use in calculating Q
177  ×
178  √x
179  XEQ 01  Multiply by 2π and take reciprocal
180  STO 10  Save actual f for use in calculating Q
181  R/S  Display actual f
182  RCL 09  ( R2C2 )
183  RCL 08  ( R1C1 R2C2 )
184  FS? 00  High-pass filter?
185  x↔y  ( R2C2 R1C1 )
186  1
187  RCL 15
188  −
189  ×
190  +
191  XEQ 02  R1 or (R1||R3)
192  RCL 07
193  ×
194  +
195  RCL 10  Recall actual frequency
196  ×
197  XEQ 01  Multiply by 2π and take reciprocal
198  R/S  Display actual Q
199  RCL 04
200  RCL 05
201  x≠0?
202  ÷
203  1
204  +
205  XEQ 02  R1 or (R1||R3)
206  ×
207  RCL 01
208  ÷
209  RTN  Return actual Gain
210♦   LBL 02  Return either R1 or (R1||R3)
211  RCL 01
212  FS? 00  High-pass filter?
213  RTN  Return just R1
214  1/x
215  RCL 03
216  x≠0?  R3 exists? (0 means not)
217  1/x
218  +
219  1/x
220  RTN

## Registers and Flags

Register Use
00  C – capacitor scale
01,02,03  R1, R2, R3 – filter resistors
04,05  RF, RG – feedback resistors
06,07  C1, C2 – capacitors
08  n – variable used during computation
09  N – variable used during computation
11  f – cutoff frequency
12  Q – filter quality
13  H – overall gain
14  α – input attenuator gain
15  K – internal gain
10  Temporary register
Flag Meaning
00  High-pass filter

## Revision History

2008-Dec-21 — Initial release.

## References

1. Analysis of the Sallen-Key Architecture (Rev.B), Texas Instruments Application Report SLOA024B, James Karki, 2002

2. Low-Sensitivity, Lowpass Filter Design, National Semiconductor (now Texas Instruments) Application Note OA-27, Kumen Blake, 1996

3. Low-Sensitivity, Highpass Filter Design, National Semiconductor (now Texas Instruments) Application Note OA-29, Kumen Blake, 1996

## Related Articles

If you've found this article useful, you may also be interested in:

## 1 Comment

1. October 25, 2015

Hi Stefan, first off many thanks for sharing your programs on your web site, and congrats of a superb documentation – real world class.

I’m also writing to ask you if you’ll agree with adding three of those into a EE-Filters collection that I’ve prepared into a ROM image – to use with v41 Emulator or MLDL-like devices (You heard of the 41CL perhaps?).

You’re probably moved to greener pastures but if you’d like to try the module let me know an email address where I can send it to – I modify them a litlee bit to take advantage of the 41-style data entry and menu prompts, but besides that they’re as you wrote them.

Hope to hear form you soon, thanks again and best wishes,
‘Angel Martin