Outils pour utilisateurs

Outils du site


ssi_elec_regulation_asservissement

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
ssi_elec_regulation_asservissement [2025/11/29 14:15] mistert2ssi_elec_regulation_asservissement [2025/12/09 13:54] (Version actuelle) mistert2
Ligne 4: Ligne 4:
  
 {{https://mistert.freeboxos.fr/cours/_/_herbin/TSI-2022/régulation - asservissement/TSSI cours  asservissement.pdf}} {{https://mistert.freeboxos.fr/cours/_/_herbin/TSI-2022/régulation - asservissement/TSSI cours  asservissement.pdf}}
 +
 +==== MODELES MATLAB  A SAUVEGARDER ====
 +
 +{{https://mistert.freeboxos.fr/cours/_/_herbin/TSI-2022/régulation - asservissement/regulationPID_2022a.slx}}
 +
 +{{https://mistert.freeboxos.fr/cours/_/_herbin/TSI-2022/régulation - asservissement/filtreNumerique_2022a.slx}}
 +
  
 ---- ----
Ligne 33: Ligne 40:
 Manipulations : Manipulations :
  
-Envoyer une commande PWM fixe (ex : 50 %, puis 80 %) +  Choisir le mode boucle ouverte 
-* Observer la vitesse indiquée par le programme +  * Choisir une consigne en <mt>tr/min</mt> 
-* Bloquer légèrement l’axe du moteur avec le doigt+  * Observer la vitesse indiquée par le programme 
 +  * Bloquer légèrement l’axe du moteur avec le doigt
  
 Observations attendues : Observations attendues :
  
-* La vitesse chute immédiatement lorsque l’axe est freiné +  * La vitesse chute immédiatement lorsque l’axe est freiné 
-* Le moteur ne corrige pas cette chute : c’est normal en boucle ouverte +  * Le moteur ne corrige pas cette chute : c’est normal en boucle ouverte 
-* La vitesse dépend de la charge, des frottements et de la tension+  * La vitesse dépend de la charge, des frottements et de la tension
  
 Conclusion : Conclusion :
Ligne 52: Ligne 60:
 Manipulations : Manipulations :
  
-* Activer le correcteur proportionnel : <mt>u = K_p \cdot e</mt> +  * Activer le correcteur proportionnel : <mt>u = K_p \cdot e</mt> 
-* Fixer une consigne (ex : 1500 tr/min) +  * Fixer une consigne (ex : 1500 tr/min) 
-* Le programme convertit automatiquement en ticks/s +  * Le programme convertit automatiquement en ticks/s 
-* Freiner légèrement le moteur avec le doigt +  * Freiner légèrement le moteur avec le doigt 
-* Augmenter progressivement K_p : 0.2 → 0.5 → 1.0 → 2.0+  * Augmenter progressivement K_p : 0.2 → 0.5 → 1.0 → 2.0
  
 Observations attendues : Observations attendues :
  
-* Le moteur augmente la PWM pour compenser la perturbation +  * Le moteur augmente la PWM pour compenser la perturbation 
-* La vitesse remonte partiellement +  * La vitesse remonte partiellement  
-* Il reste un écart statique : <mt>\text{vitesse réelle} < \text{consigne}</mt> +  * Il reste un écart statique : <mt>\text{vitesse réelle} < \text{consigne}</mt> 
-* Si K_p devient trop grand : oscillations, vibrations, instabilité+  * Si K_p devient trop grand : oscillations, vibrations, instabilité
  
-Conclusion : +Conclusion : Le correcteur P réduit l’erreur, mais ne la supprime pas
-Le correcteur P réduit l’erreur, mais ne la supprime pas+
  
 ---- ----
Ligne 74: Ligne 81:
 Manipulations : Manipulations :
  
-* Ajouter le terme intégral : <mt>u = K_p e ;+K_I \int e(t)\,dt</mt> +  * Ajouter le terme intégral : <mt>u = K_p e + K_I \int e(t)\,dt</mt> 
-* Débuter avec K_I = 0.05, puis 0.1 max +  * Débuter avec <mt>K_I</mt> = 0.05, puis 0.1 max 
-* Freiner l’axe puis relâcher+  * Freiner l’axe puis relâcher
  
 Observations attendues : Observations attendues :
  
-* L’erreur statique disparaît +  * L’erreur statique disparaît 
-* La vitesse atteint précisément la consigne +  * La vitesse atteint précisément la consigne 
-* Si K_I trop fort : dépassement, oscillations lentes, instabilité+  * Si <mt>K_I</mt> trop fort : dépassement, oscillations lentes, instabilité
  
-Conclusion : +Conclusion : Le correcteur I supprime l’erreur statique, mais ne doit jamais être trop fort
-Le correcteur I supprime l’erreur statique, mais ne doit jamais être trop fort+
  
 ---- ----
Ligne 93: Ligne 99:
 Manipulations : Manipulations :
  
-* Ajouter le terme dérivé : <mt>u = K_p e ;+K_I \int e\,dt ;+K_D \frac{de}{dt}</mt> +  * Ajouter le terme dérivé : <mt>u = K_p e + K_I \int e\,dt + K_D \frac{de}{dt}</mt> 
-* Tester avec K_D = 0.01, puis 0.05 +  * Tester avec <mt>K_D</mt> = 0.01, puis 0.05 
-* Freiner l’axe pour observer la réaction+  * Freiner l’axe pour observer la réaction
  
 Observations attendues : Observations attendues :
  
-* Le système est mieux amorti +  * Le système est mieux amorti 
-* Le dépassement diminue +  * Le dépassement diminue 
-* La stabilité augmente+  * La stabilité augmente
  
-Attention : +Attention : Si <mt>K_D</mt> trop élevé → bruit, vibrations, instabilité
-Si K_D trop élevé → bruit, vibrations, instabilité+
  
-Conclusion : +Conclusion : Le terme D stabilise le système, mais n’améliore pas la précision
-Le terme D stabilise le système, mais n’améliore pas la précision+
  
 ---- ----
Ligne 122: Ligne 126:
 ==== Code Arduino du TP (consigne en tr/min, PID en ticks/s) ==== ==== Code Arduino du TP (consigne en tr/min, PID en ticks/s) ====
  
-<code> +<code C++
-/=== TP : PID régulation vitesse moteur CC === +/
-// Consigne entrée en tours/minute (tr/min) +   ====================================== 
-// Le programme convertit en ticks/s pour le PID +      TP REGULATION : MODE BO MODE PID 
-// Mesure du codeur sur interruption+   ======================================
  
-// --- Paramètres codeur --- +   MODE BO : 
-const int TICKS_PAR_TOUR = 20  // à adapter selon votre codeur+     - PWM = conversion(consigne_tr/min) 
 +     - codeur mesure mais NE corrige PAS 
 +     aucune régulation 
 + 
 +   MODE PID : 
 +     consigne tr/min convertie en ticks/s 
 +     codeur mesure vitesse 
 +     - PID corrige PWM 
 +*/ 
 + 
 +const int TICKS_PAR_TOUR = 90 // à ajuster selon le codeur
  
 // --- Pont en H --- // --- Pont en H ---
Ligne 135: Ligne 149:
 const int M_AR = 6;   // PWM reverse const int M_AR = 6;   // PWM reverse
  
-// --- Codeur incrémental --- +// --- Codeur --- 
-const int canalA = 2;   // interruption 0+const int canalA = 2;
 const int canalB = 11; const int canalB = 11;
  
-volatile long ticks = 0;  // compteur modifié par ISR+volatile long ticks = 0;
  
-// === PID === +// --- PID ---
-float consigne = 0;        // consigne en ticks/s+
 float kp = 0.8; float kp = 0.8;
 float ki = 0.1; float ki = 0.1;
Ligne 150: Ligne 163:
 float integral = 0; float integral = 0;
  
-// === Période mesure ===+float consigne_rpm = 0;      // consigne entrée par Serial (tr/min) 
 +float consigne_ticks_s 0;  // consigne convertie pour le PID 
 + 
 +// --- Modes --- 
 +enum Mode { BO, PID_MODE }; 
 +Mode mode BO; 
 + 
 +// --- Mesure ---
 unsigned long lastMeasure = 0; unsigned long lastMeasure = 0;
-const unsigned long period = 100;  // 100 ms+const unsigned long period = 100; // 100 ms 
 + 
 + 
 +// ============ INTERRUPTIONS CODEUR ============ 
 +void ISR_codeur() { 
 +  if (digitalRead(canalB)) 
 +    ticks++; 
 +  else 
 +    ticks--; 
 +
 + 
 + 
 +// ============ CONVERSION tr/min -> PWM (BO) ============ 
 +int rpmToPWM(float rpm) { 
 +  // Ajuste selon ton moteur 
 +  // Ex : 0–150 tr/min -> 0–255 PWM 
 +  if (rpm < 0) rpm = 0; 
 +  if (rpm > 150) rpm = 150; 
 + 
 +  return map(rpm, 0, 150, 0, 255); 
 +
  
-// === Conversion tr/min -> ticks/s === +// ============ CONVERSION tr/min -> ticks/(PID) ============ 
-float trMinToTicksSec(float rpm) {+float rpmToTicksSec(float rpm) {
   return (rpm * TICKS_PAR_TOUR) / 60.0;   return (rpm * TICKS_PAR_TOUR) / 60.0;
 } }
  
-// === Prototypes === + 
-void ISR_codeur(); +// ============ COMMANDE MOTEUR ============ 
-void commandeMoteur(float pwm); +void setPWM(int pwm) { 
-float lireConsigne();+  if (pwm >= 0) { 
 +    digitalWrite(M_AR, LOW); 
 +    analogWrite(M_AV, pwm); 
 +  } else { 
 +    digitalWrite(M_AV, LOW); 
 +    analogWrite(M_AR, -pwm); 
 +  } 
 +}
  
  
 +// =============================================
 +//                    SETUP
 +// =============================================
 void setup() { void setup() {
   Serial.begin(9600);   Serial.begin(9600);
Ligne 170: Ligne 221:
   pinMode(M_AV, OUTPUT);   pinMode(M_AV, OUTPUT);
   pinMode(M_AR, OUTPUT);   pinMode(M_AR, OUTPUT);
- 
   pinMode(canalB, INPUT);   pinMode(canalB, INPUT);
  
   attachInterrupt(digitalPinToInterrupt(canalA), ISR_codeur, RISING);   attachInterrupt(digitalPinToInterrupt(canalA), ISR_codeur, RISING);
  
-  Serial.println("=== TP : Regulation PID de vitesse ==="); +  Serial.println("=== TP REGULATION BO / PID ==="); 
-  Serial.println("Entrez une consigne en tr/min (ex : 1500):");+  Serial.println("Tapez BO ou PID pour changer de mode."); 
 +  Serial.println("Tapez une consigne en tr/min (ex : 150)");
 } }
  
  
-// ====================== LOOP ===========================+// ============================================= 
 +//                    LOOP 
 +// =============================================
 void loop() { void loop() {
  
-  // --- Lecture consigne en tr/min ---+  // ----------- Lecture mode consigne ------------
   if (Serial.available() > 0) {   if (Serial.available() > 0) {
-    float rpm lireConsigne(); +    String txt Serial.readStringUntil('\n'); 
-    consigne = trMinToTicksSec(rpm);+    txt.trim(); 
 + 
 +    if (txt.equalsIgnoreCase("BO")) { 
 +      mode = BO; 
 +      Serial.println("Mode = BOUCLE OUVERTE"); 
 +      return; 
 +    } 
 + 
 +    if (txt.equalsIgnoreCase("PID")) { 
 +      mode = PID_MODE; 
 +      Serial.println("Mode = PID"); 
 +      return; 
 +    } 
 + 
 +    // Sinon c'est une consigne tr/min 
 +    consigne_rpm = txt.toFloat(); 
 +    consigne_ticks_s rpmToTicksSec(consigne_rpm);
  
     Serial.print("Consigne = ");     Serial.print("Consigne = ");
-    Serial.print(rpm); +    Serial.print(consigne_rpm); 
-    Serial.print(" tr/min  ->  "); +    Serial.print(" tr/min  -> "); 
-    Serial.print(consigne);+    Serial.print(consigne_ticks_s);
     Serial.println(" ticks/s");     Serial.println(" ticks/s");
   }   }
  
-  // --- PID toutes les 100 ms ---+ 
 +  // ----------- Mesure toutes les 100 ms -----------
   unsigned long now = millis();   unsigned long now = millis();
-  if (now - lastMeasure >= period) { +  if (now - lastMeasure period) return; 
-    lastMeasure = now;+  lastMeasure = now;
  
-    long ticksMesures = ticks; +  long ticks_mes = ticks; 
-    ticks = 0;+  ticks = 0;
  
-    float vitesse ticksMesures * (1000.0 / period);  // ticks/s+  float vitesse_ticks_s ticks_mes * (1000.0 / period); 
 +  float vitesse_rpm = (vitesse_ticks_s * 60.0) TICKS_PAR_TOUR;
  
-    // === PID === + 
-    erreur = consigne vitesse;+  // ============================================ 
 +  //                 MODE BO 
 +  // ============================================ 
 +  if (mode == BO) { 
 + 
 +    int pwm = rpmToPWM(consigne_rpm);  // conversion directe consigne → PWM 
 +    setPWM(pwm); 
 + 
 +    Serial.print("[BO] consigne = "); 
 +    Serial.print(consigne_rpm); 
 +    Serial.print(" tr/min | vitesse = "); 
 +    Serial.print(vitesse_ticks_s); 
 +    Serial.print(" ticks/s | "); 
 +    Serial.print(vitesse_rpm); 
 +    Serial.print(" tr/min | PWM = "); 
 +    Serial.println(pwm); 
 + 
 +    return; 
 +  } 
 + 
 + 
 +  // ============================================ 
 +  //                 MODE PID 
 +  // ============================================ 
 +  if (mode == PID_MODE) { 
 + 
 +    erreur = consigne_ticks_s vitesse_ticks_s;
     integral += erreur * (period / 1000.0);     integral += erreur * (period / 1000.0);
     float deriv = (erreur - erreurPrec) / (period / 1000.0);     float deriv = (erreur - erreurPrec) / (period / 1000.0);
Ligne 213: Ligne 310:
     float commande = kp * erreur + ki * integral + kd * deriv;     float commande = kp * erreur + ki * integral + kd * deriv;
  
-    // Saturation+    // saturation
     if (commande > 255) commande = 255;     if (commande > 255) commande = 255;
     if (commande < -255) commande = -255;     if (commande < -255) commande = -255;
  
-    commandeMoteur(commande);+    setPWM(commande);
  
-    // Affichage +    Serial.print("[PID] consigne = "); 
-    Serial.print("Consigne ticks/= "); +    Serial.print(consigne_rpm); 
-    Serial.print(consigne); +    Serial.print(" tr/min | vitesse = "); 
-    Serial.print("Vitesse = "); +    Serial.print(vitesse_ticks_s); 
-    Serial.print(vitesse); +    Serial.print(" ticks/| "); 
-    Serial.print(" | PWM = ");+    Serial.print(vitesse_rpm); 
 +    Serial.print(" tr/min | PWM = ");
     Serial.println(commande);     Serial.println(commande);
-  } 
-} 
  
- +    return;
-// === INTERRUPTIONS CODEUR === +
-void ISR_codeur() { +
-  if (digitalRead(canalB)) +
-    ticks++; +
-  else +
-    ticks--; +
-+
- +
- +
-// === COMMANDE MOTEUR === +
-void commandeMoteur(float pwm) { +
-  if (pwm >= 0) { +
-    digitalWrite(M_AR, LOW); +
-    analogWrite(M_AV, pwm); +
-  } else { +
-    digitalWrite(M_AV, LOW); +
-    analogWrite(M_AR, -pwm);+
   }   }
 } }
  
- 
-// === LECTURE CONSIGNE === 
-float lireConsigne() { 
-  String txt = Serial.readStringUntil('\n'); 
-  txt.trim(); 
-  return txt.toFloat(); 
-} 
 </code> </code>
ssi_elec_regulation_asservissement.1764425721.txt.gz · Dernière modification : de mistert2