ssi_elec_regulation_asservissement
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| ssi_elec_regulation_asservissement [2025/11/29 14:20] – mistert2 | ssi_elec_regulation_asservissement [2025/12/09 13:54] (Version actuelle) – mistert2 | ||
|---|---|---|---|
| Ligne 4: | Ligne 4: | ||
| {{https:// | {{https:// | ||
| + | |||
| + | ==== MODELES MATLAB | ||
| + | |||
| + | {{https:// | ||
| + | |||
| + | {{https:// | ||
| + | |||
| ---- | ---- | ||
| Ligne 33: | Ligne 40: | ||
| Manipulations : | Manipulations : | ||
| - | * Choisir | + | * Choisir |
| - | < | + | |
| * Observer la vitesse indiquée par le programme | * Observer la vitesse indiquée par le programme | ||
| * Bloquer légèrement l’axe du moteur avec le doigt | * Bloquer légèrement l’axe du moteur avec le doigt | ||
| Ligne 74: | Ligne 81: | ||
| Manipulations : | Manipulations : | ||
| - | * Ajouter le terme intégral : <mt>u = K_p e ;+; K_I \int e(t)\, | + | * Ajouter le terme intégral : <mt>u = K_p e + K_I \int e(t)\, |
| - | * Débuter avec K_I = 0.05, puis 0.1 max | + | * Débuter avec <mt>K_I</ |
| * Freiner l’axe puis relâcher | * Freiner l’axe puis relâcher | ||
| Ligne 82: | Ligne 89: | ||
| * 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, | + | * Si <mt>K_I</ |
| Conclusion : Le correcteur I supprime l’erreur statique, mais ne doit jamais être trop fort | Conclusion : Le correcteur I supprime l’erreur statique, mais ne doit jamais être trop fort | ||
| Ligne 92: | Ligne 99: | ||
| Manipulations : | Manipulations : | ||
| - | * Ajouter le terme dérivé : <mt>u = K_p e ;+; K_I \int e\,dt ;+; K_D \frac{de}{dt}</ | + | * Ajouter le terme dérivé : <mt>u = K_p e + K_I \int e\,dt + K_D \frac{de}{dt}</ |
| - | * Tester avec K_D = 0.01, puis 0.05 | + | * Tester avec <mt>K_D</ |
| * Freiner l’axe pour observer la réaction | * Freiner l’axe pour observer la réaction | ||
| Ligne 102: | Ligne 109: | ||
| * La stabilité augmente | * La stabilité augmente | ||
| - | Attention : Si K_D trop élevé → bruit, vibrations, instabilité | + | Attention : Si <mt>K_D</ |
| Conclusion : Le terme D stabilise le système, mais n’améliore pas la précision | Conclusion : Le terme D stabilise le système, mais n’améliore pas la précision | ||
| Ligne 119: | 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) ==== | ||
| - | < | + | < |
| - | // === TP : PID régulation vitesse moteur CC === | + | /* |
| - | // Consigne entrée en tours/ | + | |
| - | // Le programme convertit en ticks/s pour le PID | + | TP REGULATION : MODE BO / MODE PID |
| - | // Mesure du codeur sur interruption | + | ====================================== |
| - | // --- Paramètres | + | MODE BO : |
| - | const int TICKS_PAR_TOUR = 20; | + | - PWM = conversion(consigne_tr/min) |
| + | - codeur | ||
| + | - 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 | ||
| // --- Pont en H --- | // --- Pont en H --- | ||
| Ligne 132: | Ligne 149: | ||
| const int M_AR = 6; // PWM reverse | const int M_AR = 6; // PWM reverse | ||
| - | // --- Codeur | + | // --- 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 147: | Ligne 163: | ||
| float integral = 0; | float integral = 0; | ||
| - | // === Période mesure === | + | float consigne_rpm = 0; |
| + | float consigne_ticks_s | ||
| + | |||
| + | // --- 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 |
| - | // === Conversion | + | |
| - | float trMinToTicksSec(float rpm) { | + | // ============ 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 | ||
| + | float rpmToTicksSec(float rpm) { | ||
| return (rpm * TICKS_PAR_TOUR) / 60.0; | return (rpm * TICKS_PAR_TOUR) / 60.0; | ||
| } | } | ||
| - | // === Prototypes === | ||
| - | void ISR_codeur(); | ||
| - | void commandeMoteur(float pwm); | ||
| - | float lireConsigne(); | ||
| + | // ============ COMMANDE MOTEUR ============ | ||
| + | void setPWM(int pwm) { | ||
| + | if (pwm >= 0) { | ||
| + | digitalWrite(M_AR, | ||
| + | analogWrite(M_AV, | ||
| + | } else { | ||
| + | digitalWrite(M_AV, | ||
| + | analogWrite(M_AR, | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // ============================================= | ||
| + | // SETUP | ||
| + | // ============================================= | ||
| void setup() { | void setup() { | ||
| Serial.begin(9600); | Serial.begin(9600); | ||
| Ligne 167: | Ligne 221: | ||
| pinMode(M_AV, | pinMode(M_AV, | ||
| pinMode(M_AR, | pinMode(M_AR, | ||
| - | |||
| pinMode(canalB, | pinMode(canalB, | ||
| attachInterrupt(digitalPinToInterrupt(canalA), | attachInterrupt(digitalPinToInterrupt(canalA), | ||
| - | Serial.println(" | + | Serial.println(" |
| - | Serial.println(" | + | Serial.println(" |
| + | Serial.println(" | ||
| } | } | ||
| - | // ====================== LOOP =========================== | + | // ============================================= |
| + | // | ||
| + | // ============================================= | ||
| void loop() { | void loop() { | ||
| - | // --- Lecture | + | // ----------- Lecture |
| if (Serial.available() > 0) { | if (Serial.available() > 0) { | ||
| - | | + | |
| - | consigne = trMinToTicksSec(rpm); | + | |
| + | |||
| + | if (txt.equalsIgnoreCase(" | ||
| + | mode = BO; | ||
| + | Serial.println(" | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | if (txt.equalsIgnoreCase(" | ||
| + | mode = PID_MODE; | ||
| + | Serial.println(" | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | // Sinon c'est une consigne | ||
| + | consigne_rpm = txt.toFloat(); | ||
| + | consigne_ticks_s | ||
| Serial.print(" | Serial.print(" | ||
| - | Serial.print(rpm); | + | Serial.print(consigne_rpm); |
| - | Serial.print(" | + | Serial.print(" |
| - | Serial.print(consigne); | + | Serial.print(consigne_ticks_s); |
| Serial.println(" | Serial.println(" | ||
| } | } | ||
| - | | + | |
| + | | ||
| unsigned long now = millis(); | unsigned long now = millis(); | ||
| - | if (now - lastMeasure | + | if (now - lastMeasure |
| - | | + | lastMeasure = now; |
| + | |||
| + | long ticks_mes = ticks; | ||
| + | ticks = 0; | ||
| + | |||
| + | float vitesse_ticks_s | ||
| + | float vitesse_rpm = (vitesse_ticks_s * 60.0) / TICKS_PAR_TOUR; | ||
| + | |||
| + | |||
| + | // ============================================ | ||
| + | // MODE BO | ||
| + | // ============================================ | ||
| + | if (mode == BO) { | ||
| + | |||
| + | | ||
| + | setPWM(pwm); | ||
| + | |||
| + | Serial.print(" | ||
| + | Serial.print(consigne_rpm); | ||
| + | Serial.print(" | ||
| + | Serial.print(vitesse_ticks_s); | ||
| + | Serial.print(" | ||
| + | Serial.print(vitesse_rpm); | ||
| + | Serial.print(" | ||
| + | Serial.println(pwm); | ||
| + | |||
| + | return; | ||
| + | } | ||
| - | long ticksMesures = ticks; | ||
| - | ticks = 0; | ||
| - | float vitesse = ticksMesures * (1000.0 | + | |
| + | // | ||
| + | | ||
| + | if (mode == PID_MODE) { | ||
| - | | + | erreur = consigne_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 210: | 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; | ||
| - | | + | |
| - | | + | |
| - | Serial.print(" | + | Serial.print(consigne_rpm); |
| - | Serial.print(consigne); | + | Serial.print(" |
| - | Serial.print(" | + | Serial.print(vitesse_ticks_s); |
| - | Serial.print(vitesse); | + | Serial.print(" |
| - | Serial.print(" | + | Serial.print(vitesse_rpm); |
| + | Serial.print(" | ||
| 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, | + | |
| - | analogWrite(M_AV, | + | |
| - | } else { | + | |
| - | digitalWrite(M_AV, | + | |
| - | analogWrite(M_AR, | + | |
| } | } | ||
| } | } | ||
| - | |||
| - | // === LECTURE CONSIGNE === | ||
| - | float lireConsigne() { | ||
| - | String txt = Serial.readStringUntil(' | ||
| - | txt.trim(); | ||
| - | return txt.toFloat(); | ||
| - | } | ||
| </ | </ | ||
ssi_elec_regulation_asservissement.1764426044.txt.gz · Dernière modification : de mistert2
