Building simple function generators using OpAmps (OpAmp based multivibrator)

24 Jan 2022 - tsp
Last update 25 Jan 2022
19 mins

The following blog article will look into a pretty simple multivibrator circuit that can be used to build simple function generators using common off the shelf operational amplifiers such as the popular and cheap LM358. Those circuits are of course limited by the gain-bandwidth product of the amplifiers. Usually I won’t use such a circuit in my day to day applications when requiring a square wave oscillation though - there are readily available oscillators, direct digital synthesis (DDS) is trivial especially for lower frequencies and using fast digital analog converters one can also use the direct digital synthesis principle for arbitrary waveform generators anyways.

A look at Schmitt triggers

The main building block of such oscillators is the inverting Schmitt trigger configuration of operational amplifiers. Note that here it’s assumed to have dual rail supply, i.e. there is a positive ($V_{cc}$) and a negative ($V_{ss}$) supply voltage.

The input and output signal are referenced against ground. Usually one assumes that the positive and negative supply voltage are symmetric towards ground - this does not play a role for the Schmitt trigger but will be pleasant for the oscillator later on.

How does the Schmitt trigger work? First let’s look at the feedback network on the non inverting input. Since the current flowing into the OpAmp is assumed to be ideally zero (for LM358 it’s below $100 nA$) the total current over this network can be described as

[ I_{1,2} = \frac{U_{out}}{R_1 + R_2} \\ \to U_2 = R_2 * \frac{U_{out}}{R_1 + R_2} \\ U_2 = U_{out} * \underbrace{\frac{R_2}{R_1 + R_2}}_{\alpha} ]

Since there is no feedback from the output to the input signal the operational amplifier can be assumed to have infinite gain. This means the output voltage is ideally clamped by the supply voltage - in reality it’s limited by the capabilities of the amplifier to a little bit smaller range.

[ U_{out} = \begin{cases} V_{ss} & \forall U_{-} > U_{+} \\ U_{vcc} & \forall U_{+} > U_{-} \end{cases} ]

Since we know the behavior is discrete one can look at two distinct cases. In the first case the output voltage starts at $U_{out} = V_{cc}$ and the input voltage had been larger than $V_{ss} * \alpha$:

[ U_{out} = V_{cc} \\ U_{in}^{+} = U_{out} * \alpha ]

The operational amplifier stays in this state as long as

[ U_{in}^{-} < V_{cc} * \alpha ]

The second case is valid as long as the output of the amplifier is in $U_{out} = V_{ss}$ state (i.e. pulled low).

[ U_{out} = V_{ss} \\ U_{in}^{+} = V_{ss} * \alpha ]

The amplifier keeps that state as long as

[ U_{in}^{-} > U_{ss} * \alpha ]

As one can see the trigger points for state change are non symmetric:

• Going from high to low at $U_{in}^{-} = V_{cc} * \alpha$
• Going from low to high at $U_{in}^{-} = V_{ss} * \alpha$

Square wave oscillator

Now let’s build an multivibrator (or square wave oscillator) out of this Schmitt trigger. This is done by simply generating the input voltage of an resistor - capacitor (RC) network that’s charged or discharged by the output voltage of the amplifier. This works because of the chosen inverting Schmitt trigger topology. When the input voltage grows above a threshold the output voltage swings to negative supply voltage, the capacitor gets discharged. In case the voltage falls below the lower threshold the output voltage swings back up and charged the capacitor again. The time constant of the RC network determines the oscillation frequency. Since the output of the operational amplifier always goes into saturation (at least in theory) the output is a square wave. The RC network has to be designed to not overload the amplifier and usually one requires an additional buffering stage at the output when one wants to drive a significant load.

To analyze this circuit one has first to recall the charging and discharging process of an capacitor via a resistor:

Capacitor charging and discharging

To model the charging and discharging of a capacitor one just has to recall the definition of capacitance $C$ and current $I$:

[ Q(t) = C * U_c(t) \\ I_c(t) = \frac{\partial Q(t)}{\partial t} \\ \to \frac{\partial}{\partial t} Q(t) = \frac{\partial}{\partial t}(C * U_c(t)) \\ I_c(T) = \frac{\partial C}{\partial t} * U_c(t) + C * \frac{\partial U_c(t)}{\partial t} ]

Since one can assume that the capacitance is constant over time (thus $\frac{\partial C}{\partial t} = 0$) in most application this simplifies to the differential equation

[ I_c(T) = C * \frac{\partial U_c(t)}{\partial t} ]

Looking only at the RC network built by $R_3$ and $C$ one can see that the voltage drop across both components has to be $U_{out}$ and that the voltage drop over the resistor $R_3$ is determined just by Ohm’s law:

[ U_{out} = U_3(t) + U_c(t) \\ U_3(t) = R_3 * I_c(t) \\ \to U_{out} = R_3 * I_c(t) + U_c(t) \\ \to U_{out} - U_c(t) = R_3 * I_c(t) \\ U_{out} - U_c(t) = R_3 * C * \frac{\partial U_c(t)}{\partial t} ]

This differential equation can easily be solved by separation of variables:

[ \frac{\partial t}{R_3 * C} = \frac{\partial U_c(t)}{U_{out} - U_c(t)} \\ \int \frac{\partial t}{R_3 * C} = \int \frac{\partial U_c(t)}{U_{out} - U_c(t)} ]

Now one can integrate both parts separately:

[ \int \frac{\partial t}{R_3 * C} = \frac{t}{R_3 * C} + c_1 \\ \int \frac{\partial U_c(t)}{\underbrace{U_{out} - U_c(t)}_{\chi}} = - \int \frac{\partial \chi}{\chi} \\ \int \frac{\partial U_c(t)}{\underbrace{U_{out} - U_c(t)}_{\chi}} = - ln(\chi) = - ln(U_{out} - U_c(t)) + c_2 \\ ]

Inserting into the equation above and combining both additive constants $c_1$ and $c_2$ into one $c_3$:

[ \int \frac{\partial t}{R_3 * C} = \int \frac{\partial U_c(t)}{U_{out} - U_c(t)} \\ \frac{t}{R_3 * C} + c_1 = -ln(U_{out} - U_{c}(t)) + c_2 \\ \frac{t}{R_3 * C} + c_3 = -ln(U_{out} - U_{c}(t)) ]

As usual the integration constant can be determined from boundary conditions. For the initial charging process one can assume that $U_c(t=0) = 0$:

[ \frac{0}{R_3 * C} + c_3 = -ln(U_{out} - U_{c}(t=0)) \\ c_3 = -ln(U_{out}) ]

Inserting into the expression above:

[ \frac{t}{R_3 * C} + c_3 = -ln(U_{out} - U_{c}(t)) \\ \frac{t}{R_3 * C} - ln(U_{out}) = -ln(U_{out} - U_{c}(t)) \\ \frac{t}{R_3 * C} = -ln(U_{out} - U_{c}(t)) + ln(U_{out}) \\ -\frac{t}{R_3 * C} = ln(U_{out} - U_{c}(t)) - ln(U_{out}) \\ -\frac{t}{R_3 * C} = ln(\frac{U_{out} - U_{c}(t)}{U_{out}}) \\ e^{-\frac{t}{R_3 * C}} = \frac{U_{out} - U_{c}(t)}{U_{out}} \\ U_{out} * e^{-\frac{t}{R_3 * C}} = U_{out} - U_{c}(t) \\ U_{out} * e^{-\frac{t}{R_3 * C}} - U_{out} = - U_{c}(t) \\ U_{c}(t) = U_{out} (1 - e^{-\frac{t}{R_3 * C}}) ]

The discharging process or a charging process where the initial voltage is not zero can be modeled in an analog fashion:

[ U(t = 0) = U_0 \neq 0 \\ c_3 = - ln(U_{out} - U_0) \\ \frac{t}{R_3 * C} + c_3 = -ln(U_{out} - U_{c}(t)) \\ \frac{t}{R_3 * C} - ln(U_{out} - U_0) = -ln(U_{out} - U_{c}(t)) \\ \ldots \\ \to U_c(t) = (U_{out} - U_0) * e^{\frac{t}{R_3 * C}} - U_{out} ]

Modeling the oscillator

The initial half swing charging process

When one assumes that the initial charge of the capacitor is zero, i.e. $U_c(t=0) = 0$ and that the operational amplifier goes into positive saturation, i.e. $U_{out} = V_{cc}$ the amplifier stays in saturation till the trigger point at $U_{cc} * \alpha$ is reached, i.e. as long as $U_in^{-} < U_cc * \alpha$. Thus the state switches at $U_c(t) = U_{cc} * \alpha$:

[ U_c(t) = U_{cc} * \underbrace{\frac{R_2}{R_1 + R_2}}_{\alpha} \\ U_{cc} * (1 - e^{-\frac{t}{R_3 * C}}) = U_{cc} * \alpha \\ 1 - e^{-\frac{t}{R_3 * C}} = \alpha \\ -e^{-\frac{t}{R_3 * C}} = \alpha - 1 \\ -\frac{t}{R_3 * C} = ln(1 - \alpha) \\ t_0 = - R_3 * C * ln(1 - \alpha) ]

The full discharge phase

After initially charging the operational amplifier switches output into negative saturation (i.e. $U_{out} = V_{ss}$ with $U_0 = U_{cc} * \alpha$). The oscillator will then stay in this state till the trigger point at $U_{ss} * \alpha$ is reached again:

[ U_c(t) = (U_{ss} - U_0) * e^{-\frac{t}{R_3 * C}} - U_{ss} \\ U_c(t) = (U_{ss} - U_{cc} * \alpha) * e^{-\frac{t}{R_3 * C}} - U_{ss} \\ \to U_c(t) = U_{ss} * \alpha \\ (U_{ss} - U_{cc} * \alpha) * e^{-\frac{t}{R_3 * C}} - U_{ss} = U_{ss} * \alpha \\ (U_{ss} - U_{cc} * \alpha) * e^{-\frac{t}{R_3 * C}} = U_{ss} * (\alpha + 1) \\ e^{-\frac{t}{R_3 * C}} = \frac{U_{ss} * (\alpha + 1)}{U_{ss} - U_{cc} * \alpha} \\ -\frac{t}{R_3 * C} = ln(\frac{U_{ss} * (\alpha + 1)}{U_{ss} - U_{cc} * \alpha}) \\ t_1 = - R_3 * C * ln(\frac{U_{ss} * (\alpha + 1)}{U_{ss} - U_{cc} * \alpha}) ]

The next full charge cycle

After a full discharge cycle the operational amplifier swings back to it’s positive saturation voltage and stays there till the voltage again passes over the trigger point. The equations are the same as for the full discharge cycle, thus one can simply reuse the result:

[ t_2 = - R_3 * C * ln(\frac{U_{cc} (\alpha + 1)}{U_{cc} - U_{ss} * \alpha}) ]

Now we make our lives easier. We assume that the supply voltage is symmetric with respect to ground, i.e. that $U_{ss} = -U_{cc}$. This simplifies the equations of the full charging and discharging cycle and let’s one calculate a really simple expression for the period $T$ of the oscillation (recall $\alpha = \frac{R_2}{R_1 + R_2}): [ t_1 = - R_3 * C * ln(\frac{U_{ss} * (\alpha + 1)}{U_{ss} - U_{cc} * \alpha}) \\ \to t_1 = R_3 * C * ln(\frac{1 + \alpha}{1 - \alpha}) \\ t_2 = - R_3 * C * ln(\frac{U_{cc} (\alpha + 1)}{U_{cc} - U_{ss} * \alpha}) \\ \to t_2 = R_3 * C * ln(\frac{1 + \alpha}{1 - \alpha}) \\ T = t_1 + t_2 \\ \to T = 2 * R_3 * C * ln(\frac{1 + \alpha}{1 - \alpha}) ] Backsubstitution of$\alpha$: [ \to T = 2 * R_3 * C * ln(\frac{1 + \frac{R_2}{R_1 + R_2}}{1 - \frac{R_2}{R_1 + R_2}}) \\ \to T = 2 * R_3 * C * ln(\frac{\frac{R_2 + R_1 + R_2}{R_1 + R_2}}{\frac{R_1 + R_2 - R_2}{R_1 + R_2}}) \\ \to T = 2 * R_3 * C * ln(\frac{\frac{R_2 + R_1 + R_2}{R_1 + R_2}}{\frac{R_1}{R_1 + R_2}}) \\ \to T = 2 * R_3 * C * ln(\frac{R_1 + 2 R_2}{R_1}) \\ \to T = 2 * R_3 * C * ln(1 + 2 * \frac{R_2}{R_1}) ] Thus the frequency can be expressed by$R_1, R_2, R_3$and$C$: [ f = \frac{1}{T} \\ f = \frac{1}{2 * R_3 * C * ln(1 + 2 * \frac{R_2}{R_1})} ] Since one sees that there is a linear dependence of the period duration to$R_3$that’s usually the variable that’s tuned for variable frequency oscillators. For simple experimental setups this is often done by using an potentiometer in the feedback path ($R_3$). Digital control for this resistor is usually not done since it’s easier to build a fully integrated square wave oscillator using microcontrollers by using their internal timers anyways. Simple build using only positive supply voltage So now one knows how to build a simple square wave oscillator using an rail-to-rail operational amplifier - which is something that one can do perfectly well in any laboratory setting - the question arises how to do this using only a positive supply rail. The simplest solution is simply to apply some kind of biasing. Just recall that negative voltage is only negative because of your choice of the reference$0$. The most simple - and for experiments on the breadboard perfectly valid - approach is to add a voltage divider and apply it’s center tap as the operational amplifiers ground reference: Since the biasing network will not really divide the voltages in half due to loading in the upper branch (and by the remaining circuit) it might be a good idea to use a second amplifier as a comparator at the output: This schematic is so simple it can be built using common of the shelf operational amplifiers such as the LM358 that already includes two amplifiers in a single package on a breadboard for educational purposes (I’m usually not a huge fan of breadboards but for demonstration purposes it’s acceptable to use them - even when playing around I’d usually prefer using at least a hole matrix board or a proper PCB) Tuning such an oscillating circuit to 10 Hz one could use: • The voltage divider of the biasing network has been built in a symmetric way:$R_{T1} = R_{T2} = 10 k\Omega$• The divider for the Schmitt trigger configuration is also done simply symmetric:$R_1 = R_2 = 10 k\Omega$• Choosing the capacitor has been done by looking at different resistor values$R_3$for different available metallic film capacitors - the decisions for a low frequency oscillator fell onto a$C = 10 \mu F$capacitor • Inserting into the equations the best fit is a readily available$R_3 = 4.7 k\Omega$resistor for a quick build (won’t be exactly 10 Hz though) The setup is really simple and could be done on a breadboard as shown on the following photograph (not really recommended): Building this circuit on a breadboard (note that this introduces massively parasitic capacitance and additional resistivity as well as non higher frequency capable connections - if one tries more than just experimenting or demonstrating one should at least solder or better use a proper PCB - this really saves much trouble independent of experience or carefulness) yields the following waveform on the output: When looking at the capacitor one can see the periodic charging and discharging cycle: All waveforms have been captured using an Hantek 6022BE USB digital oscilloscope using OpenHantek on FreeBSD. (Note: Amazon affiliate link, this pages author profits from qualified purchases) From square waves to triangular oscillations Moving from a square wave to triangular signal shape is pretty simple. If one thinks about it a triangular wave is just the integral of a square wave. Looking only at the stabilized output and assuming the capacitor is always charged up to$V_{max}$and down to$V_{min}$: [ U_{out} = \begin{cases} V_{cc} & t < \frac{T}{2} \\ V_{ss} & t >= \frac{T}{2} \end{cases} \\ \int_{0}^{\frac{T}{2}} U_{out} dt = \int_{0}^{\frac{T}{2}} V_{cc} dt \\ \to \int_{0}^{\frac{T}{2}} U_{out} dt = V_{min} + V_{cc} * \frac{T}{2} \\ \to \int_{\frac{T}{2}}^{T} U_{out} dt = V_{max} - V_{ss} * \frac{T}{2} ] The OpAmp integrator Implementing an integrator using operational amplifiers is pretty straight forward. Sometimes one sees simpler circuits that do seem to work by circuit analysis - but the additional resistors are required in practice to prevent saturation caused by input offset and leakage currents. • One chooses$R_7 = R_6$so that the input leakage current is of the same dimension and thus the input offset voltage at$0V$is the same for both inputs. This reduces introducing an integration over a constant term that might lead to saturation of the output when using small input signals • The feedback bypass resistor$R_8$limits the open loop gain. This is important flow low frequency signals or DC conditions. In these the ideal amplifier with an infinite open loop gain would saturate even due to small variations in the input voltage. To analyze this circuit one basically looks at the current flowing over the capacitor back into the inverting amplifier input$I_{C2}$. This has to be the same as the current$I_{7}$flowing into the input of the integrator circuit. [ U_{in} = R_7 * I_{7} \to I_{7} = \frac{U_{in}}{R_7} \\ I_{C2} = C * \frac{\partial U_{C}}{\partial t} + \frac{U_{C}}{R_8} ] Now let’s assume for a moment that$R_8 \to \infty$: [ U_{in} = R_7 * I_{7} \to I_{7} = \frac{U_{in}}{R_7} \\ I_{C2} = C * \frac{\partial U_{C}}{\partial t} ] Now applying Kirchhoff’s law: [ \frac{U_{in}}{R_7} + C \frac{\partial U_{out}}{\partial t} = 0 \\ \frac{U_{in}}{R_7} = - C \frac{\partial U_{out}}{\partial t} \\ \frac{U_{in}}{R_7 * C} = - \frac{\partial U_{out}}{\partial t} \\ \frac{1}{R_7 * C} \int_0^{t} U_{in} dt = - \int_0^t \frac{\partial U_{out}}{\partial t} dt \\ U_{out} = - \frac{1}{R_7 * C} \int_0^{t} U_{in} dt + c_1 ] As one can see the output voltage with$R_8 \to \infty$is really just the integral over the input signal. The discrete time applied to the integral can be realized via some discharge switch (like a MosFET) or by applying constant drift compensation ($R_8 \neq \infty$) and applying only non constant signals: [ \frac{U_{in}}{R_7} + C \frac{\partial U_{out}}{\partial t} + \frac{U_{out}}{R_8} = 0 \\ \frac{U_{in}}{R_7} = - C \frac{\partial U_{out}}{\partial t} - \frac{U_{out}}{R_8} \\ \frac{U_{in}}{R_7 * C} = - \frac{\partial U_{out}}{\partial t} - \frac{1}{C} \frac{U_{out}}{R_8} \\ \frac{1}{R_7 * C} \int_0^{t} U_{in} dt = - \int_0^t \frac{\partial U_{out}}{\partial t} dt - \int_{0}^{t} \frac{1}{C} \frac{U_{out}}{R_8} dt \\ U_{out} - \frac{1}{R_8 * C} \int_{0}^{t} U_{out} dt = - \frac{1}{R_7 * C} \int_0^{t} U_{in} dt + c_1 ] In this case one would really have to solve the inhomogeneous differential equation but since$R_8$is usually chosen pretty large such that$U_{out} \gg \frac{1}{R_8 * C} \int_{0}^{t} U_{out} dt$this term is neglected in most designs. Square wave to triangular conversion Now that one knows how the integrator works and that integration over a square wave yields a triangular shape the only remaining important part to notice is that the integrator also might saturate. The longer the square wave duty cycle is the slower the output rise time is allowed to be. As one can see the output voltage scales with$\frac{1}{R_7 * C}$thus one can control the slope via larger$R_7$or larger capacitance$C$. To limit this one can look at the slowest oscillation frequency and require the charging process not to provide enough current to saturate the output over a full swing and assume the input to the integrator is$U_{vcc}\$ (related to shifted ground):

[ U_{max} = - \frac{1}{R_7 * C} \int_0^{T} U_{in} dt \\ U_{max} = - \frac{1}{R_7 * C} \int_0^{T} U_{vcc} dt \\ U_{max} = - \frac{T * U_{vcc}}{R_7 * C} \\ \to R_7 = - \frac{T * U_{vcc}}{U_{max} * C} \to C = - \frac{T * U_{vcc}}{U_{max} * R_7} ]