1

I am trying to write a program in Python which can plot the I-V curves of a bipolar transistor with given device parameters Is, Vt, Va, and Beta. I also want to be able to, given the Q-point of the device, to compute the small signal parameters r_pi, ro, and transconductance.

I created a GUI using the libraries, PyQt4, matplotlib, and numpy. My problem is that my curves are not coming out as expected and I'm not sure why. I've provided my code for calculating the collector current, Ic. Does anyone know what I might be doing wrong? For the parameters I used the values:

Is = 10*10^-15, Beta = 100, Vt = 0.025, and Va = 100

I think maybe I might be use bad voltage values for Vbe and Vce, but I'm not sure.

Code:

import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
import numpy as np
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt

import random
Vbe = [0 for x in range(7)]
Vbc = [0 for x in range(7)]

class Window(QtGui.QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)

        #### Create Widgets ####
        self.plotButton = QtGui.QPushButton('Plot')
        self.plotButton.setFixedWidth(100)
        self.plotButton.setFixedHeight(30)
        self.plotButton.clicked.connect(self.plot)

        self.clearButton = QtGui.QPushButton('Clear Plot')
        self.clearButton.setFixedWidth(100)
        self.clearButton.setFixedHeight(30)
        self.clearButton.clicked.connect(self.clear)

        self.calculate = QtGui.QPushButton('r_pi, r_o, g_m')
        self.calculate.setFixedWidth(120)
        self.calculate.setFixedHeight(30)
        self.calculate.clicked.connect(self.stuff)

        self.param = QtGui.QLabel('<b>Enter Parameters:</b>')
        self.param.setAlignment(QtCore.Qt.AlignLeft)


        self.beta = QtGui.QLineEdit()
        self.beta.setFixedWidth(70)
        self.bLabel = QtGui.QLabel('Beta')
        self.bLabel.setAlignment(QtCore.Qt.AlignRight)

        self.Is = QtGui.QLineEdit()
        self.Is.setFixedWidth(70)
        self.IsLabel = QtGui.QLabel('I<sub>s</sub>')
        self.IsLabel.setAlignment(QtCore.Qt.AlignRight)

        self.Vt = QtGui.QLineEdit()
        self.Vt.setFixedWidth(70)
        self.VtLabel = QtGui.QLabel('V<sub>T</sub>')
        self.VtLabel.setAlignment(QtCore.Qt.AlignRight)

        self.Va = QtGui.QLineEdit()
        self.Va.setFixedWidth(70)
        self.VaLabel = QtGui.QLabel('V<sub>A</sub>')
        self.VaLabel.setAlignment(QtCore.Qt.AlignRight)

        self.VceEdit = QtGui.QLineEdit()
        self.VceEdit.setFixedWidth(70)
        self.VceEdit.setAlignment(QtCore.Qt.AlignLeft)
        self.VceLabel = QtGui.QLabel('V<sub>CE</sub> (Q-Point)')
        self.VceLabel.setAlignment(QtCore.Qt.AlignRight)

        self.IcEdit = QtGui.QLineEdit()
        self.IcEdit.setFixedWidth(70)
        self.IcEdit.setAlignment(QtCore.Qt.AlignLeft)
        self.IcLabel = QtGui.QLabel('I<sub>C</sub> (Q-Point)')
        self.IcLabel.setAlignment(QtCore.Qt.AlignRight)

        #### Set The Layout ####
        layout = QtGui.QVBoxLayout()

        layout.addWidget(self.canvas)
        layout.addWidget(self.param)

        layout2 = QtGui.QHBoxLayout()

        layout2.addWidget(self.bLabel)
        layout2.addWidget(self.beta)

        layout2.addWidget(self.IsLabel)
        layout2.addWidget(self.Is)

        layout2.addWidget(self.VtLabel)
        layout2.addWidget(self.Vt)

        layout2.addWidget(self.VaLabel)
        layout2.addWidget(self.Va)

        layout2.addWidget(self.VceLabel)
        layout2.addWidget(self.VceEdit)
        layout2.addWidget(self.IcLabel)
        layout2.addWidget(self.IcEdit)

        layout.addLayout(layout2)

        layout.addWidget(self.plotButton)
        layout.addWidget(self.clearButton)
        layout.addWidget(self.calculate)

        self.setLayout(layout)

    def clear(self):
        plt.clf()
        plt.cla()
        print ('cleared')

    def stuff(self):
        self.qIc1       = str("%s" % self.IcEdit.text())
        self.qVc1       = str("%s" % self.VceEdit.text())


    def plot(self):
        plt.cla()
        self.betaVal    = str("%s" % self.beta.text())
        self.IsVal      = str("%s" % self.Is.text())
        self.VtVal      = str("%s" % self.Vt.text())
        self.VaVal      = str("%s" % self.Va.text())


        #### Compute Collector Current ####
        data1, data2, data3 = [], [], []
        Vbe1, Vbe2, Vbe3 = [], [], []
        Vce1, Vce2, Vce3 = [], [], []

        x1, x2, x3 = 6, 5, 4 #Vce
        y1, y2, y3 = 5, 4, 2 #Vbe

        for j in range(600): 
            x1, x2, x3 = x1 + 0.01, x2 + 0.01, x3 + 0.01
            y1, y2, y3 = y1 + 0.01, y2 + 0.01, y3 + 0.01

            Vce1.append(x1)
            Vbe1.append(y1)
            Vce2.append(x2)
            Vbe2.append(y2)
            Vbe3.append(x3)
            Vce3.append(y3)

        for i in range(600):
            e1 = np.exp(Vbe1[i]/float(self.VtVal))
            e2 = np.exp((Vbe1[i] - Vce1[i])/float(self.VtVal))
            e3 = (float(self.IsVal)/float(self.betaVal))*(np.exp((Vbe1[i] - Vce1[i])/float(self.VtVal)) - 1)
            e4 = (Vce1[i] + float(self.VaVal))/float(self.VaVal)
            subtract = float(self.IsVal)*(e1 - e2) - e3
            ic = subtract * e4
            data1.append(ic)

            e1 = np.exp(Vbe2[i]/float(self.VtVal))
            e2 = np.exp((Vbe2[i] - Vce2[i])/float(self.VtVal))
            e3 = (float(self.IsVal)/float(self.betaVal))*(np.exp((Vbe2[i] - Vce2[i])/float(self.VtVal)) - 1)
            e4 = (Vce2[i] + float(self.VaVal))/float(self.VaVal)
            subtract = float(self.IsVal)*(e1 - e2) - e3
            #m1 = float(self.IsVal)*subtract
            ic = subtract  * e4
            data2.append(ic)

            e1 = np.exp(Vbe3[i]/float(self.VtVal))
            e2 = np.exp((Vbe3[i] - Vce3[i])/float(self.VtVal))
            e3 = (float(self.IsVal)/float(self.betaVal))*(np.exp((Vbe3[i] - Vce3[i])/float(self.VtVal)) - 1)
            e4 = (Vce3[i] + float(self.VaVal))/float(self.VaVal)
            subtract = float(self.IsVal)*(e1 - e2) - e3
            #m1 = float(self.IsVal)*subtract
            ic = subtract * e4
            data3.append(ic)

        self.ax = self.figure.add_subplot(111)
        plt.xlabel('Vce')
        plt.ylabel('Ic')
        plt.title('BJT I-V Characteristics')
        self.ax.plot(data1, 'r')
        self.ax.plot(data2, 'b')
        self.ax.plot(data3, 'g')
        self.canvas.draw()



if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    main = Window()
    main.setWindowTitle('BJT I-V Curve Plotter')
    main.resize(1000, 600)
    main.show()

    sys.exit(app.exec_())

My results:

https://drive.google.com/file/d/0B3fmw_rxjp4nYVVMR2x2RThXTXc/view?usp=sharing

what I would expect:

https://awrcorp.com/download/faq/english/examples/images%5Cbjt_amp_oppnt_bjt_iv_curves_graph.gif

M4rtini
  • 13,186
  • 4
  • 35
  • 42
  • 2
    To save people time and effort, give your entire code example that includes the plot you're getting and maybe even what you would expect to see. – jonnybazookatone Jan 18 '15 at 19:34
  • 1
    No problem. I just updated my post – user1982824 Jan 18 '15 at 19:42
  • This looks more like a content question than a technical one. For example, it could be possible you made a typo in the transcription of the bipolar transistor formulas. – jonnybazookatone Jan 18 '15 at 20:00
  • Well I'm quite certain that the equations I'm using is correct. I've verified them multiple times. I think what I am having trouble with is determining how to pick the right values for collector-emmitter and base-emitter voltage – user1982824 Jan 18 '15 at 20:05
  • 2
    You'd get better help if you simplified the code to just what's needed for your question. For example, PyQt4 has nothing to do with your question, but I don't have it installed, and therefore can't run your code. How many people here know about transistors and have PyQt4 installed? My guess is not many. See http://stackoverflow.com/help/mcve – tom10 Jan 18 '15 at 21:52
  • Are you sure, you have all your values right, since the exponentials make very large numbers (10^176). Your ``Vbe`` voltages do not look too plausible to me. BTW, using Numpy arrays (e.g., http://matplotlib.org/examples/subplots_axes_and_figures/subplot_demo.html) will make you code much shorter and much more readable. – Dietrich Jan 18 '15 at 22:39
  • Furthermore, doing ``exp(a*x) - exb(b*x)`` with ``a,b>0`` is numerically unstable for increasing ``x`` (due to the limited number of digits of floats). Above a certain threshold, you need to evaluate such expressions differently. You could try ``exp(d)*(exp(a*x-d) - exp(b*x-d))``, choosing ``d`` that way that ``a*x-d`` and ``b*x-d`` will be close to zero. – Dietrich Jan 18 '15 at 22:54
  • Thanks for the tips. I realized my mistake. I should have a constant Vbe and an array of values for Vce. I'll switch to using bumpy arrays, thats a good idea. – user1982824 Jan 19 '15 at 01:14

0 Answers0