Table des matières Python

Simulations SPICE : introduction

1. Introduction

Le programme SPICE (Simulated Program with Integrated Circuit Emphasis) effectue des simulations de circuits électroniques analogiques. La version de référence (spice 2g6, 1983) est écrite en fortran. Une version plus récente (spice 3, 1985) est écrite en C. De nombreux logiciels commerciaux de simulation utilisent le moteur de calcul de SPICE, en ajoutant des fonctions supplémentaires.

On s'intéresse ici aux versions libres de spice, ngspice et SpiceOpus, qui reposent sur spice3f5. Ces deux programmes lisent un fichier texte comportant une description du circuit et différentes commandes. La commande PLOT permet de tracer des courbes mais ne permet pas d'exporter sous forme de fichier. La commande PRINT permet d'exporter les résultats dans un fichier texte. Nous utiliserons une fonction python permettant de lire les fichiers produits par PRINT. Voir la page Lecture des sorties SPICE avec Python pour l'utilisation de cette fonction. Voir aussi Lecture des sorties SPICE avec Mathematica.

Le présent document explique le principe d'utilisation de SPICE (ngspice) à travers un exemple simple. Seules les fonctions les plus courantes sont décrites. Pour plus d'informations, lire la documentation de référence SPICE.

Voir aussi les pages Simulation SPICE des transistors bipolaires, Simulation SPICE des transistors à effet de champ JFET et Simulation SPICE des amplificateurs opérationnels.

2. Description du circuit

On considère comme exemple le circuit suivant :

figureA.svgFigure pleine page

Il faut tout d'abord numéroter les nœuds du circuit, en attribuant le numéro 0 à la masse. Ce circuit comporte 3 nœuds (sans compter la masse).

Une source de tension est définie par la syntaxe suivante :

Vxxx N1 N2

Le nom commence par V et xxx est un nom qui permet d'identifier la source s'il y en a plusieurs. N1 et N2 sont les deux nœuds de la source : la tension appliquée est par convention VN1-VN2.

Une resistance est définie par :

Rxxx N1 N2 VALEUR

La valeur est donnée en Ω. Pour entrer une valeur très petite ou très grande, on peut utiliser un des multiples définis dans le tableau suivant :

Multiples
SymboleFacteur
T1E12
G1E9
MEG1E6
K1E3
M1E-3
U1E-6
N1E-9
P1E-12
F1E-15

La syntaxe des capacités et des inductances est similaire, avec des noms commençant respectivement par C et L.

Voici la description du circuit précédent avec des valeurs numériques pour les composants passifs :

V1 1 0
R1 1 2 10K
C1 2 0 100N
L1 2 3 10M
R 3 0 10
              

La description de ce circuit n'est pas tout à fait complète. Il faut encore préciser le type de source de tension, qui dépend du type d'analyse que l'on souhaite effectuer.

3. Analyse en continu

Pour faire une analyse en continu, il faut ajouter l'option DC aux sources. Par exemple, une source appliquant une tension continue de 1 volt sera définie par :

V1 1 0 DC 1V

Le symbole V accolé à 1 n'est pas pris en compte par SPICE : il est ajouté pour rendre le code plus lisible.

L'analyse en continu est définie par la commande .DC. les commandes sont précédées d'un point. On peut aussi placer toutes les commandes (sans les points) entre les deux commandes .CONTROL et .ENDC.

La commande .DC effectue en fait un balayage de tensions ou de courants continus, c'est-à-dire ayant une valeur constante. Voici sa syntaxe minimale :

.DC SRC1 START1 STOP1 INC1

SRC1 désigne la source (de tension ou de courant) dont on veut faire varier la valeur. START1 est la valeur de départ, STOP1 la valeur finale et INC1 l'incrément.

La description du circuit et les commandes se placent dans un fichier .cir. Voici le fichier .cir complet pour le circuit précédent, avec une analyse DC :

Circuit RLC
V1 1 0 DC
R1 1 2 10K
C1 2 0 100N
L1 2 3 10M
R 3 0 10
.CONTROL
DC V1 0 10 1
PLOT V(2)
.ENDC
.END
            

La première ligne est le nom du circuit. La dernière ligne doit être .END. La commande PLOT a été ajoutée.

Pour traiter ce fichier avec ngspice, ouvrir ngspice depuis une console puis exécuter

source circuit-RLC-1.cir

La courbe tracée est la tension du nœud 2 en fonction de la tension balayée (v-sweep), qui est ici la tension de la source V1. Dans le cas présent, la courbe obtenue est linéaire car le circuit est linéaire.

Pour récupérer les données dans python (ou dans Mathematica), nous allons remplacer la commande PLOT par la commande PRINT, en redirigeant la sortie vers un fichier :

Circuit RLC
V1 1 0 DC
R1 1 2 10K
C1 2 0 100N
L1 2 3 10M
R 3 0 10
.CONTROL
DC V1 0 10 1
PRINT V(2) > export-2.txt
.ENDC
.END
            

Dans ce cas, on peut exécuter le fichier avec ngspice sans ouvrir la console ngspice (mode batch avec l'option -b) :

Le fichier texte obtenu contient une colonne pour v-sweep, une colonne pour v(2). La fonction python lectureSpicePrint.py décrite dans Lecture des sorties SPICE avec Python permet de lire ce fichier (dans certains cas les valeurs exportées sont complexes).

from lectureSpicePrint import lectureSpicePrint
from matplotlib.pyplot import *

data = lectureSpicePrint("export-2.txt")
V1 = data["v-sweep"]
V2 = data["v(2)"]
            

Voici le tracé de V2 en fonction de V1 :

figure(figsize=(6,6))
plot(V1,V2)
xlabel("V1 (V)")
ylabel("V2 (V)")
grid()
            
plotA.svgFigure pleine page

4. Analyse en régime sinusoïdal

Pour effectuer une analyse fréquentielle en régime sinusoïdal, il faut déclarer une source en mode AC, avec la syntaxe suivante :

Vxxx N1 N2 AC (AMP) (PHASE)

Les paramètres entre parenthèses sont facultatifs. AMP est l'amplitude de la source sinusoïdal (en V ou en A). Sa valeur par défaut est 1. Ce paramètre est sans importance pour les circuits linéaires. PHASE est la phase de la source, nulle par défaut.

L'analyse est définie par la commande .AC, dont la syntaxe est :

.AC BALAYAGE NB_POINTS FSTART STOP

FSTART et la fréquence de départ, FSTOP la fréquence d'arrivée (en Hertz). Il y a trois types de balayage :

Voici le fichier .cir pour une analyse fréquentielle de 100 Hz à 100 kHz :

Circuit RLC
V1 1 0 AC 1
R1 1 2 10K
C1 2 0 100N
L1 2 3 10M
R 3 0 10
.CONTROL
AC DEC 100 100 100K
PRINT VDB(2) VP(2) > export-3.txt
.ENDC
.END
            

Dans ce cas, les données exportées sont la tension du nœud 2 en décibel et la phase en radian. Si le nœud est la sortie d'un filtre, on obtient directement le gain en décibel car l'entrée a une amplitude de 1. La phase obtenue est le déphasage par rapport à l'entrée puisque celle-ci a une phase de 0.

On peut aussi exporter la tension sous forme de nombres complexes, avec :

PRINT V(2)

Le tracé du diagramme de Bode directement dans ngspice est obtenu avec les commandes :

PLOT VDB(2)
PLOT VP(2)

Voici le tracé du diagramme de Bode en python :

data = lectureSpicePrint("export-3.txt")
freq = data["frequency"]
gdb = data["vdb(2)"]
phi = data["vp(2)"]
figure(figsize=(10,10))
subplot("211")
plot(freq,gdb)
xscale('symlog')
xlabel('f (Hz)')
ylabel('GdB')
grid()
subplot("212")
plot(freq,phi)
xscale('symlog')
xlabel('f (Hz)')
ylabel('phi (rad)')
grid()
            
plotB.svgFigure pleine page

Dans certains cas, la grandeur que l'on veut étudier est un courant. Pour obtenir le courant dans une branche, il faut ajouter une source de tension DC de tension nulle dans cette branche. Voici par exemple comment obtenir le courant dans l'inductance :

Circuit RLC
V1 1 0 AC 1
R1 1 2 10K
C1 2 0 100N
L1 2 3 10M
R 3 4 10
VIL 4 0 DC 0
.CONTROL
AC DEC 100 100 100K
PRINT I(VIL) > export-4.txt
.ENDC
.END
            

La source VIL a été ajoutée entre la résistance R et la masse, pour obtenir le courant dans cette branche. La syntaxe I(Vxxx) permet d'obtenir le courant traversant une source de tension. La sortie en décibel et en phase ne fonctionne pas sur ngspice pour le courant; on doit donc exporter la tension sous forme de nombres complexes. Le calcul du gain et du déphasage se fait sans difficulté avec python :

import numpy
data = lectureSpicePrint("export-4.txt")
freq = data["frequency"]
iL = data["i(vil)"]
gdb = 20*numpy.log10(numpy.absolute(iL))
phi = numpy.angle(iL)
figure(figsize=(10,10))
subplot("211")
plot(freq,gdb)
xscale('symlog')
xlabel('f (Hz)')
ylabel('GdB')
grid()
subplot("212")
plot(freq,phi)
xscale('symlog')
xlabel('f (Hz)')
ylabel('phi (rad)')
grid()
            
plotC.svgFigure pleine page

5. Analyse transitoire

L'analyse transitoire, appelée plus généralement analyse temporelle, consiste à obtenir les tensions en fonction du temps. Pour cela, il faut définir précisément les signaux temporels délivrés par les sources. Les différents types de signaux sont :

Nous allons décrire en détail la source PULSE. Consulter SPICE pour les autres sources.

La syntaxe d'une source à impulsion est :

Vxxx N1 N2 PULSE(V1 V2 TD TR TF PW PER)

Les paramètres sont :

L'analyse transitoire est obtenue avec la commande .TRAN, dont voici la syntaxe :

.TRAN PAS TSTOP

PAS est le pas de temps, TSTOP le temps final.

Il peut être nécessaire de préciser certaines conditions initiales. Pour cela, on utilise la commande .IC. On peut aussi ajouter l'option IC à certains composants.

Voyons comment obtenir la réponse à un échelon avec le circuit étudié :

Circuit RLC
V1 1 0 PULSE(0 1 0 0 0 10M 20M)
R1 1 2 10K
C1 2 0 100N
L1 2 3 10M
R 3 4 10
VIL 4 0 DC 0
.CONTROL
IC V(2)=0
TRAN 1U 20M
PRINT V(2) > export-5.txt
.ENDC
.END
            
data = lectureSpicePrint("export-5.txt")
time = data["time"]*1000
V2 = data["v(2)"]
figure(figsize=(15,5))
plot(time,V2)
xlabel("t (ms)")
ylabel("V2 (V)")
grid()
            
plotD.svgFigure pleine page
Creative Commons LicenseTextes et figures sont mis à disposition sous contrat Creative Commons.