I'm trying to build an op-amp model with saturation. I've made some progress on this goal, I'm using the following code to generate my system of equations for the circuit (my apologies for the non-standard notation/syntax):
In this code here, 'p', 'n', and 'o' are the terminals of the op-amp, 'vpp' and 'vnn' are the power supply terminals of the op-amp. Terminals have a property 'V' that is a variable representing the voltage at the node that terminal is connected to. So for example, 'p.V - n.V' means the voltage differential between the positive and negative inputs of the op-amp.
Now, this model works great when vpp and vnn are equal to +/-X, where X is some constant voltage from some other nodes in the circuit. However, when vpp and vnn are not equal in magnitude (for example, +9V and 0V, a typical case I'm trying to simulate unsuccessfully...), the output is not correct.
Now, it's pretty obvious why the above will not work when vpp and vnn are not equally balanced around 0. The computation to saturate the voltage with ArcTan clearly is not correct in this case; it is only considering the difference between vpp and vnn, and the result is saturated around 0. However, my problem is I cannot figure out what it should be. My first naive guess was to add (vpp.V + vnn.V) /2 to Vout after saturating it, and this actually works for some input signals (it appears to work when the signal is large enough to actually saturate), but it is clearly wrong as well.
A bonus question: I'm trying to simulate this all in real time, meaning I don't have a lot of time to spend finding roots of these equations. The above is challenging because the derivative of arctan is very near zero for most of its domain, causing newton's method to not converge easily. I'd like to replace ArcTan with something that isn't quite as correct, but maybe helps newton's method converge more easily. I'm thinking something based on log instead of arctan, like maybe something along the lines of ln(1 + abs(x)) * sign(x). This is much easier to deal with when finding roots. I realize this won't saturate as "strongly", but I'm hoping it will still sound mostly correct while being much faster to solve...
I'd appreciate any thoughts on this topic!
Rich (BB code):
// The input terminals are connected by a resistor Rin, add that to the MNA system.
Resistor.Analyze(p, n, Rin);
// Compute Vout using Vout = A*Vin
Expression Vout = Aol * (p.V - n.V);
// Saturate the output if the power supply terminals are connected.
Expression Vmax = vpp.V - vnn.V;
Vout = (Vmax / Pi) * ArcTan(Vout / Vmax);
// Output current = (Vout - Out.V) / Rout
AddTerminal(o, (Vout - o.V) / Rout);
Now, this model works great when vpp and vnn are equal to +/-X, where X is some constant voltage from some other nodes in the circuit. However, when vpp and vnn are not equal in magnitude (for example, +9V and 0V, a typical case I'm trying to simulate unsuccessfully...), the output is not correct.
Now, it's pretty obvious why the above will not work when vpp and vnn are not equally balanced around 0. The computation to saturate the voltage with ArcTan clearly is not correct in this case; it is only considering the difference between vpp and vnn, and the result is saturated around 0. However, my problem is I cannot figure out what it should be. My first naive guess was to add (vpp.V + vnn.V) /2 to Vout after saturating it, and this actually works for some input signals (it appears to work when the signal is large enough to actually saturate), but it is clearly wrong as well.
A bonus question: I'm trying to simulate this all in real time, meaning I don't have a lot of time to spend finding roots of these equations. The above is challenging because the derivative of arctan is very near zero for most of its domain, causing newton's method to not converge easily. I'd like to replace ArcTan with something that isn't quite as correct, but maybe helps newton's method converge more easily. I'm thinking something based on log instead of arctan, like maybe something along the lines of ln(1 + abs(x)) * sign(x). This is much easier to deal with when finding roots. I realize this won't saturate as "strongly", but I'm hoping it will still sound mostly correct while being much faster to solve...
I'd appreciate any thoughts on this topic!