Ngspice is always right (a little note for simulation debugging)

Obviously that is not true but helps to find your mistakes in your “Transient Analysis”!

Time step is too small:

  • This is the most frequent error and is very annoying because it has nothing to do with the problem
  • (Upd1) “Often stems from numerical instability caused by floating (unconnected) nodes, inconsistent definitions, or problematic source configurations.” - ChatGPT (It actually helped.)
  • Something is not right in your circuit. This does not mean changing the timestep or putting in control statements does not help to get a result. It will not remove the problem and more headache is coming.
  • Check missing SPICE model or subcircuit
  • Check if you used the correct file of the model you wanted, copy all model files in the working directory! Do not link, or browse from distant folders! Prefer one model per file, no big bundles!
  • Check if the model’s pinout is connected correctly to the symbol
  • Run Electrical Rules Checker, look for unconnected, multiple labels in one node
  • Have you moved a label, added a new label, deleted a label from somewhere and now there is a lonely label not connected to anything
  • (Upd3) Is there a lot of switching:
    .options method=gear chgtol=1e-11 reltol=0.01 rshunt=1G rseries=0.05 cshunt=1p trtol=1 - Holger’s tip
    (ngspice manual 43plus: 11.1.4 Transient Analysis Options)

The graph does not look like it should:

  • Circuit is just warming up, caps are charging. The time-frame is too short and you only see the startup of the circuit
  • “Timestep is too long so it just jumps over rapid changes and shows a line” - You could think that but that timestep in the settings is just “drawing” timestep and if you set 1sec and 1 sec to Timestep and Final time it still will show the 100hz wave. So you still have a problem in your circuit. If you set it smaller you can make cleaner graphs, spikes and ripples vanish etc. and it slows the calculation a lot.
    “runs into trouble and keeps backing up, making the
    internal timestep smaller in an attempt to not guess so far into the future
    from the last known good point.”
    Re: [Ngspice-users] Timestep too small: how to avoid it?
    So “Max timestep does that” and when it is not given it is 50 step between start_time and end_time.

Simulation just calculates, just calculates, rows are not changing in the output:

  • Something is not right in your circuit
  • I made this by putting a voltage source somewhere inside to simulate a changing voltage
  • Run Electrical Rules Checker, look for the “power” message, add PWR_FLAG

Simulation was good a second ago and now is acting weird:

  • You still have a something wrong
  • Divide the circuit into blocks and shut them off one by one with the Attributes->Exclude from simulation
  • Do not forget there can be excluded parts in your circuit! :slight_smile:
  • (Upd 2) Are the opamps in the correct direction? Noninv ↔ Inv!

Make small test circuits separately to prove your idea is working then copy paste.
Make labels group by parts of your circuit: supply_…, pwm_in, pwm_out, pwm_trigger so it is easy to find them in the list.

Make dual/quad models easy to import in KiCad:

.subckt LMX24_LM2902_QUAD U1_out U1_inv U1_noninv Vpoz U2_noninv U2_inv U2_out U3_out U3_inv U3_noninv Vneg U4_noninv U4_inv U4_out
XU1 U1_noninv U1_inv Vpoz Vneg U1_out LMX24_LM2902
XU2 U2_noninv U2_inv Vpoz Vneg U2_out LMX24_LM2902
XU3 U3_noninv U3_inv Vpoz Vneg U3_out LMX24_LM2902
XU4 U4_noninv U4_inv Vpoz Vneg U4_out LMX24_LM2902
.ends LMX24_LM2902_QUAD
.subckt LM339_QUAD U2_out U1_out Vpoz U1_inv U1_noninv U2_inv U2_noninv U4_inv U4_noninv U3_inv U3_noninv Vneg U3_out U4_out
XU1 U1_noninv U1_inv Vpoz Vneg U1_out LM339A
XU2 U2_noninv U2_inv Vpoz Vneg U2_out LM339A
XU3 U3_noninv U3_inv Vpoz Vneg U3_out LM339A
XU4 U4_noninv U4_inv Vpoz Vneg U4_out LM339A
.ends LM339_QUAD

Rename the model file if you mess with it! “LM324new.symforKiCAD.cir”

(I also have to say the residual-current device (RCD) is also always right. Except when it is not but that is an exception not a general thing.)

Correct me if I am wrong!
Thanks!

1 Like

Lots of good tips here. I will add:

Some circuits are difficult to simulate no matter what, like those that have time constants that are one or more orders of magnitude different. Switching power converters are one such type of circuit.

Do not trust vendors’ subcircuit models. They might be fine. They might be partially or completely wrong, they might only work in a narrow range, or they might contain hidden widely different time constants, discontinuities, or other such numerical bugaboos. Some of them have built-in spice errors and will bring the simulator to a grinding halt. If you have problems, it’s good practice to check vendor-supplied models.

Don’t put complete faith in results. Spice and its relatives are powerful, useful, and in many cases necessary to design and understand circuit behavior. However, you should have a qualitative idea of what to expect. Dig into the areas where expectations and results diverge.

John

2 Likes

There is no .step in ngspice but there are expressions for component values. If you want to see the effect of different values of a resistor for example choose “Behavioral” from the simulation model and give an expression instead of a static value: ‘200 + 40.18 * time’
(So it goes from 200ohms to 240.18ohms in 1 sec.)
Do not let it go to zero! Between " ’ " and use spaces! “time” is a builtin variable in seconds.

PT100 simulation with a simple resisitor (270-380°C): ’ 200 + 40.18 * (0.5 + 0.5 * cos( 2 * pi * time / 2)) ’

You can use c style expressions to set the value:
https://nmg.gitlab.io/ngspice-manual/interactiveinterpreter/expressions,functions,andconstants.html

Here is a pot turning itself:
spinningpot.lib

* "spinning" (+0.002ohm error to avoid zero)
* rt: one rotation's time in seconds

.subckt spiningpot r0 wiper r1  r=10k rt=1
rupper r1 wiper r = { (0.5 - 0.5 * cos( 2 * pi * time / rt )) * r + 0.001 }
rlower wiper r0 r = { (0.5 + 0.5 * cos( 2 * pi * time / rt )) * r + 0.001 }
.ends spiningpot
1 Like