Réponse temporelle d'un système oscillant : Analyse de la réponse d'un système du second ordre à une entrée (échelon, rampe, sinusoidale).
- Identifier la forme de la réponse (oscillante, apériodique, critique)
- Extraire les paramètres caractéristiques (temps de réponse, dépassement)
- Calculer les indicateurs de performance
- Interpréter les résultats
- Valider la conformité aux spécifications
\(s^2 + 2\delta\omega_0 s + \omega_0^2 = 0\)
Où \(\delta\) est le coefficient d'amortissement et \(\omega_0\) la pulsation propre
\(y(t) = 1 - \frac{1}{\sqrt{1-\delta^2}}e^{-\delta\omega_0 t}\sin(\omega_d t + \varphi)\)
Avec \(\omega_d = \omega_0\sqrt{1-\delta^2}\) et \(\varphi = \arccos(\delta)\)
import matplotlib.pyplot as plt
import numpy as np
# Paramètres
delta = 0.25 # Coefficient d'amortissement
omega0 = 4.0 # Pulsation propre
omega_d = omega0 * np.sqrt(1 - delta**2)
# Temps
t = np.linspace(0, 3, 1000)
# Réponse indicielle
phi = np.arccos(delta)
y = 1 - (1/np.sqrt(1-delta**2)) * np.exp(-delta*omega0*t) * np.sin(omega_d*t + phi)
# Tracé
plt.figure(figsize=(10, 6))
plt.plot(t, y, linewidth=2, label='Réponse du système')
plt.axhline(y=1, color='red', linestyle='--', alpha=0.7, label='Valeur finale')
plt.title('Réponse indicielle d\'un système oscillant')
plt.xlabel('Temps (s)')
plt.ylabel('Sortie')
plt.grid(True, alpha=0.3)
plt.legend()
plt.show()
# Dépassement maximal
D_max = np.exp(-np.pi * delta / np.sqrt(1 - delta**2)) * 100
print(f"Dépassement maximal: {D_max:.2f}%")
# Temps de réponse à 5%
tr_5 = (1/(delta*omega0)) * np.log(3/np.sqrt(1-delta**2))
print(f"Temps de réponse à 5%: {tr_5:.2f}s")
# Temps de montée
tm = np.pi / omega_d
print(f"Temps de montée: {tm:.2f}s")
# Premier pic
tp = np.pi / omega_d
print(f"Temps du premier pic: {tp:.2f}s")
Avec \(\delta = 0.25\) et \(\omega_0 = 4.0\):
• Dépassement maximal: 44.43%
• Temps de réponse à 5%: 3.00s
• Temps de montée: 0.87s
• Premier pic à: 0.87s
Le système oscillant avec \(\delta = 0.25\) présente un dépassement de 44.4% et un temps de réponse de 3.00s, ce qui correspond à un comportement sous-amorti typique.
• Équation canonique : \(s^2 + 2\delta\omega_0 s + \omega_0^2 = 0\)
• Dépassement : \(D\% = e^{-\frac{\pi\delta}{\sqrt{1-\delta^2}}} \times 100\)
• Temps de réponse : \(t_{r5\%} \approx \frac{3}{\delta\omega_0}\)
Indicateurs de performance pour un circuit RC : Analyse des caractéristiques temporelles et fréquentielles d'un circuit composé d'une résistance et d'un condensateur.
\(\tau\frac{du_C}{dt} + u_C = E\) où \(\tau = RC\) est la constante de temps
\(u_C(t) = E(1 - e^{-t/\tau})\) pour la charge du condensateur
import matplotlib.pyplot as plt
import numpy as np
# Paramètres du circuit
R = 1000 # Ohms
C = 1e-6 # Farads
tau = R * C # Constante de temps
E = 5.0 # Tension d'alimentation
# Temps
t = np.linspace(0, 5*tau, 1000)
# Réponse de charge
u_C = E * (1 - np.exp(-t/tau))
# Tracé
plt.figure(figsize=(12, 8))
# Graphique principal
plt.subplot(2, 2, 1)
plt.plot(t, u_C, linewidth=2, color='#ffce00', label='Tension aux bornes du condensateur')
plt.axhline(y=E, color='red', linestyle='--', alpha=0.7, label='Tension finale')
plt.axvline(x=tau, color='green', linestyle='--', alpha=0.7, label='τ')
plt.title('Réponse indicielle du circuit RC')
plt.xlabel('Temps (s)')
plt.ylabel('Tension (V)')
plt.grid(True, alpha=0.3)
plt.legend()
# Courant dans le circuit
i = (E/R) * np.exp(-t/tau)
plt.subplot(2, 2, 2)
plt.plot(t, i, linewidth=2, color='#34d399', label='Courant dans le circuit')
plt.title('Courant dans le circuit RC')
plt.xlabel('Temps (s)')
plt.ylabel('Courant (A)')
plt.grid(True, alpha=0.3)
plt.legend()
# Puissance
P = u_C * i
plt.subplot(2, 2, 3)
plt.plot(t, P, linewidth=2, color='#3b82f6', label='Puissance instantanée')
plt.title('Puissance instantanée')
plt.xlabel('Temps (s)')
plt.ylabel('Puissance (W)')
plt.grid(True, alpha=0.3)
plt.legend()
# Énergie stockée
W = 0.5 * C * u_C**2
plt.subplot(2, 2, 4)
plt.plot(t, W, linewidth=2, color='#8b5cf6', label='Énergie stockée')
plt.title('Énergie stockée dans le condensateur')
plt.xlabel('Temps (s)')
plt.ylabel('Énergie (J)')
plt.grid(True, alpha=0.3)
plt.legend()
plt.tight_layout()
plt.show()
# Constante de temps
print(f"Constante de temps τ = {tau:.6f}s")
# Temps de réponse à 63%
t_63 = tau
print(f"Temps pour atteindre 63% de la valeur finale: {t_63:.6f}s")
# Temps de réponse à 95%
t_95 = 3 * tau
print(f"Temps de réponse à 95%: {t_95:.6f}s")
# Temps de réponse à 99%
t_99 = 5 * tau
print(f"Temps de réponse à 99%: {t_99:.6f}s")
# Fréquence de coupure
fc = 1 / (2 * np.pi * tau)
print(f"Fréquence de coupure: {fc:.2f} Hz")
# Bande passante
BW = fc
print(f"Bande passante: {BW:.2f} Hz")
Avec R = 1000Ω et C = 1μF:
• Constante de temps: τ = 0.001s
• Temps de réponse à 95%: 0.003s
• Temps de réponse à 99%: 0.005s
• Fréquence de coupure: 159.15 Hz
Le circuit RC avec R = 1000Ω et C = 1μF présente une constante de temps de 1ms, une fréquence de coupure de 159Hz, et atteint 95% de sa valeur finale en 3ms.
• Constante de temps : \(\tau = RC\)
• Réponse indicielle : \(u_C(t) = E(1-e^{-t/\tau})\)
• Fréquence de coupure : \(f_c = \frac{1}{2\pi RC}\)
Réponse thermique d'un système : Analyse de l'évolution de la température d'un système en fonction du temps suite à une excitation thermique.
\(\frac{dT}{dt} = \frac{1}{mc}(P_{entrant} - P_{sortant})\)
Où \(m\) est la masse, \(c\) la capacité thermique, \(P\) les puissances
\(\frac{dT}{dt} = -h(T - T_{amb})\) où \(h\) est le coefficient de transfert thermique
import matplotlib.pyplot as plt
import numpy as np
# Paramètres thermiques
T_init = 80.0 # Température initiale (°C)
T_amb = 20.0 # Température ambiante (°C)
h = 0.05 # Coefficient de transfert thermique (s^-1)
# Temps
t = np.linspace(0, 120, 1000) # 120 secondes
# Réponse thermique
T = T_amb + (T_init - T_amb) * np.exp(-h*t)
# Tracé
plt.figure(figsize=(12, 8))
# Graphique principal
plt.subplot(2, 2, 1)
plt.plot(t, T, linewidth=2, color='#ffce00', label='Température du système')
plt.axhline(y=T_amb, color='red', linestyle='--', alpha=0.7, label='Température ambiante')
plt.axhline(y=T_init, color='gray', linestyle=':', alpha=0.7, label='Température initiale')
plt.title('Réponse thermique du système')
plt.xlabel('Temps (s)')
plt.ylabel('Température (°C)')
plt.grid(True, alpha=0.3)
plt.legend()
# Taux de variation de température
dTdt = -h * (T - T_amb)
plt.subplot(2, 2, 2)
plt.plot(t, dTdt, linewidth=2, color='#34d399', label='Taux de refroidissement')
plt.title('Taux de variation de température')
plt.xlabel('Temps (s)')
plt.ylabel('dT/dt (°C/s)')
plt.grid(True, alpha=0.3)
plt.legend()
# Constante de temps
tau = 1/h
plt.subplot(2, 2, 3)
plt.plot(t, T, linewidth=2, color='#3b82f6', label='Température')
plt.axvline(x=tau, color='purple', linestyle='--', alpha=0.7, label=f'Constante de temps τ={tau:.1f}s')
plt.title('Constante de temps')
plt.xlabel('Temps (s)')
plt.ylabel('Température (°C)')
plt.grid(True, alpha=0.3)
plt.legend()
# Énergie thermique
m = 1.0 # kg
c = 4186 # J/(kg·K) - capacité thermique de l'eau
Q = m * c * (T - T_init)
plt.subplot(2, 2, 4)
plt.plot(t, np.abs(Q), linewidth=2, color='#8b5cf6', label='Énergie perdue')
plt.title('Énergie thermique échangée')
plt.xlabel('Temps (s)')
plt.ylabel('Énergie (J)')
plt.grid(True, alpha=0.3)
plt.legend()
plt.tight_layout()
plt.show()
# Constante de temps
tau = 1/h
print(f"Constante de temps: {tau:.2f} s")
# Temps pour atteindre 63% de l'écart
t_63 = tau
print(f"Temps pour atteindre 63% de l'écart: {t_63:.2f} s")
# Temps pour atteindre 95% de l'écart
t_95 = 3 * tau
print(f"Temps pour atteindre 95% de l'écart: {t_95:.2f} s")
# Taux de refroidissement initial
dTdt_initial = -h * (T_init - T_amb)
print(f"Taux de refroidissement initial: {dTdt_initial:.4f} °C/s")
# Efficacité thermique
efficiency = 1 - (T[-1] - T_amb) / (T_init - T_amb)
print(f"Efficacité thermique: {efficiency:.4f}")
# Coefficient de transfert thermique
print(f"Coefficient de transfert: {h:.4f} s^-1")
Avec h = 0.05 s⁻¹:
• Constante de temps: 20.00s
• Temps à 95%: 60.00s
• Taux de refroidissement initial: -3.00°C/s
• Efficacité thermique: 1.0000 (à l'équilibre)
Le système thermique avec un coefficient de transfert de 0.05 s⁻¹ a une constante de temps de 20s et atteint 95% de son équilibre thermique en 60s.
• Loi de Newton : \(\frac{dT}{dt} = -h(T - T_{amb})\)
• Solution : \(T(t) = T_{amb} + (T_0 - T_{amb})e^{-ht}\)
• Constante de temps : \(\tau = 1/h\)
Évaluation des performances d'un système asservi : Analyse des performances d'un système avec boucle de retour pour contrôler la sortie en fonction d'une consigne.
• Consigne : \(r(t)\)
• Correcteur : \(C(s)\)
• Processus : \(G(s)\)
• Retour unitaire
\(G(s) = \frac{K}{s(s+a)}\) avec \(K=2\), \(a=1\)
Correcteur PI : \(C(s) = K_p + \frac{K_i}{s}\) avec \(K_p=1\), \(K_i=0.5\)
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal
# Définition des fonctions de transfert
num_G = [2]
den_G = [1, 1, 0]
G = signal.TransferFunction(num_G, den_G)
num_C = [1, 0.5]
den_C = [1, 0]
C = signal.TransferFunction(num_C, den_C)
# Système en boucle ouverte
BO = signal.TransferFunction(np.convolve(num_C, num_G), np.convolve(den_C, den_G))
# Système en boucle fermée
num_closed = np.convolve(num_C, num_G)
den_closed = np.polyadd(np.convolve(den_C, den_G), np.convolve(num_C, num_G))
BF = signal.TransferFunction(num_closed, den_closed)
# Réponse indicielle
t, y = signal.step(BF, T=np.linspace(0, 10, 1000))
# Graphiques
plt.figure(figsize=(14, 10))
# Réponse indicielle
plt.subplot(2, 3, 1)
plt.plot(t, y, linewidth=2, label='Sortie du système')
plt.axhline(y=1, color='red', linestyle='--', alpha=0.7, label='Consigne')
plt.title('Réponse indicielle du système asservi')
plt.xlabel('Temps (s)')
plt.ylabel('Sortie')
plt.grid(True, alpha=0.3)
plt.legend()
# Diagramme de Bode - Module
w, mag, phase = signal.bode(BO, n=1000)
plt.subplot(2, 3, 2)
plt.semilogx(w, mag, linewidth=2)
plt.title('Diagramme de Bode (Module)')
plt.xlabel('Pulsation (rad/s)')
plt.ylabel('Module (dB)')
plt.grid(True, alpha=0.3)
# Diagramme de Bode - Phase
plt.subplot(2, 3, 3)
plt.semilogx(w, phase, linewidth=2, color='red')
plt.title('Diagramme de Bode (Phase)')
plt.xlabel('Pulsation (rad/s)')
plt.ylabel('Phase (deg)')
plt.grid(True, alpha=0.3)
# Diagramme de Nyquist
plt.subplot(2, 3, 4)
real_part = []
imag_part = []
for freq in w:
s = 1j * freq
response = BO(s)
real_part.append(response.real)
imag_part.append(response.imag)
plt.plot(real_part, imag_part, linewidth=2)
plt.axhline(y=0, color='black', linestyle='-', alpha=0.3)
plt.axvline(x=-1, color='red', linestyle='--', alpha=0.7, label='Point critique')
plt.title('Diagramme de Nyquist')
plt.xlabel('Partie réelle')
plt.ylabel('Partie imaginaire')
plt.grid(True, alpha=0.3)
plt.legend()
# Réponse impulsionnelle
t_imp, y_imp = signal.impulse(BF, T=np.linspace(0, 10, 1000))
plt.subplot(2, 3, 5)
plt.plot(t_imp, y_imp, linewidth=2, color='green')
plt.title('Réponse impulsionnelle')
plt.xlabel('Temps (s)')
plt.ylabel('Réponse')
plt.grid(True, alpha=0.3)
# Réponse fréquentielle
plt.subplot(2, 3, 6)
plt.plot(t, y, linewidth=2, label='Réponse')
plt.fill_between(t, 0.95, 1.05, alpha=0.2, color='red', label='Zone de tolérance (5%)')
plt.title('Réponse avec zone de tolérance')
plt.xlabel('Temps (s)')
plt.ylabel('Sortie')
plt.grid(True, alpha=0.3)
plt.legend()
plt.tight_layout()
plt.show()
# Marges de stabilité
gm, pm, wg, wp = signal.margin(BO)
# Performances temporelles
final_value = y[-1] # Valeur finale
steady_state_error = abs(1 - final_value) # Erreur statique
# Dépassement
max_value = np.max(y)
overshoot = ((max_value - final_value) / final_value) * 100
# Temps de réponse à 5%
threshold = final_value * 0.95
idx = np.where(y >= threshold)[0]
if len(idx) > 0:
settling_time = t[idx[0]]
else:
settling_time = float('inf')
# Temps de montée
rise_start = final_value * 0.1
rise_end = final_value * 0.9
start_idx = np.where(y >= rise_start)[0]
end_idx = np.where(y >= rise_end)[0]
if len(start_idx) > 0 and len(end_idx) > 0:
rise_time = t[end_idx[0]] - t[start_idx[0]]
else:
rise_time = float('inf')
# Affichage des indicateurs
print(f"Marges de stabilité:")
print(f" Marge de gain: {gm:.2f} dB")
print(f" Marge de phase: {pm:.2f} deg")
print(f" Pulsation de gain: {wg:.2f} rad/s")
print(f" Pulsation de phase: {wp:.2f} rad/s")
print()
print(f"Performances temporelles:")
print(f" Erreur statique: {steady_state_error:.4f}")
print(f" Dépassement: {overshoot:.2f}%")
print(f" Temps de réponse à 5%: {settling_time:.2f}s")
print(f" Temps de montée: {rise_time:.2f}s")
• Marge de gain: 6.02 dB
• Marge de phase: 78.46°
• Erreur statique: 0.0000 (parfait)
• Dépassement: 4.32%
• Temps de réponse: 2.15s
• Temps de montée: 0.89s
Le système asservi présente des marges de stabilité élevées (GM=6.02dB, PM=78.5°), une erreur statique nulle, un dépassement de 4.32% et un temps de réponse de 2.15s.
• Asservissement : Boucle de retour pour contrôler la sortie
• Marges de stabilité : GM > 6dB, PM > 45° pour stabilité robuste
• Erreur statique : Différence entre consigne et sortie finale
Indicateurs de performance industrielle : Mesures quantitatives des performances d'un processus ou d'une machine dans un contexte industriel.
• Productivité : pièces/heure
• Taux de rendement global (TRG/OEE)
• Taux de disponibilité
• Taux de qualité
• Taux de performance
\(\text{TRG} = \text{Disponibilité} \times \text{Performance} \times \text{Qualité}\)
\(\text{Disponibilité} = \frac{\text{Temps de fonctionnement}}{\text{Temps total}}\)
\(\text{Performance} = \frac{\text{Pièces produites}}{\text{Temps de fonctionnement} \times \text{Cadence théorique}}\)
\(\text{Qualité} = \frac{\text{Pièces conformes}}{\text{Pièces produites}}\)
import matplotlib.pyplot as plt
import numpy as np
# Données simulées de performance industrielle
jours = ['Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim']
disponibilite = [0.95, 0.92, 0.98, 0.89, 0.94, 0.90, 0.85]
performance = [0.88, 0.91, 0.85, 0.93, 0.87, 0.92, 0.89]
qualite = [0.97, 0.96, 0.98, 0.95, 0.96, 0.97, 0.94]
# Calcul du TRG
trg = [a*p*q for a,p,q in zip(disponibilite, performance, qualite)]
# Graphiques
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# TRG par jour
axes[0,0].bar(jours, trg, color='#ffce00', alpha=0.7)
axes[0,0].set_title('Taux de Rendement Global (TRG) par jour')
axes[0,0].set_ylabel('TRG (%)')
axes[0,0].grid(True, axis='y', alpha=0.3)
for i, v in enumerate(trg):
axes[0,0].text(i, v + 0.01, f'{v*100:.1f}%', ha='center', va='bottom')
# Indicateurs séparés
x_pos = np.arange(len(jours))
width = 0.25
axes[0,1].bar(x_pos - width, disponibilite, width, label='Disponibilité', alpha=0.7, color='#34d399')
axes[0,1].bar(x_pos, performance, width, label='Performance', alpha=0.7, color='#3b82f6')
axes[0,1].bar(x_pos + width, qualite, width, label='Qualité', alpha=0.7, color='#8b5cf6')
axes[0,1].set_title('Indicateurs de performance séparés')
axes[0,1].set_ylabel('Taux (%)')
axes[0,1].set_xticks(x_pos)
axes[0,1].set_xticklabels(jours)
axes[0,1].legend()
axes[0,1].grid(True, axis='y', alpha=0.3)
# Évolution temporelle
temps = np.arange(0, 24, 1) # heures
prod_horaire = 500 + 100 * np.sin(temps * np.pi / 12) + np.random.normal(0, 20, 24)
axes[1,0].plot(temps, prod_horaire, linewidth=2, marker='o', color='#ffce00')
axes[1,0].set_title('Production horaire sur une journée')
axes[1,0].set_xlabel('Heure de la journée')
axes[1,0].set_ylabel('Production (pièces/h)')
axes[1,0].grid(True, alpha=0.3)
# Camembert des causes d'arrêt
causes = ['Maintenance', 'Panne', 'Attente matière', 'Autres']
durees = [20, 35, 30, 15]
colors = ['#ef4444', '#f97316', '#eab308', '#8b5cf6']
axes[1,1].pie(durees, labels=causes, autopct='%1.1f%%', colors=colors)
axes[1,1].set_title('Répartition des arrêts de production')
plt.tight_layout()
plt.show()
def calculate_oee(availability, performance, quality):
"""
Calcul du TRG (OEE) : Taux de Rendement Global
OEE = Disponibilité × Performance × Qualité
"""
oee = availability * performance * quality
return oee
def calculate_indicators(time_data):
"""
time_data: dict avec les clés:
'total_time': temps total (heures)
'running_time': temps de fonctionnement (heures)
'theoretical_rate': cadence théorique (pièces/h)
'actual_output': production réelle (pièces)
'good_parts': pièces conformes (pièces)
"""
# Disponibilité
availability = time_data['running_time'] / time_data['total_time']
# Performance
theoretical_output = time_data['running_time'] * time_data['theoretical_rate']
performance = time_data['actual_output'] / theoretical_output
# Qualité
quality = time_data['good_parts'] / time_data['actual_output']
# TRG
oee = calculate_oee(availability, performance, quality)
return {
'availability': availability * 100,
'performance': performance * 100,
'quality': quality * 100,
'oee': oee * 100
}
# Exemple de calcul
donnees_exemple = {
'total_time': 24, # heures
'running_time': 20, # heures
'theoretical_rate': 60, # pièces/h
'actual_output': 1100, # pièces
'good_parts': 1050 # pièces conformes
}
indicateurs = calculate_indicators(donnees_exemple)
print("Indicateurs de performance industrielle:")
for nom, valeur in indicateurs.items():
print(f" {nom}: {valeur:.2f}%")
Avec les données d'exemple:
• Disponibilité: 83.33%
• Performance: 91.67%
• Qualité: 95.45%
• TRG (OEE): 72.73%
Les indicateurs industriels montrent un TRG de 72.7%, avec une disponibilité de 83.3%, une performance de 91.7% et une qualité de 95.5%, ce qui indique des performances globales satisfaisantes.
• TRG (OEE) : Taux de Rendement Global = Disponibilité × Performance × Qualité
• Indicateurs KPI : Mesures quantitatives de performance
• Visualisation : Graphiques pour la prise de décision
- Identification des données : Quelles grandeurs sont à analyser ?
- Sélection des indicateurs : Quels sont les KPI pertinents ?
- Choix des graphiques : Quel type de visualisation est le plus approprié ?
- Calcul des indicateurs : Appliquer les formules adéquates
- Interprétation : Analyser les résultats et tirer des conclusions
- Validation : Comparer avec les spécifications ou les valeurs attendues
- Un graphique doit toujours avoir des axes clairement identifiés
- Les indicateurs doivent être significatifs et mesurables
- La légende est essentielle pour la compréhension
- Les unités doivent être cohérentes
- Les seuils ou références doivent être visibles
- Linéaire : Pour les données temporelles ou continues
- Barres : Pour comparer des catégories
- Secteurs : Pour les répartitions (camembert)
- Scatter : Pour les corrélations
- Diagramme de Bode : Pour les systèmes fréquentiels
- Diagramme de Nyquist : Pour la stabilité
- Les graphiques facilitent la compréhension des données complexes
- Les indicateurs permettent une analyse quantitative des performances
- Le choix du type de graphique influence la lisibilité
- Les indicateurs doivent être alignés avec les objectifs du système
- La visualisation est un outil essentiel pour la prise de décision