[ARDUINO] Asservissement grâce au PID

Le problème exposé dans ce sujet a été résolu.

Pour moi, il est anormal que si les 2 moteurs ont des poussées différentes, le drone reste stabilisé à 180° mais je ne sais pas pourquoi cela le fait… Une idée @Aabu ?

Merci pour ces conseils ! Je vais regarder…

+0 -0

Après je peux me tromper … @Aabu. Cependant, je pense que physiquement, il est dur de maintenir un système à une même position alors que les 2 moteurs ont des poussées qui ne se compensent pas…, ce qui me parait bizarre c’est que pourtant sur Matlab, avec 2 poussées ne se compensant pas, "l’angle" reste à 180°…

EDIT : Je crois avoir compris ce que tu voulais dire avec le bloc intégrateur et la condition initiale mais la commande et l’angle tendent vers l’infini donc la simulation se termine avec une erreur…

+0 -0

Après je peux me tromper …

Parfois, il faut savoir prendre un peu conscience en soi. ;)

Cependant, je pense que physiquement, il est dur de maintenir un système à une même position alors que les 2 moteurs ont des poussées qui ne se compensent pas…, ce qui me parait bizarre c’est que pourtant sur Matlab, avec 2 poussées ne se compensant pas, "l’angle" reste à 180°…

Tu es sur la bonne voie. Si les deux moteurs ne se compensent pas (à cause de la commande du contrôleur), mais que le système reste à une position donnée, ça veut probablement dire que quelque part, il y a quelque chose qui se comporte comme un couple sur le système, et qui compense le déséquilibre des moteurs. Alors évidemment, c’est une anomalie.

Les conseils que j’ai donné précédemment devraient t’aider à trouver ce qui cause cette anomalie dans ton système.

EDIT : Je crois avoir compris ce que tu voulais dire avec le bloc intégrateur et la condition initiale mais la commande et l’angle tendent vers l’infini donc la simulation se termine avec une erreur…

Jupiter41

C’est probablement lié au problème précédent. Je ne garantis rien, c’est juste une intuition.

+0 -0

Merci pour tes conseils @Aabu ! :)

Je vais me pencher sur ce que me renvoie chaque signals et essayé de vérifier en calculant, je ferais ça le plus rapidement possible, c’est-à-dire pas tout de suite ^^ (peut-être Lundi).

Je dois toutefois avouer que pour le moment je n’ai absolument aucune idée de ce qui pourrait agir comme un couple en sachant que je n’ai pas vraiment ajouter d’autres choses que sur le programme Arduino (mais avec ce que tu écris j’imagine que ce qui est formule pour la commande etc.. est correct donc j’en déduis qu’il s’agit d’une chose que j’ai rajouter sur Simulink). Cela me semble être une trop grosse coïncidence que les poussées se bloque lorsque l’angle atteint 180° qui est comme par hasard la position voulue ^^.

J’ajoute que l’on peut d’or et déjà éliminer le petit système au début (avec le Signal Builder et le NOT) étant donné que j’ai déjà essayé de le remplacer par un bloc intégrateur avec 100 pour condition initiale et que j’avais toujours ce problème (les valeurs tendent vers l’infini).

Hum, alors c’est sûrement mal fait (tu penses que ça peut venir de là ? Je ne vois pas trop comment cette partie pourrait agir comme un couple mais bon ^^(car c’est vraie qu’à part ça je n’ai rien ajouté d’autre par rapport au programme Arduino je crois…)) mais j’ai fais comme ça :p :

Réglage du bloc
Réglage du bloc
Erreur
Erreur
Tout
Tout
+0 -0

Tu as quoi dans ta boîte calcul de l’angle ce coup-ci ?


Sinon, j’ai fait des tests chez moi (j’ai pas pu résister). J’ai peut-être identifié quelque chose de très subtil que tu auras énormément de mal à trouver seul. Avant d’expliquer, j’aimerai être sûr d’avoir quelque chose de comparable avec toi. Si tu pouvais me faire un petit résumé de ton Simulink, ça me serait utile. Au minimum :

  • la vue globale,
  • le contenu de chaque boîte,
  • les paramètres du PID (et de tes intégrateurs),
  • et quelques courbes, même si ça part à l’infini (angle, erreur, commande du PID, pousée droite et poussée gauche, au minimum).

Je n’avais rien changé dans le bloc Angle du coup (si tu voulais la version avec le NOT etc… tu as la vue globale quelques messages plus haut et le reste n’a pas changé ^^) :

Global
Global
Angle
Angle
Poussées
Poussées
Paramètres PID
Paramètres PID
Paramètres Intégrator
Paramètres Intégrator
Graphique Erreur
Graphique Erreur
Graphique Commande
Graphique Commande
Graphique Poussées
Graphique Poussées
Graphique Angle
Graphique Angle

Et voilà ! :p

Bonjour,

Problème 1

Tu as une incohérence de signe entre le calcul des forces de poussée et le calcul de l’angle. Le problème peut être corrigé en changeant un des deux blocs.

C’est un peu difficile quand on n’a pas l’habitude, mais on peut le voir en raisonnant qualitativement. Les coefficients du PID positifs indiquent qu’une erreur qui augmente implique une commande qui augmente. Ensuite, on voit dans le calcul des poussées qu’une commande qui augmente implique la différence "poussée droite - poussée gauche" diminue. Enfin, dans ton calcul de l’angle, on voit que "poussée droite - poussée gauche" qui diminue, ça fait diminuer l’accélération et donc la vitesse (que sur laquelle tu régules à parce que tu as rajouté ton intégrateur). En gros, on a Err    Cmd    PdPg    Acc    VitesseErr \uparrow \implies Cmd \uparrow \implies Pd - Pg \downarrow \implies Acc \downarrow \implies Vitesse \downarrow.

Là où c’est problématique, c’est que pour une consigne fixe, à zéro par exemple, une diminution de la vitesse crée une augmentation de l’erreur (on a un signe moins dans le retour). Cela veut dire qu’on a une boucle : Err    Cmd    PdPg    Acc    Vitesse    ErrErr \uparrow \implies Cmd \uparrow \implies Pd - Pg \downarrow \implies Acc \downarrow \implies Vitesse \downarrow \implies Err \uparrow. Cela veut dire que quand on a une erreur qui augmente et qu’on essaie de la corriger… cela contribue à faire augmenter l’erreur !

Cette rétroaction anormale fait partir en cacahouète le système.
Cette rétroaction anormale fait partir en cacahouète le système.

Quand on corrige ce défaut, cela devient mieux. Je te laisse chercher comment corriger (tu peux sûrement t’inspirer de ton code, qui ne présente pas cette erreur apparemment).

Avec correction, tout va bien.
Avec correction, tout va bien.

Le fait que ça marche quand on régule sur l’accélération et non la vitesse vient du fait que sans intégrateur, le PID arrive à rattraper la bêtise, ce qu’il est incapable de faire quand on régule sur la vitesse. Ce qui nous amène au deuxième problème.

Problème 2

Il faut que tu mettes deux intégrateurs afin de calculer l’angle, tout simplement parce que tu veux faire un asservissement de position, et pas de vitesse ou d’accélération.

Normalement, une fois que tu auras corrigé le problème 1, l’asservissement sur la vitesse devrait fonctionner. Cependant, j’ai vu des choses bizarres de mon côté que tu vas peut-être voir également : avec deux intégrateurs, ça diverge ! Edit: essaie avec seulement un contrôleur PI, avec un PID ça marche quand on regarde pas trop près).

C’est un phénomène que tu ne peux pas voir dans la réalité, et qui est causé par une simplification dans la modélisation. Quand tu auras trouvé le problème 1, j’essaierai de t’expliquer celui-là et une solution potentielle. Surtout si ça ne marche pas chez toi non plus.

+0 -0

Merci beaucoup pour tes explications, très détaillées ! Je pense avoir identifié le problème, et l’avoir réglé car j’obtiens de bons résultats (enfin normalement :p), mais avec ce que j’ai modifié cela veux dire qu’il y a un problème de signe dans la formule de l’angle non ? :

Problème 1 :

  • L’ancienne formule : -0,29Pg + 0,29Pd = J accélération_angulaire, après correction sur le modèle :
    0,29Pg - 0,29Pd = J
    accélération_angulaire.

  • Mais maintenant les images :) :

Global
Global
Erreur
Erreur
Commande
Commande
Poussées
Poussées

Et enfin :

Angle
Angle

Problème 2 :

Si je n’ai pas fait d’erreur au dessus, tout marche bien et je n’ai donc pas ce problème :)

+0 -0

avec ce que j’ai modifié cela veux dire qu’il y a un problème de signe dans la formule de l’angle non ? :

Problème 1 :

  • L’ancienne formule : -0,29Pg + 0,29Pd = J accélération_angulaire, après correction sur le modèle :
    0,29Pg - 0,29Pd = J
    accélération_angulaire.

En fait, l’erreur est lié à une convention d’orientation différente entre la formule que tu cites et celle qui calcule les poussées. Il suffit de changer une des deux. En théorie, il y a même moyen de changer ça en changeant le signe des coefficients du PID, mais c’est un coup à s’embrouiller totalement.

Problème 2 :

Si je n’ai pas fait d’erreur au dessus, tout marche bien et je n’ai donc pas ce problème :)

Jupiter41

Tu as essayé avec juste un PI au lieu d’un PID ? Il peut potentiellement se passer des choses intéressantes. Après peu importe, si ça marche, tant mieux.


Sinon, j’ai une suggestion pour toi : regarde les valeurs de la commande et des poussées, et dis-moi si ça te fait tiquer.

Regarde aussi si ta condition initiale dans l’intégrateur est bien là où tu veux, je crois que tu as mis une condition sur la vitesse, à moins que je ne me trompe.

Maintenant que tu as quelque chose qui marche dans les grandes lignes, cela devrait devenir un peu plus facile, le plus dur est fait ! Il y a encore pas mal de travail pour dégrossir, mais ce sera moins douloureux pour toi (j’espère).

Merci énormément pour tes précisions :)

  • Non, je n’avais pas essayé et je viens de le faire : le système diverge bien (je me retrouve avec le même problème qu’avant ^^), pourquoi cela fait-il ça avec un correcteur PI au lieu d’un correcteur PID ?

  • En regardant assez rapidement, la seule chose qui a pu me faire tiquer c’est les valeurs assez énormes que prennent les poussées et la commande au début :p

  • Tu as l’œil aiguisé :), j’avais bien laissé la condition initiale à 100 dans l’intégrateur pour la vitesse quand j’ai ajouté celui pour l’angle (dans lequel j’avais également mis une condition initiale à 100).

  • Dégrossir ? Ça devrais aller, enfin j’espère :lol:.

Merci énormément pour tes précisions :)

  • Non, je n’avais pas essayé et je viens de le faire : le système diverge bien (je me retrouve avec le même problème qu’avant ^^), pourquoi cela fait-il ça avec un correcteur PI au lieu d’un correcteur PID ?

De manière intuitive, tout se passe comme si la présence des deux intégrateurs retardait le système. Le retard est tel qu’un contrôleur PI se retrouve à réagir parfois à l’opposé de ce qu’il devrait, parce que l’information avec laquelle il travaille est périmée. C’est un peu comme un conducteur ivre qui perçoit et agit lentement, tellement qu’il finit par tourner le volant dans la direction inverse du virage et sortir de la route.

En rajoutant le D, on se retrouve avec un correcteur qui sait mieux anticiper en prenant en compte les variations du signal et est ainsi capable de mieux contrôler le système. Ce type de contrôleur voit dans l’avenir d’une certaine manière.

Tout ça se justifie rigoureusement avec les théories de l’automatique, notamment tout ce qui a trait à la stabilité des asservissements.

  • En regardant assez rapidement, la seule chose qui a pu me faire tiquer c’est les valeurs assez énormes que prennent les poussées et la commande au début :p

Oui, et ça n’arrivera pas dans la réalité, à cause des limites des moteurs. Tu auras ce qu’on appelle de la saturation. Dans une bonne simulation, il faut la prendre en compte.

  • Dégrossir ? Ça devrais aller, enfin j’espère :lol:.
Jupiter41

Ça dépend fortement de ton objectif, mais il y a beaucoup de pistes d’amélioration :

  • prendre en compte la saturation de la poussée (au niveau des poussées bien sûr, mais aussi du contrôleur) ;
  • trouver le J (au passage vérifie la manière dont tu prends en compte J, je crois qu’il y a une boulette) ;
  • relier tes poussées à la physique, parce qu’actuellement c’est un peu abstrait (le contrôleur commande l’ECS, et pas la force directement) ;
  • s’assurer que les unités sont cohérentes (t’as des degrés, des formules qui s’utilisent en radians, etc) ;
  • améliorer l’esthétique, c’est un peu le chaos ton Simulink. :D
  • D’accord merci pour ces précisions ! Je vais regarder ça un peu plus précisément car même cela ne me seras pas forcément utile, ça m’intéresse :)

  • Oui c’est ce à quoi j’ai pensé, et j’avais déjà essayé en changant les paramètres du bloc PID et ça ne marchait pas… Mais en réessayant je viens de me rendre compte que je n’avais pas testé avec la dernière version du modèle et que ça marche ! :) :

Paramètres du bloc PID
Paramètres du bloc PID
Graphique de la commande (les poussées ne dépassent pas 1000 également)
Graphique de la commande (les poussées ne dépassent pas 1000 également)
  • Je vais demander à mes professeurs pour J, et d’accord je vais regarder ça.
  • Oui c’était l’étape suivante : rajouter une simulation des moteurs.
  • Effectivement, mais est-ce vraiment grave ? L’angle est en radian à la sortie de l’intégrateur donnant l’angle non ? Ou à d’autres endroits aussi ?.
  • Je le trouvais joli moi :p Je vais l’arranger un peu ^^.

Merci énormément pour ton aide et tes conseils en tout cas ! Je ne sais vraiment pas ce que j’aurais pu faire tout seul ^^.

En tout cas, il me reste une autre chose importante à faire (mais beaucoup moins difficile) : récupérer le temps que met le système avant de se stabiliser, j’aimerais regarder si il est possible de récupérer le temps à partir duquel l’angle reste à 180° et de l’afficher dans un Display "automatiquement" afin d’éviter de devoir regarder l’abscisse des graphiques :).

Salut !

C’est re-moi @Aabu :) Je reviens annoncer que le système réel marche enfin bien :p il reste de mini réglages à faire sur le PID et cela seras bon (le drone revient assez rapidement vers 180° mais il fait ensuite 180.3 180.2 180.1 puis 180 plus lentement et je pense que l’on peut encore réduire un peu les oscillations (car il y en a encore un tout petit peu ^^)). La simulation Simulink, avec les mêmes valeurs du PID (P : 20, I : 0.008, D : 1750) montre bien ce qui se passe.

Du coup, j’aimerais mesurer les écarts simulé/réel mais je galère un peu avec Simulink : le temps est bizarre car je ne crois pas que cela soit des secondes… Par exemple si je règle la durée de la simulation à 10000, comme ça :

Image utilisateur
Image utilisateur

Et que je chronomètre, à la fin le temps sur celui-ci n’est pas 10s mais plutôt 7–8s… Saurais-tu comment faire ?

Merci d’avance !

+0 -0

Salut,

Encore une fois, c’est un peu dur à distance pour ce genre de sujet.

À ma connaissance, le temps de simulation de Simulink est bien en secondes. S’il y a un problème, c’est probablement lié à autre chose.

Si mes souvenirs sont bons, tu n’as pas modélisé dans Simulink exactement comme dans la réalité. Dans Simulink, ton contrôleur PID est un contrôleur à temps continu, alors que dans ton système réel, il s’agit d’un contrôleur à temps discret. Si le contrôleur discret est suffisamment rapide, son comportement ressemblera très fortement au contrôleur continu. Cependant, le comportement identique des deux contrôleurs n’est pas obtenu pour des coefficients identiques. Il faut faire une conversion qui prend en compte le temps d’échantillonnage du contrôleur discret. Est-ce que tu as fait ça correctement ?

Et que je chronomètre, à la fin le temps sur celui-ci n’est pas 10s mais plutôt 7–8s… Saurais-tu comment faire ?

Tu chronomètres quoi ? Je n’ai pas compris.

Merci de ta réponse !

C’est ce que je pensais aussi, c’est bizarre…

Tes souvenirs sont bons, en essayant de mettre le bloc PID Controller en mode Discret donc comme ça :

Vue globale
Vue globale
Paramètres du bloc
Paramètres du bloc

Je me retrouve avec cette erreur :

Erreur
Erreur

Et je ne sais pas trop comment la régler… J’avais essayé en mettant Sample time = 15 (période d’échantillonnage sur Arduino) mais j’ai la même erreur mais l’angle final est beaucoup plus élevé (*10^4)…

Je chronomètre le temps qui s’écoule entre le moment ou j’appuie sur le bouton "Run" de la simulation et la fin de la simulation (avec en temps de simulation 10000 (comme mis dans l’image).

Et je ne sais pas trop comment la régler… J’avais essayé en mettant Sample time = 15 (période d’échantillonnage sur Arduino) mais j’ai la même erreur mais l’angle final est beaucoup plus élevé (*10^4)…

Si tu mets 15, ça veut dire 15 s. Je ne crois pas que sur Arduino tu contrôles toutes les 15 secondes. ;)

Je chronomètre le temps qui s’écoule entre le moment ou j’appuie sur le bouton "Run" de la simulation et la fin de la simulation (avec en temps de simulation 10000 (comme mis dans l’image).

Si tu fais une simulation normale, il n’y a pas de raison que la simulation dure le même temps que dans la réalité. C’est assez logique : si tu simules quelque chose qui prend 10 ans dans la vraie vie, on ne vas pas attendre 10 ans pour avoir le résultat !

C’est vrai avec 15e-3, ça marche beaucoup mieux ! :p

C’est vrai que c’est logique mais du coup comment calculer le temps que met le système avant de retourner à sa position d’origine (et que ce temps soit "le même" que dans la réalité) ?

Si ta simulation est bien faite (bonne modélisation, paramètres bien déterminés, etc.), alors la simulation et la réalité devraient être pareils. En particulier, le temps de stabilisation dans la simulation devrait être le même que dans la réalité. Il suffit de comparer les sorties de la simulation (temps et valeurs des signaux) et ceux de la réalité (idem temps et valeurs des signaux).

+0 -0

Oui c’est vrai, c’est ce que je suis censé vérifier ^^ mais justement si :

Si tu fais une simulation normale, il n’y a pas de raison que la simulation dure le même temps que dans la réalité. C’est assez logique : si tu simules quelque chose qui prend 10 ans dans la vraie vie, on ne vas pas attendre 10 ans pour avoir le résultat !

Comment obtenir le bon temps pour pouvoir comparer avec le temps réel ?

Comment obtenir le bon temps pour pouvoir comparer avec le temps réel ?

Jupiter41

Tu peux obtenir le temps de simulation (et les autres variables de la simulation) de plein de manière différentes :

  1. en visualisant avec une scope (c’est l’abscisse) ;
  2. en visualisant avec le data inspector (pas sûr du nom), pareil tu as l’abscisse qui est le temps ;
  3. en exportant l’enregistrement d’une scope vers l’espace de travail (voir dans les options des scopes) ;
  4. en exportant vers l’espace de travail avec des blocs to workspace ;
  5. en exportant vers l’espace de travail avec les fonctionnalités de data logging.

La meilleure méthode dépend de ce que tu veux faire exactement et du niveau d’automatisation dont tu as besoin. Les solutions les plus simples sont probablement la 1, 3 et 4.

Ce sujet est verrouillé.