ax = fig.add_subplot(1, 1, 1) eee51.add_hline_text(ax, 0, 1e5, \ r'{:.1f}dB'.format(0)) ic_labels = [r'$I_C = 1mA$', r'$I_C = 10mA$'] files = [cfg['ac_sim_1mA'], cfg['ac_sim_10mA']] for file, ic_label in zip(files, ic_labels): freq = [] ic1 = [] with open(file, 'r') as f: for line in f: freq.append(float(line.split()[0])) ic1_real = float(line.split()[1]) ic1_imag = float(line.split()[2]) ic1.append(((ic1_real**2) + (ic1_imag**2))**0.5) index, ic1_sim = eee51.find_in_data(ic1, 1.0) ax.semilogx(freq, 20*np.log10(ic1), '-', \ label = ic_label) eee51.add_vline_text(ax, freq[index], 20, \ '{:.2f}MHz'.format(freq[index]/1e6)) eee51.label_plot(plt_cfg, fig, ax) plt.savefig('bjt_2n3904_ft.png')
'legend_loc': 'upper left', 'add_legend': True, 'legend_title': None } # plot the transfer characteristics at 2.5V fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(vbe_mV, eee51.scale_vec(ic2, g51.milli), '--', \ label = 'simulation ($V_{CE}$=2.5V)') ax.plot(vbe_mV, ic_ideal_mA, \ label = 'ideal BJT using $I_S$=' + \ si_format(bjt_Is, precision=2) + r'A, $n$={:.2f}, and '.format(bjt_n) + \ r'$|V_A|$={:.2f}'.format(abs(g51.bjt_VA))) eee51.add_vline_text(ax, reqd_vbe/g51.milli, 2.5, '$V_{BE}$ = ' + \ '{:.1f}mV'.format(reqd_vbe/g51.milli)) eee51.add_hline_text(ax, specs['ic']/g51.milli, 550, \ '$I_C$ = {:.1f}mA'.format(specs['ic']/g51.milli)) eee51.label_plot(plt_cfg, fig, ax) # get the derivative of ic with respect to vbe dic2 = np.diff(ic2) / np.diff(vbe) dic_ideal = np.diff(ic_ideal) / np.diff(vbe) index, vbe_sim = eee51.find_in_data(vbe, reqd_vbe) gm_sim = dic2[index - 1] gm_ideal = dic_ideal[index - 1] # calculate the bjt small signal parameters
'legend_loc': 'lower left', 'add_legend': False, 'legend_title': None } fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.set_ylim(-275, 75) ax.semilogx(freq, 20 * np.log10(vo_mag), '-') eee51.add_hline_text(ax, Ao_dB_calc, 1e2, \ r'$A_0$ = {:.1f}dB'.format(Ao_dB_calc)) for w, label in zip(popt[1:], labels): eee51.add_vline_text(ax, w / (2 * math.pi ), -250, label + \ si_format(w / (2 * math.pi ), precision=2) + 'Hz') eee51.add_vline_text(ax, fu, -250, r'$f_u=$' + \ si_format(fu, precision=2) + 'Hz') eee51.label_plot(plt_cfg, fig, ax) plt.savefig(output_mag_file) # define the plot parameters plt_cfg = { 'grid_linestyle': 'dotted', 'title': r'Common-Emitter Amplifier Frequency Response', 'xlabel': r'Frequency [Hz]', 'ylabel': r'Magnitude Response Slope [dB/decade]', 'legend_loc': 'lower left', 'add_legend': False,
} # plot the amplifier transfer characteristics fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(eee51.scale_vec(vin, g51.milli), vout, '--', \ label = r'$v_{OUT}$ with $R_C=$2.5 k$\Omega$') ax2 = ax.twinx() ax2.set_ylabel(r'$I_C$ [mA]') ax2.plot(eee51.scale_vec(vin, g51.milli), eee51.scale_vec(ic, g51.milli), \ ':', color='orangered', label = r'$I_C$') ax2.legend(loc='upper right') eee51.add_vline_text(ax, 0, 0, r'$V_{BE}$ = ' + \ '{:.1f}mV'.format(reqd_vbe/g51.milli)) eee51.add_hline_text(ax, vo_dc, -75, \ r'$V_{OUT}=$' + '{:.2f}V'.format(vo_dc)) eee51.label_plot(plt_cfg, fig, ax) plt.savefig('2N2222A_ce_transfer.png') # get the gain via the slope of the transfer curve gain_ss = np.diff(vout) / np.diff(vin) ro_calc = abs(g51.bjt_VA) / ic[index] gm_calc = ic[index] / (bjt_n * g51.VT) gain_calc = -gm_calc * eee51.r_parallel([Rc, ro_calc])
} # plot the amplifier transfer characteristics fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(eee51.scale_vec(vin, g51.milli), vout, '--', \ label = r'$v_{OUT}$') ax2 = ax.twinx() ax2.set_ylabel(r'$I_C$ [mA]') ax2.plot(eee51.scale_vec(vin, g51.milli), eee51.scale_vec(ic1, g51.milli), \ ':', color='orangered', label = r'$I_C$') ax2.legend(loc='upper right') eee51.add_vline_text(ax, 0, 0, r'$V_{BE}$ = ' + \ '{:.1f}mV'.format(vbe1_used/g51.milli)) eee51.add_hline_text(ax, vo_dc, -75, \ r'$V_{OUT}=$' + '{:.2f}V'.format(vo_dc)) eee51.add_hline_text(ax2, ic1[index]/g51.milli, 50, \ r'$I_C=$' + '{:.2f}mA'.format(ic1[index]/g51.milli)) eee51.label_plot(plt_cfg, fig, ax) plt.savefig('amp_ce_cm_transfer2.png') # get the gain via the slope of the transfer curve gain_ss = np.diff(vout) / np.diff(vin) ro1_calc = abs(npn_2n3904['VA']) / ic1[index] ro2_calc = abs(pnp_2n3906['VA']) / ic1[index]
'legend_loc' : 'upper left', 'add_legend' : True, 'legend_title' : None } # plot the transfer characteristics at 200mV fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(vbe_mV, ic_mA, '--', label = 'simulation ($V_{CE}$=0.2V)') ax.plot(vbe_mV, ic_ideal_mA, \ label = 'ideal BJT using $I_S$=' + \ si_format(bjt_Is, precision=2) + r'A, $n$={:.2f}, and '.format(bjt_n) + \ r'$|V_A|$={:.2f}'.format(abs(g51.bjt_VA))) # add_vline_text(ax, vbe_1mA_sim_mV, 3, '{:.1f}mV'.format(vbe_1mA_sim_mV)) eee51.add_vline_text(ax, vbe_spec_ideal_mV, 3, '{:.1f}mV'.format(vbe_spec_ideal_mV)) eee51.add_hline_text(ax, specs['ic']/g51.milli, 550, \ '{:.1f}mA'.format(specs['ic']/g51.milli)) eee51.label_plot(plt_cfg, fig, ax) plt.savefig('2N2222A_transfer_200mV.png') # calculate the vbe needed for vce = 2.5V reqd_vbe = eee51.bjt_find_vbe(specs['ic'], specs['vce'], \ bjt_Is, bjt_n, g51.bjt_VA) # generate the ic for the ideal bjt model # using our values for Is, n, and VA at vce = 2.5V g51.update_bjt_vce(specs['vce'])
'title': 'BJT 2N2222A Output Characteristics (sim)', 'xlabel': r'$V_{CE}$ [V]', 'ylabel': r'$I_C$ [mA]', 'legend_loc': 'upper left', 'add_legend': False } # plot the output characteristics fig = plt.figure() ax = fig.add_subplot(1, 1, 1) for m, v in enumerate(vbe): ax.plot(vce, eee51.scale_vec(ic[m], g51.milli), \ label = '{:.2f}V'.format(v)) eee51.add_vline_text(ax, 0.2, 1.3, r'$V_{CE,sat}$=' + '{:.1f}V'.format(0.2)) # reorder the legend entries for easier reading handles, labels = ax.get_legend_handles_labels() ax.legend(handles[::-1], labels[::-1], title='$V_{BE}$', bbox_to_anchor=(1, 1)) eee51.label_plot(plt_cfg, fig, ax) plt.savefig('2N2222A_output.pdf') # plot the output characteristics and curve-fitted lines to show VA fig = plt.figure() ax = fig.add_subplot(1, 1, 1) for m, v in enumerate(vbe): ax.plot(vce, eee51.scale_vec(ic[m], g51.milli), \ label = '{:.2f}V'.format(v))
} # plot the amplifier transfer characteristics fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(eee51.scale_vec(vin, g51.milli), vout, '--', \ label = r'$v_{OUT}$') ax2 = ax.twinx() ax2.set_ylabel(r'$I_C$ [mA]') ax2.plot(eee51.scale_vec(vin, g51.milli), eee51.scale_vec(ic1, g51.milli), \ ':', color='orangered', label = r'$I_C$') ax2.legend(loc='upper right') eee51.add_vline_text(ax, 0, 0, r'$V_{IN}$ = ' + \ '{:.1f}mV'.format(0)) eee51.add_vline_text(ax, 10, 0, r'$V_{IN}$ = ' + \ '{:.1f}mV'.format(10)) eee51.add_vline_text(ax, -10, 0, r'$V_{IN}$ = ' + \ '{:.1f}mV'.format(-10)) eee51.add_hline_text(ax, vo_dc, -75, \ r'$V_{OUT}=$' + '{:.2f}V'.format(vo_dc)) eee51.add_hline_text(ax2, ic1[index]/g51.milli, 50, \ r'$I_C=$' + '{:.2f}mA'.format(ic1[index]/g51.milli)) eee51.label_plot(plt_cfg, fig, ax) plt.savefig('amp_ce_cm2_transfer.png')
for cm_file, cm_label in zip(cm_files, cm_labels): vcm = [] itail = [] vop = [] with open(cm_file, 'r') as f: for line in f: vcm.append(float(line.split()[0])) itail.append(float(line.split()[1])) vop.append(float(line.split()[3])) ax.plot(vcm, eee51.scale_vec(itail, g51.milli), '-', \ label = cm_label) eee51.add_vline_text(ax, vicmin, 0, r'$V_{ic,\min}$ = ' + \ '{:.3f}'.format(vicmin)) eee51.add_vline_text(ax, vicmax, 0, r'$V_{ic,\max}$ = ' + \ '{:.3f}'.format(vicmax)) eee51.label_plot(plt_cfg, fig, ax) plt.savefig('diff_amp1_vcm_itail.png') dm_files = [cfg['transfer_vic=1.2'], \ cfg['transfer_vic=1.8'], \ cfg['transfer_vic=2.4']] vic_values = [1.2, 1.8, 2.4] vod_values = [[], [], []] for dm_file, vic_value, vod_value in zip(dm_files, vic_values, vod_values): # plot the differential mode characteristics
ax.plot(eee51.scale_vec(vin, g51.micro), vout, '--', \ label = r'$v_{OUT}$') ax2 = ax.twinx() ax2.set_ylabel(r'$I_C$ [mA]') ax2.plot(eee51.scale_vec(vin, g51.micro), eee51.scale_vec(ic1, g51.milli), \ ':', color='orangered', label = r'$I_{C1}$') ax2.plot(eee51.scale_vec(vin, g51.micro), eee51.scale_vec(ic5, g51.milli), \ ':', color='purple', label = r'$I_{C5}$') ax2.set_ylim(0.8, 1.1) ax2.legend(loc='upper right') eee51.add_vline_text(ax, 0, 0.2, r'$V_{IN}$ = ' + \ '{:.1f}mV'.format(0)) eee51.add_vline_text(ax, 125, 0.2, r'$V_{IN}$ = ' + \ '{:.1f}'.format(125) + r'$\mu V$') eee51.add_vline_text(ax, -125, 0.2, r'$V_{IN}$ = ' + \ '{:.1f}'.format(-125) + r'$\mu V$') eee51.add_hline_text(ax, vo_dc, -400, \ r'$V_{OUT}=$' + '{:.2f}V'.format(vo_dc)) eee51.add_hline_text(ax2, ic5[index]/g51.milli, 200, \ r'$I_{C5}=$' + '{:.3f}mA'.format(ic5[index]/g51.milli)) ax2.text(200, ic1[index]/g51.milli, \ r'$I_{C1}=$' + '{:.3f}mA'.format(ic1[index]/g51.milli), \
'ylabel': r'Voltage [V]', 'legend_loc': 'lower left', 'add_legend': True, 'legend_title': None } fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax.plot(eee51.scale_vec(vid, g51.micro), vo1, '-', \ label = r'$v_{o1}$') ax.plot(eee51.scale_vec(vid, g51.micro), vo2, '-', \ label = r'$v_{o2}$') ax.plot(eee51.scale_vec(vid, g51.micro), vo3, '-', \ label = r'$v_{o3}$') eee51.add_vline_text(ax, 0, 0, \ '{:.2f}V'.format(0)) eee51.add_hline_text(ax, vo1[index], -750, \ r'{:.3f}V'.format(vo1[index])) eee51.add_hline_text(ax, vo2[index], -750, \ r'{:.3f}V'.format(vo2[index])) eee51.add_hline_text(ax, vo3[index], -750, \ r'{:.3f}V'.format(vo3[index])) eee51.label_plot(plt_cfg, fig, ax) plt.savefig('opamp1_transfer.png') # define the plot parameters plt_cfg = { 'grid_linestyle': 'dotted', 'title': r'3-Stage Op-Amp DC Transfer Curve',
'title': 'BJT 2N2222A Output Characteristics (sim)', 'xlabel': r'$V_{CE}$ [V]', 'ylabel': r'$I_C$ [mA]', 'legend_loc': 'upper left', 'add_legend': False } # plot the output characteristics fig = plt.figure() ax = fig.add_subplot(1, 1, 1) for m, v in enumerate(vbe): ax.plot(vce, eee51.scale_vec(ic[m], g51.milli), \ label = '{:.2f}V'.format(v)) eee51.add_vline_text(ax, 0.2, 1.3, r'$V_{CE,sat}$=' + '{:.1f}V'.format(0.2)) # reorder the legend entries for easier reading handles, labels = ax.get_legend_handles_labels() ax.legend(handles[::-1], labels[::-1], title='$V_{BE}$', bbox_to_anchor=(1, 1)) eee51.label_plot(plt_cfg, fig, ax) plt.savefig('2N2222A_output.png') # plot the output characteristics and curve-fitted lines to show VA fig = plt.figure() ax = fig.add_subplot(1, 1, 1) for m, v in enumerate(vbe): ax.plot(vce, eee51.scale_vec(ic[m], g51.milli), \ label = '{:.2f}V'.format(v))