Sometimes you need to simulate an opamp by hand to figure why is it doing some
thing or the other. So you start from the definition:
V_out = A * (V+ - V-)
and use it for our particular case:
V_out = A * (V+ - V_out)
if you solve it algebraically, it gives you the correct answer:
V_out = A / (A + 1) * V+
The bad news is that the same method gives you the answer for buffer with a
_positive_ feedback, which in reality wouldn't work:
V_out = A / (A - 1) * V-
Something is missing.
falstad circuit simulator has the same problem
If you decide to solve this equation iterativelly instead of algebraically, it
will diverge quickly (but it will probably hit the rails before reaching the
petavolts shown below):
>>> Vout = 4
>>> Vplus = 4.3
>>> A = 100
>>> for _ in range(10):
... Vout = A * (Vplus - Vout)
... print(Vout)
...
29.999999999999982
-2569.999999999998
257429.99999999983
-25742569.999999985
2574257429.9999986
-257425742569.99985
25742574257429.984
-2574257425742568.5
2.574257425742573e+17
-2.574257425742573e+19
It seems that the high amplification factor will amplify every error on input
beyond any reasonable value. Only if the reaction of the amplifier to errors
could be a little "tamer". Say limit the change per iteration (simulation step)
to something significantly smaller than the amplification factor! For example,
let's limit the reaction to error of "1" to "0.5" after amplification:
>>> def limit(old, new, max_diff):
... if new < old:
... return max(new, old - max_diff)
... else:
... return min(new, old + max_diff)
...
>>> limit(5, 6, 0.2)
5.2
>>> limit(5, 4, 0.2)
4.8
>>>
... Vout = 4
>>> Vplus = 4.3
>>> A = 100
>>> for _ in range(100):
... Vout = limit(Vout, A * (Vplus - Vout), 1 / (A * 2))
... print(Vout)
...
4.005
4.01
4.015
4.02
4.0249999999999995
4.029999999999999
4.034999999999999
4.039999999999999
...
4.254999999999995
4.2599999999999945
4.254999999999995
4.2599999999999945
That's almost the algebraical solution (100/101*4.3 = 4.257...).
With the new simulation the example with positive feedback will slowly but
relentlessly fuck off towards the rail.
>>> Vout = 4
>>> Vplus = 4.3
>>> A = 100
>>> for _ in range(100):
... Vout = limit(Vout, A * (Vout - Vplus), 1 / (A * 2))
... print(Vout)
...
3.995
3.99
3.9850000000000003
3.9800000000000004
...
3.5050000000000106
...
-1.4199999999999287
-1.4249999999999285
So real op-amps have a thing called "slew rate" which is usually specified in
V per us, which is the maximal rate of change they are willing to output in
given time. This is not as much technological constrain as the core of how
they operate: op-amp works by slowly changing its output in the direction of
the error and waiting for the feedback to signal whether it had reached its
desired goal.
pink is amp input, yellow amp output
This of course has several problems. One of it is that the feedback function
has to be quick enough, so that the op-amp has a change to settle. If we
introduce just enough delay in the feedback loop, we will get this:
delay in feedback, circuit at the end
The good thing is that the opamp "algorithm" works very well with all sorts of
feedback functions, provided that the feedback does increase/decrease the
difference in the correct direction.
falstad
This circuit sets whatever voltage drop on transistor R1 (in this case 1V,
thus we want 5-1=4 V at point X). You get 1V over that transistor no matter
the R2 transistor (up to a limit) and no matter the diode drop the transistor
requires, all through the magic of feedback.
Also note: this op-amp configuration has feedback via the "plus" pin, because
the higher the opamp sets its output, the lower goes the voltage in point "X"
(and if you are like me, you might have had associated the "+" and "-" inputs
of opamp with "positive" and "negative" feedback, with which they have nothing
in common).
[TODO: put here some interesting feedback circuits]
General-purpose opamps has slew rate around 1V/us, which limits how many
"analog operations" per second you can do, or the limit on signal frequency
it can amplify (ie. you want the buffered sine signal to go 0...5V...0, you can
do this only 100_000 times per second, which means max. 100 KHz signals).
Also: the op-amp with which I'm testing this (MCP6002) has a slight delay
before it changes its output:
how did it get there?
I'm not sure why, it's likely that this is for noise reduction. If you feed it
with PWM fast enought (and with low duty cycle), you will get nothing on
output:
mcp6002
It's also quite useful for simulating delay - I connected four op-amps like
this to produce the image with opamp trying to catch up:
Anyway, that's all I wanted to say.