LP23 : Aspects analogique et numérique du traitement d’un signal - étude spectrale
Biblio
- Trop compliqué et complet : si on se pose une question la réponse y sera : Traitement des signaux et acquisition de données, Francis Cottet éditions Dunod
- Regarder programme psi et bouquins de PSI, ça balise un peu la leçon c’est mieux
- Dunod PSI tout en un
- Précis électronique PSI : la base sur le filtrage et la DSF
- Electronique, Pérez
- Transmission de signaux, Christophe More
Notions importantes : Spectre d’un signal temporel, description via TF, application filtrage. Numérisation : échantillonnage, FFT et critère de Shannon. Peut être une dernière partie sur la modulation en amplitude nécessaire pour transporter la voix par exemple ?
Plans possibles
- I Outils d’analyse spectrale : 1) Signal périodique et DSF, spectre 2) Filtrage : couper fréquences … Application au passe haut de l’oscillo, transition numérique?
- II Aquisition d’un signal : 1) échantillonnage d’un signal 2) traitement : FFT, critère de Shannon, application au repliement et diapason?
- III Modulation/démodulation fil rouge objectif radio : 1) multiplication de signaux, appliction modulante porteuse. 2) Transmission du signal et modulation en amplitude 3) Démodulation ouvertude détection synchrone
Regarder du côté de la modulation à porteuse conservée. Le risque de ce plan est qu’on part.
On pourrait faire une leçon qui se base sur un niveau de prérequis plus avancé, notemment pour “traitement linéaire et non linéaire d’un signal”, et prendre fil rouge modulation/Démodulation pour la radio :
- Intro : Radio émet voix, problème bruit, vitesse de propagation(?), antennes longues
- I Modulation d’amplitude : 1) Multiplication de signaux avec le montage, et ce que ça permet 2) Application radio : porteuse et enveloppe, spectre
- II Réception du signal et démodulation : Détection synchrone, problèmes associés
Peut être dans le cas non linéaire discuter de la non validité de la notation cpx.
Manips possibles
- translation de fréquence diapason
- Modulation en amplitude
- Etude du filtre de l’oscillo
- Multiplexage optique
Python
Modulation et échantillonnage
import numpy as np
import matplotlib.pyplot as plt
t=np.linspace(0,2e-2,1000)
# Signal s
fm=100
fp=500
s=(1+0.5*np.sin(2*np.pi*t*fm))*np.sin(2*np.pi*t*fp)
m=(1+0.5*np.sin(2*np.pi*t*fm))
# Signal échantillonné
N=30
t_ech=np.linspace(0,2e-2,N)
s_ech=(1+0.5*np.sin(2*np.pi*t_ech*fm))*np.sin(2*np.pi*t_ech*fp)
#Graphique
plt.figure()
plt.plot(1000*t,s,'red',lw=3)
plt.plot(1000*t,m,'orange',lw=2)
plt.plot(1000*t,-m,'orange',lw=2)
(markerLines, stemLines, baseLines) =plt.stem(1000*t_ech,s_ech,linefmt='b--')
plt.setp(markerLines,markersize=10)
plt.setp(stemLines, lw=2)
plt.xlabel('t [ms]',size=20)
plt.ylabel('$u_e$(t) [V]',size=20)
plt.xticks(size=15)
plt.yticks(size=15)
plt.title('Signal modulé avec $f_m$=100 Hz et $f_p$=500 Hz\nÉchantillonnage : N=30 points et $T_0$=20 ms',size=20)
#plt.title('Signal modulé avec $f_m$=100 Hz et $f_p$=2 kHz',size=20)
plt.grid()
plt.show()
# Fonction d'échantillonnage
dt=0.1e-3
p=[]
for t_i in t:
t_ech_i=np.argmin(np.abs(t_ech-t_i))
if t_ech[t_ech_i]<=t_i<=t_ech[t_ech_i]+dt:
p.append(1)
else:
p.append(0)
plt.figure()
plt.plot(1000*t,p,'black',lw=3)
plt.xlim(0,5)
plt.xlabel('t [ms]',size=20)
plt.ylabel('p(t) [V]',size=20)
plt.xticks(size=15)
plt.yticks(size=15)
plt.grid()
plt.show()
Filtrage linéaire
Filtre et passe bas:
import numpy as np
from matplotlib import pyplot as plt
R=5000
C=1e-6
w0=1/(R*C)
Tp=1/(100*w0)
T0=100*Tp
f0=10
def H(x):
return np.sqrt(1/((1+(R*C*2*np.pi*x)**2)))
def Gdb(x):
return 20*np.log(H(x))
f=np.logspace(1,3,num=1000)
for i in range(len(f)):
f[i]=np.int(f[i])
frequences=np.zeros(len(f))
def horizon(x):
return (x/x)*-3
for i in range(len(f)):
if i%2==1 and f[i]>=f0:
frequences[i]=1/i
fig,ax=plt.subplots()
ax2=ax.twinx()
ax2.vlines(f0,0,1,color='green',linewidth=2,label="Spectre du signal (f0="+str(f0)+"Hz)")
for n in range(2,np.int(f[len(f)-1]/f0)):
if n%2==1:
ax2.vlines(n*f0,0,(1/n),color='green',linewidth=2)
ax.semilogx(f,Gdb(f),label="Bode du filtre, f0="+str(round(w0/(2*np.pi),1))+"Hz")
ax.semilogx(f,horizon(f),color='r')
ax.set_ylabel("Gdb (dB)")
ax2.set_ylabel("Amplitude normalisée")
ax.set_xlabel("Frquence (Hz)")
fig.legend(fontsize=12,loc='lower left')
#plt.semilogx(f,horizon(f))
DSF du signal créneau :
#-----------------------------------------------------------------------
# Analyse spectrale d'un signal quelconque
#
# Utiliser la barre inférieure pour sélectionner le nombre d'harmoniques
#-----------------------------------------------------------------------
# Renseignements/bugs : Guillaume Dewaele <agreg(at)sci-phy.org>
#-----------------------------------------------------------------------
# Paramètres modifiables
# Nombre d'harmoniques considérées
max_harm = 40
# Bibliothèque de fonctions
@np.vectorize
def triangle(t) :
return -0.25+t if t<0.5 else 0.75-t
@np.vectorize
def scie(t) :
return -0.25+t if t<0.75 else t-1.25
@np.vectorize
def creneau(t) :
return -0.5 + (1.0 if 0.1<=t<0.6 else 0.0)
@np.vectorize
def bruitblanc(t) :
np.random.seed(int(t*1000000))
return np.random.random()-0.5
# Choix de la fonction
foo = creneau
#-----------------------------------------------------------------------
# Bibliothèques utilisées
import numpy as np
import numpy.fft as fft
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as ani
import matplotlib.widgets as mwg
#-----------------------------------------------------------------------
# Détection utilisation hors Pyzo
if '__iep__' not in globals() :
matplotlib.interactive(False)
# Calcul du spectre
N = 8192
T = np.linspace(0.0, 1.0, N)
Y = foo(T)
Yp = fft.fft(Y)
# Tracés
Tr = np.linspace(0.0, 2.0, 2*N)
Ampl = 20*np.log10(np.abs(Yp[:max_harm]))
# Signal
axTmp = plt.axes([0.11, 0.6, 0.78, 0.32])
axTmp.plot(Tr, np.concatenate([Y, Y]), "k--")
partial, = axTmp.plot(Tr, np.concatenate([Y, Y]), "b")
axTmp.set_xlim([0, 2])
axTmp.set_ylim([ min(Y) - (max(Y)-min(Y))*0.3, max(Y) + (max(Y)-min(Y))*0.3 ])
axTmp.set_title("signal")
axTmp.set_ylabel("amplitude")
axTmp.set_xlabel("temps (t/T0)")
# Spectre
axTmp = plt.axes([0.11, 0.15, 0.78, 0.32])
axTmp.bar(np.arange(max_harm)-0.5, Ampl, color="white")
rects = axTmp.bar(np.arange(max_harm)-0.5, Ampl, color="blue")
axTmp.set_xlim([0, max_harm])
axTmp.set_ylim([0, np.max(Ampl)*1.1])
axTmp.set_title("spectre")
axTmp.set_ylabel("amplitude (dB)")
axTmp.set_xlabel("fréquences (f/f0)")
# Slider
axTmp = plt.axes([0.11, 0.035, 0.78, 0.035])
slider = mwg.Slider(axTmp, '', valmin=0, valmax=max_harm, valinit=max_harm)
def Update(i) :
PartialY = np.real(fft.ifft(Yp * np.fromfunction(lambda j : j<=i, (len(Yp),))))
partial.set_data(Tr, 2*np.concatenate([PartialY, PartialY]))
for j, rect in enumerate(rects) :
rect.set_height(0 if j>i else Ampl[j])
slider.on_changed(Update)
Update(max_harm)
# Détection utilisation hors Pyzo
if '__iep__' not in globals() :
plt.show()