Learn about circuit error analysis and how we can use simple scripting languages to perform complex simulations.

Monte Carlo analysis is a technique/algorithm that we can use as analog circuit designers to get a more realistic sense of how a circuit will perform when taking into account component tolerances. This can be much more useful than doing worst-case analysis which can in some cases produces results that will never be seen when actually building the circuit.

Some SPICE programs can perform Monte Carlo analysis but the only ones that I know of cost enough that make it impracticable for hobbyists or even some professionals to use or bother with. Using SPICE programs also has its own limitations and may not be able to model the parameters appropriately.

For this tutorial, we will be using PHP to perform the analysis, modeling resistors using a Gaussian distribution function. This is useful because when you buy say, 1% SMD resistors, you’ll find more values that fall between +/- 0.5% than you will have between +/- 1.0%. There have been some articles published that show some manufacturers follow something very close to a Gaussian distribution. There has also been some discussion around 5% resistors completely missing 1% values as the manufacturer just bins these separately.

See http://www.kerrywong.com/2013/02/01/100k-5-carbon-film-resistor-value-distribution/

and http://dangerousprototypes.com/2010/07/01/actual-values-of-10-tolerance-resistors/

Regardless, for the purpose of this discussion, we’re going to assume the resistors that we’re using have a Gaussian distribution and 99.9% of the values fall within the component tolerance of the part (+/- 3 sigma).

In PHP, we need a way to generate a random number that follows a Gaussian distribution as this is not built into PHP by default. The following function was taken from http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform and ported to PHP.

function generateGaussianNoise($mu, $sigma) { $epsilon = 0.00001; static $z0 = 0.0; static $z1 = 0.0; static $generate = false; $generate = !$generate; if( $generate == false ) { return $z1 * $sigma + $mu; } $u1 = 0.0; $u2 = 0.0; do { $u1 = ((float)mt_rand())/((float)mt_getrandmax()); $u2 = ((float)mt_rand())/((float)mt_getrandmax()); } while( $u1 < $epsilon ); $z0 = sqrt(-2.0 * log($u1)) * cos(2.0 * M_PI * $u2); $z1 = sqrt(-2.0 * log($u1)) * sin(2.0 * M_PI * $u2); return $z0 * $sigma + $mu; }

Using this random number generator we can generate a value for one of our components in the later simulation.

function value($typ, $tol, $tempco, $temp) { $mu = $typ; $sigma = $typ * $tol / 3.0; $value = generateGaussianNoise($mu, $sigma); $value = $value * (1 + ($temp-25)*$tempco); return $value; }

value() can be used to generate a resistor value for example of 10 kOhm, 1% tolerance, temperature coefficient of 100 ppm and temperature of 25 degrees C using:

value(10000, 0.01, 100e-6, 25)

The temperature coefficient is separate from this discussion but I wanted to include in the function just to get people thinking.

Okay I want to backtrack now and do some worst-case error analysis of a simple resistor voltage divider and then we’ll go ahead and apply Monte Carlo analysis using the functions that I’ve described above.

Using worst-case error analysis, the function V_out would be evaluated at the component minimum and maximum values. The resulting output voltages would be used to calculate error.

Say V_in = 2 V, R1 = 10 kOhm (1%), R2 = 10 kOhm (1%).

This equates to +/- 1% error in the divider output voltage. Please note that depending on the resistor ratio, the error of a simple voltage divider with 1% resistors can get up to 2%. See http://www.electronicproducts.com/Passive_Components/Resistors_and_Potentiometers/Resistive_voltage_dividers.aspx for a good explanation on why.

Now the fun part, let’s run this through 1 million simulations with different resistor values, randomized using Gaussian distributions and see what we can learn. Here are the results:

Minimum error: -0.95%

Maximum error: +0.97%

Error Mean: -0.0002%

Standard Deviation: 0.233%

The minimum and maximum error is very close to the worst-case error analysis and if you ran enough simulations they will approach those values. However, with some basic statistics we can get an idea of how this is distributed. The mean value is close enough to 0% that we can ignore the decimal point that I decided to include. The standard deviation, by definition, tells us that 68.2% of our test cases fall between +/- 0.233%, 95.4% of our test cases fall between +/- 0.466% and so on.

This is really important information for a designer and how you end up deciding on using it is up to you. Monte Carlo analysis becomes even more useful when you’re simulating equations with more variables as it becomes more and more unlikely that all of the variables will be at the’re worst-case values.

If you’d like to download my simulation and try it for yourself, please help yourself to the link below.

Those million dollar simulator products you describe, offer a dozen different probability density functions to choose from; Gaussian is just one of them. More importantly, these simulators let you apply Monte Carlo techniques to all circuit elements, not just resistors. They let you apply Monte Carlo to arbitrary circuit topologies with arbitrary numbers of circuit elements, not just (two resistor voltage dividers). They let you apply Monte Carlo to all analysis types (AC, DC, Transient, Pole-Zero), not just DC operating point.

This article was intended to describe a very simple example of how this technique could be applied. It can be expanded far beyond some simple resistors.

It should also be noted that this technique is not limited to Gaussian distribution functions, any distribution function can be used.