Browse Source

Add new SOA parameters (safe operating area) for BJT.

We now scan for max of Ic, Ib, power, taking into
account the max allowed temperature, using the thermal
resistance rth0 model parameter between juntion and ambient.

Two user options are there: If rth0 is given, we calculate
a derating of the max power allowed.
Without a constant max power according to model param pow_max
is assumed.

The new model parameters for the bipolar model are:
pow_max, ic_max, ib_max, te_max, and rth0, in addition
to the already existing vbe_max, vbc_max, adn vce_max.
pre-master-46
Holger Vogt 5 years ago
parent
commit
a08e6a0676
  1. 19
      examples/soa/bjt-soa.cir
  2. 7
      src/spicelib/devices/bjt/bjt.c
  3. 15
      src/spicelib/devices/bjt/bjtdefs.h
  4. 13
      src/spicelib/devices/bjt/bjtmask.c
  5. 21
      src/spicelib/devices/bjt/bjtmpar.c
  6. 14
      src/spicelib/devices/bjt/bjtsetup.c
  7. 72
      src/spicelib/devices/bjt/bjtsoachk.c

19
examples/soa/bjt-soa.cir

@ -0,0 +1,19 @@
SOA check for bipolar
Vce c 0 -1
Ib b 0 -1u
Ve e 0 0
Q1 c b e MPSA92
.MODEL MPSA92 PNP(IS=9.53E-14 ISE=8.37E-13 ISC=9.99E-11 XTI=3.00 BF=9.80E1 BR=4.78 IKF=3.49E-2 IKR=1.00 XTB=1.5 VAF=2.60E2 VAR=1.40E2 VJE=3.00E-1 VJC=3.00E-1 RE=1.00E-2 RC=1.00E-2 RB=2.76E1 RBM=6.66E-2 IRB=7.02E-4 CJE=9.54E-11 CJC=4.66E-11 .00 FC=5.00E-1 NF=1.00 NR=1.55 NE=1.49 NC=1.50 MJE=4.26E-1 MJC=7.00E-1 TF=9.52E-10 TR=516.9p ITF=4.12E-1 VTF=9.99E5 XTF=1.03 EG=1.11 VCEO=300 ICRATING=500m MFG=SIEMENS pow_max=0.625 rth0=200 tnom=25)
.option warn=1 maxwarns=2
.temp 50
.control
dc Vce 0 -200 -0.1 Ib 0 80u 8u
plot i(Ve)
.endc
.end

7
src/spicelib/devices/bjt/bjt.c

@ -229,7 +229,12 @@ IFparm BJTmPTable[] = { /* model parameters */
IOP("d", BJT_MOD_XD, IF_REAL, "Temperature exponent of VO"),
IOP("vbe_max", BJT_MOD_VBE_MAX, IF_REAL, "maximum voltage B-E junction"),
IOP("vbc_max", BJT_MOD_VBC_MAX, IF_REAL, "maximum voltage B-C junction"),
IOP("vce_max", BJT_MOD_VCE_MAX, IF_REAL, "maximum voltage C-E branch")
IOP("vce_max", BJT_MOD_VCE_MAX, IF_REAL, "maximum voltage C-E branch"),
IOP("pow_max", BJT_MOD_POW_MAX, IF_REAL, "maximum device power dissipation"),
IOP("ic_max", BJT_MOD_IC_MAX, IF_REAL, "maximum collector current"),
IOP("ib_max", BJT_MOD_IB_MAX, IF_REAL, "maximum base current"),
IOP("te_max", BJT_MOD_TE_MAX, IF_REAL, "maximum temperature"),
IOP("rth0", BJT_MOD_RTH0, IF_REAL, "thermal resistance juntion to ambient"),
};
char *BJTnames[] = {

15
src/spicelib/devices/bjt/bjtdefs.h

@ -498,6 +498,11 @@ typedef struct sBJTmodel { /* model structure for a bjt */
double BJTvbeMax; /* maximum voltage over B-E junction */
double BJTvbcMax; /* maximum voltage over B-C junction */
double BJTvceMax; /* maximum voltage over C-E branch */
double BJTicMax; /* maximum collector current */
double BJTibMax; /* maximum base current */
double BJTpowMax; /* maximum device power dissipation */
double BJTteMax; /* maximum device temperature */
double BJTrth0; /* thermal resistance juntion to ambient */
unsigned BJTsubsGiven : 1;
unsigned BJTtnomGiven : 1;
@ -617,6 +622,11 @@ typedef struct sBJTmodel { /* model structure for a bjt */
unsigned BJTvbeMaxGiven : 1;
unsigned BJTvbcMaxGiven : 1;
unsigned BJTvceMaxGiven : 1;
unsigned BJTpowMaxGiven : 1;
unsigned BJTicMaxGiven : 1;
unsigned BJTibMaxGiven : 1;
unsigned BJTteMaxGiven : 1;
unsigned BJTrth0Given : 1;
} BJTmodel;
#ifndef NPN
@ -770,6 +780,11 @@ enum {
BJT_MOD_VBE_MAX,
BJT_MOD_VBC_MAX,
BJT_MOD_VCE_MAX,
BJT_MOD_POW_MAX,
BJT_MOD_IC_MAX,
BJT_MOD_IB_MAX,
BJT_MOD_TE_MAX,
BJT_MOD_RTH0,
};
/* device questions */

13
src/spicelib/devices/bjt/bjtmask.c

@ -416,6 +416,19 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value)
return(OK);
case BJT_MOD_VCE_MAX:
value->rValue = here->BJTvceMax;
case BJT_MOD_IC_MAX:
value->rValue = here->BJTicMax;
return(OK);
case BJT_MOD_IB_MAX:
value->rValue = here->BJTibMax;
return(OK);
case BJT_MOD_POW_MAX:
value->rValue = here->BJTpowMax;
case BJT_MOD_RTH0:
value->rValue = here->BJTrth0;
return(OK);
case BJT_MOD_TE_MAX:
value->rValue = here->BJTteMax;
return(OK);
default:
return(E_BADPARM);

21
src/spicelib/devices/bjt/bjtmpar.c

@ -506,6 +506,27 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel)
mods->BJTvceMax = value->rValue;
mods->BJTvceMaxGiven = TRUE;
break;
case BJT_MOD_IC_MAX:
mods->BJTicMax = value->rValue;
mods->BJTicMaxGiven = TRUE;
break;
case BJT_MOD_IB_MAX:
mods->BJTibMax = value->rValue;
mods->BJTibMaxGiven = TRUE;
break;
case BJT_MOD_POW_MAX:
mods->BJTpowMax = value->rValue;
mods->BJTpowMaxGiven = TRUE;
break;
case BJT_MOD_TE_MAX:
mods->BJTteMax = value->rValue;
mods->BJTteMaxGiven = TRUE;
break;
case BJT_MOD_RTH0:
mods->BJTrth0 = value->rValue;
mods->BJTrth0Given = TRUE;
break;
default:
return(E_BADPARM);
}

14
src/spicelib/devices/bjt/bjtsetup.c

@ -369,6 +369,20 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
model->BJTvceMax = 1e99;
}
if(!model->BJTicMaxGiven) {
model->BJTicMax = 1e99;
}
if(!model->BJTibMaxGiven) {
model->BJTibMax = 1e99;
}
if(!model->BJTpowMaxGiven) {
model->BJTpowMax = 1e99;
}
if(!model->BJTteMaxGiven) {
model->BJTteMax = 1e99;
}
/*
* COMPATABILITY WARNING!
* special note: for backward compatability to much older models, spice 2G

72
src/spicelib/devices/bjt/bjtsoachk.c

@ -18,13 +18,20 @@ BJTsoaCheck(CKTcircuit *ckt, GENmodel *inModel)
BJTmodel *model = (BJTmodel *) inModel;
BJTinstance *here;
double vbe, vbc, vce; /* actual bjt voltages */
double pow;
double ic, ib; /* actual bjt currents */
int maxwarns;
static int warns_vbe = 0, warns_vbc = 0, warns_vce = 0;
static int warns_pow = 0, warns_ic = 0, warns_ib = 0;
if (!ckt) {
warns_vbe = 0;
warns_vbc = 0;
warns_vce = 0;
warns_pow = 0;
warns_ic = 0;
warns_ib = 0;
return OK;
}
@ -65,7 +72,72 @@ BJTsoaCheck(CKTcircuit *ckt, GENmodel *inModel)
warns_vce++;
}
ic = fabs(*(ckt->CKTstate0 + here->BJTcc));
if (ic > fabs(model->BJTicMax))
if (warns_ic < maxwarns) {
soa_printf(ckt, (GENinstance*)here,
"Ic=%.4g A at Vce=%.4g V has exceeded Ic_max=%.4g A\n",
ic, vce, model->BJTicMax);
warns_ic++;
}
ib = fabs(*(ckt->CKTstate0 + here->BJTcb));
if (ib > fabs(model->BJTibMax))
if (warns_ib < maxwarns) {
soa_printf(ckt, (GENinstance*)here,
"Ib=%.4g A at Vbe=%.4g V has exceeded Ib_max=%.4g A\n",
ib, vbe, model->BJTibMax);
warns_ib++;
}
if (warns_pow < maxwarns) {
pow = fabs(*(ckt->CKTstate0 + here->BJTcc) *
(*(ckt->CKTrhsOld + here->BJTcolNode) -
*(ckt->CKTrhsOld + here->BJTemitNode))
);
pow += fabs(*(ckt->CKTstate0 + here->BJTcb) *
(*(ckt->CKTrhsOld + here->BJTbaseNode) -
*(ckt->CKTrhsOld + here->BJTemitNode))
);
pow += fabs(*(ckt->CKTstate0 + here->BJTcdsub) *
(*(ckt->CKTrhsOld + here->BJTsubstConNode) -
*(ckt->CKTrhsOld + here->BJTsubstNode))
);
if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && !(ckt->CKTmode &
MODETRANOP)) {
pow += *(ckt->CKTstate0 + here->BJTcqsub) *
fabs(*(ckt->CKTrhsOld + here->BJTsubstConNode) -
*(ckt->CKTrhsOld + here->BJTsubstNode));
}
pow *= here->BJTm;
/* derating without self-heating, external temp and model tnom given */
if (model->BJTrth0Given && model->BJTpowMaxGiven && model->BJTtnomGiven) {
double pow_max;
if (here->BJTtemp < model->BJTtnom)
pow_max = model->BJTpowMax;
else {
pow_max = model->BJTpowMax - (here->BJTtemp - model->BJTtnom) / model->BJTrth0;
pow_max = (pow_max > 0) ? pow_max : 0.;
}
if (pow > pow_max) {
soa_printf(ckt, (GENinstance*)here,
"Pow=%.4g W has exceeded Pow_max=%.4g W\n at Vce=%.4g V, Ib=%.4g A, Ic=%.4g A, and Te=%.4g C\n",
pow, pow_max, vce, ib, ic, here->BJTtemp - CONSTCtoK);
warns_pow++;
}
}
/* no derating */
else {
if (pow > model->BJTpowMax) {
soa_printf(ckt, (GENinstance*)here,
"Pow=%.4g W has exceeded Pow_max=%.4g W\n at Vce=%.4g V, Ib=%.4g A, and Ic=%.4g A\n",
pow, model->BJTpowMax, vce, ib, ic);
warns_pow++;
}
}
}
}
}
return OK;

Loading…
Cancel
Save