Beispiel #1
0
def make_thd_plot(thdplot, sinplot, voltages):
    thdplot.set_ylabel("thd (dB)")
    thdplot.set_xlabel("control current (mA)")
    thdplot.set_title("total harmonic distortion")
    sinplot.set_xticks([], [])
    #sinplot.set_yticks([],[])
    #sinplot.set_title("sine shape at cc = 1mA")
    #for voltage in np.arange(3,18, 1):
    for voltage in voltages:
        printall(ns.cmd("alter v1 %f" % voltage))
        printall(ns.cmd("alter v2 %f" % voltage))

        y = []
        x = my_logspace(0.01, 1, 8)
        for current in x:
            printall(ns.cmd("alter i1 %fm" % current))
            y.append(calc_thd(300))

        printall(ns.cmd("alter i1 40u"))
        _, signal, time = simulate_waveform(300,
                                            n_periods=1,
                                            steps_per_period=64)

        thdplot.plot(x / 1000, np.log10(y) * 10, label="+/- %fV" % voltage)
        sinplot.plot(time, signal)

    thdplot.set_xscale('log')

    fmt_mA = ticker.EngFormatter(unit='A')
    fmt_dB = ticker.FormatStrFormatter('%.0f dB')
    thdplot.xaxis.set_major_formatter(fmt_mA)
    thdplot.yaxis.set_major_formatter(fmt_dB)
Beispiel #2
0
    def test_cmd(self):
        self.assertEqual(ns.cmd('print planck'), ['planck = 6.626200e-34'])
        self.assertEqual(ns.cmd('print' + ' ' * 200 + 'kelvin'),
                         ['kelvin = -2.73150e+02'])

        # Command too long
        self.assertRaises(ValueError, ns.cmd, 'print' + ' ' * 2000 + 'kelvin')
Beispiel #3
0
    def test_cmd(self):
        self.assertEqual(ns.cmd('print planck'),
                         ['planck = 6.626200e-34'])
        self.assertEqual(ns.cmd('print' + ' ' * 200 + 'kelvin'),
                         ['kelvin = -2.73150e+02'])

        # Command too long
        self.assertRaises(ValueError, ns.cmd, 'print' + ' ' * 2000 + 'kelvin')
Beispiel #4
0
def sim():
    tb = testbench(common_emitter_amplifer())
    circuit = Builder(tb).compile()
    circuit.to_spice('common_emitter_amplifier.sp')
    ng.source('common_emitter_amplifier.sp')
    ng.cmd('tran 50us 10ms')

    print('\n'.join(ng.vector_names()))
    time, tp1 = map(ng.vector, ['time', 'V(VOUT)'])
    plt.plot(time, tp1, label='VOUT')
    plt.legend()
    plt.show()
Beispiel #5
0
 def test_default_codemodels(self):
     """Test presence of one model from each default .cm library"""
     required_models = {'spice2poly', 'sine', 'd_nor', 'aswitch',
                        'd_to_real'}
     existing_models = {line.partition(' ')[0]
                        for line in ns.cmd('devhelp')[1:]}
     self.assertEqual(required_models, required_models & existing_models)
Beispiel #6
0
def plot_bode(outfile):
    plt.clf()
    printall(ns.cmd("alter c6 100u"))
    #printall(ns.cmd("alter v1 3"))
    #printall(ns.cmd("alter v2 3"))

    gains = [500**(1 / n) for n in range(3, 0, -1)]
    impedances = [1000, 10 * 1000, 100 * 1000, 1000 * 1000, 10 * 1000 * 1000]
    currents_mA = [0] + list(my_logspace(0.0001, 10, 5 if DRAFT_MODE else 16))

    _, plots = plt.subplots(
        len(gains),
        len(impedances) + 1,
        gridspec_kw={'width_ratios': [3] * len(impedances) + [1]})

    fmt_Hz = ticker.EngFormatter(unit='Hz')
    fmt_dB = ticker.EngFormatter(unit='dB')
    ohmfmt = ticker.EngFormatter(unit="Ω")

    for y, gain in enumerate(gains):
        for x, impedance_ohms in enumerate(impedances):
            update_amplifier(impedance_ohms, gain)
            plot_single_bode_family(plots[y][x], currents_mA)
            plots[y][x].set_ylim(10 * math.log10(gain / 500) - 55,
                                 10 * math.log10(gain / 500) + 5)
            plots[y][x].xaxis.set_major_formatter(fmt_Hz)
            plots[y][x].yaxis.set_major_formatter(fmt_dB)

            if x == 0:
                plots[y][x].text(0,
                                 0.5,
                                 'gain = %.1f×\n\n\n\n' % gain,
                                 fontsize=10,
                                 horizontalalignment='right',
                                 verticalalignment='center',
                                 transform=plots[y][x].transAxes,
                                 rotation='vertical')

            if y == 0:
                plots[y][x].text(0.5,
                                 1.0,
                                 'impedance = %s\n' %
                                 ohmfmt.format_data(impedance_ohms),
                                 fontsize=10,
                                 horizontalalignment='center',
                                 verticalalignment='baseline',
                                 transform=plots[y][x].transAxes)
            if y == len(gains) - 1:
                plots[y][x].set_xlabel("Frequency")

    for p in plots:
        p[-1].axis(False)

    fmt = ticker.EngFormatter(unit="A")
    make_legend([fmt.format_data(c / 1000) for c in currents_mA], plots[0][-1])

    plt.gcf().set_size_inches(20, 11)
    if outfile is not None:
        plt.savefig(outfile)
Beispiel #7
0
def update_amplifier(impedance_ohms, factor):
    factor /= PREGAIN
    if not TWO_STAGE_AMP:
        r78 = impedance_ohms
        r910 = r78 * factor
        printall(ns.cmd("alter r7 %f" % r78))
        printall(ns.cmd("alter r8 %f" % r78))
        printall(ns.cmd("alter r9 %f" % r910))
        printall(ns.cmd("alter r10 %f" % r910))
    else:
        factor_sqrt = math.sqrt(factor)
        r78 = impedance_ohms
        r910 = r78 * factor_sqrt
        printall(ns.cmd("alter r7 %f" % r78))
        printall(ns.cmd("alter r8 %f" % r78))
        printall(ns.cmd("alter r9 %f" % r910))
        printall(ns.cmd("alter r10 %f" % r910))
        printall(ns.cmd("alter r101 %f" % r78))
        printall(ns.cmd("alter r102 %f" % r910))
Beispiel #8
0
def simulate_waveform(freq, n_periods=2, t_skip_ms=25, steps_per_period=200):
    period = 1 / freq
    timestep = period / steps_per_period

    # set the input frequency
    printall(ns.cmd("let tmp =  @v4[sin]"))
    printall(ns.cmd("let tmp[2] = %f" % freq))
    printall(ns.cmd("alter @v4[sin] = tmp"))

    skip_periods = math.ceil(t_skip_ms / 1000 * freq)
    actual_t_skip_ms = skip_periods / freq * 1000
    t_run_ms = actual_t_skip_ms + n_periods / freq * 1000

    ns.destroy()
    print("tran %fu %fm %fm" %
          (timestep * 1000000, t_run_ms, actual_t_skip_ms))
    ns.cmd("tran %fu %fm %fm" %
           (timestep * 1000000, t_run_ms, actual_t_skip_ms))

    return ns.vector('signal_in'), ns.vector('signal_out'), (
        ns.vector('time') - actual_t_skip_ms / 1000)
Beispiel #9
0
def plot_bode2(outfile):
    plt.clf()
    printall(ns.cmd("alter c6 100u"))

    currents_mA = [0] + list(my_logspace(0.0001, 0.1, 5 if DRAFT_MODE else 16))
    headroom = 1  # set to 2.5 possibly
    update_amplifier(10000, 500 / headroom)

    if DRAFT_MODE:
        xlen, ylen = 3, 2
    else:
        xlen, ylen = 7, 5

    max_resonance_gain = 1 / 25 * headroom
    resonance_gains = list(
        np.arange(0, max_resonance_gain, max_resonance_gain / (xlen * ylen)))
    _, plots = plt.subplots(xlen, ylen)

    fmt_Hz = ticker.EngFormatter(unit='Hz')
    fmt_dB = ticker.EngFormatter(unit='dB')
    ohmfmt = ticker.EngFormatter(unit="Ω")

    for i, resonance_gain in enumerate(resonance_gains):
        x = i % ylen
        y = int(i / ylen)
        print("\n######\n####### %s\n######\n" % resonance_gain)
        printall(ns.cmd("alter r122 %f" % (100000 * resonance_gain)))
        plot_single_bode_family(plots[y][x], currents_mA)
        plots[y][x].set_ylim(-55, 15)
        plots[y][x].xaxis.set_major_formatter(fmt_Hz)
        plots[y][x].yaxis.set_major_formatter(fmt_dB)
        plots[y][x].set_title("gain = %7.5f" % resonance_gain, y=1.0, pad=-14)

    plt.gcf().set_size_inches(20, 11)
    if outfile is not None:
        plt.savefig(outfile)
Beispiel #10
0
def calc_attenuation_and_phase(freq,
                               control_current_mA,
                               n_periods=2,
                               t_skip_ms=25,
                               steps_per_period=200,
                               debug=False):
    # set the control current
    printall(ns.cmd("alter i1 %fm" % control_current_mA))

    signal_in, signal_out, time = simulate_waveform(freq, n_periods, t_skip_ms,
                                                    steps_per_period)

    amplitude_in = np.max(signal_in) - np.min(signal_in)
    amplitude_out = np.max(signal_out) - np.min(signal_out)

    zeros = zero_crossings(signal_out)
    if len(zeros) >= 3:
        pmax = int((zeros[0] + zeros[1]) / 2)
        pmin = int((zeros[1] + zeros[2]) / 2)
        print(pmax, pmin)

        if signal_out[pmax] < signal_out[pmin]:
            pmin, pmax = pmax, pmin

        period = ((time[pmax] * freq - 1 / 4) % 1.0) * math.pi * 2
        if period > math.pi:
            period -= 2 * math.pi
    else:
        period = np.nan

    attenuation_db = math.log10(amplitude_out / amplitude_in) * 10

    print(attenuation_db, period)

    if debug:
        plt.plot(time, signal_in)
        plt.plot(time, signal_out)
        plt.pause(3)

    return attenuation_db, period
Beispiel #11
0
def run_sim(varactor_voltage):

    ngspyce.cmd(f'alterparam varactor_bias_voltage = {varactor_voltage}')
    ngspyce.cmd('reset')
    # ngspyce.cmd('stop after 10000')
    step_ps = 1  #not always obeyed - ngspice sets its own timestep.
    sim_duration = 100000
    n_steps = sim_duration / step_ps
    # ngspyce.cmd(" ")
    ngspyce.cmd(f'tran {step_ps}p {sim_duration}ps uic')

    timesteps = ngspyce.vector('time')
    v_collector = ngspyce.vector('v(E1)')
    v_base = ngspyce.vector('v(Base)')
    varactor_bias = ngspyce.vector('v(Vvaractor)')
    output = ngspyce.vector('v(output)')

    stable_running_point = -1 * len(v_collector) // 3
    v_collector_trimmed = v_collector[
        stable_running_point:]  # lots of noise on startup. we want to trim that out of the FFT.
    spectrum = np.fft.fft(v_collector_trimmed)
    spectrum_freqs = np.fft.fftfreq(
        len(v_collector_trimmed),
        d=(timesteps[-1] - timesteps[stable_running_point]) /
        len(v_collector_trimmed))

    spectrum_begin_indice = np.abs(spectrum_freqs - 100e6).argmin()
    spectrum_end_indice = np.abs(spectrum_freqs - 25e9).argmin()
    #normalize
    spectrum_norm = np.linalg.norm(
        spectrum[spectrum_begin_indice:spectrum_end_indice].clip(min=0))
    if (spectrum_norm):
        fft_cleaned = spectrum[spectrum_begin_indice:spectrum_end_indice].clip(
            min=0) / spectrum_norm
    else:
        fft_cleaned = np.zeros_like(
            spectrum[spectrum_begin_indice:spectrum_end_indice])
    spectrum_freqs = spectrum_freqs[spectrum_begin_indice:spectrum_end_indice]

    fft_cleaned = fft_cleaned[:int(
        600)]  # trim all spectra to the same length 2ps,800, 5ps, 600
    spectrum_freqs = spectrum_freqs[:int(600)]
    return [
        np.array(np.abs(fft_cleaned)),
        np.array(spectrum_freqs), timesteps, v_collector, v_base,
        varactor_bias, output
    ]
Beispiel #12
0
import ngspyce
import numpy as np
from matplotlib import pyplot as plt

ngspyce.source('quad.net')
#trrandom(2 2m 0 10m 0)
ngspyce.cmd('tran 1m 20m')
print('\n'.join(ngspyce.vector_names()))
time, vsin, vcos = map(ngspyce.vector, ['time', 'Vsin', 'Vcos'])
#np.savetxt('vcos.txt', vcos)
#np.savetxt('vsin.txt', vsin)
#np.savetxt('time.txt', time)
#exit()
plt.plot(time, vcos, label='Vcos')
plt.plot(time, vsin, label='Vsin')
plt.legend()
plt.show()
Beispiel #13
0
# Plot the frequency response of an RC low-pass filter

import ngspyce
from matplotlib import pyplot as plt
import numpy as np

# Reat netlist
ngspyce.cmd('source lowpass.net')
# Calculate small-signal transfer function between 10kHz and 100MHz, with 5
# points per decade
ngspyce.cmd('ac dec 5 10k 100meg')

# Read results
freq = np.abs(ngspyce.vector('frequency'))
vout = ngspyce.vector('vout')

# And plot them
fig = plt.figure()
fig.suptitle('Frequency response of an RC low-pass filter')

ax = fig.add_subplot(1,2,1)
ax.semilogx(freq, 20*np.log10(np.abs(vout)))
ax.set_xlabel('Frequency [Hz]')
ax.set_ylabel('Magnitude [dB]')

ax = fig.add_subplot(1,2,2)
ax.semilogx(freq, np.angle(vout,True))
ax.set_xlabel('Frequency [Hz]')
ax.set_ylabel('Phase [degrees]')
Beispiel #14
0
# Plot output voltages of an operational amplifier quadrature oscillator
import ngspyce
import numpy as np
from matplotlib import pyplot as plt

# Load netlist
ngspyce.cmd(b'source quad.net')
# Simulate 10 ms
ngspyce.cmd(b'tran 12n 10m 1n')

# Read results
time, vsin, vcos = map(ngspyce.vector, ['time','Vsin','Vcos'])
# And plot them
plt.plot(time*1e3, vcos, label='Vcos')
plt.plot(time*1e3, vsin, label='Vsin')

plt.title('Quadrature op-amp oscillator output voltage')
plt.xlabel('Time [ms]')
plt.ylabel('Voltage [V]')
plt.savefig('quad.png')
plt.show()
Beispiel #15
0
"""
Plot output voltages of an operational amplifier quadrature oscillator
"""

import ngspyce
import numpy as np
from matplotlib import pyplot as plt

# Load netlist
ngspyce.source('quad.net')
# Simulate 10 ms
ngspyce.cmd('tran 12n 10m 1n')

# Read results
time, vsin, vcos = map(ngspyce.vector, ['time', 'Vsin', 'Vcos'])
# And plot them
plt.plot(time * 1e3, vcos, label='Vcos')
plt.plot(time * 1e3, vsin, label='Vsin')

plt.title('Quadrature op-amp oscillator output voltage')
plt.xlabel('Time [ms]')
plt.ylabel('Voltage [V]')
plt.savefig('quad.png')
plt.show()
Beispiel #16
0
 def test_vector(self):
     ns.cmd('let myvector = unitvec(4)')
     self.assertEqual(list(ns.vector('myvector')), [1, 1, 1, 1])
Beispiel #17
0
 def test_vector_names(self):
     ns.cmd('set curplot = new')
     names = list('abdf')
     for name in names:
         ns.cmd('let {} = 0'.format(name))
     self.assertEqual(sorted(ns.vector_names()), names)
Beispiel #18
0
def set_input_amplitude(amplitude):
    printall(ns.cmd("let tmp =  @v4[sin]"))
    printall(ns.cmd("let tmp[1] = %f" % amplitude))
    printall(ns.cmd("alter @v4[sin] = tmp"))
Beispiel #19
0
"""
Plot output voltages of an operational amplifier quadrature oscillator
"""

import ngspyce
import numpy as np
from matplotlib import pyplot as plt

# Load netlist
ngspyce.source('quad.net')
# Simulate 10 ms
ngspyce.cmd('tran 12n 10m 1n')

# Read results
time, vsin, vcos = map(ngspyce.vector, ['time', 'Vsin', 'Vcos'])
# And plot them
plt.plot(time*1e3, vcos, label='Vcos')
plt.plot(time*1e3, vsin, label='Vsin')

plt.title('Quadrature op-amp oscillator output voltage')
plt.xlabel('Time [ms]')
plt.ylabel('Voltage [V]')
plt.savefig('quad.png')
plt.show()
Beispiel #20
0
"""
Plot the output characteristics for the BC337 NPN transistor
"""

import ngspyce
import numpy as np
from matplotlib import pyplot as plt

# Load netlist
ngspyce.source('npn.net')

# Sweep both base and collector current
ngspyce.cmd('dc vcc 0 2 .05 vbb .7 1.2 .1')

# Load simulation results into numpy arrays
vb, vc, Ivcc = map(ngspyce.vector, ['Vb', 'Vc', 'I(Vcc)'])

# Correct the sign for collector current
ic = -Ivcc

plt.figure()
# Plot one line per base voltage
series = np.unique(vb)
for _vb in series:
    plt.plot(vc[vb == _vb],
             ic[vb == _vb],
             '-',
             label='Vb = {:.1f}'.format(_vb))

plt.legend()
plt.title('Output characteristics for BC337')
Beispiel #21
0
import ngspyce
import numpy as np
from matplotlib import pyplot as plt

ngspyce.cmd(b'source quad.net')
#trrandom(2 2m 0 10m 0)
ngspyce.cmd(b'tran 1m 20m')
print('\n'.join(ngspyce.vectorNames()))
vcos, vsin, time = ngspyce.vectors(['Vcos','Vsin','time']).values()
#np.savetxt('vcos.txt', vcos)
#np.savetxt('vsin.txt', vsin)
#np.savetxt('time.txt', time)
#exit()
plt.plot(time,vcos, label='Vcos')
plt.plot(time,vsin, label='Vsin')
plt.legend()
plt.show()

Beispiel #22
0
# Plot the output characteristics for the BC337 NPN transistor

import ngspyce
import numpy as np
from matplotlib import pyplot as plt

# Load netlist
ngspyce.cmd(b'source npn.net')
# Sweep both base and collector current
ngspyce.cmd(b'dc vcc 0 2 .05 vbb .7 1.2 .1')

# Load simulation results into numpy arrays
vb, vc, Ivcc = map(ngspyce.vector, ['Vb', 'Vc', 'I(Vcc)'])
# Correct the sign for collector current
ic = -Ivcc

plt.figure()
# Plot one line per base voltage
series = np.unique(vb)
for _vb in series:
    plt.plot(vc[vb==_vb], ic[vb==_vb], '-', label='Vb = {}'.format(_vb))
    
plt.legend()
plt.title('Output characteristics for BC337')
plt.xlabel('Collector-emitter voltage [V]')
plt.ylabel('Collector current [A]')
plt.savefig('bc337.png')
plt.show()
Beispiel #23
0
"""
Plot the output characteristics for the BC337 NPN transistor
"""

import ngspyce
import numpy as np
from matplotlib import pyplot as plt

# Load netlist
ngspyce.source('npn.net')

# Sweep both base and collector current
ngspyce.cmd('dc vcc 0 2 .02 vbb .7 1.2 .1')

# Load simulation results into numpy arrays
vb, vc, Ivcc = map(ngspyce.vector, ['Vb', 'Vc', 'I(Vcc)'])

# Correct the sign for collector current
ic = -Ivcc

plt.figure()
# Plot one line per base voltage
series = np.unique(vb)
for _vb in series:
    plt.plot(vc[vb == _vb], ic[vb == _vb], '-',
             label='Vb = {:.1f}'.format(_vb))

plt.legend(loc='center right')
plt.title('Output characteristics for BC337')
plt.xlabel('Collector-emitter voltage [V]')
plt.ylabel('Collector current [A]')