A Wien bridge oscillator is a type of electronic oscillator that generates sine waves. See https://en.wikipedia.org/wiki/Wien_bridge_oscillator.
Design calculations for Wien Bridge Oscillator. See page 21-1 of Handbook of Operational Amplifier Circuit Design, by David F. Stout and edited by Milton Kaufman. Reference designators match figure 21.1.
The Opamp used in the implementation is a LM324, from the TI datasheet:
Input bias current: 20nA
output offset voltage: 1.4 volts due to 20nA input bias current. 1.4 volts in the test condition measured under open loop conditions.
unity gain frequency: 1.2 MHz
Notes:
from math import *
# opamp parameters
Ib1 = 20.0e-9 #input bias current of A1
dVo_max = 0.1 #output offset due to bias current of A1
fu2 = 1.2e6 #unity gain cross over freuqncy of A1
#frequency of oscillation
fo = 1.0 #design frequency at mid band
# step 1: compute a value for R1_max
R1_max = dVo_max/Ib1
print('R1_max = {:.2f}'.format(R1_max))
#step 2: determine other resistor values
R2 = sqrt(R1_max)
R4 = R2
R5 = R2
R6 = R2
R3 = 1.1*R2
R6 = 4.5*R3 # 100.0*R3
# display resistor values
#print('R1 = {:.2f}'.format(R1))
print('R2 = {:.2f}'.format(R2))
print('R3 = {:.2f}'.format(R3))
print('R4 = {:.2f}'.format(R4))
print('R5 = {:.2f}'.format(R5))
print('R6 = {:.2f}'.format(R6))
#step 3: determine nominal values for C1 and C2
C1 = 1.0/(2.0*pi*fo*R2)
C2 = C1
#display capacitor values
print('C1 = {:.3e}'.format(C1))
print('C2 = {:.3e}'.format(C2))
#step 4: compute fixed portion of R1
R1_min = (R4**2.0/(4.0*pi**2.0*R2*C1*C2*fu2**2.0))**0.3333
print('R1_min = {:.2f}'.format(R1_min))
#step 5: compute frequency limits
fo_max = (fu2/(4.0*pi**2.0*R2*R4*C1*C2))**0.333
fo_min = (1/(2.0*pi))*(Ib1/(R2*C1*C2*dVo_max))**0.5
print('fo_min = {:f}'.format(fo_min))
print('fo_max = {:f}'.format(fo_max))
#step 6, oscillator frequency is recalculated
fo_min = 1/((2*pi)*(R1_max*R2*C1*C2)**0.5)
print('fo_min = {:f}'.format(fo_min))
R1_nom = R2
fo_nom = 1/((2*pi)*(R1_nom*R2*C1*C2)**0.5)
print('fo_nom = {:f}'.format(fo_nom))
R1_mid = (R1_min+R1_max)/2.0 #set R1 to be the mid point between min and max values of R1
fo_mid = 1/((2*pi)*(R1_mid*R2*C1*C2)**0.5)
print('fo_mid = {:f}'.format(fo_mid))
fo_max = 1/((2*pi)*(R1_min*R2*C1*C2)**0.5)
print('fo_max = {:f}'.format(fo_max))