Dans cet exercice, on cherche à simuler numériquement l’évolution des tensions dans l’oscillateur de Wien à l’aide de la méthode d’Euler.
On note la sortie de l’amplificateur non-inverseur et la tension de sortie du filtre de Wien.
Les fonctions de transfert de l’amplificateur et du filtre sont respectivement :
1/ Montrer que la sortie de l’amplificateur non-inverseur vérifie l’équation différentielle
La première fonction de transfert donne simplement
La seconde peut se réécrire
soit, en multipliant par
ce qui donne en temporel
La méthode d’Euler ne s’applique qu’à des équations différentielles du premier ordre. Il est alors nécessaire de transformer ces équations en équations d’ordre 1. Pour cela, on introduit et .
2/ Montrer que les deux équations de la question précédente peuvent se réécrire sous la forme suivante :
L’équation différentielle de la question précédente peut se réécrire
soit, en remplaçant avec et
Les trois autres sont simplement des définitions de et et de la relation entre et vue à la question précédente.
Pour résoudre numériquement ces équations, la méthode d’Euler consiste à discrétiser le temps en intervalles de durée et à approximer les dérivées par des différences finies (relation de Tailor).
On note ; ; et .
3/ Montrer que , , et vérifient les relations de récurrence suivantes :
4/ Compléter le code suivant permettant de simuler numériquement l’évolution des tensions dans l’oscillateur de Wien.
import numpy as np
R1 = 1000# Ohm
R2 = 2001# Ohm
C = 1E-6# F
R = 1000# Ohm
T = ...# s période présumée
Dt = T/100# s pas de temps
tmax = 100*T# s durée de la simulation
N = int(tmax//dt)# nombre de points de la simulation
t = np.linspace(0,tmax, N)# tableau des temps
v = np.zeros(N)# V tableau des tensions v
vp = np.zeros(N)# V/s dérivée de v
s = np.zeros(N)# V tableau des tensions s
sp = np.zeros(N)# V/s dérivée de s
v[0] = 0.1 # petite perturbation initiale
for i in range(1,N):# Calcul de s et v au cours du temps grâce à la méthode d'Euler
s[i] = (1+R2/R1)*v[i-1]
sp[i] = ...
vp[i] = ...
v[i] = ...import numpy as np
R1 = 1000# Ohm
R2 = 2001# Ohm
C = 1E-6# F
R = 1000# Ohm
T = 2*np.pi*R*C# s période présumée
Dt = T/100# s pas de temps
tmax = 100*T# s durée de la simulation
N = int(tmax//dt)# nombre de points de la simulation
t = np.linspace(0,tmax, N)# tableau des temps
v = np.zeros(N)# V tableau des tensions v
vp = np.zeros(N)# V/s dérivée de v
s = np.zeros(N)# V tableau des tensions s
sp = np.zeros(N)# V/s dérivée de s
v[0] = 0.1 # petite perturbation initiale
for i in range(1,N):# Calcul de s et v au cours du temps grâce à la méthode d'Euler
s[i] = (1+R2/R1)*v[i-1]
sp[i] = (s[i] - s[i-1])/dt
vp[i] = vp[i-1] + dt*(-3/(R*C)*vp[i-1] - 1/(R*C)**2*v[i-1] + 1/(R*C)*sp[i])
v[i] = v[i-1] + dt*vp[i-1]La saturation de l’amplificateur n’a pas encore été prise en compte. Une vérification doit être introduite entre les lignes 24 et 25 du code précédent pour s’assurer que la tension de sortie de l’amplificateur ne dépasse pas la tension de saturation .
5/ Compléter les lignes à introduire entre les lignes 24 et 25 du code précédent pour prendre en compte la saturation de l’amplificateur.
if s[i] > Vsat :
s[i] = ...
elif s[i] < -Vsat :
s[i] = ...if s[i] > Vsat :
s[i] = Vsat
elif s[i] < -Vsat :
s[i] = -VsatOn souhaite maintenant visualiser les résultats de la simulation. Pour cela, on peut utiliser la bibliothèque matplotlib pour tracer les tensions et en fonction du temps.
6/ Compléter le code suivant pour tracer les tensions et en fonction du temps.
import matplotlib.pyplot as plt
plt.figure(1)
plt.clf()
plt.plot(..., label='s(t)')
plt.plot(..., label='v(t)')
plt.xlabel('Temps (s)')
plt.ylabel('Tension (V)')
plt.legend()
plt.grid()
plt.show()import matplotlib.pyplot as plt
plt.figure(1)
plt.clf()
plt.plot(t, s, label='s(t)')
plt.plot(t, v, label='v(t)')
plt.xlabel('Temps (s)')
plt.ylabel('Tension (V)')
plt.legend()
plt.grid()
plt.show()En théorie, on s’attend à ce que la tension soit “plus sinusoïdale” que la tension . Pour vérifier cela, on peut effectuer une transformée de Fourier sur les signaux simulés et comparer les spectres obtenus.
Le code suivant permet de calculer et de tracer les spectres des signaux et .
vTF = np.abs(np.fft.rfft(v)) # calcul du spectre de v
vTF = vTF/vTF.max() # normalisation du spectre pour pouvoir le comparer à celui de s
sTF = np.abs(np.fft.rfft(s)) # calcul du spectre de s
sTF = sTF/sTF.max() # normalisation
fréquences = np.fft.rfftfreq(N, dt) # calcul des fréquences associées aux spectres
plt.figure(2)
plt.clf()
plt.plot(fréquences, sTF, label="spectre de s")
plt.plot(fréquences, vTF, label="spectre de v")
plt.legend())
plt.xlabel("fréquence (Hz)")
plt.ylabel("spectre (sans unité)")
plt.show()7/ Parmi les deux signaux, lequel a des harmoniques les plus grandes ? Est-ce conforme à ce que l’on attendait ? Quel est l’impact de sur le spectre ?
Le spectre de a des harmoniques plus grandes que celui de . Cela est conforme à ce que l’on attendait, car la tension est filtrée par le filtre de Wien, ce qui réduit les harmoniques.
Plus est grand, plus les harmoniques de et sont importantes et plus les signaux s’éloignent de sinusoïdes.