Asservissement position avec correcteur PI

a marqué ce sujet comme résolu.
Auteur du sujet

Bonjour à tous,

Je suis nouveau sur ce forum et je le trouve super intéressant. Du coup, j’ai souhaité partager le problème que je rencontre actuellement sur un asservissement de position de moteur à courant continu. Je vais essayer d’être le plus précis possible dans mes explications.

Description de mon application : j’effectue un asservissement numérique avec un Atmega328 à l’aide d’Arduino. Ce microcontrôleur vient commander un moteur CC à travers un pont en H. En particulier, la commande est générée par la PWM du microcontrôleur, et est ensuite dirigée vers des portes logiques qui délivrent eux-même le signal PWM et son complément au pont en H. Le moteur est équipé d’une roue codeuse à effet Hall pour capter la rotation de son axe rotor. Ce capteur fourni des fronts, provoqué par un changement d’angle, que je viens compter avec le µC (l’angle parcouru entre 2 tick est de 30°). Ref. moteur : https://www.pololu.com/product/3215

Les couples résistants élevés induits par la charge mécanique m’empêche d’utiliser un servomoteur. Le moteur possède donc un réducteur 1:20.4 pour palier à ce problème. L’axe de sorti parcourt dans l’application, au maximum 3 tours.

Pour les besoins de mon application, le axe moteur doit atteindre la consigne sans erreur statique (c’est primordial). J’ai donc souhaité implanter un correcteur PI.

Dans un premier temps, j’ai commencé par un asservissement avec correction proportionnelle seulement dont voici le code :

void Asservissement(float ConsignePositionRotor) // fonction d'asservissement effectuée toutes les 79ms
{ 
  // Chaine directe 
  ErreurCourante = ConsignePositionRotor - PositionCouranteRotor ; // Calcul de l'erreur

  RapportCyclique =  Kp * ErreurCourante + 127 ; // Correcteur PI
                                                                    
  if (  RapportCyclique > 255 ){// Saturation dans un sens de rotation
    RapportCyclique = 255;
  }
  if (  RapportCyclique < 0 ){// Saturation dans l'autre de rotation
    RapportCyclique = 0;
  }

  OCR2A = RapportCyclique ; // Registre de la valeur de rapport cyclique de la PWM de l'Atmega328

  // Chaine de retour  
  if (ErreurCourante > 0){
    PositionCouranteRotor = PositionCouranteRotor + TCNT1 ;
    TCNT1 = 0 ;
  }
  if (ErreurCourante < 0){
    PositionCouranteRotor = PositionCouranteRotor - TCNT1 ;
    TCNT1 = 0 ;
  }
}

Cette fonction est effectuée toutes les 26.3ms. TCNT1 est le registre du compteur 1 de l’atmega qui compte les 'ticks’ de ma roue codeuse. Toutes les variables sont réinitialisées à chaque fin d’asservissement. Enfin, la constante 127 est ajouté à la variable RapportCyclique pour utiliser les deux sens de rotations(de 0 à 127, on tourne dans un sens et de 127 à 255, on tourne dans l’autre).

J’ai ensuite testé plusieurs consignes d’angles pour 3 valeurs gain Kp (0.25, 0.5 et 0.75) afin de tester cette asservissement tout neuf.

Pour Kp = 0.25 : L’amortissement du système est faible, ce qui est a priori normal. Mais l’erreur statique est quant à elle constante quelque soit la consigne. D’après mes souvenirs des cours d’automatiques, l’erreur statique doit être proportionnelle à la valeur de la consigne. => Donc là… pas bon.

Pour Kp = 0.5 : Il y a un faible dépassement et quelques oscillations, mais l’erreur statique remontée par le µC est quasiment nulle, alors que le rotor a parcouru en réalité, un angle bien plus important que la consigne demandée… => Donc là, pas bon non plus.

Pour Kp = 0.75 : Même constat que pour Kp = 0.5 hormis une légère amplification des oscillations (erreur statique remontée par le µC toujours nulle alors que l’angle parcouru en réalité, est beaucoup, beaucoup plus important que la consigne demandée). => Pas bon non plus…

Voilà mon soucis… J’ai l’impression qu’il y a un truc qui m’échappe… peut-être que j’emploie une mauvaise méthode ?

En vous remerciant par avance pour toutes vos réponses. Bonne soirée !

PS : j’ai des photos de mes courbes mais je n’arrive pas à les intégrer dans le message…

Édité par clem34

+0 -0

Salut,

Sans les images, c’est plus difficile de t’aider. Normalement, il suffit de les copier-coller dans la zone d’édition depuis le presse-papiers ou d’y glisser-déposer le fichier.

+0 -0
Auteur du sujet

Merci pour ton aide Aabu. Voici les images.

Les courbes ont été tracé à l’aide du traceur de l’environnement Arduino (qui ne présente visiblement pas les échelles… :o)

Légende et axe :
En bleu => Angle parcouru par le rotor
En rouge => Erreur entre consigne et angle parcouru
En orange => Rapport cyclique
En vert => Consigne
X => n-ième asservissement

Pour Kp = 0.25

graphe_2.png
graphe_2.png

L’amortissement du système est faible, ce qui est a priori normal. Mais l’erreur statique est quant à elle constante quelque soit la consigne. D’après mes souvenirs des cours d’automatiques, l’erreur statique doit être proportionnelle à la valeur de la consigne. => Donc là… pas bon.

Pour Kp = 0.5

graphe_3.png
graphe_3.png

Il y a un faible dépassement et quelques oscillations, mais l’erreur statique remontée par le µC est quasiment nulle, alors que le rotor a parcouru en réalité, un angle bien plus important que la consigne demandée… => Donc là, pas bon non plus.

Pour Kp = 0.75

graphe_4.png
graphe_4.png

Même constat que pour Kp = 0.5 hormis une légère amplification des oscillations (erreur statique remontée par le µC toujours nulle alors que l’angle parcouru en réalité, est beaucoup, beaucoup plus important que la consigne demandée). => Pas bon non plus…

Édité par clem34

+0 -0

Allô,

Même le système tel que décrit n’est pas totalement linéaire, le théorie s’applique a peu près. Si je comprend bien les courbes, la variable controlée, l’angle, vert, suit approximativement la consigne, vert avec +- une erreur parfaitement normale dans un asservissement proportionnel seulement, ce qui me semble le cas si jai bien compris le script Arduino. S’il est désire une erreur plus faible il faut introduire une composante intégrale a l algorithme. Contrôle PI plutôt que P seulement. Cette fonction devra ajouter (sommer) à la variable controlée une valeur égale a I= SUM(Ki * erreur) ou SUM est l’intégration (sommation a chaque n tours de boucle). Ceci si les constantes sont ajustées correctement va réduire l’erreur a zéro sans oscillation du système en régime permanent.

Je me permet de mentionner cet article qui aborde le même type de sujet et vaut d’être consulté:
https://zestedesavoir.com/forums/sujet/11649/arduino-asservissement-grace-au-pid/

Édité par dubser

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte