[ARDUINO] Asservissement grâce au PID

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

Bonne idée, je vais faire ça ! :lol: (des que l’on a projet, c’est à dire je ne sais pas trop quand, peut-être Samedi). Je te tiendrai au courant !

Merci énormément pour ton aide @Aabu en tout cas !

PS : Pour quelle raison, la valeur de la poussée moyenne peut-elle être choisie "aléatoirement" ? (pour que je puisse l’expliquer ;))

EDIT : Mon programme "final" :

////////////////////////////////////
// Les bibliothèques nécessaires  //
////////////////////////////////////

#include <Wire.h>
#include <ADXL345.h>

#define MOT_G ... // A REMPLACER
#define MOT_D ... // A REMPLACER

/* Variables */

double pitch = 0.00 ;

ADXL345 adxl ; // Variable adxl en relation avec la bibliothèque ADXL345 

float erreur = 0 ; // Erreur = consigne - mesure

float consigne = 90 ; // Valeur à atteindre (modifiable)

const float Kp = 10 ; // Constante du paramètre proportionnel
const float Ki = 0.4 ; // Constante du paramètre intégral
const float Kd = 20 ; // Constante du paramètre dérivée

float erreur_precedente = 0 ;
float somme_erreurs = 0 ;
float variation_erreur = 0 ;

float mesure = 0 ;

int poussee_g = 0 ; // Poussée du moteur gauche (à déterminer)
int poussee_d = 0 ; // Poussée du moteur droit (à déterminer)

float commande = 0 ; // Commande = différence de pousée entre les moteurs : cmd = poussee_g - poussee_d

const int periode = 15 ; // Période d'échantillonage = Pause à la fin du programme Arduino = Temps d'execution de la fonction loop()

const int poussee_moyenne = 100 ; // Poussée moyenne, déterminée aléatoirement mais dois rester logique

void setup() {

  pinMode(MOT_G, OUTPUT) ;
  pinMode(MOT_D, OUTPUT) ;

  Serial.begin(9600) ; // Moniteur série sur 9600 bauds (bits/s)

  adxl.powerOn() ; // Démarrage du capteur accéléromètre/gyroscope

}

void loop() {
  
  int x,y,z ;  
  adxl.readXYZ(&x, &y, &z) ; // Lecture des valeurs issues de  l'accéléromètre et stockage dans les variables x,y,z
  
  // Valeurs de sorties x, y, z 

  double x_Buff = float(x) ;
  double y_Buff = float(y) ;
  double z_Buff = float(z) ;

  pitch = atan2((- x_Buff) , sqrt(y_Buff * y_Buff + z_Buff * z_Buff)) * 63 ;
  mesure = pitch ; // Mesure finale
  
    erreur = consigne - mesure ; // Calcul de l'écart entre la consigne et la mesure (-> erreur) => Paramètre proportionnel
    somme_erreurs += erreur ; // Paramètre intégral
    variation_erreur = erreur - erreur_precedente ; // Paramètre dérivée

    commande = (Kp * erreur) + (Ki * somme_erreurs * periode) + ((Kd * variation_erreur) / periode) ; // Calcul de la commande

    erreur_precedente = erreur ; // Stockage de l'erreur actuelle

    // Conditions pour éviter la saturation (dépassage des valeurs limites (Démarrage du moteur/Moteur à fond)) :

    if (commande < ...) commande = ... ; // A REMPLACER par la valeur pour laquelle les moteurs démarrent /!\
    else if (commande > ...) commande = ... ; // A REMPLACER par la valeur pour laquelle les moteurs s'arrêtent /!\

    // Détermination de la pousée des moteurs :

    poussee_g = (1/2) * commande + poussee_moyenne ; // Poussee du moteur gauche
    poussee_d = poussee_moyenne - (1/2) * commande ; // Poussee du moteur droit

    // Envoie de ces poussées aux moteurs :

    analogWrite(MOT_G, poussee_g) ;
    analogWrite(MOT_D, poussee_d) ;

    /* Debug */

    //Serial.println(erreur) ;

    //Serial.print("Temps : ") ;
    //Serial.println(millis()) ;
    
    //Serial.print("Mesure : ") ;
    Serial.println(mesure) ;

    //Serial.print("Commande : ") ;
    //Serial.println(commande) ;

    
    delay(15) ; // Pause (= periode)

}
+0 -0

PS : Pour quelle raison, la valeur de la poussée moyenne peut-elle être choisie "aléatoirement" ? (pour que je puisse l’expliquer ;))

C’est assez simple : la poussée moyenne correspond à la force avec laquelle le drone doit tirer vers le haut (purement vers le haut sans rotation sur lui-même). Sur ton montage, comme il ne s’agit pas d’un vrai drone, et qu’il sera attaché à un pivot, cette poussée moyenne sera toujours compensée par le pivot. Tu peux donc mettre ce que tu veux.

Et si tu veux un mot meilleur que « aléatoirement », tu peux dire « arbitrairement ». Mais garde en tête que ce n’est pas totalement arbitraire : idéalement, il faudrait choisir une poussée qui permet au drone de se maintenir à une altitude stable et qui permet de jouer avec la vitesse des moteurs (si tu es à fond, tu ne va pas pouvoir ajuster les deux moteurs, et le système simple que je propose merdouille).

Bonjour !

Me voilà de retour @Aabu avec quelques nouvelles ! Après avoir mis en place le programme (avec quelques modifications en plus), et plusieurs tests, ça marche ! Il faut encore régler les paramètres du PID mais cela fait ce que l’on souhaite.

Maintenant les nouveaux problèmes arrivent : il faut que je modélise le système sur Matlab Simulink, je me permet de continuer sur ce sujet car c’est la suite du programme Arduino, ça peux toujours être intéressant pour ceux lisant ce sujet, cette fois cela seras de la modélisation pur et simple (pas besoin de communiquer avec Arduino). Je n’ai pas encore commencé donc je poste juste ça au cas ou quelqu’un ait des conseils à me donner.

Voici ce que je dois faire : nous rentrerons manuellement une consigne (qui seras égale à la position de base du système modélisé (180°)), puis en modélisant les moteurs (brushless) et le PID, je devrais modéliser la réponse du système (poussée des moteurs, commande …) jusqu’à ce que le système retourne à sa position initiale afin de pouvoir faire l’écart entre le temps de réponse du modèle et la réalité.

Je me suis fait une petite liste de ce que je dois faire :

  • Bloc contenant la consigne (facile ^^)

  • Modéliser le PID (je ne sais pas trop la difficulté) : Bloc PID Controller + Fonction de Transfert ? ou + Formule déterminé précédemment ?

  • Modéliser les 2 moteurs : facile si un moteur brushless a à peu près la même modélisation qu’un moteur à courant continu.

  • Afficher la commande et la poussée de chaque moteur (facile) : Data Simulation Inspector pour faire un graphique

  • Récupérer le temps de réponse (angle des 2 moteurs = position initiale) : Je n’ai pas trouvé de bloc permettant de calculer le temps depuis lequel la simulation est en cours… -> Faire stopper la simulation dès que cette position est atteinte et voir le temps de simulation indiqué par Simulink ?

Cordialement et Merci d’avance !

+0 -0

Après avoir mis en place le programme (avec quelques modifications en plus), et plusieurs tests, ça marche ! Il faut encore régler les paramètres du PID mais cela fait ce que l’on souhaite.

Voilà une bonne nouvelle ! C’est possible d’avoir une petite vidéo pour voir ce que ça donne ? :)

  • Récupérer le temps de réponse (angle des 2 moteurs = position initiale) : Je n’ai pas trouvé de bloc permettant de calculer le temps depuis lequel la simulation est en cours… -> Faire stopper la simulation dès que cette position est atteinte et voir le temps de simulation indiqué par Simulink ?
Jupiter41

Si tu as une courbe dans le « Data Inspector », tu peux mesurer le temps de réponse à la main, en regardant la courbe. Autrement, la technique la plus courante serait de traiter tes données dans Matlab avec un script, en les exportant depuis Simulink. Si tu ne connais pas bien Matlab, le faire à la main demande moins d’apprentissage.

Merci de ta réponse @Aabu !

Pas de problème, je t’enverrais une vidéo dès que le système fonctionnera parfaitement, mais du coup je n’ai pas projet avant 3semaines donc il faudra attendre un peu :).

Si tu as une courbe dans le « Data Inspector », tu peux mesurer le temps de réponse à la main, en regardant la courbe. Autrement, la technique la plus courante serait de traiter tes données dans Matlab avec un script, en les exportant depuis Simulink. Si tu ne connais pas bien Matlab, le faire à la main demande moins d’apprentissage.

Aabu

Je verrais quand j’aurais une courbe ^^. Sinon que penses-tu de cette question ? :

  • Modéliser le PID (je ne sais pas trop la difficulté) : Bloc PID Controller + Fonction de Transfert ? ou + Formule déterminé précédemment ?
Jupiter41
+0 -0

Pour ta dernière question, les différentes solutions sont quasi-équivalentes. Toutes ont des avantages et des inconvénients. Le plus simple pour toi est probablement de faire le PID avec les blocs élémentaires (somme, intégrateur, gain, dérivateur, etc). Cela te donne une maîtrise de ce que tu fais qui est difficilement atteignable si tu ne comprends pas bien le bloc PID de la bibliothèque.

D’accord merci beaucoup @Aabu

Je pense que je vais essayer d’utiliser le PID Controller car je pense avoir à peu près compris comment il fonctionne grâce aux exemples que j’ai pu trouver.

Pour convertir cette commande je vais garder la formule déterminé précédemment du coup :) comme ça je n’embête pas mon professeur de SI et on verras plus le lien entre le programme Arduino et la modélisation !

Je vais essayer de commencer ça pendant les vacances :)

J’aurais une dernière petite question avant de commencer @Aabu :

Dans la simulation, imaginons que l’on mette une consigne de 180° donc les 2 moteurs sont à plat, et une perturbation de -70° : ainsi l’angle seras de 110° mais comment le représenter ? Un angle c’est par rapport à 2 vecteurs, mais il n’y en as pas dans une simulation, donc que représente t-il ? Comment savoir de quel côté le bras penche (exemple correspondant au modèle réel) ? … Et comment déterminer cet angle par rapport à la vitesse de rotation des moteurs ?

Je suis désolé si ce n’est pas très clair… Mais merci d’avance pour ta réponse !

EDIT : J’ai fait cela pour le moment :

Image utilisateur Image utilisateur

Mais je ne vois pas trop quoi faire ensuite…

+0 -0

J’aurais une dernière petite question avant de commencer @Aabu

Il n’y a pas qu’une seule question, tu triches. ;)

Dans la simulation, imaginons que l’on mette une consigne de 180° donc les 2 moteurs sont à plat, et une perturbation de -70° : ainsi l’angle seras de 110° mais comment le représenter ?

Tu poses une question en donnant à moitié la réponse : l’angle sera représenté par sa mesure. Autrement dit, tu auras un signal qui correspond à la valeur de l’angle (en degrés par exemple).

Un angle c’est par rapport à 2 vecteurs, mais il n’y en as pas dans une simulation, donc que représente t-il ?

Drôle de question encore ! C’est toi qui choisis ce que représente l’angle. Ta simulation ne le devinera pas pour toi.

Tu sembles confondre deux concepts : la définition d’un angle et sa mesure. Un angle (orienté) peut notamment être défini par un couple de vecteurs ou la donnée de trois points. Sa mesure correspond à son degré d’ouverture, et permet de comparer tous les angles entre eux. Par exemple, l’angle au coin d’une pièce et celui d’une équerre mesurent tout deux 90°, mais ne sont pas définis par les mêmes vecteurs.

En dehors de ta simulation, tu définis des angles. Dans ta simulation, tu simules comment leurs mesures évoluent en fonction des autres grandeurs.

Comment savoir de quel côté le bras penche (exemple correspondant au modèle réel) ?

Cela dépend de comment tu définis tes angles… L’orientation choisie en particulier. C’est toi qui choisis, mais attention à garder les équations cohérentes avec ce choix.

Et comment déterminer cet angle par rapport à la vitesse de rotation des moteurs ?

C’est une questions très vaste. La réponse correspondante serait : avec les lois de la physique.

Tu devrais vraiment faire un schéma-bloc détaillé de TON système avec ses différents éléments… Cela t’aiderait beaucoup.

Image utilisateur Image utilisateur

Mais je ne vois pas trop quoi faire ensuite…

Jupiter41

C’est un bon début. Pour progresser, il faudrait que tu t’intéresses au lien entre les poussées des moteurs et ce que tu appelles perturbation (mais tu devrais choisir un autre nom, c’est utilisé pour autre chose en automatique).

Ce lien fait notamment intervenir les forces exercées par les moteurs, la géométrie du drone, un couple et une équation très connue liant le couple à la vitesse angulaire.

Merci énormément pour ta réponse @Aabu !

Désolé pour les plusieurs questions j’essayais de décomposer ma question en plusieurs pour qu’elle soit plus claire :).

Dans la simulation, imaginons que l’on mette une consigne de 180° donc les 2 moteurs sont à plat, et une perturbation de -70° : ainsi l’angle seras de 110° mais comment le représenter ?

Tu poses une question en donnant à moitié la réponse : l’angle sera représenté par sa mesure. Autrement dit, tu auras un signal qui correspond à la valeur de l’angle (en degrés par exemple).

Un angle c’est par rapport à 2 vecteurs, mais il n’y en as pas dans une simulation, donc que représente t-il ?

Drôle de question encore ! C’est toi qui choisis ce que représente l’angle. Ta simulation ne le devinera pas pour toi.

Tu sembles confondre deux concepts : la définition d’un angle et sa mesure. Un angle (orienté) peut notamment être défini par un couple de vecteurs ou la donnée de trois points. Sa mesure correspond à son degré d’ouverture, et permet de comparer tous les angles entre eux. Par exemple, l’angle au coin d’une pièce et celui d’une équerre mesurent tout deux 90°, mais ne sont pas définis par les mêmes vecteurs.

En dehors de ta simulation, tu définis des angles. Dans ta simulation, tu simules comment leurs mesures évoluent en fonction des autres grandeurs.

Aabu

Tu résumes ici bien ce que je pensais : j’ai du mal à me représenter la mesure de l’angle dans la simulation.

Comment savoir de quel côté le bras penche (exemple correspondant au modèle réel) ?

Cela dépend de comment tu définis tes angles… L’orientation choisie en particulier. C’est toi qui choisis, mais attention à garder les équations cohérentes avec ce choix.

Aabu

Je pense que je vais laisser comme ça pour le moment et je verrais ça après en cas de problème ^^. J’ai fait un petit schéma bloc, je ne sais pas si il correspond à ce que tu attendais mais le voilà :

Image utilisateur
Image utilisateur

(Bon mon écriture est un peu bizarre car j’essayais de bien détacher les lettres au cas ou ma photo serais flou mais elle ne l’ai pas :p)

J’ai aussi une photo du système réel complètement construit (si ça peut aider) :

Image utilisateur
Image utilisateur

C’est un bon début. Pour progresser, il faudrait que tu t’intéresses au lien entre les poussées des moteurs et ce que tu appelles perturbation (mais tu devrais choisir un autre nom, c’est utilisé pour autre chose en automatique).

Ce lien fait notamment intervenir les forces exercées par les moteurs, la géométrie du drone, un couple et une équation très connue liant le couple à la vitesse angulaire.

Aabu

J’imagine que tu parles de la formule C = P/Vrot avec C le couple (N.m), P la puissance (W) et Vrot la vitesse angulaire (rotation) (rad.s) qui implique que C augmente lorsque P augmente également et/ou Vrot diminue mais je ne vois pas trop encore comment m’en servir pour trouver le nouvel angle…

+0 -0

Si j’ai bien suivie mon cours @Aabu :) : le couple peut être considéré comme un moment cinétique puisque son unité N.m montre que c’est bien le produit scalaire entre une force et une distance, on le note vecteur C.

Ensuite j’imagine qu’il faut utiliser la formule de "la somme des moments s’exercent en un point" = Jg * accélération angulaire (car je ne vois pas trop comment utiliser celle de la somme des forces extérieures).

Et enfin, j’imagine (encore :lol:) que des angles apparaitront lorsque l’on feras la somme des moments (dans les forces) puisque l’on peut représenter des triangles rectangles avec les moteurs :

Image utilisateur
Image utilisateur

Non ?

+0 -0

Étant donné que l’accélération est la dérivée de la vitesse qui est la dérivée de la position, je pense que c’est pareil avec des angles donc accélération angulaire = dvrot/dt = (d0/dt)2 (avec 0 la position en radians et vrot la vitesse de rotation en rad.s-1).

Donc je n’ai bien pas besoin de calculer la somme des forces extérieurs mais juste faire la somme des moments = Jg * (d0/dt)2 et étant donnée qu’un moteur est un cylindre Jg = (mR^2)/2 ?, non @Aabu ? :)

+0 -0

Ce n’est pas le couple du moteur qui compte pour l’angle, c’est celui que tu appliques à la traverse de ton drone autour du pivot !

Le couple du moteur est important pour sa vitesse de rotation et la force qu’il va appliquer "verticalement" (la poussée en gros).

D’accord @Aabu ! :) Du coup les forces externes sont : le poids et la poussée, lorsque le drone est stabilisé les 2 forces se compensent (mais je ne suis pas sûr que cela serve), puis je fais la somme des moments (pas besoin de faire la somme des forces ?) = Jg * accélération angulaire. Mais comment calculer Jg ? Une fois que je l’aurais j’imagine qu’il faudra résoudre l’équation pour obtenir l’accélération angulaire puis par intégration calculer l’angle, non ?

Mais comment calculer Jg ?

Dans un premier temps, tu n’as pas besoin de calculer le moment d’inertie, vu que tu peux toujours l’ajuster après coup. Pour le calculer, ce n’est pas forcément évident, vu que ça dépend de la répartition des masses. Si tes moteurs sont très lourds, cela sera plus simple. C’est aussi possible de le mesurer. Demande conseil à ton professeur, en fonction du matériel à disposition, il y a peut-être une solution plus facile pour vous.

Une fois que je l’aurais j’imagine qu’il faudra résoudre l’équation pour obtenir l’accélération angulaire puis par intégration calculer l’angle, non ?

Jupiter41

Tout à fait. Après, tu n’as pas besoin de résoudre l’équation formellement ; ton outil de simulation le fera pour toi.

D’accord, merci beaucoup de ta réponse @Aabu !

Pour le moment d’inertie, Jg, mes moteurs sont assez lourds mais je vais voir avec mes professeurs. Je verrai pour commencer à faire la simulation plus tard car j’ai une semaine de bac blanc à la rentrée à réviser :'( Je te tiendrais au courant :)

+0 -0
Ce sujet est verrouillé.