Aller au contenu


Photo
- - - - -

PID


  • Veuillez vous connecter pour répondre
19 réponses à ce sujet

#1 microrupteurman2

microrupteurman2

    Pilier du forum

  • Membres
  • PipPipPipPipPip
  • 2 029 messages
  • Gender:Male
  • Location:33
  • Interests:Tout

Posté 18 février 2012 - 12:08

Bonjour,

Voici a quoi ressembler l'aplication d'un pid il y a plusieures semaines pour moi :

isoazds pae ooazep ^ze fiz^ezi ôs diz a)àz dkq,d $z)oàiq dxkzi 8 dzo zixlq:m"ç dkçesi diozkms20!!;;skj

Donc, j'ai fait des recherches. J'avais deja Ce lien qui ce promenait dans mes favoris. Pendant mes recherches, je suis tombé sur ça et en regardant les fonctions des fonctions (!) J'ai compris (J'espere).

Donc, un PID (grossierement) ajuste une sortie en fonction d'une ou plusieurs entrée. Les entrées = Mes codeurs; les sorties = mes moteurs.

Donc il faux deux compteur, un par moteur pour les Ticks des codeurs, et comme 1 tour d'axe moteur = 360T (pris sur une seul sortie sans detection de sens), si la vitesse du moteur1 = moteur2 , compteur1 = compteur2. Mais ce n'est pas TRUE (!), nos deux moteurs peuvent etre identique en tout points, mais il est peut probable que sous un meme voltage il tourne exactement a la meme vitesse, il peut meme y avoir des fluctuation de la tension/intensité dans les moteurs suivant le type de terrain rencontré. (ex: un cailloux devant une roue = roue bloqué et l'autre qui continue a avancé !)

Donc le PID va 'contraidre' les 2 moteurs a avoir un meme rythme, en fonction des compteurs. Il va accelerer, ralentir les moteurs de facon a ce que compteur1 = compteur2..

Pour commencer, Ais je tout bien compris ??

Cdlt, Fabi1.
 
 
 

#2 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 24 février 2012 - 11:10

Voila, t'as compris à quoi sert un asservissement (qu'il soit de type P, PI, PID ou autre d'ailleurs).

Si ça peut t'aider : http://www.ferdinandpiette.com/blog/2011/08/implementer-un-pid-sans-faire-de-calculs/

++
Black Templar

Mon site internet : http://ferdinandpiette.com/


#3 microrupteurman2

microrupteurman2

    Pilier du forum

  • Membres
  • PipPipPipPipPip
  • 2 029 messages
  • Gender:Male
  • Location:33
  • Interests:Tout

Posté 25 février 2012 - 12:44

Merci BT, Ton article m'a un peu mis dans le flous...

Ca a bien l'aire compliquer ..... Je pense que ca va prendre du temps a realiser ça...
Si vous avez d'autre source, je suis preneur !

Merci
 
 
 

#4 arobose

arobose

    Nouveau membre

  • Membres
  • 62 messages
  • Gender:Male
  • Location:Meyreuil-France
  • Interests:Robotique
    Informatique
    Electronique

Posté 25 février 2012 - 10:21

Hello microrupteurman2,

Je pense qu'avant d'avoir des sources, le mieux est d'assimiler le fonctionnement d'un asservisement. C'est à dire avoir la notion de l'influence du gain proportionnel, de l'intégrateur et du dérivateur. Pas forcement besoin de maitriser la technique mathématique.

Le code d'un PID n'a rien de compliqué en soi. Et lorsque tu as compris la théorie, tu sais le développer toi-même. La problèmatique réside plutôt sur le réglage des paramètres pour obtenir la meilleure réponse possible. Et si le fonctionnement n'est pas bien assimilé, ça me parait difficile d'arriver à un bon réglage.


Pour compléter l'excellent tuto de Black Templar, avec l'une des références du genre est un article en anglais de Tim Wescott qui a été repris sur pas mal de site: http://www.eetimes.com/ContentEETimes/Documents/Embedded.com/2000/f-wescot.pdf

Et un tuto de feue l'association ANCR:
http://ancrobot.free.fr/Old_version/fichtech/action/pid/index.htm

Arobose.

#5 microrupteurman2

microrupteurman2

    Pilier du forum

  • Membres
  • PipPipPipPipPip
  • 2 029 messages
  • Gender:Male
  • Location:33
  • Interests:Tout

Posté 26 février 2012 - 01:26

Merci, Arobose.

Effectivement l'article de l'asso ANCR est pas mal, j'ai enfin compris kd kp ki.
 
 
 

#6 microrupteurman2

microrupteurman2

    Pilier du forum

  • Membres
  • PipPipPipPipPip
  • 2 029 messages
  • Gender:Male
  • Location:33
  • Interests:Tout

Posté 08 mars 2012 - 09:16

Re !

JE revient vers vous pour savoir si vous aurez pas des lien avec des exemples sur arduino. J'ai trouvé du code, mais ce n'ai pas le langage arduino.
Je continue de chercher..
Merci
 
 
 

#7 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 19 avril 2012 - 12:47

Tiens, tu me donnes une idée là !

Vu que j'ai un moteur avec une codeuse qui est dans un carton, je vais essayer de l'asservir avec l'Arduino !
ça me fera un bon exercice pratique et si ça peut t'aider au passage, c'est encore mieux !

Je vais essayer de trouver un peu de temps ce WE !

++
Black Templar


EDIT : je ferais plutôt ça dans 2 semaines car je viens de me rendre compte que je n'ai pas de transistors de puissances ! Je viens d'en commander, mais je ne les recevrais qu'en début de semaine prochaine

Mon site internet : http://ferdinandpiette.com/


#8 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 20 avril 2012 - 11:04

Plop !

J'avais oublié que j'ai reçu des MOSFET de puissance dans ma dernière commande ! :)
Du coup, j'ai pu, d'une part, apprendre à utiliser ce composant (je n'en avais jamais utilisé) et d'autre part, commander mon moteur !

Voila la partie commande du moteur. Rien de bien compliqué. Le transistor bipolaire viens driver le NMOS.
Les roues ne tournent que dans un seul sens. La diode de roue libre protège mon électronique de commande.

Lorsque l'arduino envoie 0V, le moteur tourne et quand il envoi 5V, le moteur s'arrête.

Fichier joint  commande_moteur.png   23,07 Ko   59 téléchargement(s)


Pour le programme Arduino, j'ai mis en place un asservissement proportionnel intégrateur (PI).
J'ai branché ma codeuse sur la pin 2 de l'Arduino Méga (c'est la pin d'interruption 0). A chaque fois que l'état de la codeuse change (bas ou haut), je déclenche l'interruption et j'incrémente une variable qui répertorie le nombre de fois que la codeuse à changé d'état.

Tous les 20ms (50 fois par second), j'exécute la fonction asservissement() qui a pour but de calculer la commande à envoyer au moteur.
Dans cette fonction, je calcul le nombre de tour de roue par seconde en fonction du nombre de fois que la codeuse à changé d'état durant les 20 dernières millisecondes.
Je calcule l'erreur, c'est à dire la différence entre le nombre de tours de roue par seconde voulu et réel.
Je calcule la commande à l'aide d'un PI (proportionnel intégrateur). Je n'ai pas mis en place le dérivateur pour faire un PID complet car je n'ai pas encore de quoi tracer précisément la réponse en fonction de la consigne, mais j'y travail ^^) donc un simple PI suffit largement pour le moment.

Une fois la commande calculé, je l'envoi au moteur (en inversé puisque mon moteur tourne pour une commande de 0 !!)

Je n'oublie pas de remettre à 0 le nombre de changement d'état de ma codeuse !

Voila le code :
/**
 * Asservissement d'un moteur à l'aide d'un régulateur PI
 * Avril 2012 - Black Templar
 */

#include <SimpleTimer.h> // http://arduino.cc/playground/Code/SimpleTimer

SimpleTimer timer; 				// Timer pour échantillonnage
const int _MOTEUR =  9;        	// Digital pin pour commande moteur
unsigned int tick_codeuse = 0; 	// Compteur de tick de la codeuse
int cmd = 0;   					// Commande du moteur

const int frequence_echantillonnage = 50;  // Fréquence du pid
const int rapport_reducteur = 29;      	// Rapport entre le nombre de tours de l'arbre moteur et de la roue
const int tick_par_tour_codeuse = 16;  	// Nombre de tick codeuse par tour de l'arbre moteur

float consigne_moteur_nombre_tours_par_seconde = 5.;  //  Nombre de tours de roue par seconde

float somme_erreur = 0;  // Somme des erreurs pour l'intégrateur
float kp = 50;   		// Coefficient proportionnel
float ki = 10;   		// Coefficient intégrateur

/* Routine d'initialisation */
void setup() {
  Serial.begin(9600); 		// Initialisation port COM
  pinMode(_MOTEUR, OUTPUT);   // Sortie moteur  
  analogWrite(_MOTEUR, 255);  // Sortie moteur à 0
  
  attachInterrupt(0, compteur, CHANGE);	// Interruption sur tick de la codeuse
  timer.setInterval(1000/frequence_echantillonnage, asservissement);  // Interruption pour calcul du PID et asservissement
}

/* Fonction principale */
void loop(){
  timer.run();
  delay(10);
}

/* Interruption sur tick de la codeuse */
void compteur(){
  tick_codeuse++;  // On incrémente le nombre de tick de la codeuse
}

/* Interruption pour calcul du PID */
void asservissement()
{
  // Calcul de l'erreur
  int frequence_codeuse = frequence_echantillonnage*tick_codeuse;
  float nb_tour_par_sec = (float)frequence_codeuse/(float)tick_par_tour_codeuse/(float)rapport_reducteur;  
  float erreur = consigne_moteur_nombre_tours_par_seconde - nb_tour_par_sec;
  somme_erreur += erreur;
  
  // PI : calcul de la commande
  cmd = kp*erreur + ki*somme_erreur;
	
  // Normalisation et contrôle du moteur
  if(cmd < 0) cmd=0;
  else if(cmd > 255) cmd = 255;
  analogWrite(_MOTEUR, 255-cmd);
  
  // DEBUG
  Serial.print(tick_codeuse);
  Serial.print(" : ");
  Serial.print(frequence_codeuse);
  Serial.print(" : ");
  Serial.print(nb_tour_par_sec,4);
  Serial.print(" : ");
  Serial.print(erreur,4);
  Serial.print(" : ");
  Serial.println(cmd);
  
  // Réinitialisation du nombre de tick de la codeuse
  tick_codeuse=0;
}


Pour les coefficients de mon PI, j'ai pris 50 pour le proportionnel et 10 pour l'intégrateur. Comment ai-je fait pour trouver ces valeurs :
  • J'ai défini l'intégrateur ki à 0
  • J'ai défini le proportionnel kp à 1
  • J'ai constaté que l'erreur était toujours très grande même après quelques secondes (erreur statique)
  • J'ai augmenter le proportionnel kp pour diminuer l'erreur statique
  • Pour un proportionnel kp de 50, j'ai une erreur statique d'environ 10%, mais j'ai choisi de m'arrêter là ! (choix arbitraire)
  • J'ai donc fixé l'intégrateur ki à 1
  • L'erreur finale est passé de 10% à 0% !! L'asservissement est donc réussi ! Néanmoins, j'ai remarqué que le temps que mettait le moteur à arrivé à une erreur de 0% était assez grand (quelques secondes)
  • J'ai augmenté l'intégrateur ki pour réduire le temps de stabilisation du moteur
  • Pour une valeur ki de 10, le moteur se stabilise en moins d'une seconde


Voila. Bien évidement, les coefficients kp et ki dépendent du moteur utilisé ainsi que de la fréquence de calcul du PID (50Hz pour moi)


Si on regarde quelques résultats du débugage lorsque le moteur est stable, on constate que le moteur est en effet stable (l'erreur oscille autour de 0) ^^
tick_codeuse_20ms : frequence_codeuse : erreur : commande
47 : 2350 : 5.0647 : -0.0647 : 48
46 : 2300 : 4.9569 : 0.0431 : 54
47 : 2300 : 4.9569 : 0.0431 : 54
47 : 2350 : 5.0647 : -0.0647 : 48
46 : 2300 : 4.9569 : 0.0431 : 54
48 : 2350 : 5.0647 : -0.0647 : 48
47 : 2300 : 4.9569 : 0.0431 : 54
A l'oreille, le moteur tournait bien à la bonne fréquence

++
Black Templar

P.S. : La bibliothèque SimpleTimer est à télécharger ici et à installer sur Arduino !
P.S. 2 : Je vais essayer de me former à Processing pour pouvoir tracer un graph de la réponse du moteur en fonction de la consigne !

Mon site internet : http://ferdinandpiette.com/


#9 microrupteurman2

microrupteurman2

    Pilier du forum

  • Membres
  • PipPipPipPipPip
  • 2 029 messages
  • Gender:Male
  • Location:33
  • Interests:Tout

Posté 21 avril 2012 - 12:47

!!! Un grand merci ! Ce code me servira, je pense le moment venu.. Et en aidera plus d'un !
:) :) :)
 
 
 

#10 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 21 avril 2012 - 06:25

!!! Un grand merci ! Ce code me servira, je pense le moment venu.. Et en aidera plus d'un !
:) :) :)


Mais de rien !

J'ai intégré le dérivateur cette après midi, mais les résultats ne sont pas flagrants... ça devait réduire l'amplitude des parasites, mais au final, ça ne fait rien :)
Je n'ai pas encore trouvé pourquoi, mais j'ai ma petite idée ! (le coefficient dérivateur corrige les erreurs d'accélération (vu qu'on asservi en vitesse), il doit y avoir un truc à trouver à ce niveau ! ...)


Voila deux de mes résultats (chaque courbe est le résultat d'une moyenne de 10 séries de mesures) :

Pour Kp = 300 ; Ki = 4.2 et Kp = 0 ou 160
Fichier joint  PID_v1.png   47,34 Ko   54 téléchargement(s)

Pour Kp = 300 ; Ki = 6 ; Kp = 0 ou 160
Fichier joint  PID_v2.png   46,93 Ko   45 téléchargement(s)

Et le code qui m'a permis de faire ça :
/**
 * Asservissement d'un moteur à l'aide d'un régulateur PI
 * Avril 2012 - Black Templar
 */

#include <SimpleTimer.h> // http://arduino.cc/playground/Code/SimpleTimer

SimpleTimer timer;     			// Timer pour échantillonnage
const int _MOTEUR =  9;        	// Digital pin pour commande moteur
unsigned int tick_codeuse = 0; 	// Compteur de tick de la codeuse
int cmd = 0;           			// Commande du moteur

const int frequence_echantillonnage = 50;  // Fréquence du pid
const int rapport_reducteur = 29;      	// Rapport entre le nombre de tours de l'arbre moteur et de la roue
const int tick_par_tour_codeuse = 16;  	// Nombre de tick codeuse par tour de l'arbre moteur

float consigne_moteur_nombre_tours_par_seconde = 5.;  //  Nombre de tours de roue par seconde

float erreur_precedente = 0;
float somme_erreur = 0;   // Somme des erreurs pour l'intégrateur
float kp = 300;   		// Coefficient proportionnel
float ki = 6;//4.2; 			// Coefficient intégrateur
float kd = 160; 			// Coefficient dérivateur

int stop_display = 3*50;

/* Routine d'initialisation */
void setup() {
  Serial.begin(9600); 		// Initialisation port COM
  pinMode(_MOTEUR, OUTPUT);   // Sortie moteur  
  analogWrite(_MOTEUR, 255);  // Sortie moteur à 0
  
  delay(5000);            	// Pause de 5 sec pour laisser le temps au moteur de s'arréter si celui-ci est en marche
  
  attachInterrupt(0, compteur, CHANGE);	// Interruption sur tick de la codeuse
  timer.setInterval(1000/frequence_echantillonnage, asservissement);  // Interruption pour calcul du PID et asservissement
}

/* Fonction principale */
void loop(){
  timer.run();
  delay(10);
}

/* Interruption sur tick de la codeuse */
void compteur(){
  tick_codeuse++;  // On incrémente le nombre de tick de la codeuse
}

/* Interruption pour calcul du PID */
void asservissement()
{
  // Calcul de l'erreur
  int frequence_codeuse = frequence_echantillonnage*tick_codeuse;
  float nb_tour_par_sec = (float)frequence_codeuse/(float)tick_par_tour_codeuse/(float)rapport_reducteur;  
  float erreur = consigne_moteur_nombre_tours_par_seconde - nb_tour_par_sec;
  somme_erreur += erreur;
  float delta_erreur = erreur-erreur_precedente;
  erreur_precedente = erreur;
  
  // PDI : calcul de la commande
  cmd = kp*erreur + ki*somme_erreur + kd*delta_erreur;
	
  // Normalisation et contrôle du moteur
  if(cmd < 0) cmd=0;
  else if(cmd > 255) cmd = 255;
  analogWrite(_MOTEUR, 255-cmd);
  
  // DEBUG
  if(stop_display >= 0) 
  {
	Serial.println(nb_tour_par_sec,8);
	stop_display--;
  }
  
  // Réinitialisation du nombre de tick de la codeuse
  tick_codeuse=0;
}

++
Black Templar

Mon site internet : http://ferdinandpiette.com/


#11 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 22 avril 2012 - 09:02

Plop !

J'ai synthétisé mes résultats dans un article.
http://www.ferdinandpiette.com/blog/2012/04/asservissement-en-vitesse-dun-moteur-avec-arduino/

++
Black Templar

Mon site internet : http://ferdinandpiette.com/


#12 lestephanoi

lestephanoi

    Habitué

  • Membres
  • PipPip
  • 161 messages
  • Gender:Male

Posté 24 avril 2012 - 02:30

Bonjour,

En numérique pour utiliser une commande par PID je vous conseille la transformé en Z, certes il faut avoir des connaissances en mathématique mais après l'utilisation est assez simple (enfin je trouve). Je vous aurais bien expliqué un peu plus mais je n'ai pas trop le temps alors je vous ai trouvé un cour qui explique assez bien :   Fichier joint  systemes-asservis-echantillonnes.pdf   213,38 Ko   219 téléchargement(s).

Si vous avez des questions n'hésitez pas.



#13 Black Templar

Black Templar

    Membre

  • Membres
  • PipPipPipPipPip
  • 1 430 messages
  • Gender:Male
  • Location:Lille

Posté 24 avril 2012 - 02:52

En numérique pour utiliser une commande par PID je vous conseille la transformé en Z, certes il faut avoir des connaissances en mathématique mais après l'utilisation est assez simple (enfin je trouve). Je vous aurais bien expliqué un peu plus mais je n'ai pas trop le temps alors je vous ai trouvé un cour qui explique assez bien ...


+1 !

Si vous avez le niveau mathématiques (asservissement analogique, transformée de Laplace, distributions et analyse fréquentielle, bases en numériques (échantillonnage, quantification, shanon, TFD), etc.) alors la transformée en Z est un must have qui vous permettra de refaire l'étude complète d'un système asservi en numérique.
Autrement, et bien le réglage d'un PID de façon adhoc marche aussi très bien wink.gif

++
Black Templar

Mon site internet : http://ferdinandpiette.com/


#14 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 7 905 messages
  • Gender:Male
  • Location:Anglet
  • Interests:Robotique, Entrepreneuriat, Innovation, Programmation, Résolution de problème, Recherche de solutions, Mécanique, Electronique, Créer, Concevoir

Posté 26 mars 2017 - 09:29

Afin de compléter le site indiqué par Black Templar vous trouverez ci contre un tutoriel complet simplifié pour l'utilisation d'un PID pour l'asservissement d'un moteur


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !

 

Les réalisations de Mike118  

 

 

 


#15 Telson

Telson

    Membre chevronné

  • Membres
  • PipPipPipPip
  • 975 messages
  • Gender:Male
  • Location:Punaauai - Tahiti

Posté 26 mars 2017 - 09:37

:clapping: :clapping: :clapping: :clapping: :thank_you: :thank_you: :thank_you:



#16 Melmet

Melmet

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 116 messages
  • Gender:Male
  • Location:Saint-Sozy (46200)

Posté 26 mars 2017 - 10:03

Wooowwww, très bien fait le tuto. BRAVO :)


Ne demande jamais à un robot de faire ce que tu peux faire toi même. :nono: :laugh1:


#17 levend

levend

    Pilier du forum

  • Membres
  • PipPipPipPipPip
  • 4 435 messages
  • Gender:Male
  • Location:Vendée
  • Interests:Robotique, informatique, architecture et patrimoine...

Posté 28 mars 2017 - 03:12

Ma question vous semblera peut-être stupide, pas surprenant elle vient de moi :D : avec un PID peut-on "piloter" autre chose qu'un moteur comme par exemple un fil chauffant (comme ceux des cigarettes électroniques) ? Evidemment je pense qu'il est nécessaire d'avoir une sonde de température...

 

Cela fait pas mal de temps que je me pose la question et là avec la remontée du sujet...

J'avais lu quelques chose sur une fonderie DIY faite avec un fil chauffant, le sujet ne détaillait pas trop la partie électronique mais il me semble qu'il parlait d'un PID.

Cela pourrait aussi servir pour réaliser un plateau chauffant pour imprimante 3D, par exemple, surtout si le plateau est grand.



#18 Oracid

Oracid

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 4 390 messages
  • Gender:Male

Posté 28 mars 2017 - 06:25

Ma question vous semblera peut-être stupide, pas surprenant elle vient de moi :D : avec un PID peut-on "piloter" autre chose qu'un moteur comme par exemple un fil chauffant (comme ceux des cigarettes électroniques) ?

Perso, je dirais, oui !
Que l'on veuille stabiliser une vitesse ou une température, l'objectif est bien de stabiliser une grandeur physique.
Et d'ailleurs, cela m'étonnerait que ce ne soit pas déjà le cas pour le tube chauffant d'une imprimante 3D, et pourquoi pas pour le plateau.
Ma chaine vidéo YouTube : https://www.youtube....wMz-IzZqyvqEUek

#19 R1D1

R1D1

    Modérateur et Membre passionné

  • Modérateur
  • PipPipPipPipPip
  • 1 142 messages
  • Gender:Male
  • Location:Autriche

Posté 28 mars 2017 - 12:25

(...)

Cela fait pas mal de temps que je me pose la question et là avec la remontée du sujet...

J'avais lu quelques chose sur une fonderie DIY faite avec un fil chauffant, le sujet ne détaillait pas trop la partie électronique mais il me semble qu'il parlait d'un PID.

Cela pourrait aussi servir pour réaliser un plateau chauffant pour imprimante 3D, par exemple, surtout si le plateau est grand.

En effet, le PID est juste un algorithme de régulation, donc une méthode pour s'assurer qu'une grandeur contrôlée est bien à la valeur désirée (consigne). En robotique, on trouve très souvent l'exemple de la vitesse de rotation, mais on peut appliquer ce type de méthode à d'autres grandeurs : accélération, position (servomoteur), force, température (ton four ou ton chauffage domestique), débit, tension, etc.


R1D1 - Calculo Sed Ergo Sum -- en ce moment, Projet Ballista
Avatar tiré du site bottlebot

#20 levend

levend

    Pilier du forum

  • Membres
  • PipPipPipPipPip
  • 4 435 messages
  • Gender:Male
  • Location:Vendée
  • Interests:Robotique, informatique, architecture et patrimoine...

Posté 28 mars 2017 - 06:57

Merci pour vos réponses, comme ça je me coucherai moins bête ce soir :D .






0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users