asservissement de position

Bonjour à tous,

Je fais un projet sur un asservissement de position, et pour cela j’utilise un accéléromètre et un moteur à courant continu. J’utilise également un inverseur 3 positions (ON OFF ON) qui me permet de donner ma consigne.

J’ai réussit à faire un programme qui marche bien, je vous le mets ici :

int E1 = 5; 
int M1 = 4;
const int I1 = 2; 
const int I2 = 3; 

const int Voie_0=0;
int mesure_brute=0;


void setup()
{
    pinMode(M1, OUTPUT);  
    pinMode(I1, INPUT); 
    pinMode(I2, INPUT); 
    
    Serial.begin(115200);
    
} // fin du setup





void loop()
{


  //int value1 = digitalRead(I1); 
  //int value2 = digitalRead(I2);
  mesure_brute=analogRead(Voie_0);
  //Serial.println(mesure_brute);
  int angle = -0.651*mesure_brute+329; 
  Serial.println(angle); // afficher à la ligne l'angle

  //delay(1000); 
 
  
 if (angle<0)
 {
    digitalWrite(M1, HIGH);
    Serial.println("HIGH");
     
  }


 if (angle>0)
 {
   digitalWrite(M1, LOW);
   Serial.println("LOW");
 }
 
 
 analogWrite(E1,50);
 
  }

Cependant, ce programme ne prend pas en compte ma consigne. Mon but dans ce projet et d’arriver à maintenir une position angulaire (l’équation “angle = -0.651*mesure_brute+329” me donne l’angle, et le fait très bien, le problème n’est pas là). En fait je voudrais à l’aide de mon inverseur donner une consigne, c’est-à-dire faire tourner mon moteur jusqu’à une position voulue (mon moteur étant relié à une “planche” où est fixé dessus l’accéléromètre, donc je veux conserver la mesure de l’angle donnée par l’accéléromètre). J’ai donc essayé de modifier mon programme pour arriver à cela, mais le moteur “bourre” quand je téléverse le programme dans mon arduino (uno).

Quelqu’un saurait-il comment faire le bon programme ? Je vous laisse un schéma pour illustrer la situation, ainsi que le programme “modifié”.

int E1 = 5; 
int M1 = 4;
const int I1 = 2; 
const int I2 = 3; 

const int Voie_0=0;
int mesure_brute=0;


void setup()
{
    pinMode(M1, OUTPUT);  
    pinMode(I1, INPUT); 
    pinMode(I2, INPUT); 
    
    Serial.begin(115200);
    
} // fin du setup





void loop()
{
 while (I1==1 or I2==1)
  mesure_brute=analogRead(Voie_0);
  int consigne = -0.651*mesure_brute+329;


  //int value1 = digitalRead(I1); 
  //int value2 = digitalRead(I2);
  mesure_brute=analogRead(Voie_0);
  //Serial.println(mesure_brute);
  int angle = -0.651*mesure_brute+329; 
  Serial.println(angle); // afficher à la ligne l'angle

  //delay(1000); 
 
  
 if (angle<consigne)
 {
    digitalWrite(M1, HIGH);
    Serial.println("HIGH");
     
  }


 if (angle>consigne)
 {
   digitalWrite(M1, LOW);
   Serial.println("LOW");
 }
 
 analogWrite(E1,50);
 
  }

Merci de votre réponse, et bonne soirée à tous !

bonjour,
je sais pas ou est passée ma réponse, donc je me retape le tout.

  int consigne = -0.651*mesure_brute+329;

et

  int angle = -0.651*mesure_brute+329;

sont identiques, comment veux tu qu'un soit supèrieur ou inférieur à l'autre?

après comment veux tu que ceci soit valable?

while (I1==1 or I2==1)

tu déclare avant

const int I1 = 2; 
const int I2 = 3;

sans modifié leur valeur après avec un Read vu qu'ils sont en INPUT
donc tes conditions ne sont jamais bonnes

Bonjour,

Pour mon "int consigne" et "int angle" c'est vrai que ça ne peut pas marcher… Mais alors comment définir ma consigne ? Parce que dans mon programme je n'ai qu'une seule équation qui me donne mon angle.

I1 et I2 sont les sorties de mon inverseur. Pour moi (je dis bien "pour moi" car ce n'est sans doute pas comme ça qu'il faut penser) quand je dis I1==1 par exemple, c'est que ma sortie de l'inverseur I1 est au niveau logique 1, donc qu'elle est actionnée. Je voulais donc me servir de ce "1" en question, pour que mon programme sache ce qui me permet de donner ma consigne, en l'occurrence quand I1 ou I2 est actionné.

Merci beaucoup pour ton aide !

Ce qu'il veut dire c'est que ces 2 variables ne sont jamais modifiées.

tu devrais alors décommenter :

 //int value1 = digitalRead(I1);
  //int value2 = digitalRead(I2);

Et faire un test value1==1 or value2==1

Pour le réglage de la consigne ... Si j'ai bien compris ton inverseur on off on te sert à faire tourner le moteur (dans un sens ou dans l'autre) pour régler ta consigne et la position neutre est celle où le moteur doit conserver la consigne ?

Si c'est ça, la règle est assez facile : quand le bouton est sur on, tu fais bouger ton moteur et tu mesures ton angle et tu affectes sa valeur a la consigne
Quand tu remets ton inter sur off, tu mesures ton angle et tu le compares a la consigne

Loop
Valeur1 = digitalRead...
Valeur2 = digitalRead...
Angle = ....
If valeur1==1
Tourne moteur sens 1
Consigne = angle
Else if valeur2==1
Tourne moteur sens2
Consigne =angle
Else
If angle > consigne
Tourne moteur sens 1
Else
Tourne moteur sens 2
Fin du loop

Bonsoir,

Oui c'est exactement cela que je cherche à faire.

Par contre, dans ce schéma du programme à suivre que tu viens de me donner, comment et où dois-je déclarer mon "consigne" ?

Déclares consigne avant le setup comme ça sa valeur sera visible dans tous le programme
Au départ elle vaudra par defaut 0 ... A toi de voir si ça te convient

Mais il y a une chose que je ne comprends pas : il faut que je déclare consigne et angle ? Pour déclarer mon angle, je vais faire "int angle = -0.651*mesure_brute+329" mais pour ma consigne, je mets quoi ? Je peux pas remettre la même équation ?

Je viens d'essayer de modifier mon programme, mais comme je n'ai pas le moteur sous la main, je ne peux pas vérifier s'il marche. Je suis toujours perplexe sur la façon dont j'ai posé "consigne"... Je le poste ici, et pourrais-tu me dire ce que tu en penses ? (en tout cas, au niveau "écriture du programme" il est bon, puisque Arduino le vérifie parfaitement)

int E1 = 5; 
int M1 = 4;
const int I1 = 2; 
const int I2 = 3; 

const int Voie_0=0;
int mesure_brute=0;
int consigne = -0.651*mesure_brute+329;


void setup()
{
    pinMode(M1, OUTPUT);  
    pinMode(I1, INPUT); 
    pinMode(I2, INPUT); 
    
    Serial.begin(115200);
    
} // fin du setup



void loop()
{
 
 

  int value1 = digitalRead(I1); 
  int value2 = digitalRead(I2);
  mesure_brute=analogRead(Voie_0); // info de l'accéléromètre
  //Serial.println(mesure_brute);
  int angle = -0.651*mesure_brute+329; 
  Serial.println(angle); // afficher à la ligne l'angle

  //delay(1000); 

 if (value1==1)
  {
    digitalWrite(M1, HIGH);
    consigne==angle ;
   }
  
 else if (value2==1)
 {
    digitalWrite(M1, LOW);
    consigne==angle;   
  }


 else 
 {
 if (angle>consigne)
 {
   digitalWrite(M1, HIGH);
   //Serial.println("LOW");
 }
 else 
 {
   digitalWrite(M1, LOW);
  }
 analogWrite(E1,50);
  }
 
  }

Merci à tous pour l'aide !

Pour l'initialisation c'est bon ... Tu pourrais aussi dans le setup lire la valeur de mesures brutes ( comme tu le fais dans le loop) et initialiser la valeur de la consigne avec cette mesure ... Ainsi ton moteur ne bougera pas au démarrage (angle mesuré au départ = consigne)

Dans le loop quand tu écris consigne==angle, tu n'auras pas le résultat que tu attends ... Je te laisse réfléchir un peu

J'ajouterai des Serial.print dans les différents tests du loop pour vérifier que ton programme passe bien là où il faut et je mettrai un petit delay(200) à la fin du loop pour le calmer

Si tu n'as pas de moteur tu mets des serial.print ...

Au niveau câblage du moteur tu fais comment ? Car je ne vois pas comment tu inverses son sens de rotation

Je n'ai pas très bien compris l'histoire du mesure brute…

C'était consigne=angle du coup ?

int E1 = 5; 
int M1 = 4;
const int I1 = 2; 
const int I2 = 3; 

const int Voie_0=0;
int mesure_brute=0;
int consigne = -0.651*mesure_brute+329;


void setup()
{
    pinMode(M1, OUTPUT);  
    pinMode(I1, INPUT); 
    pinMode(I2, INPUT); 
    
    
    Serial.begin(115200);
    
} // fin du setup



void loop()
{
 
 

  int value1 = digitalRead(I1); 
  int value2 = digitalRead(I2);
  mesure_brute=analogRead(Voie_0); // info de l'accéléromètre
  //Serial.println(mesure_brute);
  int angle = -0.651*mesure_brute+329; 
  Serial.println(angle); // afficher à la ligne l'angle

  //delay(1000); 

 if (value1==1)
  {
    digitalWrite(M1, HIGH);
    consigne=angle ;
    Serial.println("value1==1");
   }
  
 else if (value2==1)
 {
    digitalWrite(M1, LOW);
    consigne=angle; 
    Serial.println("value2==1");
  }


 else 
 {
 if (angle>consigne)
 {
   digitalWrite(M1, HIGH);
   Serial.println("HIGH");
 }
 else 
 {
   digitalWrite(M1, LOW);
   Serial.println("LOW");
  }
 analogWrite(E1,50);
  }
 delay(200);
  }

Le câblage c'est le même que j'ai mis dans la pièce jointe, j'ai relié mes 2 sorties de mon inverseur sur le 2 et 3 de l'arduino, puis j'ai relié mon moteur sur un shield L298P. Je sais pas si je suis assez clair ?

Autant pour moi, je n'avais pas vu le schéma du moteur ...

Au démarrage du programme tu as le choix entre :
1: (Ce que tu as fait) initialiser la valeur de mesure_brute à zero, et calculer la consigne qui en decoule avec la formule ... Donc au démarrage ton moteur va tourner pour atteindre cette consigne

2: Soit dans le setup, tu fais mesure_brute = analogRead(Voie0), tu calcules l'angle correspondant, et tu initialises ta consigne avec cet angle... Du coup au démarrage ton moteur ne bouge pas et reste dans sa position initiale ...

L'un comme l'autre fonctionne .. C'est juste 2 façons de débuter le programme

Et oui, consigne=angle c'est mieux ...

2: Soit dans le setup, tu fais mesure_brute = analogRead(Voie0), tu calcules l'angle correspondant, et tu initialises ta consigne avec cet angle... Du coup au démarrage ton moteur ne bouge pas et reste dans sa position initiale ...

--> Donc si je fais ça, au démarrage mon moteur ne tournera pas car il sera déjà dans une position "pré-réglée" ? Je ne vois pas trop comment calculer l'angle correspondant ?

:o ... Tu n'as qu'une seule formule à utiliser pour convertir la mesure brute de ton accéléromètre en valeur d'angle ! Et c'est toujours la même et tu l'utilises déjà dans ton programme ...ou alors c'est moi qui ne comprends rien ...

Non non la formule je sais que c'est toujours la même, ce n'est pas ça que je ne comprends pas. Je ne vois juste pas comment mon programme saura quelle est ma valeur de départ si je mets le mesure_brute dans le setup ?

Bon...

Tu déclares mesure_brute ( et consigne aussi) avant le setup (ce sera une variable globale,visible partout dans ton programme)
setup()
mesure_brute = analogRead... //lecture de l'accelerometre
Angle = a x mesure_brute + b // calcul de l'angle initial
Consigne = angle //on fixe la consigne = angle initial de sorte que le moteur ne bouge pas au démarrage

Loop()
...

Désolé, je ne suis pas beaucoup expérimenté en Arduino (c'est le moins qu'on puisse dire effectivement !)

D'accord, maintenant c'est plus clair ! Je comprends mieux ce que le programme est censé faire comme tu ceci.
Mais angle = -0.651*mesure_brute+329 je devrais pas le déclarer avant le setup aussi ? Arduino risque de me le rejeter sinon ?

La c'est un problème de langage informatique ... En l'occurrence de langage C ... Arduino n'y est pour rien ... Il faudrait que tu trouves des cours sur les bases du C

Déclares angle aussi avant le setup ... Comme ça tu es tranquille.

Juste une précision, car je pense qu'on est pas sur la même longueur d'onde ... Quand tu écris int angle = -0.651*mesures + 329
Tu fais deux choses en même temps (c'est autorisé) : tu déclares une variable de type int qui s'appelle angle, et tu lui donnes comme valeur le résultat de la formule mathématique (au moment où ton programme exécute cette ligne)
On est bien d'accord qu'en déclarant angle de la sorte, il n'est pas lié en permanence avec mesure_brute ... Autrement dit si mesure_brute change de valeur, ta variable angle ne changera pas de valeur automatiquement... A chaque fois que tu lis une mesure_brute, il faut appliquer la formule mathématique pour calculer la nouvelle valeur de angle ... Ok ?

Mais mon angle je peux le déclarer en int au dessus du setup quand même ?

Oui oui, c'est mon mesure_brute qui influe sur la valeur de angle. Mais alors du coup là, si je comprends ce que tu me dis, ma variable angle ne change jamais de valeur ?
Parce que pour moi le "angle" venait chercher la valeur de mesure_brute, et l'introduisait dans l'équation mathématique pour m'en sortir une valeur de mon angle, et avant que je modifie le programme, quand je ne m'occupais pas de consigne encore, mon moteur tournait bien en fonction de la valeur de mon angle.

Dans ton premier programme, dans le loop, tu calculais l'angle avec la formule mathématique ... Ce n'est pas angle qui va chercher mesure_brute ... Les variables ne sont pas liées par une formule mathématique, même si a la déclaration tu mets une formule (c'est le résultat de la formule qui est affecté à la variable, pas la formule mathématique elle même !)

Si tu fais
Int a=1
Int c = a+ 2 // a vaut 1 et donc c vaudra 3 apres cette ligne
a = 2 // a vaut 2 maintenant mais c vaut toujours 3 !
a = 3 // a vaut 3 et c vaut toujours 3
c = 99 // a vaut 3 et c vaut 99 ...

On est d'accord ???

Ton programme
// déclaration des variables (pas besoin de leur affecter des valeurs ... )
Int angle;
Int mesure_ brute;
Int consigne;

Setup()
Pinmode....
Mesure_brute = analogRead(voie0); // lecture de la position initiale
Angle = 0.615* mesure_brute +329; // calcul de l'angle initial
Consigne = angle; // consigne init

Loop()
Mesure_brute = analogRead... // lecture de la position actuelle
Angle = 0.615* mesure_brute +329 // calcul de l'angle actuel
If (blabla)...
If (blabla)...

Si tu ne refais pas le calcul d'angle dans le loop (comme tu le faisais dans ton tout premier programme) il ne va pas se calculer tout seul par magie