Audio Total Harmonic Distortion Analyzer for LTSPICE, making THD vs. Amplitude and Frequency sweeps in LTSPICE

FFT capabilities integrated into LTSPICE simulator are nice and flexible. However, if you would like to evaluate frequency or amplitude dependence of distortions, you have to take these measurements point by point and then manually plot them.

I created an LTSPICE add-on to automate THD measurements and plot result in the form of THD vs. Amplitude and THD vs. Frequency graphs.

How my LTSPICE Audio THD Analyzer works:

It outputs sinusoidal signal with amplitude or frequency stepping sweep into device under test (DUT).  Output signal from DUT is feed into analyzer input. After waiting some time for signal to become steady state, analyzer restores fundamental and subtracts it from input signal. This subtraction allows to increase resolution or reduce measurement time for the same resolution. You can monitor residual components at “Notch output”.

Residual signal is then fed into synchronous filters and detector. Each harmonic is filtered and measured separately. Maximum of 10 harmonics are analyzed. Amount of harmonics could be easily increased by adding corresponding filters and possessing.

This is how waveforms look after analysis is completed:

Analysis Waveforms after Amplitude Sweep

Analysis Waveforms after Amplitude Sweep

Total Harmonic Distortions vs. Output Amplitude plot looks like this:

Total Harmonic Distortions vs. Output Amplitude

Total Harmonic Distortions vs. Output Amplitude

Total Harmonic Distortions vs. Frequency plot looks like this:

Total Harmonic Distortions vs. Frequency

Total Harmonic Distortions vs. Frequency

How to use LTSPICE Audio THD Analyzer:

Place THD_Analyzer.asy symbol and Analyser_Controls.txt files in the same directory, where you are saving schematic (DUT schematic),
that you would like to analyze.

Put SPICE directives “.inc Analyzer_Controls.txt” and “.tran 0 {AnalysisTime} {SettlingTime} {MaxTimestep}”  in DUT schematic .

Edit “Analyzer_Controls.txt“  to enable (uncomment) appropriate sweep (amplitude  or frequency ) and save this file.

Setup  “.param   Ag=xxx”  as amplitude for  frequency sweep or “.param   Fg=xxx” as frequency  for  amplitude  sweep.

Run the simulation.

After simulation is complete, go to View menu and open SPICE Error Log or use Ctrl+L command.

Click with right mouse button on opened Log file.

Execute “Plot .step’ed .meas data” command. Right mouse button click on opened plot and use Add Trace or Ctrl+A and select the data that you want to plot.

You may want to double click on axis to change axis limits or switch to logarithmic scale.

Notch output shows residual components, after fundamental removal.

Please note that fundamental may not be removed completely. This is not necessarily affecting resolution of measurements as soon as additional synchronous filtering is used to measure amplitude of harmonics.

Increasing SettlingTime and StrobeLength,  or (and) decreasing MaxTimestep would likely improve fundamental rejection.

Generator output is DC coupled and has 0 Ohm output impedance. Use external AC coupling and appropriate series resistor if required, to ensure proper operation of simulated circuit.

THD_Analyzer contains all necessary files and example. Unzip all files in the same directory, open “Example_BJT_THD_TEST.asc” and run simulation.
You can monitor analysis progress in the left lower corner of LTSPICE window.  After simulation and analysis is complete (including completion of .MEASURE), follow the instructions to display
results.

Comments

7 Responses to Audio Total Harmonic Distortion Analyzer for LTSPICE, making THD vs. Amplitude and Frequency sweeps in LTSPICE

  1. Luca Girotti says:

    Really huge and great job!!!! Thanks for sharing this! I have one questions for an upgrade: is it possible to add THD+N plotting (THD including noise) as an option to the pure THD? This would be helpful to conduct THD+N vs Frequency and THD+N vs Voltage plots.
    Also how to output THD vs Power and not voltage level?

    • Eugene says:

      Hello Luca. I’m not sure about THD+N, because noise requires different type of analysis. And for most of real analyzers it is like additional error that you have to leave with, but would like to get rid of. Because noise decrease resolution of THD measurements.
      Calculating power is really easy. Open script file with any text editor and find place where .MEASURE commands are located (somewhere close to the end).
      Find the line :
      .meas Fundamental_Out_V_RMS param sqrt(2)*hypot(aH1S,aH1C)
      Somewhere after this line add line:
      .meas Output_Power param (Fundamental_Out_V_RMS*Fundamental_Out_V_RMS)/Rload
      Use value of your load instead of Rload. Like in this example:
      .meas Output_Power param (Fundamental_Out_V_RMS*Fundamental_Out_V_RMS)/8
      Save changed script file.
      When you will be plotting analysis results, double click on horizontal axis (the same as if you wanted to change horizontal scale) and instead of ag or fundamental put Output_Power.

      • Luca says:

        Dear Eugene,

        noted your thinking about Noise contribution to Distorsion measurement. Thinking back about this, as from my experience, there is so big difference between “simulated” noise and “real world” noise that you are right….there is no sense to add it.

        Thanks about the hint on how to plot THD vs. Power, I will test it shortly!!!

        Thanks again for the great job you have done and donated to the public community!

  2. Ezequiel says:

    Excellent plugin man. Thanks for the great work!

  3. Marcel says:

    Hello,

    I am trying to get this running however I have a misunderstanding. I dont exactly know what “Setup “.param Ag=xxx” as amplitude for frequency sweep or “.param Fg=xxx” really means so I have skipped this step. The simulation runs and then in the log file i just get failure messages:
    Circuit: * C:\Program Files (x86)\LTC\LTspiceIV\RailTOrail-2.asc

    Direct Newton iteration for .op point succeeded.
    .step fg=20
    .step fg=43.0887
    .step fg=92.8318
    .step fg=200
    .step fg=430.887
    .step fg=928.318
    .step fg=2000
    .step fg=4308.87
    .step fg=9283.18
    .step fg=20000

    Measurement “ah1s” FAIL’ed

    Measurement “ah1c” FAIL’ed

    Measurement “avh2s” FAIL’ed

    Measurement “avh2c” FAIL’ed

    Measurement “avh3s” FAIL’ed

    Measurement “avh3c” FAIL’ed

    Measurement “avh4s” FAIL’ed

    Measurement “avh4c” FAIL’ed

    Measurement “avh5s” FAIL’ed

    Measurement “avh5c” FAIL’ed

    Measurement “avh6s” FAIL’ed

    Measurement “avh6c” FAIL’ed

    Measurement “avh7s” FAIL’ed

    Measurement “avh7c” FAIL’ed

    Measurement “avh8s” FAIL’ed

    Measurement “avh8c” FAIL’ed

    Measurement “avh9s” FAIL’ed

    Measurement “avh9c” FAIL’ed

    Measurement “avh10s” FAIL’ed

    Measurement “avh10c” FAIL’ed

    Measurement “i_in_s” FAIL’ed

    Measurement “i_in_c” FAIL’ed

    Measurement “fundamental_out_v_rms” FAIL’ed

    Measurement “gain” FAIL’ed

    Measurement “gain_db” FAIL’ed

    Measurement “phase_deg” FAIL’ed

    Measurement “z_in_mod” FAIL’ed

    Measurement “z_in_ph_deg” FAIL’ed

    Measurement “h2″ FAIL’ed

    Measurement “h3″ FAIL’ed

    Measurement “h4″ FAIL’ed

    Measurement “h5″ FAIL’ed

    Measurement “h6″ FAIL’ed

    Measurement “h7″ FAIL’ed

    Measurement “h8″ FAIL’ed

    Measurement “h9″ FAIL’ed

    Measurement “h10″ FAIL’ed

    Measurement “thd_persent” FAIL’ed

    Measurement “thd_db” FAIL’ed

    Date: Sat Dec 07 21:13:45 2013
    Total elapsed time: 105.237 seconds.

    tnom = 27
    temp = 27
    method = modified trap
    totiter = 1100051
    traniter = 1100040
    tranpoints = 550021
    accept = 550021
    rejected = 0
    matrix size = 70
    fillins = 94
    solver = Normal
    Matrix Compiler1: 11.1 KB object code size 5.6/4.0/[2.3]
    Matrix Compiler2: off [2.7]/3.0/5.3

    Please help…

    • Eugene says:

      Can you send me a simulation file?
      “.param Ag=xxx” means – set the amplitude. Example: .param Ag=1 means amplitude of 1V
      “.param Fg=xxx” means – set the frequency. Example: .param Fg=20K means frequency of 20K

      • Marcel says:

        Eugene,
        Thanks for the extra help with that.

        I got it going but I got another anomaly. When I plot the error log I get an empty chart. I took your example file and replace that circuit with my own one and ran it. I can see the waves ok but for some reason it doesn’t wanna plot. The circuit that I want to ran is a discrete op amp. If I ran your circuit it plots ok. Here is the error log for my circuit:

        Circuit: * C:\Program Files (x86)\LTC\LTspiceIV\THDvsAmplitude.asc

        Questionable use of curly braces in “b_time timescale 0 v={time}”
        Error: undefined symbol in: “[time]”
        WARNING: Less than two connections to node TIMESCALE. This node is used by B:U2:_TIME.
        WARNING: Less than two connections to node S_TIME. This node is used by B:U2:_STROBETIME.
        WARNING: Less than two connections to node E_TIME. This node is used by B:U2:_ENDTIME.
        WARNING: Less than two connections to node H2SF. This node is used by B:U2:_H2S.
        WARNING: Less than two connections to node H2CF. This node is used by B:U2:_H2C.
        WARNING: Less than two connections to node H3SF. This node is used by B:U2:_H3S.
        WARNING: Less than two connections to node H3CF. This node is used by B:U2:_H3C.
        WARNING: Less than two connections to node H4SF. This node is used by B:U2:_H4S.
        WARNING: Less than two connections to node H4CF. This node is used by B:U2:_H4C.
        WARNING: Less than two connections to node H5SF. This node is used by B:U2:_H5S.
        WARNING: Less than two connections to node H5CF. This node is used by B:U2:_H5C.
        WARNING: Less than two connections to node H6SF. This node is used by B:U2:_H6S.
        WARNING: Less than two connections to node H6CF. This node is used by B:U2:_H6C.
        WARNING: Less than two connections to node H7SF. This node is used by B:U2:_H7S.
        WARNING: Less than two connections to node H7CF. This node is used by B:U2:_H7C.
        WARNING: Less than two connections to node H8SF. This node is used by B:U2:_H8S.
        WARNING: Less than two connections to node H8CF. This node is used by B:U2:_H8C.
        WARNING: Less than two connections to node H9SF. This node is used by B:U2:_H9S.
        WARNING: Less than two connections to node H9CF. This node is used by B:U2:_H9C.
        WARNING: Less than two connections to node H10SF. This node is used by B:U2:_H10S.
        WARNING: Less than two connections to node H10CF. This node is used by B:U2:_H10C.
        Direct Newton iteration for .op point succeeded.
        Ignoring empty pin current: Ix(u2:analyzer_in)
        Ignoring empty pin current: Ix(u2:analyzer_in)
        .step ag=0.01
        .step ag=0.0316228
        .step ag=0.1

        Measurement: ah1s
        step v(ref_s) at
        1 0.00965556032077 0.01
        2 0.0305335635626 0.01
        3 0.0965555918836 0.01

        Measurement: ah1c
        step v(ref_c) at
        1 -8.43252872588e-006 0.01
        2 -2.73289685266e-005 0.01
        3 -8.70847478853e-005 0.01

        Measurement: avh2s
        step v(h2sf) at
        1 -2.11852910661e-011 0.02
        2 -2.11621496592e-010 0.02
        3 -2.11630425195e-009 0.02

        Measurement: avh2c
        step v(h2cf) at
        1 -4.7705201674e-010 0.02
        2 -4.77949177394e-009 0.02
        3 -4.78041446972e-008 0.02

        Measurement: avh3s
        step v(h3sf) at
        1 5.70093625464e-012 0.02
        2 1.80416291238e-010 0.02
        3 5.70630086246e-009 0.02

        Measurement: avh3c
        step v(h3cf) at
        1 1.00080441573e-012 0.02
        2 7.81369744796e-013 0.02
        3 -8.74136711367e-012 0.02

        Measurement: avh4s
        step v(h4sf) at
        1 2.12757688874e-016 0.02
        2 -1.74272910437e-014 0.02
        3 6.25513938116e-014 0.02

        Measurement: avh4c
        step v(h4cf) at
        1 1.00762184834e-012 0.02
        2 1.14468755347e-012 0.02
        3 2.93457432994e-012 0.02

        Measurement: avh5s
        step v(h5sf) at
        1 -3.11325389013e-014 0.02
        2 -3.27953030123e-015 0.02
        3 -1.61781582248e-013 0.02

        Measurement: avh5c
        step v(h5cf) at
        1 9.99089654605e-013 0.02
        2 1.15216872732e-012 0.02
        3 2.7830953627e-012 0.02

        Measurement: avh6s
        step v(h6sf) at
        1 -1.02843369323e-014 0.02
        2 -8.78138478758e-016 0.02
        3 -1.09351504002e-014 0.02

        Measurement: avh6c
        step v(h6cf) at
        1 9.92177855116e-013 0.02
        2 1.1357725472e-012 0.02
        3 2.78538209024e-012 0.02

        Measurement: avh7s
        step v(h7sf) at
        1 -1.02264828207e-014 0.02
        2 -1.83328598102e-014 0.02
        3 -3.11968223455e-014 0.02

        Measurement: avh7c
        step v(h7cf) at
        1 1.00319213007e-012 0.02
        2 1.16489498191e-012 0.02
        3 2.7811661078e-012 0.02

        Measurement: avh8s
        step v(h8sf) at
        1 -1.62602378597e-014 0.02
        2 -2.40356917128e-016 0.02
        3 -3.24897696568e-014 0.02

        Measurement: avh8c
        step v(h8cf) at
        1 1.00902876967e-012 0.02
        2 1.14591046825e-012 0.02
        3 2.78286278973e-012 0.02

        Measurement: avh9s
        step v(h9sf) at
        1 -1.61490441867e-014 0.02
        2 5.17499908589e-015 0.02
        3 -3.31179139598e-014 0.02

        Measurement: avh9c
        step v(h9cf) at
        1 1.00142662953e-012 0.02
        2 1.13410833518e-012 0.02
        3 2.79675796889e-012 0.02

        Measurement: avh10s
        step v(h10sf) at
        1 -7.44483778435e-015 0.02
        2 -1.66483598066e-014 0.02
        3 -3.74061241714e-014 0.02

        Measurement: avh10c
        step v(h10cf) at
        1 1.00878395626e-012 0.02
        2 1.13688394034e-012 0.02
        3 2.79177645555e-012 0.02

        Measurement: i_in_s
        step v(is_s) at
        1 -2.96332278776e-009 0.01
        2 -9.37076003605e-009 0.01
        3 -2.96330350827e-008 0.01

        Measurement: i_in_c
        step v(is_c) at
        1 -1.0766925421e-010 0.01
        2 -3.87241255854e-010 0.01
        3 -1.27133209699e-009 0.01

        Measurement: fundamental_out_v_rms
        step sqrt(2)*hypot(ah1s,ah1c)
        1 0.0136550295654
        2 0.0431809969942
        3 0.136550283103

        Measurement: gain
        step sqrt(2)*fundamental_out_v_rms/ag
        1 1.9311128006
        2 1.9311128923
        3 1.9311126231

        Measurement: gain_db
        step 20*log10(gain)
        1 5.71615285255
        2 5.71615326504
        3 5.7161520542

        Measurement: phase_deg
        step atan(ah1c/ah1s)
        1 -0.0500383372617
        2 -0.0512823907264
        3 -0.0516757969531

        Measurement: z_in_mod
        step 0.5*ag/(hypot(i_in_s,i_in_c))
        1 1686182.44797
        2 1685872.31877
        3 1685755.36105

        Measurement: z_in_ph_deg
        step (-1)*atan(i_in_c/i_in_s)
        1 -2.08086724258
        2 -2.36636864563
        3 -2.45662723988

        Measurement: h2
        step sqrt(2)*hypot(avh2s,avh2c)*100/fundamental_out_v_rms
        1 4.94556497378e-006
        2 1.56685692289e-005
        3 4.95579241898e-005

        Measurement: h3
        step sqrt(2)*hypot(avh3s,avh3c)*100/fundamental_out_v_rms
        1 5.99459101949e-008
        2 5.90883899355e-007
        3 5.90986511047e-006

        Measurement: h4
        step sqrt(2)*hypot(avh4s,avh4c)*100/fundamental_out_v_rms
        1 1.04356604181e-008
        2 3.74938138397e-009
        3 3.03994792498e-009

        Measurement: h5
        step sqrt(2)*hypot(avh5s,avh5c)*100/fundamental_out_v_rms
        1 1.03523170233e-008
        2 3.77346368649e-009
        3 2.88724080892e-009

        Measurement: h6
        step sqrt(2)*hypot(avh6s,avh6c)*100/fundamental_out_v_rms
        1 1.02762630344e-008
        2 3.71975065866e-009
        3 2.88476552017e-009

        Measurement: h7
        step sqrt(2)*hypot(avh7s,avh7c)*100/fundamental_out_v_rms
        1 1.03903226419e-008
        2 3.81560037424e-009
        3 2.88055811878e-009

        Measurement: h8
        step sqrt(2)*hypot(avh8s,avh8c)*100/fundamental_out_v_rms
        1 1.04515880752e-008
        2 3.75295216395e-009
        3 2.88233053641e-009

        Measurement: h9
        step sqrt(2)*hypot(avh9s,avh9c)*100/fundamental_out_v_rms
        1 1.03728464832e-008
        2 3.71433778249e-009
        3 2.89672804379e-009

        Measurement: h10
        step sqrt(2)*hypot(avh10s,avh10c)*100/fundamental_out_v_rms
        1 1.04479803259e-008
        2 3.72378865668e-009
        3 2.89162528097e-009

        Measurement: thd_persent
        step sqrt(h2*h2+h3*h3+h4*h4+h5*h5+h6*h6+h7*h7+h8*h8+h9*h9+h10*h10)
        1 4.94600465505e-006
        2 1.56797099432e-005
        3 4.99090614506e-005

        Measurement: thd_db
        step 20*log10(thd_persent/100)
        1 -146.114909585
        2 -136.093239511
        3 -126.036411941

        Date: Sat Dec 14 15:01:22 2013
        Total elapsed time: 33.743 seconds.

        tnom = 27
        temp = 27
        method = modified trap
        totiter = 172941
        traniter = 172934
        tranpoints = 75021
        accept = 75021
        rejected = 0
        matrix size = 111
        fillins = 92
        solver = Normal
        Thread vector: 37.4/32.8[2] 6.4/4.5[2] 21.7/7.5[2] 2.2/5.1[1] 2592/500
        Matrix Compiler1: 11.0 KB object code size 7.2/7.0/[2.6]
        Matrix Compiler2: off [2.9]/6.1/4.8

Leave a Reply

Comment moderation is in use. Your post will appear shortly.

Spammers, don't worry! Don't bother wasting your time!

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>