Asservissement grâce au PID

Bonjour,

Je suis actuellement en terminale SI et dans le cadre de cette matière, je dois réaliser un stabilisateur de drone "simplifié" c'est-à-dire ça : Arduino PID controller for one axis brushless drone motors - YouTube

L'une des problématiques de ce projet est donc l'asservissement grâce au PID.

Notre cahier des charges nous impose de considérer que le drone n'est plus stabilisé lorsque ses oscillations dépassent de plus ou moins 5degrés de 90degrés.

Nous avons réaliser un programme comprenant la mesure de l'angle (qui fonctionne) et l'asservissement par PID mais nous rencontrons 2 problèmes avec celui-ci :

  • La consigne renvoyer est parfois négative
  • Nous pouvons avoir une consigne de 200 pour un angle de 40degrés mais de 100 pour un angle de 30...

Voici le programme en question :

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

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

double pitch = 0.00;

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

const int ecart = 5;
float erreur = 0;//consigne - mesure

float consigne = 90;

float Kp = 10;
float Ki = 0.4;
float Kd = 20;

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

float mesure_ecart = 0;

float mesure = 0;
float commande = 0;

void setup(){
  Serial.begin(9600);
  adxl.powerOn();
}

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;
  
  if((mesure < (consigne - (consigne * ecart / 100))) || (mesure > (consigne + (consigne * ecart / 100)))){
  
    erreur = consigne - mesure ;
    somme_erreurs += erreur;
    variation_erreur = erreur - erreur_precedente;
    commande = (Kp * erreur) + (Ki * somme_erreurs) + (Kd * variation_erreur);
    erreur_precedente = erreur;
  
    delay(500);

  } else {

  	//Rénitialisation des variables
    
  	erreur_precedente = 0 ;
  	somme_erreurs = 0 ;
  	variation_erreur = 0 ;

  	commande = (Kp * erreur) + (Ki * somme_erreurs) + (Kd * variation_erreur); //Remettre à 0 la commande

  }

  erreur = 0 ;

}

Est-ce une méthode correcte ? Si oui, comment faire pour résoudre ces problèmes ?

Cordialement et Merci d'avance !

PS :

  • Pour l'instant nous n'avons pas de moteurs, nous réalisons donc nos tests "à la main" avec une équerre ^^
  • Les valeurs du PID sont rentrés au hasard.

Bonsoir.

La première chose c'est de contraindre la valeur de 'commande' entre deux valeurs par l'instruction:
commande = constrain(commande, valeur_mini, valeur_maxi);

Ensuite, vous allez vous heurter au problème classique de "windup" qui survient du fait que la commande appliquée au système n'est pas celle calculée par le PID.

Une recherche sur internet avec le terme "windup" devrait vous mettre sur la voie.

Quels sont tes objectifs par rapport à ce test ?

if((mesure < (consigne - (consigne * ecart / 100))) || (mesure > (consigne + (consigne * ecart / 100)))){

Merci pour vos reponses rapides et instructives !

Bilbo : Je m'informerai sur le terme "windup" et sur les 2 valeurs avec lesquelles restreindre ma commande (même si j'ai une petite idée je préfère vérifier ^^).

Alain : Tu viens de me faire remarquer une erreur dans mon premier message : mon cahier des charges m'oblige à stabiliser le "drone" lorsqu'il dépasse de plus ou moins 5% (et pas degré) 90 degrés. Du coup cette condition assure cette fonction :slight_smile:

Il y a un tutoriel à lire sur le sujet:

http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/

D'ac merci je regarderai :slight_smile:

Je viens de regarder ton tutoriel ard_newbie, j'ai exactement le même code ^^ Du coup il ne m'aide pas trop...